?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL Interpreter : HELP Command' ??
MODULE clm$help_command;

{
{ PURPOSE:
{   This module contains the processor for the HELP command.
{

?? NEWTITLE := 'Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc clt$parameter_list
*copyc cle$ecc_utilities
*copyc clt$command_processor
*copyc clt$path_name
*copyc ost$status
?? POP ??
*copyc clp$begin_utility
*copyc clp$change_variable
*copyc clp$convert_string_to_name
*copyc clp$create_procedure_variable
*copyc clp$end_utility
*copyc clp$evaluate_parameters
*copyc clp$get_utility_attributes
*copyc clp$include_command
*copyc clp$scan_expression
*copyc clp$trimmed_string_size
*copyc osp$get_status_condition_name

  CONST
    clc$command_previous_status = 'CLV$COMMAND_PREV_STATUS        ',
    clc$help_command_utility = 'CLU$HELP_COMMAND_UTILITY       ',
    subject_prefix = 'U$',
    subject_prefix_size = 2;

{
{ Check whether the text of the application value is simply a name.  If it
{ is, use the string form of that name as the evaluated result.  If it isn't,
{ evaluate the application value text as a string expression. If it isn't a
{ string expression, then pass the text back as a string.
{
{ Examples:     Specifying                Yields
{               ----------                ------
{
{               'some subject'            some subject
{               $value                    $VALUE
{               $value(p)                 "the value of parameter P"
{               %1                        %1
{

?? TITLE := 'clp$_help', EJECT ??

  PROCEDURE [XDCL] clp$_help
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE (osm$help) help, h (
{   subject, s: any of
{       data_name
{       string
{       application
{     anyend = $optional
{   manual, m: file = $system.manuals.scl
{   list, l: file = manual_pages
{   status: status = $optional
{   clv$previous_status: (BY_NAME, HIDDEN) status = $previous_status
{   )

?? PUSH (LISTEXT := ON) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 8] of clt$pdt_parameter_name,
      parameters: array [1 .. 5] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$union_type_qualifier,
        type_size_1: clt$type_specification_size,
        element_type_spec_1: record
          header: clt$type_specification_header,
        recend,
        type_size_2: clt$type_specification_size,
        element_type_spec_2: record
          header: clt$type_specification_header,
          qualifier: clt$string_type_qualifier,
        recend,
        type_size_3: clt$type_specification_size,
        element_type_spec_3: record
          header: clt$type_specification_header,
          qualifier: clt$application_type_qualifier,
        recend,
      recend,
      type2: record
        header: clt$type_specification_header,
        default_value: string (19),
      recend,
      type3: record
        header: clt$type_specification_header,
        default_value: string (12),
      recend,
      type4: record
        header: clt$type_specification_header,
      recend,
      type5: record
        header: clt$type_specification_header,
        default_value: string (16),
      recend,
    recend := [
    [1,
    [88, 7, 11, 10, 15, 14, 537],
    clc$command, 8, 5, 0, 0, 1, 0, 0, 'OSM$HELP'], [
    ['CLV$PREVIOUS_STATUS            ',clc$nominal_entry, 5],
    ['L                              ',clc$abbreviation_entry, 3],
    ['LIST                           ',clc$nominal_entry, 3],
    ['M                              ',clc$abbreviation_entry, 2],
    ['MANUAL                         ',clc$nominal_entry, 2],
    ['S                              ',clc$abbreviation_entry, 1],
    ['STATUS                         ',clc$nominal_entry, 4],
    ['SUBJECT                        ',clc$nominal_entry, 1]],
    [
{ PARAMETER 1
    [8, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 39, clc$optional_parameter,
  0, 0],
{ PARAMETER 2
    [5, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_default_parameter, 0, 19],
{ PARAMETER 3
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_default_parameter, 0, 12],
{ PARAMETER 4
    [7, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3, clc$optional_parameter, 0
  , 0],
{ PARAMETER 5
    [1, clc$hidden_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_default_parameter, 0, 16]],
{ PARAMETER 1
    [[1, 0, clc$union_type], [[clc$application_type, clc$data_name_type, clc$string_type],
    FALSE, 3],
    3, [[1, 0, clc$data_name_type]],
    8, [[1, 0, clc$string_type], [0, clc$max_string_size, FALSE]],
    4, [[1, 0, clc$application_type], [FALSE]]
    ],
{ PARAMETER 2
    [[1, 0, clc$file_type],
    '$system.manuals.scl'],
{ PARAMETER 3
    [[1, 0, clc$file_type],
    'manual_pages'],
{ PARAMETER 4
    [[1, 0, clc$status_type]],
{ PARAMETER 5
    [[1, 0, clc$status_type],
    '$previous_status']];

?? POP ??

  CONST
    p$subject = 1,
    p$manual = 2,
    p$list = 3,
    p$status = 4,
    p$clv$previous_status = 5;

  VAR
    pvt: array [1 .. 5] of clt$parameter_value;

{ TYPE
{   status_type = status
{ TYPEND

?? PUSH (LISTEXT := ON) ??

    VAR
      status_type: [STATIC, READ, cls$declaration_section] record
        header: clt$type_specification_header,
      recend := [[1, 0, clc$status_type]];

?? POP ??

    VAR
      added_subject_length: integer,
      begin_utility_attributes: array [1 .. 1] of clt$utility_attribute,
      command_line: string (256),
      command_line_length: integer,
      executing_utility: boolean,
      get_utility_attributes: array [1 .. 2] of clt$utility_attribute,
      local_status: ost$status,
      manual_file_name: clt$path_name,
      manual_file_name_size: 1 .. clc$max_path_name_size,
      previous_status_condition_name: ost$status_condition_name,
      subject_string: ^clt$string_value,
      utility_subject_string: string (osc$max_name_size + subject_prefix_size);

    subject_string := NIL;

    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF pvt [p$subject].specified THEN
      IF pvt [p$subject].value^.kind = clc$application THEN
        subject_string := pvt [p$subject].value^.application_value;
      ELSEIF pvt [p$subject].value^.kind = clc$data_name THEN
        subject_string := ^pvt [p$subject].value^.data_name_value;
      ELSE {string value}
        subject_string := pvt [p$subject].value^.string_value;
      IFEND;
    IFEND;

    executing_utility := FALSE;

{
{  The following hierarchy is used to build the EXPLAIN command:
{
{ 1.  If the MANUAL parameter is specified, then execute the EXPLAIN
{     command with the other values of the HELP command.
{
{ 2.  If the SUBJECT parameter is specified and the user is executing a
{     utility, use the utility attribute online manual name for the MANUAL
{     parameter on the EXPLAIN command.  If the user is not executing a
{     utility, use the MANUAL value from the HELP command.
{
{ 3.  If $previous_status was abnormal then the diagnostic messages manual
{     is entered, with the subject equaling the condition name of the
{     previous status.
{
{     Create a utility block via CLP$PUSH_UTILITY and then create the SCL
{     variable CLV$COMMAND_PREVIOUS_STATUS for the diagnostic messages
{     manual.  This variable is used within the manual to report a message
{     that is not listed in the messages manual.
{
{ 4.  If the user is currently executing a utility, then execute the
{     EXPLAIN command using the default MANUAL parameter unless the online
{     manual name utility attribute is non-blank and a value of
{     'U$'//utility-name for the SUBJECT.
{
{ 5.  If the user is either executing an asynchronous task or not
{     executing a utility, then execute the EXPLAIN command using the
{     default MANUAL and SUBJECT parameters.
{

  /build_explain_command/
    BEGIN

      IF pvt [p$manual].specified THEN
        STRINGREP (command_line, command_line_length, 'explain manual=', pvt [p$manual].value^.file_value^,
              ' list=', pvt [p$list].value^.file_value^);
        EXIT /build_explain_command/;
      IFEND;

      IF (pvt [p$subject].specified) OR (pvt [p$clv$previous_status].value^.status_value^.normal) THEN
        get_utility_attributes [1].key := clc$utility_name;
        get_utility_attributes [2].key := clc$utility_online_manual;
        clp$get_utility_attributes (osc$null_name, get_utility_attributes, status);
        IF status.normal THEN

{ User is currently executing a utility. Use the default online manual or
{ the utility attribute online manual name.

          IF get_utility_attributes [2].online_manual_name = osc$null_name THEN
            manual_file_name := pvt [p$manual].value^.file_value^;
            manual_file_name_size := clp$trimmed_string_size (pvt [p$manual].value^.file_value^);
          ELSE
            manual_file_name := get_utility_attributes [2].online_manual_name;
            manual_file_name_size := clp$trimmed_string_size (get_utility_attributes [2].online_manual_name);
          IFEND;

{ The help SUBJECT is either what the user specified or 'U$' concatenated
{ with the utility name.

          IF NOT pvt [p$subject].specified THEN
            utility_subject_string := subject_prefix;
            utility_subject_string (subject_prefix_size + 1, * ) := get_utility_attributes
                  [1].name (1, clp$trimmed_string_size (get_utility_attributes [1].name));
            subject_string := ^utility_subject_string;
          IFEND;
          STRINGREP (command_line, command_line_length, 'explain manual=',
                manual_file_name (1, manual_file_name_size), ' list=', pvt [p$list].value^.file_value^);
          EXIT /build_explain_command/;

{ User is not currently executing a utility.

        ELSEIF status.condition = cle$unknown_utility THEN
          STRINGREP (command_line, command_line_length, 'explain manual=', pvt [p$manual].value^.file_value^,
                ' list=', pvt [p$list].value^.file_value^);
          EXIT /build_explain_command/;

{ An unexpected error occurred in the clp$get_utilty_attributes request.

        ELSE
          RETURN;
        IFEND;
      IFEND;

{ $PREVIOUS_STATUS was abnormal - use the MESSAGES manual to explain the
{ previous status message.

      osp$get_status_condition_name (pvt [p$clv$previous_status].value^.status_value^.condition,
            previous_status_condition_name, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      begin_utility_attributes [1].key := clc$utility_command_search_mode;
      begin_utility_attributes [1].command_search_mode := clc$global_command_search;
      clp$begin_utility (clc$help_command_utility, begin_utility_attributes, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      executing_utility := TRUE;
      clp$create_procedure_variable (clc$command_previous_status, clc$xdcl_scope, clc$read_write,
            clc$immediate_evaluation, #SEQ (status_type), NIL, status);
      IF NOT status.normal THEN
        clp$end_utility (clc$help_command_utility, local_status);
        RETURN;
      IFEND;
      clp$change_variable (clc$command_previous_status, pvt [p$clv$previous_status].value, status);
      IF NOT status.normal THEN
        clp$end_utility (clc$help_command_utility, local_status);
        RETURN;
      IFEND;
      STRINGREP (command_line, command_line_length,
            'explain manual=$system.manuals.messages $child=help subject=''',
            previous_status_condition_name (1, clp$trimmed_string_size (previous_status_condition_name)),
            '''', ' list=', pvt [p$list].value^.file_value^);

    END /build_explain_command/;

{ Add SUBJECT parameter if necessary.

    IF subject_string <> NIL THEN
      STRINGREP (command_line (command_line_length, * ), added_subject_length, ' subject=''',
            subject_string^ (1, clp$trimmed_string_size (subject_string^)), '''');
      command_line_length := command_line_length + added_subject_length - 1;
    IFEND;

    clp$include_command (command_line (1, command_line_length), FALSE, status);

    IF executing_utility THEN
      clp$end_utility (clc$help_command_utility, local_status);
      IF (NOT local_status.normal) AND status.normal THEN
        status := local_status;
      IFEND;
    IFEND;

  PROCEND clp$_help;

MODEND clm$help_command;

