?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL Interpreter : Parameter List Scanner' ??
MODULE clm$f_scan_parameter_list;

{ NOTE: This module is a modification of the SCL Interpreter module CLM$SCAN_PARAMETER_LIST


?? NEWTITLE := 'Global Declarations' ??
?? NEWTITLE := 'Parameter Descriptor Table (PDT)', EJECT ??
*copyc clt$parameter_descriptor_table
?? OLDTITLE, EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc clc$max_parameters
*copyc clc$max_parameter_names
*copyc clt$parameter_list
*copyc cle$ecc_expression_result
*copyc cle$ecc_miscellaneous
*copyc cle$ecc_parameter_list
*copyc clt$command_line
*copyc clt$command_line_index
*copyc clt$command_line_size
*copyc oss$job_paged_literal
*copyc ost$status
*copyc ost$string
?? POP ??
*copyc clp$append_status_parse_state
*copyc clp$delete_current_format_token
*copyc clp$f_evaluate_expression
*copyc clp$f_scan_expression
*copyc clp$f_scan_token
*copyc clp$initialize_parse_state
*copyc clp$insert_format_marker
*copyc clp$recognize_format_tokens
*copyc clp$set_format_type
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc osv$lower_to_upper

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

  PROCEDURE [XDCL, #GATE] clp$f_scan_parameter_list
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      number_of_parameters: 0 .. clc$max_parameters,
      parameter_name_indices: ^array [1 .. * ] of 0 .. clc$max_parameter_names,
      parameter_number: 1 .. clc$max_parameters + 1,
      parameter_list_ptr: ^clt$parameter_list,
      text_ptr: ^string ( * ),
      text_size_ptr: ^clt$command_line_size,
      parse: clt$parse_state,
      local_status: ost$status;

  /scan/
    BEGIN
      local_status.normal := TRUE;
      status.normal := TRUE;
      parameter_list_ptr := ^parameter_list;
      text_ptr := NIL;
      RESET parameter_list_ptr;
      NEXT text_size_ptr IN parameter_list_ptr;
      IF (text_size_ptr <> NIL) AND (text_size_ptr^ <= clc$max_command_line_size) THEN
        NEXT text_ptr: [text_size_ptr^] IN parameter_list_ptr;
      IFEND;
      IF text_ptr = NIL THEN
        osp$set_status_abnormal ('CL', cle$garbled_parameter_list, '', local_status);
        EXIT /scan/;
      IFEND;
      parameter_number := 1;
      clp$initialize_parse_state (text_ptr, NIL, parse);
      clp$f_scan_token (clc$slu_non_space, parse);

      WHILE local_status.normal AND (NOT (parse.unit.kind = clc$lex_end_of_line)) DO
        IF (parse.unit.kind = clc$lex_comma) OR (parse.unit.kind = clc$lex_space) THEN
          REPEAT
            clp$insert_format_marker (clc$parameter_begin, 1);
            clp$insert_format_marker (clc$parameter_end, 1);
            parameter_number := parameter_number + 1;
            clp$f_scan_token (clc$slu_non_space, parse);
          UNTIL NOT ((parse.unit.kind = clc$lex_comma) OR (parse.unit_is_space));
        ELSE
          scan_parameter (parse, local_status);
          IF local_status.normal THEN
            IF (parse.unit.kind = clc$lex_comma) OR (parse.unit.kind = clc$lex_space) THEN
              clp$f_scan_token (clc$slu_non_space, parse);
            IFEND;
            parameter_number := parameter_number + 1;
          IFEND;
        IFEND;
      WHILEND;

    END /scan/;

    IF local_status.normal THEN
      status.normal := TRUE;
    ELSE
      status := local_status;
    IFEND;

  PROCEND clp$f_scan_parameter_list;
?? TITLE := 'scan_parameter', EJECT ??

  PROCEDURE scan_parameter
    (VAR parse {input, output} : clt$parse_state;
     VAR status: ost$status);

    VAR
      evaluating_list: boolean,
      parameter_given_by_name: boolean,
      parameter_name: ost$name,
      local_status: ost$status,
      next_parse: clt$parse_state,
      value: clt$value,
      value_kind_specifier: clt$value_kind_specifier;


    parameter_given_by_name := FALSE;
    evaluating_list := FALSE;
    clp$insert_format_marker (clc$parameter_begin, 1);
    IF parse.unit.kind = clc$lex_name THEN
      parameter_name := parse.text^ (parse.unit_index, parse.unit.size);
      next_parse := parse;
      clp$recognize_format_tokens (FALSE);
      clp$f_scan_token (clc$slu_non_space, next_parse);
      clp$recognize_format_tokens (TRUE);
      IF next_parse.unit.kind = clc$lex_assign THEN
        clp$set_format_type (clc$parameter_name);
        clp$f_scan_token (clc$slu_non_space, parse); {read the assignment unit
        parameter_given_by_name := TRUE;
        clp$f_scan_token (clc$slu_non_space, parse); {read the first unit of the parameter
      ELSE
        parameter_name := '';
      IFEND;
    IFEND;

    value_kind_specifier.kind := clc$any_value;
    IF parse.unit.kind = clc$lex_left_parenthesis THEN
      evaluating_list := TRUE;
    IFEND;
    clp$f_evaluate_expression (value_kind_specifier, FALSE, TRUE, parse, value, status);
    IF (NOT evaluating_list) AND (parse.unit.kind <> clc$lex_comma) THEN
      clp$f_scan_token (clc$slu_non_space, parse);
    IFEND;
    IF (parse.unit.kind <> clc$lex_end_of_line) AND (parse.unit.kind <> clc$lex_comma) AND
          (NOT parse.previous_unit_is_space) AND (NOT parse.unit_is_space) THEN
      osp$set_status_abnormal ('CL', cle$expecting_end_of_expression, '', status);
      clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
    IFEND;

    IF (NOT status.normal) AND (clc$min_ecc_expression_result <= status.condition) AND
          (status.condition <= clc$max_ecc_expression_result) THEN
      osp$append_status_parameter (osc$status_parameter_delimiter, ' for parameter', status);
      osp$append_status_parameter (' ', parameter_name, status);
    IFEND;
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF parse.unit.kind = clc$lex_end_of_line THEN
      clp$insert_format_marker (clc$parameter_end, 0);
    ELSE
      IF parse.unit.kind = clc$lex_comma THEN
        clp$insert_format_marker (clc$parameter_end, 1);
      ELSE
        clp$insert_format_marker (clc$parameter_end, 2);
      IFEND;
    IFEND;

  PROCEND scan_parameter;

MODEND clm$f_scan_parameter_list;
