?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL Interpreter : "Old" PROC/PDT declaration scanner' ??
MODULE clm$scan_proc_pdt_declaration;

{
{ PURPOSE:
{   This module contains the scanner for the "old" (pre- SCL New Types)
{   declaration of an SCL PROC or the PDT of a command.
{

?? NEWTITLE := 'Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc clc$lexical_units_size_pad
*copyc clc$max_proc_names
*copyc clc$proc_pdt_parameter_limits
*copyc cle$ecc_parameter_list
*copyc cle$ecc_parsing
*copyc cle$ecc_proc_declaration
*copyc cle$table_overflow
*copyc cle$work_area_overflow
*copyc clk$scan_proc_declaration
*copyc clt$expression_text
*copyc clt$expression_text_index
*copyc clt$expression_text_size
*copyc clt$internal_input_procedure
*copyc clt$parameter_descriptor_table
*copyc clt$proc_input_procedure
*copyc clt$proc_input_type
*copyc clt$proc_names
*copyc clt$symbolic_parameters
*copyc clt$token
*copyc clt$work_area
*copyc oss$job_paged_literal
*copyc ost$name_reference
?? POP ??
*copyc clp$append_status_parse_state
*copyc clp$echo_command
*copyc clp$evaluate_integer_expression
*copyc clp$get_command_line
*copyc clp$get_work_area
*copyc clp$identify_lexical_units
*copyc clp$initialize_parse_state
*copyc clp$scan_non_space_lexical_unit
*copyc clp$scan_unnested_rel_lex_unit
*copyc clp$scan_unnested_sep_lex_unit
*copyc i#current_sequence_position
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc osv$lower_to_upper

?? TITLE := 'clp$scan_proc_declaration', EJECT ??
*copyc clh$scan_proc_declaration

  PROCEDURE [XDCL, #GATE] clp$scan_proc_declaration
    (    input_type: clt$proc_input_type;
         get_line: clt$proc_input_procedure;
     VAR proc_name_area: SEQ ( * );
     VAR parameter_name_area: SEQ ( * );
     VAR parameter_area: SEQ ( * );
     VAR symbolic_parameter_area: SEQ ( * );
     VAR extra_info_area: SEQ ( * );
     VAR proc_names: ^clt$proc_names;
     VAR pdt: clt$parameter_descriptor_table;
     VAR symbolic_parameters: ^clt$symbolic_parameters;
     VAR status: ost$status);

    VAR
      lexical_work_area: ^clt$work_area,
      line: ^ost$string;

?? NEWTITLE := 'get_next_line', EJECT ??

    PROCEDURE get_next_line
      (VAR parse: clt$parse_state;
       VAR end_of_input: boolean;
       VAR status: ost$status);

      VAR
        ignore_index: ost$string_index,
        ignore_token: clt$token,
        lexical_units: ^clt$lexical_units;


      get_line^ (line^, ignore_index, ignore_token, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      end_of_input := line^.size = 0;

      RESET lexical_work_area;
      clp$identify_lexical_units (^line^.value (1, line^.size), lexical_work_area, lexical_units, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      clp$initialize_parse_state (^line^.value (1, line^.size), lexical_units, parse);

    PROCEND get_next_line;
?? OLDTITLE, EJECT ??

    VAR
      end_of_input: boolean,
      local_status: ost$status,
      original_work_area: ^^clt$work_area,
      parse: clt$parse_state,
      proc_or_pdt: string (4) {'PROC' or 'PDT'} ,
      work_area: ^clt$work_area;


    #KEYPOINT (osk$entry, 0, clk$scan_proc_declaration);

    status.normal := TRUE;
    local_status.normal := TRUE;

  /scan_declaration/
    BEGIN
      clp$get_work_area (#RING (^parse), original_work_area, local_status);
      IF NOT local_status.normal THEN
        EXIT /scan_declaration/;
      IFEND;
      work_area := original_work_area^;
      NEXT line IN work_area;
      NEXT lexical_work_area: [[REP osc$max_string_size + clc$lexical_units_size_pad OF clt$lexical_unit]] IN
            work_area;
      IF (line = NIL) OR (lexical_work_area = NIL) THEN
        osp$set_status_abnormal ('CL', cle$work_area_overflow, '', local_status);
        EXIT /scan_declaration/;
      IFEND;

      IF input_type = clc$pdt_input THEN
        proc_or_pdt := 'PDT ';
      ELSE
        proc_or_pdt := 'PROC';
      IFEND;
      proc_names := NIL;
      pdt.names := NIL;
      pdt.parameters := NIL;
      symbolic_parameters := NIL;

      REPEAT
        get_next_line (parse, end_of_input, status);
        IF NOT status.normal THEN
          EXIT /scan_declaration/;
        ELSEIF end_of_input THEN
          osp$set_status_abnormal ('CL', cle$expecting_proc, proc_or_pdt, local_status);
          osp$append_status_parameter (osc$status_parameter_delimiter, 'end of input', local_status);
          EXIT /scan_declaration/;
        IFEND;
        clp$scan_non_space_lexical_unit (parse);
      UNTIL parse.unit.kind <> clc$lex_end_of_line;

      clp$internal_generate_old_pdt (proc_or_pdt, ^get_next_line, work_area, parse, proc_name_area,
            parameter_name_area, parameter_area, symbolic_parameter_area, extra_info_area, proc_names,
            pdt, symbolic_parameters, local_status);
    END /scan_declaration/;

    IF NOT local_status.normal THEN
      IF local_status.condition = cle$work_area_overflow THEN
        local_status.text.size := 0;
        osp$append_status_parameter (osc$status_parameter_delimiter, 'clp$scan_proc_declaration',
              local_status);
      IFEND;
      status := local_status;
    IFEND;

    #KEYPOINT (osk$exit, 0, clk$scan_proc_declaration);

  PROCEND clp$scan_proc_declaration;
?? TITLE := 'clp$internal_generate_old_pdt', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$internal_generate_old_pdt
    (    proc_or_pdt: ost$name_reference;
         get_line: clt$internal_input_procedure;
     VAR work_area {input, output} : ^clt$work_area;
     VAR parse {input, output} : clt$parse_state;
     VAR proc_name_area: SEQ ( * );
     VAR parameter_name_area: SEQ ( * );
     VAR parameter_area: SEQ ( * );
     VAR symbolic_parameter_area: SEQ ( * );
     VAR extra_info_area: SEQ ( * );
     VAR proc_names: ^clt$proc_names;
     VAR pdt: clt$parameter_descriptor_table;
     VAR symbolic_parameters: ^clt$symbolic_parameters;
     VAR status: ost$status);

?? NEWTITLE := 'scan_proc_names', EJECT ??

    PROCEDURE scan_proc_names;

      VAR
        i: 1 .. clc$max_proc_names,
        name: ost$name,
        proc_name_area_ptr: ^SEQ ( * ),
        proc_name_count: 0 .. clc$max_proc_names;


      proc_name_count := 0;
      proc_name_area_ptr := ^proc_name_area;
      WHILE TRUE DO
        IF parse.unit.kind <> clc$lex_name THEN
          osp$set_status_abnormal ('CL', cle$expecting_proc_name, '', status);
          clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
          EXIT clp$internal_generate_old_pdt;
        IFEND;
        #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
        FOR i := 1 TO proc_name_count DO
          IF name = proc_names^ [i] THEN
            osp$set_status_abnormal ('CL', cle$duplicate_proc_name, name, status);
            EXIT clp$internal_generate_old_pdt;
          IFEND;
        FOREND;
        proc_name_count := proc_name_count + 1;
        RESET proc_name_area_ptr;
        NEXT proc_names: [1 .. proc_name_count] IN proc_name_area_ptr;
        IF proc_names = NIL THEN
          osp$set_status_abnormal ('CL', cle$table_overflow, 'Proc Names', status);
          EXIT clp$internal_generate_old_pdt;
        IFEND;
        proc_names^ [proc_name_count] := name;
        clp$scan_non_space_lexical_unit (parse);
        CASE parse.unit.kind OF
        = clc$lex_comma =
          clp$scan_non_space_lexical_unit (parse);
        = clc$lex_left_parenthesis, clc$lex_semicolon, clc$lex_end_of_line =
          RETURN;
        ELSE
          IF NOT parse.previous_unit_is_space THEN
            osp$set_status_abnormal ('CL', cle$unexpected_after_proc_name, '', status);
            clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
            EXIT clp$internal_generate_old_pdt;
          IFEND;
        CASEND;
      WHILEND;

    PROCEND scan_proc_names;
?? TITLE := 'scan_parameter_definitions', EJECT ??

    PROCEDURE scan_parameter_definitions;

      VAR
        extra_info_area_ptr: ^SEQ ( * );

?? NEWTITLE := 'scan_parameter_definition', EJECT ??

      PROCEDURE scan_parameter_definition;

        VAR
          parameter_name: ^ost$name,
          parameter_name_is_status: boolean;

?? NEWTITLE := 'scan_parameter_names', EJECT ??

        PROCEDURE scan_parameter_names
          (    parameter_count: 1 .. clc$max_parameters;
           VAR parameter_names {input, output} : ^array [1 .. * ] of clt$parameter_name_descriptor);

          VAR
            first_name_index: 1 .. clc$max_parameter_names + 1,
            i: 1 .. clc$max_parameter_names,
            name: ost$name,
            parameter_name_area_ptr: ^SEQ ( * ),
            parameter_name_count: 0 .. clc$max_parameter_names;


          #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
          parameter_name_area_ptr := ^parameter_name_area;
          IF parameter_names = NIL THEN
            parameter_name_count := 0;
          ELSE
            parameter_name_count := UPPERBOUND (parameter_names^);
          IFEND;
          first_name_index := parameter_name_count + 1;
          WHILE TRUE DO
            FOR i := 1 TO parameter_name_count DO
              IF name = parameter_names^ [i].name THEN
                osp$set_status_abnormal ('CL', cle$duplicate_parameter_name, name, status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
            FOREND;
            parameter_name_count := parameter_name_count + 1;
            RESET parameter_name_area_ptr;
            NEXT parameter_names: [1 .. parameter_name_count] IN parameter_name_area_ptr;
            IF parameter_names = NIL THEN
              osp$set_status_abnormal ('CL', cle$too_many_parameter_names, '', status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            parameter_names^ [parameter_name_count].name := name;
            parameter_names^ [parameter_name_count].number := parameter_count;
            IF parameter_name_count = first_name_index THEN
              parameter_name := ^parameter_names^ [parameter_name_count].name;
              parameter_name_is_status := name = 'STATUS';
            IFEND;
            clp$scan_non_space_lexical_unit (parse);
            CASE parse.unit.kind OF
            = clc$lex_right_parenthesis, clc$lex_semicolon, clc$lex_end_of_line, clc$lex_assign,
                  clc$lex_colon =
              RETURN;
            = clc$lex_comma =
              clp$scan_non_space_lexical_unit (parse);
            ELSE
              IF NOT parse.previous_unit_is_space THEN
                osp$set_status_abnormal ('CL', cle$unexpected_after_param_name, '', status);
                clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
            CASEND;
            IF parse.unit.kind <> clc$lex_name THEN
              osp$set_status_abnormal ('CL', cle$expecting_param_name, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
          WHILEND;

        PROCEND scan_parameter_names;
?? TITLE := 'scan_value_spec', EJECT ??

        PROCEDURE scan_value_spec
          (VAR parameter {input, output} : clt$parameter_descriptor;
           VAR symbolic_parameter {input, output} : clt$symbolic_parameter);

?? NEWTITLE := 'scan_value_list_spec', EJECT ??

          PROCEDURE scan_value_list_spec;

            VAR
              high_integer: integer,
              ignore_range_present: boolean,
              low_integer: integer,
              name: ost$name;


            clp$scan_non_space_lexical_unit (parse);
            IF NOT parse.previous_unit_is_space THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_list, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;

          /optional_list_stuff/
            BEGIN
              IF parse.unit.kind = clc$lex_name THEN
                #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
                IF (name = 'RANGE') OR (name = 'OF') THEN
                  parameter.max_value_sets := clc$max_value_sets;
                  EXIT /optional_list_stuff/;
                IFEND;
              IFEND;
              scan_integer_range (1, clc$max_value_sets, cle$list_bound_out_of_range,
                    cle$min_list_bound_gt_max, 0, low_integer, high_integer,
                    symbolic_parameter.min_value_sets, symbolic_parameter.max_value_sets,
                    ignore_range_present);
              parameter.min_value_sets := low_integer;
              parameter.max_value_sets := high_integer;

              CASE parse.unit.kind OF
              = clc$lex_name =
                #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
                IF (name = 'RANGE') OR (name = 'OF') THEN
                  EXIT /optional_list_stuff/;
                IFEND;
              = clc$lex_comma =
                clp$scan_non_space_lexical_unit (parse);
                IF parse.unit.kind = clc$lex_name THEN
                  #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
                  IF name = 'RANGE' THEN
                    EXIT /optional_list_stuff/;
                  IFEND;
                  IF name = 'OF' THEN
                    osp$set_status_abnormal ('CL', cle$unexpected_of_after_comma, '', status);
                    EXIT clp$internal_generate_old_pdt;
                  IFEND;
                IFEND;
              ELSE
                IF NOT parse.previous_unit_is_space THEN
                  osp$set_status_abnormal ('CL', cle$unexpected_after_vsc_spec, '', status);
                  clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
                  EXIT clp$internal_generate_old_pdt;
                IFEND;
              CASEND;

              scan_integer_range (1, clc$max_values_per_set, cle$list_bound_out_of_range,
                    cle$min_list_bound_gt_max, 0, low_integer, high_integer,
                    symbolic_parameter.min_values_per_set, symbolic_parameter.max_values_per_set,
                    ignore_range_present);
              parameter.min_values_per_set := low_integer;
              parameter.max_values_per_set := high_integer;

              CASE parse.unit.kind OF
              = clc$lex_name =
                #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
                IF (name = 'RANGE') OR (name = 'OF') THEN
                  EXIT /optional_list_stuff/;
                IFEND;
              = clc$lex_comma =
                clp$scan_non_space_lexical_unit (parse);
                IF parse.unit.kind = clc$lex_name THEN
                  #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
                  IF name = 'RANGE' THEN
                    EXIT /optional_list_stuff/;
                  ELSEIF name = 'OF' THEN
                    osp$set_status_abnormal ('CL', cle$unexpected_of_after_comma, '', status);
                    EXIT clp$internal_generate_old_pdt;
                  ELSE
                    osp$set_status_abnormal ('CL', cle$unexpected_after_vc_spec, name, status);
                    EXIT clp$internal_generate_old_pdt;
                  IFEND;
                IFEND;
              ELSE
                ;
              CASEND;
              osp$set_status_abnormal ('CL', cle$unexpected_after_vc_spec, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            END /optional_list_stuff/;

            IF name = 'RANGE' THEN
              parameter.value_range_allowed := clc$value_range_allowed;
              scan_value_range_spec;
            ELSE
              clp$scan_non_space_lexical_unit (parse);
              IF NOT parse.previous_unit_is_space THEN
                osp$set_status_abnormal ('CL', cle$unexpected_after_of, '', status);
                clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
            IFEND;

          PROCEND scan_value_list_spec;
?? TITLE := 'scan_value_range_spec', EJECT ??

          PROCEDURE scan_value_range_spec;

            VAR
              name: ost$name;


            clp$scan_non_space_lexical_unit (parse);
            IF NOT parse.previous_unit_is_space THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_range, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            IF parse.unit.kind <> clc$lex_name THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_range, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name <> 'OF' THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_range, name, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            clp$scan_non_space_lexical_unit (parse);
            IF NOT parse.previous_unit_is_space THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_of, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;

          PROCEND scan_value_range_spec;
?? TITLE := 'scan_var_spec', EJECT ??

          PROCEDURE scan_var_spec
            (    var_or_array: ost$name_reference;
             VAR value_kind_specifier: clt$value_kind_specifier);

            VAR
              name: ost$name;


            clp$scan_non_space_lexical_unit (parse);
            IF NOT parse.previous_unit_is_space THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_var, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            IF parse.unit.kind <> clc$lex_name THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_var, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name <> 'OF' THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_var, '', status);
              osp$append_status_parameter (osc$status_parameter_delimiter, name, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            clp$scan_non_space_lexical_unit (parse);
            IF NOT parse.previous_unit_is_space THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_of, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            IF parse.unit.kind <> clc$lex_name THEN
              osp$set_status_abnormal ('CL', cle$expecting_var_kind, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name = 'ANY' THEN
              value_kind_specifier.variable_kind := clc$any_value;
            ELSEIF name = 'BOOLEAN' THEN
              value_kind_specifier.variable_kind := clc$boolean_value;
            ELSEIF name = 'INTEGER' THEN
              value_kind_specifier.variable_kind := clc$integer_value;
            ELSEIF name = 'REAL' THEN
              value_kind_specifier.variable_kind := clc$real_value;
            ELSEIF name = 'STATUS' THEN
              value_kind_specifier.variable_kind := clc$status_value;
            ELSEIF name = 'STRING' THEN
              value_kind_specifier.variable_kind := clc$string_value;
            ELSE
              osp$set_status_abnormal ('CL', cle$expecting_var_kind, name, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            clp$scan_non_space_lexical_unit (parse);

            scan_or_key;

          PROCEND scan_var_spec;
?? TITLE := 'scan_value_kind', EJECT ??

          PROCEDURE scan_value_kind
            (VAR value_kind_specifier {input, output} : clt$value_kind_specifier);

            VAR
              name: ost$name,
              low_integer: integer,
              high_integer: integer,
              range_present: boolean;

?? NEWTITLE := 'scan_value_kind_qualifier', EJECT ??

            PROCEDURE scan_value_kind_qualifier
              (    unexpected_after: ost$status_condition;
                   nominal_low: integer;
                   nominal_high: integer;
                   out_of_range: ost$status_condition;
                   low_greater_than_high: ost$status_condition;
                   high_omitted: ost$status_condition);


              clp$scan_non_space_lexical_unit (parse);
              low_integer := nominal_low;
              high_integer := nominal_high;
              range_present := FALSE;

              CASE parse.unit.kind OF
              = clc$lex_equal, clc$lex_semicolon, clc$lex_end_of_line, clc$lex_right_parenthesis =
                RETURN;
              = clc$lex_name =
                #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
                IF name = 'OR' THEN
                  RETURN;
                IFEND;
              ELSE
                IF NOT parse.previous_unit_is_space THEN
                  osp$set_status_abnormal ('CL', unexpected_after, '', status);
                  clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
                  EXIT clp$internal_generate_old_pdt;
                IFEND;
              CASEND;

              scan_integer_range (nominal_low, nominal_high, out_of_range, low_greater_than_high,
                    high_omitted, low_integer, high_integer, symbolic_parameter.value_kind_qualifier_low,
                    symbolic_parameter.value_kind_qualifier_high, range_present);

            PROCEND scan_value_kind_qualifier;
?? OLDTITLE, EJECT ??

            IF parse.unit.kind <> clc$lex_name THEN
              osp$set_status_abnormal ('CL', cle$expecting_value_kind, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;

            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name = 'KEY' THEN
              value_kind_specifier.kind := clc$keyword_value;
              RETURN;

            ELSEIF name = 'ANY' THEN
              value_kind_specifier.kind := clc$any_value;
              clp$scan_non_space_lexical_unit (parse);

            ELSEIF name = 'BOOLEAN' THEN
              value_kind_specifier.kind := clc$boolean_value;
              clp$scan_non_space_lexical_unit (parse);

            ELSEIF name = 'INTEGER' THEN
              scan_value_kind_qualifier (cle$unexpected_after_integer, clc$min_integer, clc$max_integer,
                    cle$integer_out_of_range, cle$min_of_subrange_not_le_max, cle$max_of_subrange_omitted);
              value_kind_specifier.kind := clc$integer_value;
              value_kind_specifier.min_integer_value := low_integer;
              value_kind_specifier.max_integer_value := high_integer;

            ELSEIF name = 'FILE' THEN
              value_kind_specifier.kind := clc$file_value;
              clp$scan_non_space_lexical_unit (parse);

            ELSEIF name = 'NAME' THEN
              scan_value_kind_qualifier (cle$unexpected_after_integer, 1, osc$max_name_size,
                    cle$name_size_out_of_range, cle$min_name_size_gt_max, 0);
              value_kind_specifier.kind := clc$name_value;
              IF range_present THEN
                value_kind_specifier.min_name_size := low_integer;
              ELSE
                value_kind_specifier.min_name_size := 1;
              IFEND;
              value_kind_specifier.max_name_size := high_integer;

            ELSEIF name = 'REAL' THEN
              value_kind_specifier.kind := clc$real_value;
              clp$scan_non_space_lexical_unit (parse);

            ELSEIF name = 'STATUS' THEN
              value_kind_specifier.kind := clc$status_value;
              clp$scan_non_space_lexical_unit (parse);

            ELSEIF name = 'STRING' THEN
              scan_value_kind_qualifier (cle$unexpected_after_integer, 0, clc$max_string_size,
                    cle$string_size_out_of_range, cle$min_string_size_gt_max, 0);
              value_kind_specifier.kind := clc$string_value;
              IF low_integer >= osc$max_string_size THEN
                value_kind_specifier.min_string_size := osc$max_string_size;
              ELSE
                value_kind_specifier.min_string_size := low_integer;
              IFEND;
              IF high_integer >= osc$max_string_size THEN
                value_kind_specifier.max_string_size := osc$max_string_size;
              ELSE
                value_kind_specifier.max_string_size := high_integer;
              IFEND;

            ELSE
              value_kind_specifier.kind := clc$application_value;
              value_kind_specifier.value_name := name;
              value_kind_specifier.scanner.kind := clc$unspecified_av_scanner;
              clp$scan_non_space_lexical_unit (parse);
              CASE parse.unit.kind OF
              = clc$lex_end_of_line, clc$lex_equal, clc$lex_semicolon, clc$lex_right_parenthesis =
                RETURN;
              = clc$lex_name =
                #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
                IF name <> 'OR' THEN
                  value_kind_specifier.scanner.kind := clc$unlinked_av_scanner;
                  value_kind_specifier.scanner.name := name;
                  clp$scan_non_space_lexical_unit (parse);
                IFEND;
              ELSE
                osp$set_status_abnormal ('CL', cle$expecting_avs_name, '', status);
                clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
                EXIT clp$internal_generate_old_pdt;
              CASEND;
            IFEND;

            scan_or_key;

          PROCEND scan_value_kind;
?? TITLE := 'scan_integer_range', EJECT ??

          PROCEDURE scan_integer_range
            (    nominal_low: integer;
                 nominal_high: integer;
                 out_of_range: ost$status_condition;
                 low_greater_than_high: ost$status_condition;
                 high_omitted: ost$status_condition;
             VAR actual_low: integer;
             VAR actual_high: integer;
             VAR low_string: ^clt$expression_text;
             VAR high_string: ^clt$expression_text;
             VAR range_present: boolean);

?? NEWTITLE := 'save_subrange_expression', EJECT ??

            PROCEDURE [INLINE] save_subrange_expression
              (VAR text: ^clt$expression_text);

              VAR
                size: clt$expression_text_size,
                start_index: clt$expression_text_index;


              start_index := parse.unit_index;
              clp$scan_unnested_rel_lex_unit (parse);
              size := parse.previous_non_space_unit_index + parse.previous_non_space_unit.size - start_index;

              NEXT text: [size] IN extra_info_area_ptr;
              IF text = NIL THEN
                osp$set_status_abnormal ('CL', cle$table_overflow, 'Symbolic PDT Value', status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              text^ := parse.text^ (start_index, size);

              IF parse.unit_is_space THEN
                clp$scan_non_space_lexical_unit (parse);
              IFEND;

            PROCEND save_subrange_expression;
?? OLDTITLE, EJECT ??

            VAR
              result_integer: clt$integer;


            actual_low := nominal_low;
            actual_high := nominal_high;
            range_present := FALSE;

            IF proc_or_pdt = 'PDT' THEN
              save_subrange_expression (low_string);
            ELSE
              clp$evaluate_integer_expression (nominal_low, nominal_high, work_area, parse, result_integer,
                    status);
              IF NOT status.normal THEN
                IF status.condition = cle$integer_out_of_range THEN
                  status.condition := out_of_range;
                IFEND;
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              actual_low := result_integer.value;
            IFEND;

            IF parse.unit.kind <> clc$lex_ellipsis THEN
              IF high_omitted <> 0 THEN
                osp$set_status_abnormal ('CL', high_omitted, '', status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              actual_high := actual_low;
              high_string := low_string;
              RETURN;
            IFEND;

            range_present := TRUE;
            clp$scan_non_space_lexical_unit (parse);

            IF proc_or_pdt = 'PDT' THEN
              save_subrange_expression (high_string);
            ELSE
              clp$evaluate_integer_expression (nominal_low, nominal_high, work_area, parse, result_integer,
                    status);
              IF NOT status.normal THEN
                IF status.condition = cle$integer_out_of_range THEN
                  status.condition := out_of_range;
                IFEND;
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              actual_high := result_integer.value;
            IFEND;

            IF actual_low > actual_high THEN
              osp$set_status_abnormal ('CL', low_greater_than_high, '', status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;

          PROCEND scan_integer_range;
?? TITLE := 'scan_or_key', EJECT ??

          PROCEDURE scan_or_key;

            VAR
              name: ost$name;


            CASE parse.unit.kind OF
            = clc$lex_end_of_line, clc$lex_equal, clc$lex_semicolon, clc$lex_right_parenthesis =
              RETURN;
            ELSE
              ;
            CASEND;
            IF parse.unit.kind <> clc$lex_name THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_value_kind, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name <> 'OR' THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_value_kind, name, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            clp$scan_non_space_lexical_unit (parse);
            IF NOT parse.previous_unit_is_space THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_of, '', status); {||?? OF ?}
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            IF parse.unit.kind <> clc$lex_name THEN
              osp$set_status_abnormal ('CL', cle$expecting_key_spec, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name <> 'KEY' THEN
              osp$set_status_abnormal ('CL', cle$expecting_key_spec, name, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;

          PROCEND scan_or_key;
?? TITLE := 'scan_keyword_values', EJECT ??

          PROCEDURE scan_keyword_values
            (VAR keyword_values: ^array [1 .. * ] of ost$name);

            VAR
              i: 1 .. clc$max_keywords,
              count: 0 .. clc$max_keywords,
              name: ost$name;


            clp$scan_non_space_lexical_unit (parse);
            IF NOT parse.previous_unit_is_space THEN
              osp$set_status_abnormal ('CL', cle$unexpected_after_key, '', status);
              clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;

            NEXT keyword_values: [1 .. (#SIZE (extra_info_area_ptr^) -
                  i#current_sequence_position (extra_info_area_ptr)) DIV osc$max_name_size] IN
                  extra_info_area_ptr;
            IF keyword_values = NIL THEN
              osp$set_status_abnormal ('CL', cle$table_overflow, 'Keyword Values', status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            count := 0;

          /scan_keys/
            WHILE TRUE DO
              IF parse.unit.kind <> clc$lex_name THEN
                osp$set_status_abnormal ('CL', cle$expecting_key_in_spec, '', status);
                clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
              FOR i := 1 TO count DO
                IF name = keyword_values^ [i] THEN
                  osp$set_status_abnormal ('CL', cle$duplicate_keyword_value, name, status);
                  EXIT clp$internal_generate_old_pdt;
                IFEND;
              FOREND;
              count := count + 1;
              IF count > UPPERBOUND (keyword_values^) THEN
                osp$set_status_abnormal ('CL', cle$table_overflow, 'Keyword Values', status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              keyword_values^ [count] := name;
              clp$scan_non_space_lexical_unit (parse);
              CASE parse.unit.kind OF
              = clc$lex_comma =
                clp$scan_non_space_lexical_unit (parse);
              = clc$lex_end_of_line, clc$lex_equal, clc$lex_semicolon, clc$lex_right_parenthesis =
                EXIT /scan_keys/;
              ELSE
                ;
              CASEND;
            WHILEND /scan_keys/;

            RESET extra_info_area_ptr TO keyword_values;
            NEXT keyword_values: [1 .. count] IN extra_info_area_ptr;

          PROCEND scan_keyword_values;
?? OLDTITLE, EJECT ??

          VAR
            list_or_range_specified: boolean,
            name: ost$name;


          list_or_range_specified := FALSE;
          IF parse.unit.kind = clc$lex_name THEN
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name = 'LIST' THEN
              scan_value_list_spec;
              list_or_range_specified := TRUE;
            ELSEIF name = 'RANGE' THEN
              parameter.value_range_allowed := clc$value_range_allowed;
              scan_value_range_spec;
              list_or_range_specified := TRUE;
            IFEND;
          IFEND;

          IF parse.unit.kind = clc$lex_name THEN
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF (name = 'VAR') OR (name = 'ARRAY') THEN
              IF list_or_range_specified THEN
                osp$set_status_abnormal ('CL', cle$unsupported_parameter_spec, parameter_name^, status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              parameter.value_kind_specifier.kind := clc$variable_reference;
              IF name = 'VAR' THEN
                parameter.value_kind_specifier.array_allowed := clc$array_not_allowed;
              ELSE
                parameter.value_kind_specifier.array_allowed := clc$array_allowed;
              IFEND;
              scan_var_spec (name, parameter.value_kind_specifier);
            ELSE
              scan_value_kind (parameter.value_kind_specifier);
            IFEND;
          ELSE
            scan_value_kind (parameter.value_kind_specifier);
          IFEND;

          IF parse.unit.kind = clc$lex_name THEN
            #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
            IF name = 'KEY' THEN
              IF parameter.value_kind_specifier.kind = clc$variable_reference THEN
                osp$set_status_abnormal ('CL', cle$unsupported_parameter_spec, parameter_name^, status);
                EXIT clp$internal_generate_old_pdt;
              IFEND;
              scan_keyword_values (parameter.value_kind_specifier.keyword_values);
            IFEND;
          IFEND;

        PROCEND scan_value_spec;
?? TITLE := 'scan_default_spec', EJECT ??

        PROCEDURE scan_default_spec
          (VAR required_or_optional: clt$required_or_optional);

          VAR
            default_index: clt$expression_text_index,
            name: ost$name;


        /scan_default/
          BEGIN
            clp$scan_non_space_lexical_unit (parse);
            IF parse.unit.kind = clc$lex_name THEN
              #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
              IF name = '$REQUIRED' THEN
                required_or_optional.selector := clc$required;
                clp$scan_non_space_lexical_unit (parse);
                EXIT /scan_default/;
              ELSEIF name = '$OPTIONAL' THEN
                required_or_optional.selector := clc$optional;
                clp$scan_non_space_lexical_unit (parse);
                EXIT /scan_default/;
              IFEND;
            IFEND;
            default_index := parse.unit_index;
            clp$scan_unnested_sep_lex_unit (clc$ignore_ellipsis, parse);
            required_or_optional.selector := clc$optional_with_default;
            NEXT required_or_optional.default: [parse.unit_index - default_index] IN extra_info_area_ptr;
            IF required_or_optional.default = NIL THEN
              osp$set_status_abnormal ('CL', cle$table_overflow, 'Default Value', status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            required_or_optional.default^ := parse.text^ (default_index, parse.unit_index - default_index);
          END /scan_default/;
          IF parse.unit_is_space THEN
            clp$scan_non_space_lexical_unit (parse);
          IFEND;

        PROCEND scan_default_spec;
?? OLDTITLE, EJECT ??

        VAR
          parameter_area_ptr: ^SEQ ( * ),
          parameter_count: 0 .. clc$max_parameters,
          symbolic_parameter_area_ptr: ^SEQ ( * );


        CASE parse.unit.kind OF
        = clc$lex_right_parenthesis, clc$lex_semicolon, clc$lex_end_of_line =
          RETURN;
        = clc$lex_name =
          parameter_area_ptr := ^parameter_area;
          symbolic_parameter_area_ptr := ^symbolic_parameter_area;
          IF pdt.parameters = NIL THEN
            parameter_count := 0;
          ELSE
            parameter_count := UPPERBOUND (pdt.parameters^);
          IFEND;
        ELSE
          osp$set_status_abnormal ('CL', cle$expecting_param_def, '', status);
          clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
          EXIT clp$internal_generate_old_pdt;
        CASEND;

        parameter_count := parameter_count + 1;
        RESET parameter_area_ptr;
        NEXT pdt.parameters: [1 .. parameter_count] IN parameter_area_ptr;
        RESET symbolic_parameter_area_ptr;
        NEXT symbolic_parameters: [1 .. parameter_count] IN symbolic_parameter_area_ptr;
        IF (pdt.parameters = NIL) OR (symbolic_parameters = NIL) THEN
          osp$set_status_abnormal ('CL', cle$too_many_parameter_defs, '', status);
          EXIT clp$internal_generate_old_pdt;
        IFEND;
        symbolic_parameters^ [parameter_count].min_value_sets := NIL;
        symbolic_parameters^ [parameter_count].max_value_sets := NIL;
        symbolic_parameters^ [parameter_count].min_values_per_set := NIL;
        symbolic_parameters^ [parameter_count].max_values_per_set := NIL;
        symbolic_parameters^ [parameter_count].value_kind_qualifier_low := NIL;
        symbolic_parameters^ [parameter_count].value_kind_qualifier_high := NIL;

        scan_parameter_names (parameter_count, pdt.names);

        pdt.parameters^ [parameter_count].required_or_optional.selector := clc$optional;
        pdt.parameters^ [parameter_count].min_value_sets := 1;
        pdt.parameters^ [parameter_count].max_value_sets := 1;
        pdt.parameters^ [parameter_count].min_values_per_set := 1;
        pdt.parameters^ [parameter_count].max_values_per_set := 1;
        pdt.parameters^ [parameter_count].value_range_allowed := clc$value_range_not_allowed;
        pdt.parameters^ [parameter_count].value_kind_specifier.keyword_values := NIL;
        IF parameter_name_is_status THEN
          pdt.parameters^ [parameter_count].value_kind_specifier.kind := clc$variable_reference;
          pdt.parameters^ [parameter_count].value_kind_specifier.array_allowed := clc$array_not_allowed;
          pdt.parameters^ [parameter_count].value_kind_specifier.variable_kind := clc$status_value;
        ELSE
          pdt.parameters^ [parameter_count].value_kind_specifier.kind := clc$file_value;
        IFEND;

        IF parse.unit.kind = clc$lex_colon THEN
          clp$scan_non_space_lexical_unit (parse);
          scan_value_spec (pdt.parameters^ [parameter_count], symbolic_parameters^ [parameter_count]);
        IFEND;

        IF parse.unit.kind = clc$lex_equal THEN
          scan_default_spec (pdt.parameters^ [parameter_count].required_or_optional);
        IFEND;

      PROCEND scan_parameter_definition;
?? OLDTITLE, EJECT ??

      VAR
        end_of_input: boolean;


      extra_info_area_ptr := ^extra_info_area;
      RESET extra_info_area_ptr;
      clp$scan_non_space_lexical_unit (parse);
      WHILE TRUE DO
        scan_parameter_definition;
        CASE parse.unit.kind OF
        = clc$lex_right_parenthesis =
          clp$scan_non_space_lexical_unit (parse);
          RETURN;
        = clc$lex_semicolon =
          clp$scan_non_space_lexical_unit (parse);
        = clc$lex_end_of_line =
          REPEAT
            get_line^ (parse, end_of_input, status);
            IF NOT status.normal THEN
              EXIT clp$internal_generate_old_pdt;
            ELSEIF end_of_input THEN
              osp$set_status_abnormal ('CL', cle$expecting_param_def, 'END OF INPUT', status);
              EXIT clp$internal_generate_old_pdt;
            IFEND;
            clp$scan_non_space_lexical_unit (parse);
          UNTIL parse.unit.kind <> clc$lex_end_of_line;
        ELSE
          osp$set_status_abnormal ('CL', cle$expecting_param_def_sep, '', status);
          clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
          EXIT clp$internal_generate_old_pdt;
        CASEND;
      WHILEND;

    PROCEND scan_parameter_definitions;
?? OLDTITLE, EJECT ??

    VAR
      name: ost$name;


    status.normal := TRUE;

    proc_names := NIL;
    pdt.names := NIL;
    pdt.parameters := NIL;
    symbolic_parameters := NIL;

    IF parse.unit_is_space THEN
      clp$scan_non_space_lexical_unit (parse);
    IFEND;
    IF parse.unit.kind <> clc$lex_name THEN
      osp$set_status_abnormal ('CL', cle$expecting_proc, proc_or_pdt, status);
      clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
      RETURN;
    IFEND;
    #TRANSLATE (osv$lower_to_upper, parse.text^ (parse.unit_index, parse.unit.size), name);
    IF name <> proc_or_pdt THEN
      osp$set_status_abnormal ('CL', cle$expecting_proc, proc_or_pdt, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, name, status);
      RETURN;
    IFEND;

    clp$scan_non_space_lexical_unit (parse);
    IF NOT parse.previous_unit_is_space THEN
      osp$set_status_abnormal ('CL', cle$unexpected_after_proc, proc_or_pdt, status);
      clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
      RETURN;
    IFEND;

    scan_proc_names;
    IF (proc_or_pdt = 'PDT') AND (UPPERBOUND (proc_names^) > 1) THEN
      osp$set_status_abnormal ('CL', cle$too_many_names_for_pdt, '', status);
      RETURN;
    IFEND;

    IF parse.unit.kind = clc$lex_left_parenthesis THEN
      scan_parameter_definitions;
    IFEND;

    IF (parse.unit.kind <> clc$lex_semicolon) AND (parse.unit.kind <> clc$lex_end_of_line) THEN
      osp$set_status_abnormal ('CL', cle$expecting_command_separator, '', status);
      clp$append_status_parse_state (osc$status_parameter_delimiter, parse, status);
    IFEND;

  PROCEND clp$internal_generate_old_pdt;

MODEND clm$scan_proc_pdt_declaration;
