?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL : Data type processing routines' ??
MODULE clm$process_data_types;

{
{ PURPOSE:
{   This module contains the procedures that perform various processes with
{   data type specification and descriptions.
{

?? NEWTITLE := 'Global Declarations', EJECT ??
*IF NOT $true(osv$unix)
?? PUSH (LISTEXT := ON) ??
*copyc clt$variable_reference
*copyc cle$bad_data_value
*copyc cle$bad_type_description
*copyc cle$bad_type_specification
*copyc cle$ecc_parsing
*copyc clt$comparison_results
*copyc cle$work_area_overflow
*copyc clt$data_value
*copyc clt$type_changes
*copyc clt$type_conformance
*copyc clt$type_description
*copyc clt$type_information
*copyc clt$type_specification
*copyc clt$variable_kinds
*copyc clt$work_area
*copyc oss$job_paged_literal
*copyc ost$status
?? POP ??
*copyc clp$check_keyword
*copyc clp$search_keyword_specs
*copyc clp$longreal_compare
*copyc clp$longreal_compare_eq
*copyc clp$longreal_compare_gt
*copyc clp$longreal_compare_le
*copyc clp$longreal_compare_lt
*copyc clp$trimmed_string_size
*copyc clv$negative_infinity
*copyc clv$positive_infinity
*copyc clv$type_kind_names
*copyc clv$value_type_kinds
*copyc i#current_sequence_position
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*ELSE
*copyc i#current_sequence_position
*copyc clp$trimmed_string_size
*copyc clt$comparison_results
*copyc clp$check_keyword
*copyc cle$bad_type_description
*copyc clv$value_type_kinds
*copyc cle$bad_data_value
*copyc clt$type_conformance
*copyc clv$type_kind_names
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc clp$type_kinds_v2
*copyc clt$type_specification
*copyc clt$work_area
*copyc clt$type_description
*copyc cle$work_area_overflow
*copyc cle$bad_type_specification
*copyc ost$status
*copyc clt$data_value
*copyc cle$ecc_parsing
*copyc clv$negative_infinity
*copyc clv$positive_infinity
*copyc clc$declaration_version
*IFEND
?? TITLE := 'clp$append_status_type', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$append_status_type
    (    delimiter: char;
         type_specification: ^clt$type_specification;
     VAR status {input, output} : ost$status);

    VAR
      header: ^clt$type_specification_header,
      name: ^clt$type_name_reference,
      specification: ^clt$type_specification;


    specification := type_specification;
    RESET specification;
    NEXT header IN specification;
    IF header^.name_size = 0 THEN
      osp$append_status_parameter (delimiter, clv$type_kind_names [header^.kind], status);
    ELSE
      NEXT name: [header^.name_size] IN specification;
      osp$append_status_parameter (delimiter, name^, status);
    IFEND;

  PROCEND clp$append_status_type;
?? TITLE := 'clp$append_status_type_desc', EJECT ??

  PROCEDURE [XDCL] clp$append_status_type_desc
    (    delimiter: char;
         type_description: ^clt$type_description;
     VAR status {input, output} : ost$status);


    IF type_description^.name <> NIL THEN
      osp$append_status_parameter (delimiter, type_description^.name^, status);
    ELSE
      osp$append_status_parameter (delimiter, clv$type_kind_names [type_description^.kind], status);
    IFEND;

  PROCEND clp$append_status_type_desc;
?? TITLE := 'clp$append_status_value_type', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$append_status_value_type
    (    delimiter: char;
         value: ^clt$data_value;
     VAR status {input, output} : ost$status);


    IF (value = NIL) OR (value^.kind = clc$unspecified) THEN
      osp$append_status_parameter (delimiter, 'UNSPECIFIED value', status);
    ELSEIF value^.kind = clc$deferred THEN
      clp$append_status_type (delimiter, value^.deferred_type, status);
    ELSE
      osp$append_status_parameter (delimiter, clv$type_kind_names [clv$value_type_kinds [value^.kind]],
            status);
    IFEND;

  PROCEND clp$append_status_value_type;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$change_type_specification', EJECT ??
*copyc clh$change_type_specification

  PROCEDURE [XDCL, #GATE] clp$change_type_specification
    (    type_specification_ptr: ^clt$type_specification;
         type_changes: clt$type_changes;
     VAR status: ost$status);

    VAR
      application_type_qualifier: ^clt$application_type_qualifier,
      array_type_qualifier: ^clt$array_type_qualifier,
      date_time_type_qualifier: ^clt$date_time_type_qualifier,
      element_type_specification: ^clt$type_specification,
      field_specification: ^clt$field_specification,
      field_type_specification: ^clt$type_specification,
      header: ^clt$type_specification_header,
      i: integer,
      integer_type_qualifier: ^clt$integer_type_qualifier,
      k: integer,
      keyword_found: boolean,
      keyword_index: clt$keyword_index,
      keyword_ordinal: clt$named_entry_ordinal,
      keyword_specifications: ^clt$keyword_specifications,
      keyword_type_qualifier: ^clt$keyword_type_qualifier,
      list_type_qualifier: ^clt$list_type_qualifier_v2,
      member_type_specification_size: ^clt$type_specification_size,
      member_type_specification: ^clt$type_specification,
      name_type_qualifier: ^clt$name_type_qualifier,
      range_type_qualifier: ^clt$range_type_qualifier,
      real_type_qualifier: ^clt$real_type_qualifier,
      record_type_qualifier: ^clt$record_type_qualifier,
      string_type_qualifier: ^clt$string_type_qualifier,
      type_name: ^clt$type_name_reference,
      type_specification: ^clt$type_specification,
*IF NOT $true(osv$unix)
      union_type_qualifier: ^clt$union_type_qualifier;
*ELSE
      union_type_qualifier: ^clt$union_type_qualifier_v2;
*IFEND


    status.normal := TRUE;
    type_specification := type_specification_ptr;

  /type_specification_ok/
    BEGIN
      IF type_specification = NIL THEN
        EXIT /type_specification_ok/;
      IFEND;
      RESET type_specification;

      NEXT header IN type_specification;
*IF NOT $true(osv$unix)
      IF (header = NIL) OR (header^.version <> clc$declaration_version) OR
*ELSE
      IF (header = NIL) OR (header^.version < 1) OR (header^.version > clc$declaration_version) OR
*IFEND
            (header^.kind < LOWERVALUE (clt$type_kind)) OR (header^.kind > UPPERVALUE (clt$type_kind)) THEN
        EXIT /type_specification_ok/;
      IFEND;
      NEXT type_name: [header^.name_size] IN type_specification;
      IF type_name = NIL THEN
        EXIT /type_specification_ok/;
      IFEND;
      CASE header^.kind OF

      = clc$application_type =
        NEXT application_type_qualifier IN type_specification;
        IF application_type_qualifier = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;

      = clc$array_type =
        NEXT array_type_qualifier IN type_specification;
        IF array_type_qualifier = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;
        IF array_type_qualifier^.array_bounds_defined AND
              ((clc$min_array_bound > array_type_qualifier^.bounds.lower) OR
              (array_type_qualifier^.bounds.lower > array_type_qualifier^.bounds.upper) OR
              (array_type_qualifier^.bounds.upper > clc$max_array_bound)) THEN
          EXIT /type_specification_ok/;
        IFEND;
        IF array_type_qualifier^.element_type_specification_size > 0 THEN
          NEXT element_type_specification: [[REP array_type_qualifier^.element_type_specification_size OF
                cell]] IN type_specification;
          IF element_type_specification = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          clp$change_type_specification (element_type_specification, type_changes, status);
        IFEND;

      = clc$boolean_type =
        ;

      = clc$cobol_name_type =
        ;

      = clc$command_reference_type =
        ;

      = clc$data_name_type =
        ;

      = clc$date_time_type =
        NEXT date_time_type_qualifier IN type_specification;
        IF date_time_type_qualifier = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;

      = clc$entry_point_reference_type =
        ;

*IF NOT $true(osv$unix)
      = clc$file_type =
*ELSE
      = clc$nos_ve_file_type =
*IFEND
        ;

      = clc$integer_type =
        NEXT integer_type_qualifier IN type_specification;
        IF integer_type_qualifier = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;

      /make_integer_subrange_change/
        FOR k := 1 TO UPPERBOUND (type_changes) DO
          IF type_changes [k].kind = clc$tc_integer_subrange THEN
            integer_type_qualifier^.min_integer_value := type_changes [k].min_integer_value;
            integer_type_qualifier^.max_integer_value := type_changes [k].max_integer_value;
            EXIT /make_integer_subrange_change/;
          IFEND;
        FOREND /make_integer_subrange_change/;

      = clc$keyword_type =
        NEXT keyword_type_qualifier IN type_specification;
        IF (keyword_type_qualifier = NIL) OR (keyword_type_qualifier^.number_of_keywords < 1) OR
              (keyword_type_qualifier^.number_of_keywords > clc$max_keywords) THEN
          EXIT /type_specification_ok/;
        IFEND;
        NEXT keyword_specifications: [1 .. keyword_type_qualifier^.number_of_keywords] IN
              type_specification;
        IF keyword_specifications = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;

      /make_keyword_avail_change/
        FOR k := 1 TO UPPERBOUND (type_changes) DO
          IF type_changes [k].kind = clc$tc_keyword_availability THEN
            clp$search_keyword_specs (type_changes [k].keyword, keyword_specifications, keyword_index,
                  keyword_found);
            IF keyword_found THEN
              keyword_ordinal := keyword_specifications^ [keyword_index].ordinal;
              FOR i := 1 TO keyword_type_qualifier^.number_of_keywords DO
                IF keyword_specifications^ [i].ordinal = keyword_ordinal THEN
                  keyword_specifications^ [i].availability := type_changes [k].availability;
                IFEND;
              FOREND;
            IFEND;
          IFEND;
        FOREND /make_keyword_avail_change/;

      = clc$list_type =
        NEXT list_type_qualifier IN type_specification;
        IF (list_type_qualifier = NIL) OR (list_type_qualifier^.min_list_size >
              list_type_qualifier^.max_list_size) OR (list_type_qualifier^.max_list_size >
              clc$max_list_size) THEN
          EXIT /type_specification_ok/;
        IFEND;

      /make_list_size_change/
        FOR k := 1 TO UPPERBOUND (type_changes) DO
          IF type_changes [k].kind = clc$tc_list_size THEN
            list_type_qualifier^.min_list_size := type_changes [k].min_list_size;
            list_type_qualifier^.max_list_size := type_changes [k].max_list_size;
            EXIT /make_list_size_change/;
          IFEND;
        FOREND /make_list_size_change/;

        IF list_type_qualifier^.element_type_specification_size > 0 THEN
          NEXT element_type_specification: [[REP list_type_qualifier^.element_type_specification_size OF
                cell]] IN type_specification;
          IF element_type_specification = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          clp$change_type_specification (element_type_specification, type_changes, status);
        IFEND;

      = clc$lock_type =
        ;

      = clc$name_type =
        NEXT name_type_qualifier IN type_specification;
        IF (name_type_qualifier = NIL) OR (name_type_qualifier^.min_name_size < 1) OR
              (name_type_qualifier^.min_name_size > name_type_qualifier^.max_name_size) OR
              (name_type_qualifier^.max_name_size > osc$max_name_size) THEN
          EXIT /type_specification_ok/;
        IFEND;

      = clc$network_title_type =
        ;

      = clc$program_name_type =
        ;

      = clc$range_type =
        NEXT range_type_qualifier IN type_specification;
        IF range_type_qualifier = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;
        IF range_type_qualifier^.element_type_specification_size > 0 THEN
          NEXT element_type_specification: [[REP range_type_qualifier^.element_type_specification_size OF
                cell]] IN type_specification;
          IF element_type_specification = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          clp$change_type_specification (element_type_specification, type_changes, status);
        IFEND;

      = clc$real_type =
        NEXT real_type_qualifier IN type_specification;
        IF real_type_qualifier = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;

      /make_real_subrange_change/
        FOR k := 1 TO UPPERBOUND (type_changes) DO
          IF type_changes [k].kind = clc$tc_real_subrange THEN
            real_type_qualifier^.min_real_value.long_real := type_changes [k].min_real_value;
            real_type_qualifier^.max_real_value.long_real := type_changes [k].max_real_value;
            EXIT /make_real_subrange_change/;
          IFEND;
        FOREND /make_real_subrange_change/;

      = clc$record_type =
        NEXT record_type_qualifier IN type_specification;
        IF (record_type_qualifier = NIL) OR (record_type_qualifier^.number_of_fields < 1) OR
              (record_type_qualifier^.number_of_fields > clc$max_fields) THEN
          EXIT /type_specification_ok/;
        IFEND;
        FOR i := 1 TO record_type_qualifier^.number_of_fields DO
          NEXT field_specification IN type_specification;
          IF field_specification = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          NEXT field_type_specification: [[REP field_specification^.type_specification_size OF cell]] IN
                type_specification;
          IF field_type_specification = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          clp$change_type_specification (field_type_specification, type_changes, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        FOREND;

      = clc$scu_line_identifier_type =
        ;

      = clc$statistic_code_type =
        ;

      = clc$status_type =
        ;

      = clc$status_code_type =
        ;

      = clc$string_type =
        NEXT string_type_qualifier IN type_specification;
        IF (string_type_qualifier = NIL) OR (string_type_qualifier^.min_string_size >
              string_type_qualifier^.max_string_size) OR (string_type_qualifier^.max_string_size >
              clc$max_string_size) THEN
          EXIT /type_specification_ok/;
        IFEND;

      /make_string_size_change/
        FOR k := 1 TO UPPERBOUND (type_changes) DO
          IF type_changes [k].kind = clc$tc_string_size THEN
            string_type_qualifier^.min_string_size := type_changes [k].min_string_size;
            string_type_qualifier^.max_string_size := type_changes [k].max_string_size;
            EXIT /make_string_size_change/;
          IFEND;
        FOREND /make_string_size_change/;

      = clc$string_pattern_type =
        ;

      = clc$time_increment_type =
        ;

      = clc$time_zone_type =
        ;

      = clc$type_specification_type =
        ;

      = clc$union_type =
        NEXT union_type_qualifier IN type_specification;
        IF (union_type_qualifier = NIL) OR (union_type_qualifier^.number_of_members > clc$max_union_members)
              THEN
          EXIT /type_specification_ok/;
        IFEND;
        IF union_type_qualifier^.number_of_members > 0 THEN
          FOR i := 1 TO union_type_qualifier^.number_of_members DO
            NEXT member_type_specification_size IN type_specification;
            IF member_type_specification_size = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            NEXT member_type_specification: [[REP member_type_specification_size^ OF cell]] IN
                  type_specification;
            IF member_type_specification = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            clp$change_type_specification (member_type_specification, type_changes, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
          FOREND;
        IFEND;
*IF $true(osv$unix)

      = clc$unix_file_type =
        ;
*IFEND

      ELSE
        EXIT /type_specification_ok/;
      CASEND;
      RETURN;

    END /type_specification_ok/;
    osp$set_status_condition (cle$bad_type_specification, status);

  PROCEND clp$change_type_specification;
*IFEND
?? TITLE := 'clp$convert_type_desc_to_spec', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$convert_type_desc_to_spec
    (    type_description: ^clt$type_description;
     VAR work_area {input, output} : ^clt$work_area;
     VAR type_specification: ^clt$type_specification;
     VAR status: ost$status);

    VAR
      application_type_qualifier: ^clt$application_type_qualifier,
      array_type_qualifier: ^clt$array_type_qualifier,
      date_time_type_qualifier: ^clt$date_time_type_qualifier,
      element_type_specification: ^clt$type_specification,
      field_specification: ^clt$field_specification,
      field_type_specification: ^clt$type_specification,
      final_work_area_position: integer,
      header: ^clt$type_specification_header,
      i: integer,
      integer_type_qualifier: ^clt$integer_type_qualifier,
      keyword_specifications: ^clt$keyword_specifications,
      keyword_type_qualifier: ^clt$keyword_type_qualifier,
      list_type_qualifier: ^clt$list_type_qualifier_v2,
      member_type_specification_size: ^clt$type_specification_size,
      member_type_specification: ^clt$type_specification,
      name_type_qualifier: ^clt$name_type_qualifier,
      range_type_qualifier: ^clt$range_type_qualifier,
      real_type_qualifier: ^clt$real_type_qualifier,
      record_type_qualifier: ^clt$record_type_qualifier,
      string_type_qualifier: ^clt$string_type_qualifier,
      type_name: ^clt$type_name_reference,
*IF NOT $true(osv$unix)
      union_type_qualifier: ^clt$union_type_qualifier;
*ELSE
      union_type_qualifier: ^clt$union_type_qualifier_v2;
*IFEND


    status.normal := TRUE;
    IF type_description^.specification <> NIL THEN
      type_specification := type_description^.specification;
      RETURN;
    IFEND;

    type_specification := NIL;

  /work_area_ok/
    BEGIN
      NEXT header IN work_area;
      IF header = NIL THEN
        EXIT /work_area_ok/;
      IFEND;
      header^.version := clc$declaration_version;
      IF type_description^.name = NIL THEN
        header^.name_size := 0;
      ELSE
        header^.name_size := STRLENGTH (type_description^.name^);
        NEXT type_name: [header^.name_size] IN work_area;
        IF type_name = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        type_name^ := type_description^.name^;
      IFEND;
      header^.kind := type_description^.kind;
      CASE header^.kind OF

      = clc$application_type =
        NEXT application_type_qualifier IN work_area;
        IF application_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        application_type_qualifier^.balance_brackets := type_description^.balance_brackets;

      = clc$array_type =
        NEXT array_type_qualifier IN work_area;
        IF array_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        array_type_qualifier^.array_bounds_defined := type_description^.array_bounds_defined;
        IF array_type_qualifier^.array_bounds_defined THEN
          array_type_qualifier^.bounds.lower := type_description^.bounds.lower;
          array_type_qualifier^.bounds.upper := type_description^.bounds.upper;
        IFEND;
        IF type_description^.array_element_type_description = NIL THEN
          array_type_qualifier^.element_type_specification_size := 0;
        ELSE
          clp$convert_type_desc_to_spec (type_description^.array_element_type_description, work_area,
                element_type_specification, status);
          IF NOT status.normal THEN
            RESET work_area TO header;
            RETURN;
          IFEND;
          array_type_qualifier^.element_type_specification_size := #SIZE (element_type_specification^);
        IFEND;

      = clc$boolean_type =
        ;

      = clc$cobol_name_type =
        ;

      = clc$command_reference_type =
        ;

      = clc$data_name_type =
        ;

      = clc$date_time_type =
        NEXT date_time_type_qualifier IN work_area;
        IF date_time_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        date_time_type_qualifier^.date_and_or_time := type_description^.date_and_or_time;
        date_time_type_qualifier^.tenses := type_description^.tenses;

      = clc$entry_point_reference_type =
        ;

*IF NOT $true(osv$unix)
      = clc$file_type =
*ELSE
      = clc$nos_ve_file_type =
*IFEND
        ;

      = clc$integer_type =
        NEXT integer_type_qualifier IN work_area;
        IF integer_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        integer_type_qualifier^.min_integer_value := type_description^.min_integer_value;
        integer_type_qualifier^.max_integer_value := type_description^.max_integer_value;
        integer_type_qualifier^.default_radix := type_description^.default_radix;

      = clc$keyword_type =
        NEXT keyword_type_qualifier IN work_area;
        IF keyword_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        keyword_type_qualifier^.number_of_keywords := UPPERBOUND (type_description^.keyword_specifications^);
        NEXT keyword_specifications: [1 .. keyword_type_qualifier^.number_of_keywords] IN work_area;
        IF keyword_specifications = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        keyword_specifications^ := type_description^.keyword_specifications^;

      = clc$list_type =
        NEXT list_type_qualifier IN work_area;
        IF list_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        list_type_qualifier^.min_list_size := type_description^.min_list_size;
        list_type_qualifier^.max_list_size := type_description^.max_list_size;
        list_type_qualifier^.reserved := 0;
        list_type_qualifier^.defer_expansion := type_description^.defer_expansion;
        list_type_qualifier^.list_rest := type_description^.list_rest;
        IF type_description^.list_element_type_description = NIL THEN
          list_type_qualifier^.element_type_specification_size := 0;
        ELSE
          clp$convert_type_desc_to_spec (type_description^.list_element_type_description, work_area,
                element_type_specification, status);
          IF NOT status.normal THEN
            RESET work_area TO header;
            RETURN;
          IFEND;
          list_type_qualifier^.element_type_specification_size := #SIZE (element_type_specification^);
        IFEND;

      = clc$lock_type =
        ;

      = clc$name_type =
        NEXT name_type_qualifier IN work_area;
        IF name_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        name_type_qualifier^.min_name_size := type_description^.min_name_size;
        name_type_qualifier^.max_name_size := type_description^.max_name_size;

      = clc$network_title_type =
        ;

      = clc$program_name_type =
        ;

      = clc$range_type =
        NEXT range_type_qualifier IN work_area;
        IF range_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        IF type_description^.range_element_type_description = NIL THEN
          range_type_qualifier^.element_type_specification_size := 0;
        ELSE
          clp$convert_type_desc_to_spec (type_description^.range_element_type_description, work_area,
                element_type_specification, status);
          IF NOT status.normal THEN
            RESET work_area TO header;
            RETURN;
          IFEND;
          range_type_qualifier^.element_type_specification_size := #SIZE (element_type_specification^);
        IFEND;

      = clc$real_type =
        NEXT real_type_qualifier IN work_area;
        IF real_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        real_type_qualifier^.min_real_value.long_real := type_description^.min_real_value.long_real;
        real_type_qualifier^.max_real_value.long_real := type_description^.max_real_value.long_real;

      = clc$record_type =
        NEXT record_type_qualifier IN work_area;
        IF record_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        record_type_qualifier^.number_of_fields := type_description^.fields_pdt^.header^.number_of_parameters;
        FOR i := 1 TO record_type_qualifier^.number_of_fields DO
          NEXT field_specification IN work_area;
          IF field_specification = NIL THEN
            EXIT /work_area_ok/;
          IFEND;
          field_specification^.name := type_description^.fields_pdt^.names^ [i].name;
          field_specification^.requirement := type_description^.fields_pdt^.parameters^ [i].requirement;
          clp$convert_type_desc_to_spec (^type_description^.fields_pdt^.type_descriptions^ [i], work_area,
                field_type_specification, status);
          IF NOT status.normal THEN
            RESET work_area TO header;
            RETURN;
          IFEND;
          field_specification^.type_specification_size := #SIZE (field_type_specification^);
        FOREND;

      = clc$scu_line_identifier_type =
        ;

      = clc$statistic_code_type =
        ;

      = clc$status_type =
        ;

      = clc$status_code_type =
        ;

      = clc$string_type =
        NEXT string_type_qualifier IN work_area;
        IF string_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        string_type_qualifier^.min_string_size := type_description^.min_string_size;
        string_type_qualifier^.max_string_size := type_description^.max_string_size;
        string_type_qualifier^.literal := type_description^.literal;

      = clc$string_pattern_type =
        ;

      = clc$time_increment_type =
        ;

      = clc$time_zone_type =
        ;

      = clc$type_specification_type =
        ;

      = clc$union_type =
        NEXT union_type_qualifier IN work_area;
        IF union_type_qualifier = NIL THEN
          EXIT /work_area_ok/;
        IFEND;
        union_type_qualifier^.kinds := type_description^.kinds;
        union_type_qualifier^.only_standard_types_in_union :=
              type_description^.union_information^.only_standard_types_in_union;
        IF type_description^.member_descriptions = NIL THEN
          union_type_qualifier^.number_of_members := 0;
        ELSE
          union_type_qualifier^.number_of_members := UPPERBOUND (type_description^.member_descriptions^);
          FOR i := 1 TO union_type_qualifier^.number_of_members DO
            NEXT member_type_specification_size IN work_area;
            IF member_type_specification_size = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            clp$convert_type_desc_to_spec (^type_description^.member_descriptions^ [i], work_area,
                  member_type_specification, status);
            IF NOT status.normal THEN
              RESET work_area TO header;
              RETURN;
            IFEND;
            member_type_specification_size^ := #SIZE (member_type_specification^);
          FOREND;
        IFEND;
*IF $true(osv$unix)

      = clc$unix_file_type =
        ;
*IFEND

      ELSE
        osp$set_status_condition (cle$bad_type_description, status);
        RETURN;
      CASEND;

      final_work_area_position := i#current_sequence_position (work_area);
      RESET work_area TO header;
      NEXT type_specification: [[REP final_work_area_position - i#current_sequence_position (work_area) OF
            cell]] IN work_area;
      RETURN;

    END /work_area_ok/;
    IF header <> NIL THEN
      RESET work_area TO header;
    IFEND;
    osp$set_status_condition (cle$work_area_overflow, status);

  PROCEND clp$convert_type_desc_to_spec;
?? TITLE := 'clp$convert_type_spec_to_desc', EJECT ??

  PROCEDURE [XDCL, #GATE] clp$convert_type_spec_to_desc
    (    type_specification_ptr: ^clt$type_specification;
     VAR work_area {input, output} : ^clt$work_area;
     VAR type_description: clt$type_description;
     VAR status: ost$status);

    VAR
*IF $true(osv$unix)
      kludge_type_spec: ^ array [*] of cell,
      spot: integer,
*IFEND
      application_type_qualifier: ^clt$application_type_qualifier,
      array_type_qualifier: ^clt$array_type_qualifier,
      date_time_type_qualifier: ^clt$date_time_type_qualifier,
      element_type_specification: ^clt$type_specification,
      field_specification: ^clt$field_specification,
      field_type_specification: ^clt$type_specification,
      header: ^clt$type_specification_header,
      i: integer,
      integer_type_qualifier: ^clt$integer_type_qualifier,
      keyword_specifications: ^clt$keyword_specifications,
      keyword_type_qualifier: ^clt$keyword_type_qualifier,
      list_type_qualifier: ^clt$list_type_qualifier_v2,
      member_type_specification_size: ^clt$type_specification_size,
      member_type_specification: ^clt$type_specification,
      name_type_qualifier: ^clt$name_type_qualifier,
      range_type_qualifier: ^clt$range_type_qualifier,
      real_type_qualifier: ^clt$real_type_qualifier,
      record_type_qualifier: ^clt$record_type_qualifier,
      string_type_qualifier: ^clt$string_type_qualifier,
      type_specification: ^clt$type_specification,
*IF NOT $true(osv$unix)
      union_type_qualifier: ^clt$union_type_qualifier;
*ELSE
      union_type_qualifier_v1: ^clt$union_type_qualifier,
      union_type_qualifier: ^clt$union_type_qualifier_v2;
*IFEND


    status.normal := TRUE;
    type_specification := type_specification_ptr;

  /type_specification_ok/
    BEGIN

    /work_area_ok/
      BEGIN
        IF type_specification = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;
        RESET type_specification;

        NEXT header IN type_specification;
*IF NOT $true(osv$unix)
        IF (header = NIL) OR (header^.version <> clc$declaration_version) OR
*ELSE
        IF (header = NIL) OR
              (header^.version <> clc$declaration_version) OR
*IFEND
              (header^.kind < LOWERVALUE (clt$type_kind)) OR (header^.kind > UPPERVALUE (clt$type_kind)) THEN
          EXIT /type_specification_ok/;
        IFEND;
        type_description.specification := type_specification;
        IF header^.name_size = 0 THEN
          type_description.name := NIL;
        ELSE
          NEXT type_description.name: [header^.name_size] IN type_specification;
          IF type_description.name = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
        IFEND;
        type_description.derived_from_value_kind_spec := FALSE;
        type_description.advanced_keywords_present := FALSE;
*IF NOT $true(osv$unix)
        type_description.kinds := $clt$type_kinds [header^.kind];
*ELSE
        type_description.kinds := $clt$type_kinds_v2 [header^.kind];
*IFEND
        type_description.kind := header^.kind;
        CASE header^.kind OF

        = clc$application_type =
          NEXT application_type_qualifier IN type_specification;
          IF application_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_description.balance_brackets := application_type_qualifier^.balance_brackets;

        = clc$array_type =
          NEXT array_type_qualifier IN type_specification;
          IF array_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          IF array_type_qualifier^.array_bounds_defined THEN
            IF (clc$min_array_bound <= array_type_qualifier^.bounds.lower) AND
                  (array_type_qualifier^.bounds.lower <= array_type_qualifier^.bounds.upper) AND
                  (array_type_qualifier^.bounds.upper <= clc$max_array_bound) THEN
              type_description.array_bounds_defined := TRUE;
              type_description.bounds.lower := array_type_qualifier^.bounds.lower;
              type_description.bounds.upper := array_type_qualifier^.bounds.upper;
            ELSE
              EXIT /type_specification_ok/;
            IFEND;
          ELSE
            type_description.array_bounds_defined := FALSE;
          IFEND;
          IF array_type_qualifier^.element_type_specification_size = 0 THEN
            type_description.array_element_type_description := NIL;
          ELSE
*IF NOT $true(osv$unix)
            NEXT element_type_specification: [[REP array_type_qualifier^.element_type_specification_size OF
                  cell]] IN type_specification;
*ELSE
            NEXT kludge_type_spec: [1 .. array_type_qualifier^.element_type_specification_size] IN
                  type_specification;
            element_type_specification := #SEQ (kludge_type_spec^);
*IFEND
            IF element_type_specification = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            NEXT type_description.array_element_type_description IN work_area;
            IF type_description.array_element_type_description = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            clp$convert_type_spec_to_desc (element_type_specification, work_area,
                  type_description.array_element_type_description^, status);
            IF NOT status.normal THEN
              RESET work_area TO type_description.array_element_type_description;
              RETURN;
            IFEND;
            type_description.advanced_keywords_present := type_description.array_element_type_description^.
                  advanced_keywords_present;
          IFEND;

        = clc$boolean_type =
          ;

        = clc$cobol_name_type =
          ;

        = clc$command_reference_type =
          ;

        = clc$data_name_type =
          ;

        = clc$date_time_type =
          NEXT date_time_type_qualifier IN type_specification;
          IF date_time_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_description.date_and_or_time := date_time_type_qualifier^.date_and_or_time;
          type_description.tenses := date_time_type_qualifier^.tenses;

        = clc$entry_point_reference_type =
          ;

*IF NOT $true(osv$unix)
        = clc$file_type =
*ELSE
        = clc$nos_ve_file_type =
*IFEND
          ;

        = clc$integer_type =
          NEXT integer_type_qualifier IN type_specification;
          IF integer_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_description.min_integer_value := integer_type_qualifier^.min_integer_value;
          type_description.max_integer_value := integer_type_qualifier^.max_integer_value;
          type_description.default_radix := integer_type_qualifier^.default_radix;

        = clc$keyword_type =
          NEXT keyword_type_qualifier IN type_specification;
          IF (keyword_type_qualifier = NIL) OR (keyword_type_qualifier^.number_of_keywords < 1) OR
                (keyword_type_qualifier^.number_of_keywords > clc$max_keywords) THEN
            EXIT /type_specification_ok/;
          IFEND;
          NEXT keyword_specifications: [1 .. keyword_type_qualifier^.number_of_keywords] IN
                type_specification;
          IF keyword_specifications = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          NEXT type_description.keyword_specifications: [1 .. keyword_type_qualifier^.number_of_keywords] IN
                work_area;
          IF type_description.keyword_specifications = NIL THEN
            EXIT /work_area_ok/;
          IFEND;
          FOR i := 1 TO keyword_type_qualifier^.number_of_keywords DO
            type_description.keyword_specifications^ [i] := keyword_specifications^ [i];
            IF type_description.keyword_specifications^ [i].availability = clc$advanced_usage_entry THEN
              type_description.advanced_keywords_present := TRUE;
            IFEND;
          FOREND;

        = clc$list_type =
          NEXT list_type_qualifier IN type_specification;
          IF (list_type_qualifier = NIL) OR (list_type_qualifier^.min_list_size >
                list_type_qualifier^.max_list_size) OR (list_type_qualifier^.max_list_size >
                clc$max_list_size) THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_description.min_list_size := list_type_qualifier^.min_list_size;
          type_description.max_list_size := list_type_qualifier^.max_list_size;
          type_description.defer_expansion := list_type_qualifier^.defer_expansion;
          type_description.list_rest := list_type_qualifier^.list_rest;
          IF list_type_qualifier^.element_type_specification_size = 0 THEN
            type_description.list_element_type_description := NIL;
          ELSE
*IF NOT $true(osv$unix)
            NEXT element_type_specification: [[REP list_type_qualifier^.element_type_specification_size OF
                  cell]] IN type_specification;
*ELSE
            spot := i#current_sequence_position (type_specification);
            NEXT kludge_type_spec : [1 .. list_type_qualifier^.element_type_specification_size] IN
                  type_specification;
            element_type_specification := #SEQ (kludge_type_spec^);
*IFEND
            IF element_type_specification = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            NEXT type_description.list_element_type_description IN work_area;
            IF type_description.list_element_type_description = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            clp$convert_type_spec_to_desc (element_type_specification, work_area,
                  type_description.list_element_type_description^, status);
            IF NOT status.normal THEN
              RESET work_area TO type_description.list_element_type_description;
              RETURN;
            IFEND;
            type_description.advanced_keywords_present := type_description.list_element_type_description^.
                  advanced_keywords_present;
          IFEND;

        = clc$lock_type =
          ;

        = clc$name_type =
          NEXT name_type_qualifier IN type_specification;
          IF (name_type_qualifier <> NIL) AND (1 <= name_type_qualifier^.min_name_size) AND
                (name_type_qualifier^.min_name_size <= name_type_qualifier^.max_name_size) AND
                (name_type_qualifier^.max_name_size <= osc$max_name_size) THEN
            type_description.min_name_size := name_type_qualifier^.min_name_size;
            type_description.max_name_size := name_type_qualifier^.max_name_size;
          ELSE
            EXIT /type_specification_ok/;
          IFEND;

        = clc$network_title_type =
          ;

        = clc$program_name_type =
          ;

        = clc$range_type =
          NEXT range_type_qualifier IN type_specification;
          IF range_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          IF range_type_qualifier^.element_type_specification_size = 0 THEN
            type_description.range_element_type_description := NIL;
          ELSE
*IF NOT $true(osv$unix)
            NEXT element_type_specification: [[REP range_type_qualifier^.element_type_specification_size OF
                  cell]] IN type_specification;
*ELSE
            NEXT kludge_type_spec: [1 .. range_type_qualifier^.element_type_specification_size] IN
                  type_specification;
            element_type_specification := #SEQ (kludge_type_spec^);
*IFEND
            IF element_type_specification = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            NEXT type_description.range_element_type_description IN work_area;
            IF type_description.range_element_type_description = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            clp$convert_type_spec_to_desc (element_type_specification, work_area,
                  type_description.range_element_type_description^, status);
            IF NOT status.normal THEN
              RESET work_area TO type_description.range_element_type_description;
              RETURN;
            IFEND;
            type_description.advanced_keywords_present := type_description.range_element_type_description^.
                  advanced_keywords_present;
          IFEND;

        = clc$real_type =
          NEXT real_type_qualifier IN type_specification;
          IF real_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_description.min_real_value.long_real := real_type_qualifier^.min_real_value.long_real;
          type_description.max_real_value.long_real := real_type_qualifier^.max_real_value.long_real;

        = clc$record_type =
          NEXT record_type_qualifier IN type_specification;
          IF (record_type_qualifier = NIL) OR (record_type_qualifier^.number_of_fields < 1) OR
                (record_type_qualifier^.number_of_fields > clc$max_fields) THEN
            EXIT /type_specification_ok/;
          IFEND;
          NEXT type_description.fields_pdt IN work_area;
          IF type_description.fields_pdt = NIL THEN
            EXIT /work_area_ok/;
          IFEND;
          NEXT type_description.fields_pdt^.header IN work_area;
          IF type_description.fields_pdt^.header = NIL THEN
            RESET work_area TO type_description.fields_pdt;
            EXIT /work_area_ok/;
          IFEND;
          type_description.fields_pdt^.header^.version := clc$declaration_version;
          type_description.fields_pdt^.header^.generation_date_time.year := 86;
          type_description.fields_pdt^.header^.generation_date_time.month := 10;
          type_description.fields_pdt^.header^.generation_date_time.day := 27;
          type_description.fields_pdt^.header^.generation_date_time.hour := 10;
          type_description.fields_pdt^.header^.generation_date_time.minute := 0;
          type_description.fields_pdt^.header^.generation_date_time.second := 0;
          type_description.fields_pdt^.header^.generation_date_time.millisecond := 0;
          type_description.fields_pdt^.header^.command_or_function := clc$function;
          type_description.fields_pdt^.header^.number_of_parameter_names :=
                record_type_qualifier^.number_of_fields;
          type_description.fields_pdt^.header^.number_of_parameters :=
                record_type_qualifier^.number_of_fields;
          type_description.fields_pdt^.header^.number_of_required_parameters := 0;
          type_description.fields_pdt^.header^.number_of_advanced_parameters := 0;
          type_description.fields_pdt^.header^.number_of_hidden_parameters := 0;
          type_description.fields_pdt^.header^.number_of_var_parameters := 0;
          type_description.fields_pdt^.header^.status_parameter_number := 0;
          type_description.fields_pdt^.header^.help_module_name := osc$null_name;
          NEXT type_description.fields_pdt^.names: [1 .. record_type_qualifier^.number_of_fields] IN
                work_area;
          IF type_description.fields_pdt^.names = NIL THEN
            RESET work_area TO type_description.fields_pdt;
            EXIT /work_area_ok/;
          IFEND;
          NEXT type_description.fields_pdt^.parameters: [1 .. record_type_qualifier^.number_of_fields] IN
                work_area;
          IF type_description.fields_pdt^.parameters = NIL THEN
            RESET work_area TO type_description.fields_pdt;
            EXIT /work_area_ok/;
          IFEND;
          NEXT type_description.fields_pdt^.type_descriptions:
                [1 .. record_type_qualifier^.number_of_fields] IN work_area;
          IF type_description.fields_pdt^.type_descriptions = NIL THEN
            RESET work_area TO type_description.fields_pdt;
            EXIT /work_area_ok/;
          IFEND;
          type_description.fields_pdt^.default_names := NIL;
          type_description.fields_pdt^.default_values := NIL;
          FOR i := 1 TO record_type_qualifier^.number_of_fields DO
            NEXT field_specification IN type_specification;
            IF field_specification = NIL THEN
              RESET work_area TO type_description.fields_pdt;
              EXIT /type_specification_ok/;
            IFEND;
            NEXT field_type_specification: [[REP field_specification^.type_specification_size OF cell]] IN
                  type_specification;
            IF field_type_specification = NIL THEN
              RESET work_area TO type_description.fields_pdt;
              EXIT /type_specification_ok/;
            IFEND;
            type_description.fields_pdt^.names^ [i].name := field_specification^.name;
            type_description.fields_pdt^.names^ [i].class := clc$nominal_entry;
            type_description.fields_pdt^.names^ [i].position := i;
            type_description.fields_pdt^.parameters^ [i].name_index := i;
            type_description.fields_pdt^.parameters^ [i].availability := clc$normal_usage_entry;
            type_description.fields_pdt^.parameters^ [i].security := clc$non_secure_parameter;
            type_description.fields_pdt^.parameters^ [i].specification_methods :=
                  $clt$parameter_spec_methods [clc$specify_positionally];
            type_description.fields_pdt^.parameters^ [i].passing_method := clc$pass_by_value;
            type_description.fields_pdt^.parameters^ [i].evaluation_method := clc$immediate_evaluation;
            type_description.fields_pdt^.parameters^ [i].checking_level := clc$standard_parameter_checking;
            type_description.fields_pdt^.parameters^ [i].type_specification_size :=
                  field_specification^.type_specification_size;
            type_description.fields_pdt^.parameters^ [i].requirement := field_specification^.requirement;
            IF field_specification^.requirement = clc$required_field THEN
              type_description.fields_pdt^.header^.number_of_required_parameters :=
                    type_description.fields_pdt^.header^.number_of_required_parameters + 1;
            IFEND;
            type_description.fields_pdt^.parameters^ [i].default_name_size := 0;
            type_description.fields_pdt^.parameters^ [i].default_value_size := 0;
            clp$convert_type_spec_to_desc (field_type_specification, work_area,
                  type_description.fields_pdt^.type_descriptions^ [i], status);
            IF NOT status.normal THEN
              RESET work_area TO type_description.fields_pdt;
              RETURN;
            ELSEIF type_description.fields_pdt^.type_descriptions^ [i].advanced_keywords_present THEN
              type_description.advanced_keywords_present := TRUE;
            IFEND;
          FOREND;

        = clc$scu_line_identifier_type =
          ;

        = clc$statistic_code_type =
          ;

        = clc$status_type =
          ;

        = clc$status_code_type =
          ;

        = clc$string_type =
          NEXT string_type_qualifier IN type_specification;
          IF (string_type_qualifier <> NIL) AND (string_type_qualifier^.min_string_size <=
                string_type_qualifier^.max_string_size) AND (string_type_qualifier^.max_string_size <=
                clc$max_string_size) THEN
            type_description.min_string_size := string_type_qualifier^.min_string_size;
            type_description.max_string_size := string_type_qualifier^.max_string_size;
            type_description.literal := string_type_qualifier^.literal;
          ELSE
            EXIT /type_specification_ok/;
          IFEND;

        = clc$string_pattern_type =
          ;

        = clc$time_increment_type =
          ;

        = clc$time_zone_type =
          ;

        = clc$type_specification_type =
          ;

        = clc$union_type =
          NEXT union_type_qualifier IN type_specification;
          IF (union_type_qualifier = NIL) OR (union_type_qualifier^.number_of_members > clc$max_union_members)
                THEN
            EXIT /type_specification_ok/;
          IFEND;
*IF NOT $true(osv$unix)
          type_description.kinds := union_type_qualifier^.kinds;
*ELSE
          IF header^.version = 1 THEN
            union_type_qualifier_v1 := #LOC (union_type_qualifier^);
            clp$type_kinds_v2 (union_type_qualifier_v1^.kinds, type_description.kinds);
          ELSE
            type_description.kinds := union_type_qualifier^.kinds;
          IFEND;
*IFEND
          NEXT type_description.union_information IN work_area;
          IF type_description.union_information = NIL THEN
            EXIT /work_area_ok/;
          IFEND;
          type_description.union_information^.only_standard_types_in_union :=
                union_type_qualifier^.only_standard_types_in_union;
          type_description.union_information^.min_integer_value := clc$min_integer;
          type_description.union_information^.max_integer_value := clc$max_integer;
          type_description.union_information^.default_radix := 10;
          type_description.union_information^.min_real_value.long_real := clv$negative_infinity^;
          type_description.union_information^.max_real_value.long_real := clv$positive_infinity^;
          IF union_type_qualifier^.number_of_members = 0 THEN
            type_description.member_descriptions := NIL;
          ELSE
            NEXT type_description.member_descriptions: [1 .. union_type_qualifier^.number_of_members] IN
                  work_area;
            IF type_description.member_descriptions = NIL THEN
              RESET work_area TO type_description.union_information;
              EXIT /work_area_ok/;
            IFEND;
            FOR i := 1 TO union_type_qualifier^.number_of_members DO
              NEXT member_type_specification_size IN type_specification;
              IF member_type_specification_size = NIL THEN
                RESET work_area TO type_description.union_information;
                EXIT /type_specification_ok/;
              IFEND;
*IF NOT $true(osv$unix)
              NEXT member_type_specification: [[REP member_type_specification_size^ OF cell]] IN
                    type_specification;
*ELSE
              NEXT kludge_type_spec: [1 .. member_type_specification_size^] in type_specification;
              member_type_specification := #SEQ (kludge_type_spec^);
*IFEND
              IF member_type_specification = NIL THEN
                RESET work_area TO type_description.union_information;
                EXIT /type_specification_ok/;
              IFEND;
              clp$convert_type_spec_to_desc (member_type_specification, work_area,
                    type_description.member_descriptions^ [i], status);
              IF status.normal THEN

              /merge_member_type/
                BEGIN
                  IF type_description.member_descriptions^ [i].advanced_keywords_present THEN
                    type_description.advanced_keywords_present := TRUE;
                  IFEND;
                  CASE type_description.member_descriptions^ [i].kind OF

                  = clc$integer_type =
                    IF clc$integer_type IN type_description.kinds THEN
                      IF type_description.member_descriptions^ [i].min_integer_value <
                            type_description.union_information^.min_integer_value THEN
                        type_description.union_information^.min_integer_value :=
                              type_description.member_descriptions^ [i].min_integer_value;
                      IFEND;
                      IF type_description.member_descriptions^ [i].max_integer_value >
                            type_description.union_information^.max_integer_value THEN
                        type_description.union_information^.max_integer_value :=
                              type_description.member_descriptions^ [i].max_integer_value;
                      IFEND;
                    ELSE
                      type_description.union_information^.min_integer_value :=
                            type_description.member_descriptions^ [i].min_integer_value;
                      type_description.union_information^.max_integer_value :=
                            type_description.member_descriptions^ [i].max_integer_value;
                      type_description.union_information^.default_radix :=
                            type_description.member_descriptions^ [i].default_radix;
                    IFEND;

                  = clc$real_type =
*IF NOT $true(osv$unix)
                    IF clc$real_type IN type_description.kinds THEN
                      IF clp$longreal_compare_lt (type_description.member_descriptions^ [i].min_real_value.
                            long_real, type_description.union_information^.min_real_value.long_real) THEN
                        type_description.union_information^.min_real_value :=
                              type_description.member_descriptions^ [i].min_real_value;
                      IFEND;
                      IF clp$longreal_compare_gt (type_description.member_descriptions^ [i].max_real_value.
                            long_real, type_description.union_information^.max_real_value.long_real) THEN
                        type_description.union_information^.max_real_value :=
                              type_description.member_descriptions^ [i].max_real_value;
                      IFEND;
                    ELSE
                      type_description.union_information^.min_real_value :=
                            type_description.member_descriptions^ [i].min_real_value;
                      type_description.union_information^.max_real_value :=
                            type_description.member_descriptions^ [i].max_real_value;
                    IFEND;
*IFEND

                  = clc$union_type =
                    IF clc$integer_type IN type_description.kinds THEN
                      IF clc$integer_type IN type_description.member_descriptions^ [i].kinds THEN
                        IF type_description.member_descriptions^ [i].union_information^.min_integer_value <
                              type_description.union_information^.min_integer_value THEN
                          type_description.union_information^.min_integer_value :=
                                type_description.member_descriptions^ [i].union_information^.
                                min_integer_value;
                        IFEND;
                        IF type_description.member_descriptions^ [i].union_information^.max_integer_value >
                              type_description.union_information^.max_integer_value THEN
                          type_description.union_information^.max_integer_value :=
                                type_description.member_descriptions^ [i].union_information^.
                                max_integer_value;
                        IFEND;
                      IFEND;
                    ELSE
                      type_description.union_information^.min_integer_value :=
                            type_description.member_descriptions^ [i].union_information^.min_integer_value;
                      type_description.union_information^.max_integer_value :=
                            type_description.member_descriptions^ [i].union_information^.max_integer_value;
                      type_description.union_information^.default_radix :=
                            type_description.member_descriptions^ [i].union_information^.default_radix;
                    IFEND;

                    IF clc$real_type IN type_description.kinds THEN
*IF NOT $true(osv$unix)
                      IF clc$real_type IN type_description.member_descriptions^ [i].kinds THEN
                        IF clp$longreal_compare_lt (type_description.member_descriptions^ [i].
                              union_information^.min_real_value.long_real,
                              type_description.union_information^.min_real_value.long_real) THEN
                          type_description.union_information^.min_real_value :=
                                type_description.member_descriptions^ [i].union_information^.min_real_value;
                        IFEND;
                        IF clp$longreal_compare_gt (type_description.member_descriptions^ [i].
                              union_information^.max_real_value.long_real,
                              type_description.union_information^.max_real_value.long_real) THEN
                          type_description.union_information^.max_real_value :=
                                type_description.member_descriptions^ [i].union_information^.max_real_value;
                        IFEND;
                      IFEND;
*IFEND
                    ELSE
                      type_description.union_information^.min_real_value :=
                            type_description.member_descriptions^ [i].union_information^.min_real_value;
                      type_description.union_information^.max_real_value :=
                            type_description.member_descriptions^ [i].union_information^.max_real_value;
                    IFEND;

                  ELSE
                    ;
                  CASEND;
                END /merge_member_type/;
              IFEND;
              IF NOT status.normal THEN
                RESET work_area TO type_description.union_information;
                RETURN;
              IFEND;
            FOREND;
          IFEND;
*IF $true(osv$unix)

        = clc$unix_file_type =
          ;
*IFEND

        ELSE
          EXIT /type_specification_ok/;
        CASEND;
        RETURN;

      END /work_area_ok/;
      osp$set_status_condition (cle$work_area_overflow, status);
      RETURN;

    END /type_specification_ok/;
    osp$set_status_condition (cle$bad_type_specification, status);

  PROCEND clp$convert_type_spec_to_desc;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$create_variable_type', EJECT ??

  PROCEDURE [XDCL] clp$create_variable_type
    (    kind: clt$variable_kinds;
         max_string_size: clt$string_size;
         create_array: boolean;
         lower_bound: clt$variable_dimension;
         upper_bound: clt$variable_dimension;
     VAR work_area {input,output} : ^clt$work_area;
     VAR type_specification: ^clt$type_specification;
     VAR type_description: ^clt$type_description;
     VAR status: ost$status);

    VAR
      local_type_description: ^clt$type_description;


    status.normal := TRUE;
    type_specification := NIL;
    NEXT type_description IN work_area;
    IF type_description = NIL THEN
      osp$set_status_condition (cle$work_area_overflow, status);
      RETURN;
    IFEND;
    local_type_description := type_description;

    IF create_array THEN
      local_type_description^.specification := NIL;
      local_type_description^.name := NIL;
      local_type_description^.derived_from_value_kind_spec := FALSE;
      local_type_description^.advanced_keywords_present := FALSE;
*IF NOT $true(osv$unix)
      local_type_description^.kinds := $clt$type_kinds [clc$array_type];
*ELSE
      local_type_description^.kinds := $clt$type_kinds_v2 [clc$array_type];
*IFEND
      local_type_description^.kind := clc$array_type;
      local_type_description^.array_bounds_defined := TRUE;
      local_type_description^.bounds.lower := lower_bound;
      local_type_description^.bounds.upper := upper_bound;
      NEXT local_type_description^.array_element_type_description IN work_area;
      IF local_type_description^.array_element_type_description = NIL THEN
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      local_type_description := local_type_description^.array_element_type_description;
    IFEND;

    local_type_description^.specification := NIL;
    local_type_description^.name := NIL;
    local_type_description^.derived_from_value_kind_spec := FALSE;
    local_type_description^.advanced_keywords_present := FALSE;

    CASE kind OF
    = clc$boolean_value =
*IF NOT $true(osv$unix)
      local_type_description^.kinds := $clt$type_kinds [clc$boolean_type];
*ELSE
      local_type_description^.kinds := $clt$type_kinds_v2 [clc$boolean_type];
*IFEND
      local_type_description^.kind := clc$boolean_type;
    = clc$integer_value =
*IF NOT $true(osv$unix)
      local_type_description^.kinds := $clt$type_kinds [clc$integer_type];
*ELSE
      local_type_description^.kinds := $clt$type_kinds_v2 [clc$integer_type];
*IFEND
      local_type_description^.kind := clc$integer_type;
      local_type_description^.min_integer_value := clc$min_integer;
      local_type_description^.max_integer_value := clc$max_integer;
      local_type_description^.default_radix := 10;
    = clc$real_value =
*IF NOT $true(osv$unix)
      local_type_description^.kinds := $clt$type_kinds [clc$real_type];
*ELSE
      local_type_description^.kinds := $clt$type_kinds_v2 [clc$real_type];
*IFEND
      local_type_description^.kind := clc$real_type;
      local_type_description^.min_real_value.long_real := clv$negative_infinity^;
      local_type_description^.max_real_value.long_real := clv$positive_infinity^;
    = clc$status_value =
*IF NOT $true(osv$unix)
      local_type_description^.kinds := $clt$type_kinds [clc$status_type];
*ELSE
      local_type_description^.kinds := $clt$type_kinds_v2 [clc$status_type];
*IFEND
      local_type_description^.kind := clc$status_type;
    = clc$string_value =
*IF NOT $true(osv$unix)
      local_type_description^.kinds := $clt$type_kinds [clc$string_type];
*ELSE
      local_type_description^.kinds := $clt$type_kinds_v2 [clc$string_type];
*IFEND
      local_type_description^.kind := clc$string_type;
      local_type_description^.min_string_size := 0;
      local_type_description^.max_string_size := max_string_size;
      local_type_description^.literal := FALSE;
    ELSE
{Should not get here.}
      osp$set_status_condition (cle$bad_variable_kind, status);
      RETURN;
    CASEND;

    clp$convert_type_desc_to_spec (type_description, work_area, type_specification, status);

  PROCEND clp$create_variable_type;
*IFEND
?? TITLE := 'clp$derive_type_desc_from_value', EJECT ??

  PROCEDURE [XDCL] clp$derive_type_desc_from_value
    (    value: ^clt$data_value;
     VAR work_area {input, output} : ^clt$work_area;
     VAR type_description: clt$type_description;
     VAR status: ost$status);

    VAR
*IF NOT $true(osv$unix)
      unqualified_union_type_desc: [STATIC, READ, oss$job_paged_literal] clt$type_description :=
            [NIL, NIL, FALSE, FALSE, -$clt$type_kinds [], clc$union_type, NIL,
*ELSE
      unqualified_union_type_desc: [STATIC, READ] clt$type_description :=
            [NIL, NIL, FALSE, FALSE, -$clt$type_kinds_v2 [], clc$union_type, NIL,
*IFEND
            ^unqualified_union_information],
*IF NOT $true(osv$unix)
      unqualified_union_information: [STATIC, READ, oss$job_paged_literal] clt$union_type_information :=
            [FALSE, clc$min_integer, clc$max_integer, 10, [{-$INFINITY} 3, [[0d000(16), 0], [0d000(16), 0]]],
            [{$INFINITY} 3, [[5000(16), 0], [5000(16), 0]]]];
*ELSE
      unqualified_union_information: [STATIC, READ] clt$union_type_information :=
            [FALSE, clc$min_integer, clc$max_integer, 10,
*copy cli$longreal_negative_infinity
            ,
*copy cli$longreal_positive_infinity
            ];
*IFEND

    VAR
      current_value: ^clt$data_value,
      i: integer,
      type_conformance: clt$type_conformance;


    status.normal := TRUE;

    IF value = NIL THEN
      type_description := unqualified_union_type_desc;
      RETURN;
    IFEND;

    type_description.specification := NIL;
    type_description.name := NIL;
    type_description.derived_from_value_kind_spec := FALSE;
    type_description.advanced_keywords_present := FALSE;

    CASE value^.kind OF

    = clc$application =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$application_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$application_type];
*IFEND
      type_description.kind := clc$application_type;
      type_description.balance_brackets := FALSE;

    = clc$array =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$array_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$array_type];
*IFEND
      type_description.kind := clc$array_type;
      IF value^.array_value = NIL THEN
        osp$set_status_condition (cle$bad_data_value, status);
        RETURN;
      IFEND;
      type_description.array_bounds_defined := TRUE;
      type_description.bounds.lower := LOWERBOUND (value^.array_value^);
      type_description.bounds.upper := UPPERBOUND (value^.array_value^);
      NEXT type_description.array_element_type_description IN work_area;
      IF type_description.array_element_type_description = NIL THEN
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      clp$derive_type_desc_from_value (value^.array_value^ [1], work_area,
            type_description.array_element_type_description^, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF (type_description.array_element_type_description^.kind <> clc$union_type) OR
            (type_description.array_element_type_description^.member_descriptions <> NIL) THEN

      /check_array_elements/
        FOR i := LOWERBOUND (value^.array_value^) + 1 TO UPPERBOUND (value^.array_value^) DO
          clp$validate_value_conformance (value^.array_value^ [i],
                type_description.array_element_type_description, type_conformance);
          IF type_conformance < clc$conforms_to_type THEN
            type_description.array_element_type_description^ := unqualified_union_type_desc;
            EXIT /check_array_elements/;
          IFEND;
        FOREND /check_array_elements/;
      IFEND;

    = clc$boolean =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$boolean_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$boolean_type];
*IFEND
      type_description.kind := clc$boolean_type;

    = clc$cobol_name =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$cobol_name_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$cobol_name_type];
*IFEND
      type_description.kind := clc$cobol_name_type;

    = clc$command_reference =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$command_reference_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$command_reference_type];
*IFEND
      type_description.kind := clc$command_reference_type;

    = clc$data_name =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$data_name_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$data_name_type];
*IFEND
      type_description.kind := clc$data_name_type;

    = clc$date_time =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$date_time_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$date_time_type];
*IFEND
      type_description.kind := clc$date_time_type;
      type_description.date_and_or_time := $clt$date_and_or_time [clc$date, clc$time];
      type_description.tenses := $clt$date_time_tenses [clc$past, clc$present, clc$future];

    = clc$entry_point_reference =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$entry_point_reference_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$entry_point_reference_type];
*IFEND
      type_description.kind := clc$entry_point_reference_type;

*IF NOT $true(osv$unix)
    = clc$file =
      type_description.kinds := $clt$type_kinds [clc$file_type];
      type_description.kind := clc$file_type;
*ELSE
    = clc$nos_ve_file =
      type_description.kinds := $clt$type_kinds_v2 [clc$nos_ve_file_type];
      type_description.kind := clc$nos_ve_file_type;
*IFEND

    = clc$integer =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$integer_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$integer_type];
*IFEND
      type_description.kind := clc$integer_type;
      type_description.min_integer_value := clc$min_integer;
      type_description.max_integer_value := clc$max_integer;
      type_description.default_radix := 10;

    = clc$keyword =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$keyword_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$keyword_type];
*IFEND
      type_description.kind := clc$keyword_type;
      NEXT type_description.keyword_specifications: [1 .. 1] IN work_area;
      IF type_description.keyword_specifications = NIL THEN
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      type_description.keyword_specifications^ [1].keyword := value^.keyword_value;
      type_description.keyword_specifications^ [1].class := clc$nominal_entry;
      type_description.keyword_specifications^ [1].availability := clc$normal_usage_entry;
      type_description.keyword_specifications^ [1].ordinal := 1;

    = clc$list =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$list_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$list_type];
*IFEND
      type_description.kind := clc$list_type;
      type_description.min_list_size := 0;
      type_description.max_list_size := clc$max_list_size;
      type_description.list_rest := value^.generated_via_list_rest;
      type_description.defer_expansion := FALSE;
      NEXT type_description.list_element_type_description IN work_area;
      IF type_description.list_element_type_description = NIL THEN
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      clp$derive_type_desc_from_value (value^.element_value, work_area,
            type_description.list_element_type_description^, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF (type_description.list_element_type_description^.kind <> clc$union_type) OR
            (type_description.list_element_type_description^.member_descriptions <> NIL) THEN
        current_value := value^.link;

      /check_list_elements/
        WHILE current_value <> NIL DO
          IF current_value^.kind <> clc$list THEN
            osp$set_status_condition (cle$bad_data_value, status);
            RETURN;
          ELSEIF current_value^.element_value = NIL THEN
            IF current_value^.link <> NIL THEN
              osp$set_status_condition (cle$bad_data_value, status);
              RETURN;
            IFEND;
          ELSE
            clp$validate_value_conformance (current_value^.element_value,
                  type_description.list_element_type_description, type_conformance);
            IF type_conformance < clc$conforms_to_type THEN
              type_description.list_element_type_description^ := unqualified_union_type_desc;
              EXIT /check_list_elements/;
            IFEND;
          IFEND;
          current_value := current_value^.link;
        WHILEND /check_list_elements/;
      IFEND;

    = clc$lock =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$lock_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$lock_type];
*IFEND
      type_description.kind := clc$lock_type;

    = clc$name =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$name_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$name_type];
*IFEND
      type_description.kind := clc$name_type;
      type_description.min_name_size := 1;
      type_description.max_name_size := osc$max_name_size;

    = clc$network_title =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$network_title_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$network_title_type];
*IFEND
      type_description.kind := clc$network_title_type;

    = clc$program_name =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$program_name_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$program_name_type];
*IFEND
      type_description.kind := clc$program_name_type;

    = clc$range =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$range_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$range_type];
*IFEND
      type_description.kind := clc$range_type;
      NEXT type_description.range_element_type_description IN work_area;
      IF type_description.range_element_type_description = NIL THEN
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      clp$derive_type_desc_from_value (value^.low_value, work_area,
            type_description.range_element_type_description^, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF (value^.high_value <> value^.low_value) AND ((type_description.range_element_type_description^.
            kind <> clc$union_type) OR (type_description.range_element_type_description^.
            member_descriptions <> NIL)) THEN
        clp$validate_value_conformance (value^.high_value, type_description.range_element_type_description,
              type_conformance);
        IF type_conformance < clc$conforms_to_type THEN
          type_description.range_element_type_description^ := unqualified_union_type_desc;
        IFEND;
      IFEND;

    = clc$real =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$real_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$real_type];
*IFEND
      type_description.kind := clc$real_type;
      type_description.min_real_value.long_real := clv$negative_infinity^;
      type_description.max_real_value.long_real := clv$positive_infinity^;

    = clc$record =
      IF value^.field_values = NIL THEN
        osp$set_status_condition (cle$bad_data_value, status);
        RETURN;
      IFEND;
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$record_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$record_type];
*IFEND
      type_description.kind := clc$record_type;
      NEXT type_description.fields_pdt IN work_area;
      IF type_description.fields_pdt = NIL THEN
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      NEXT type_description.fields_pdt^.header IN work_area;
      IF type_description.fields_pdt^.header = NIL THEN
        RESET work_area TO type_description.fields_pdt;
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      type_description.fields_pdt^.header^.version := clc$declaration_version;
      type_description.fields_pdt^.header^.generation_date_time.year := 87;
      type_description.fields_pdt^.header^.generation_date_time.month := 12;
      type_description.fields_pdt^.header^.generation_date_time.day := 10;
      type_description.fields_pdt^.header^.generation_date_time.hour := 11;
      type_description.fields_pdt^.header^.generation_date_time.minute := 55;
      type_description.fields_pdt^.header^.generation_date_time.second := 0;
      type_description.fields_pdt^.header^.generation_date_time.millisecond := 0;
      type_description.fields_pdt^.header^.command_or_function := clc$function;
      type_description.fields_pdt^.header^.number_of_parameter_names := UPPERBOUND (value^.field_values^);
      type_description.fields_pdt^.header^.number_of_parameters := UPPERBOUND (value^.field_values^);
      type_description.fields_pdt^.header^.number_of_required_parameters := 0;
      type_description.fields_pdt^.header^.number_of_advanced_parameters := 0;
      type_description.fields_pdt^.header^.number_of_hidden_parameters := 0;
      type_description.fields_pdt^.header^.number_of_var_parameters := 0;
      type_description.fields_pdt^.header^.status_parameter_number := 0;
      type_description.fields_pdt^.header^.help_module_name := osc$null_name;
      NEXT type_description.fields_pdt^.names: [1 .. UPPERBOUND (value^.field_values^)] IN work_area;
      IF type_description.fields_pdt^.names = NIL THEN
        RESET work_area TO type_description.fields_pdt;
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      NEXT type_description.fields_pdt^.parameters: [1 .. UPPERBOUND (value^.field_values^)] IN work_area;
      IF type_description.fields_pdt^.parameters = NIL THEN
        RESET work_area TO type_description.fields_pdt;
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      NEXT type_description.fields_pdt^.type_descriptions: [1 .. UPPERBOUND (value^.field_values^)] IN
            work_area;
      IF type_description.fields_pdt^.type_descriptions = NIL THEN
        RESET work_area TO type_description.fields_pdt;
        osp$set_status_condition (cle$work_area_overflow, status);
        RETURN;
      IFEND;
      type_description.fields_pdt^.default_names := NIL;
      type_description.fields_pdt^.default_values := NIL;
      FOR i := 1 TO UPPERBOUND (value^.field_values^) DO
        type_description.fields_pdt^.names^ [i].name := value^.field_values^ [i].name;
        type_description.fields_pdt^.names^ [i].class := clc$nominal_entry;
        type_description.fields_pdt^.names^ [i].position := i;
        type_description.fields_pdt^.parameters^ [i].name_index := i;
        type_description.fields_pdt^.parameters^ [i].availability := clc$normal_usage_entry;
        type_description.fields_pdt^.parameters^ [i].security := clc$non_secure_parameter;
        type_description.fields_pdt^.parameters^ [i].specification_methods :=
              $clt$parameter_spec_methods [clc$specify_positionally];
        type_description.fields_pdt^.parameters^ [i].passing_method := clc$pass_by_value;
        type_description.fields_pdt^.parameters^ [i].evaluation_method := clc$immediate_evaluation;
        type_description.fields_pdt^.parameters^ [i].checking_level := clc$standard_parameter_checking;
        type_description.fields_pdt^.parameters^ [i].type_specification_size := 0;
        type_description.fields_pdt^.parameters^ [i].default_name_size := 0;
        type_description.fields_pdt^.parameters^ [i].default_value_size := 0;
        type_description.fields_pdt^.parameters^ [i].requirement := clc$optional_field;
        IF value^.field_values^ [i].value = NIL THEN
          type_description.fields_pdt^.type_descriptions^ [i] := unqualified_union_type_desc;
        ELSE
          type_description.fields_pdt^.header^.number_of_required_parameters :=
                type_description.fields_pdt^.header^.number_of_required_parameters + 1;
          clp$derive_type_desc_from_value (value^.field_values^ [i].value, work_area,
                type_description.fields_pdt^.type_descriptions^ [i], status);
          IF NOT status.normal THEN
            RESET work_area TO type_description.fields_pdt;
            RETURN;
          IFEND;
        IFEND;
      FOREND;

    = clc$scu_line_identifier =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$scu_line_identifier_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$scu_line_identifier_type];
*IFEND
      type_description.kind := clc$scu_line_identifier_type;

    = clc$statistic_code =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$statistic_code_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$statistic_code_type];
*IFEND
      type_description.kind := clc$statistic_code_type;

    = clc$status =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$status_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$status_type];
*IFEND
      type_description.kind := clc$status_type;

    = clc$status_code =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$status_code_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$status_code_type];
*IFEND
      type_description.kind := clc$status_code_type;

    = clc$string =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$string_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$string_type];
*IFEND
      type_description.kind := clc$string_type;
      type_description.min_string_size := 0;
      type_description.max_string_size := clc$max_string_size;
      type_description.literal := FALSE;

    = clc$string_pattern =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$string_pattern_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$string_pattern_type];
*IFEND
      type_description.kind := clc$string_pattern_type;

    = clc$time_increment =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$time_increment_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$time_increment_type];
*IFEND
      type_description.kind := clc$time_increment_type;

    = clc$time_zone =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$time_zone_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$time_zone_type];
*IFEND
      type_description.kind := clc$time_zone_type;

    = clc$type_specification =
*IF NOT $true(osv$unix)
      type_description.kinds := $clt$type_kinds [clc$type_specification_type];
*ELSE
      type_description.kinds := $clt$type_kinds_v2 [clc$type_specification_type];
*IFEND
      type_description.kind := clc$type_specification_type;

    = clc$unspecified =
      type_description := unqualified_union_type_desc;
*IF $true(osv$unix)

    = clc$unix_file =
      type_description.kinds := $clt$type_kinds_v2 [clc$unix_file_type];
      type_description.kind := clc$unix_file_type;
*IFEND

    ELSE
      osp$set_status_condition (cle$bad_data_value, status);
      RETURN;
    CASEND;

  PROCEND clp$derive_type_desc_from_value;
?? TITLE := 'clp$derive_type_spec_from_value', EJECT ??
*copyc clh$derive_type_spec_from_value

  PROCEDURE [XDCL, #GATE] clp$derive_type_spec_from_value
    (    value: ^clt$data_value;
     VAR work_area {input, output} : ^clt$work_area;
     VAR type_specification: ^clt$type_specification;
     VAR status: ost$status);

    VAR
      type_description: clt$type_description;


    clp$derive_type_desc_from_value (value, work_area, type_description, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$convert_type_desc_to_spec (^type_description, work_area, type_specification, status);

  PROCEND clp$derive_type_spec_from_value;
?? TITLE := 'clp$evaluate_type_conformance', EJECT ??

  PROCEDURE [XDCL] clp$evaluate_type_conformance
    (    subject_type_description: ^clt$type_description;
         target_type_description: ^clt$type_description;
         minimum_type_conformance: clt$type_conformance;
     VAR status: ost$status);

    VAR
      i: integer,
      max_real_order: mlt$compare,
      min_real_order: mlt$compare,
      subject_keyword: clt$keyword,
      target_keyword: clt$keyword,
      type_conformance: clt$type_conformance;


    status.normal := TRUE;

    IF (subject_type_description = NIL) OR (target_type_description = NIL) THEN
      osp$set_status_condition (cle$undefined_type, status);
      RETURN;
    IFEND;

    CASE target_type_description^.kind OF

    = clc$application_type =
      IF subject_type_description^.kind = clc$application_type THEN
        IF minimum_type_conformance > clc$conforms_to_generic_type THEN
          IF (subject_type_description^.balance_brackets <> target_type_description^.balance_brackets) THEN
            osp$set_status_condition (cle$balance_brackets_dont_match, status);
            RETURN;
          IFEND;
          IF subject_type_description^.name = NIL THEN
            IF target_type_description^.name = NIL THEN
              RETURN;
            IFEND;
          ELSEIF target_type_description^.name <> NIL THEN
            IF subject_type_description^.name^ = target_type_description^.name^ THEN
              RETURN;
            IFEND;
          IFEND;
          osp$set_status_condition (cle$application_name_mismatch, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$array_type =
      IF subject_type_description^.kind = clc$array_type THEN
        IF target_type_description^.array_bounds_defined THEN
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            IF subject_type_description^.array_bounds_defined THEN
              IF (subject_type_description^.bounds.lower <> target_type_description^.bounds.lower) OR
                    (subject_type_description^.bounds.upper <> target_type_description^.bounds.upper) THEN
                osp$set_status_condition (cle$array_bounds_dont_match, status);
                RETURN;
              IFEND;
            ELSE
              osp$set_status_condition (cle$array_bounds_dont_match, status);
              RETURN;
            IFEND;
          IFEND;
        ELSEIF subject_type_description^.array_bounds_defined THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            osp$set_status_condition (cle$array_bounds_dont_match, status);
            RETURN;
          IFEND;
        IFEND;

        IF minimum_type_conformance >= clc$conforms_to_type THEN
          IF target_type_description^.array_element_type_description = NIL THEN
            IF subject_type_description^.array_element_type_description <> NIL THEN
              osp$set_status_condition (cle$unknown_array_element_type, status);
            IFEND;
          ELSE
            clp$evaluate_type_conformance (subject_type_description^.array_element_type_description,
                  target_type_description^.array_element_type_description, minimum_type_conformance, status);
            IF NOT status.normal THEN
              IF status.condition = cle$wrong_kind_of_value THEN
                status.condition := cle$wrong_kind_of_element_type;
              IFEND;
            IFEND;
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$boolean_type =
      IF subject_type_description^.kind <> clc$boolean_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$cobol_name_type =
      IF subject_type_description^.kind <> clc$cobol_name_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$command_reference_type =
      IF subject_type_description^.kind <> clc$command_reference_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$data_name_type =
      IF subject_type_description^.kind <> clc$data_name_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$date_time_type =
      IF (subject_type_description^.kind = clc$date_time_type) THEN
        IF minimum_type_conformance > clc$conforms_to_type THEN
          IF (subject_type_description^.date_and_or_time = target_type_description^.date_and_or_time) THEN
            IF (subject_type_description^.tenses <> target_type_description^.tenses) THEN
              osp$set_status_condition (cle$date_time_tenses_dont_match, status);
            IFEND;
          ELSE
            osp$set_status_condition (cle$date_time_types_dont_match, status);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$entry_point_reference_type =
      IF subject_type_description^.kind <> clc$entry_point_reference_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

*IF NOT $true(osv$unix)
    = clc$file_type =
      IF subject_type_description^.kind <> clc$file_type THEN
*ELSE
    = clc$nos_ve_file_type =
      IF subject_type_description^.kind <> clc$nos_ve_file_type THEN
*IFEND
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$integer_type =
      IF subject_type_description^.kind = clc$integer_type THEN
        IF (subject_type_description^.min_integer_value >= target_type_description^.min_integer_value) AND
              (subject_type_description^.max_integer_value <= target_type_description^.max_integer_value) THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF (subject_type_description^.min_integer_value <> target_type_description^.min_integer_value) OR
                  (subject_type_description^.max_integer_value <> target_type_description^.max_integer_value)
                  THEN
              osp$set_status_condition (cle$integer_ranges_dont_match, status);
            ELSEIF (subject_type_description^.default_radix <> target_type_description^.default_radix) THEN
              osp$set_status_condition (cle$integer_radices_dont_match, status);
            IFEND;
          IFEND;
        ELSE
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$integer_ranges_dont_match, status);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$keyword_type =
      IF subject_type_description^.kind = clc$keyword_type THEN
        IF UPPERBOUND (subject_type_description^.keyword_specifications^) <=
              UPPERBOUND (target_type_description^.keyword_specifications^) THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF UPPERBOUND (subject_type_description^.keyword_specifications^) =
                  UPPERBOUND (target_type_description^.keyword_specifications^) THEN
              FOR i := 1 TO UPPERBOUND (subject_type_description^.keyword_specifications^) DO
                IF subject_type_description^.keyword_specifications^ [i] <>
                      target_type_description^.keyword_specifications^ [i] THEN
                  osp$set_status_condition (cle$keywords_dont_match, status);
                  RETURN;
                IFEND;
              FOREND;
            ELSE
              osp$set_status_condition (cle$keywords_dont_match, status);
              RETURN;
            IFEND;
          IFEND;
          FOR i := 1 TO UPPERBOUND (subject_type_description^.keyword_specifications^) DO
            IF subject_type_description^.keyword_specifications^ [i].class = clc$nominal_entry THEN
              subject_keyword := subject_type_description^.keyword_specifications^ [i].keyword;
            ELSE
              clp$check_keyword (subject_type_description^.keyword_specifications^ [i].keyword,
                    subject_type_description^.keyword_specifications, subject_keyword);
            IFEND;
            clp$check_keyword (subject_type_description^.keyword_specifications^ [i].keyword,
                  target_type_description^.keyword_specifications, target_keyword);
            IF subject_keyword <> target_keyword THEN
              IF minimum_type_conformance > clc$conforms_to_type THEN
                osp$set_status_abnormal ('CL', cle$unknown_keyword, subject_keyword, status);
                RETURN;
              IFEND;
            IFEND;
          FOREND;
        ELSEIF minimum_type_conformance > clc$conforms_to_generic_type THEN
          osp$set_status_condition (cle$keywords_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$list_type =
      IF subject_type_description^.kind = clc$list_type THEN
        IF minimum_type_conformance >= clc$conforms_to_type THEN
          IF target_type_description^.list_element_type_description = NIL THEN
            IF minimum_type_conformance > clc$conforms_to_type THEN
              IF subject_type_description^.list_element_type_description <> NIL THEN
                osp$set_status_condition (cle$unknown_list_element_type, status);
                RETURN;
              IFEND;
            IFEND;
          ELSE
            clp$evaluate_type_conformance (subject_type_description^.list_element_type_description,
                  target_type_description^.list_element_type_description, minimum_type_conformance, status);
            IF NOT status.normal THEN
              IF status.condition = cle$wrong_kind_of_value THEN
                IF target_type_description^.list_rest AND
                      (target_type_description^.list_element_type_description^.kind = clc$list_type) THEN
                  status.normal := TRUE;
                ELSE
                  status.condition := cle$wrong_kind_of_element_type;
                IFEND;
              IFEND;
              RETURN;
            IFEND;
          IFEND;
        IFEND;

        IF (target_type_description^.min_list_size <= subject_type_description^.min_list_size) AND
              (subject_type_description^.max_list_size <= target_type_description^.max_list_size) THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF (target_type_description^.min_list_size <> subject_type_description^.min_list_size) OR
                  (subject_type_description^.max_list_size <> target_type_description^.max_list_size) THEN
              osp$set_status_condition (cle$list_sizes_dont_match, status);
            ELSEIF (subject_type_description^.list_rest <> target_type_description^.list_rest) THEN
              osp$set_status_condition (cle$list_rest_doesnt_match, status);
            ELSEIF subject_type_description^.defer_expansion AND
                  (NOT target_type_description^.defer_expansion) THEN
              osp$set_status_condition (cle$defer_expans_doesnt_match, status);
            IFEND;
          IFEND;
        ELSE
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$list_sizes_dont_match, status);
          IFEND;
        IFEND;

      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$lock_type =
      IF subject_type_description^.kind <> clc$lock_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$name_type =
      IF subject_type_description^.kind = clc$name_type THEN
        IF (target_type_description^.min_name_size <= subject_type_description^.min_name_size) AND
              (subject_type_description^.max_name_size <= target_type_description^.max_name_size) THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF (target_type_description^.min_name_size <> subject_type_description^.min_name_size) OR
                  (subject_type_description^.max_name_size <> target_type_description^.max_name_size) THEN
              osp$set_status_condition (cle$name_sizes_dont_match, status);
            IFEND;
          IFEND;
        ELSE
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$name_sizes_dont_match, status);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$network_title_type =
      IF subject_type_description^.kind <> clc$network_title_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$program_name_type =
      IF subject_type_description^.kind <> clc$program_name_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$range_type =
      IF subject_type_description^.kind = clc$range_type THEN
        IF target_type_description^.range_element_type_description = NIL THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF subject_type_description^.range_element_type_description <> NIL THEN
              osp$set_status_condition (cle$unknown_range_element_type, status);
            IFEND;
          IFEND;
        ELSE
          clp$evaluate_type_conformance (subject_type_description^.range_element_type_description,
                target_type_description^.range_element_type_description, minimum_type_conformance, status);
          IF NOT status.normal THEN
            IF status.condition = cle$wrong_kind_of_value THEN
              status.condition := cle$range_types_dont_match;
            IFEND;
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$real_type =
      IF subject_type_description^.kind = clc$real_type THEN
*IF NOT $true(osv$unix)
        max_real_order := clp$longreal_compare (subject_type_description^.max_real_value.long_real,
              target_type_description^.max_real_value.long_real, clc$infinities_equal);
        min_real_order := clp$longreal_compare (subject_type_description^.min_real_value.long_real,
              target_type_description^.min_real_value.long_real, clc$infinities_equal);
        IF (min_real_order = clc$equal) AND (max_real_order = clc$equal) THEN
          ;
        ELSEIF (min_real_order IN $clt$comparison_results [clc$left_is_greater,
              clc$equal]) AND (max_real_order IN $clt$comparison_results [clc$right_is_greater, clc$equal])
              THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            osp$set_status_condition (cle$real_subranges_dont_match, status);
          IFEND;
        ELSE
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$real_subranges_dont_match, status);
          IFEND;
        IFEND;
*IFEND
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$record_type =
      IF subject_type_description^.kind = clc$record_type THEN
        IF subject_type_description^.fields_pdt^.header^.number_of_parameters <=
              target_type_description^.fields_pdt^.header^.number_of_parameters THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF subject_type_description^.fields_pdt^.header^.number_of_parameters <>
                  target_type_description^.fields_pdt^.header^.number_of_parameters THEN
              osp$set_status_condition (cle$number_of_fields_dont_match, status);
              RETURN;
            IFEND;
          IFEND;
        ELSE
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$number_of_fields_dont_match, status);
            RETURN;
          IFEND;
        IFEND;

        IF minimum_type_conformance >= clc$conforms_to_type THEN
          FOR i := 1 TO subject_type_description^.fields_pdt^.header^.number_of_parameters DO
            IF (subject_type_description^.fields_pdt^.names^ [i].name <>
                  target_type_description^.fields_pdt^.names^ [i].name) THEN
              osp$set_status_condition (cle$field_names_dont_match, status);
              RETURN;
            ELSEIF (subject_type_description^.fields_pdt^.parameters^ [i].requirement >
                  target_type_description^.fields_pdt^.parameters^ [i].requirement) THEN
              osp$set_status_condition (cle$field_requirements_mismatch, status);
              RETURN;
            ELSEIF (minimum_type_conformance = clc$identical_types) AND
                  (subject_type_description^.fields_pdt^.parameters^ [i].requirement <>
                  target_type_description^.fields_pdt^.parameters^ [i].requirement) THEN
              osp$set_status_condition (cle$field_requirements_mismatch, status);
              RETURN;
            IFEND;
            clp$evaluate_type_conformance (^subject_type_description^.fields_pdt^.type_descriptions^ [i],
                  ^target_type_description^.fields_pdt^.type_descriptions^ [i], minimum_type_conformance,
                  status);
            IF NOT status.normal THEN
              IF status.condition = cle$wrong_kind_of_value THEN
                status.condition := cle$field_types_dont_match;
                osp$append_status_parameter (osc$status_parameter_delimiter,
                      subject_type_description^.fields_pdt^.names^ [i].name, status);
              IFEND;
              RETURN;
            IFEND;
          FOREND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$scu_line_identifier_type =
      IF subject_type_description^.kind <> clc$scu_line_identifier_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$statistic_code_type =
      IF subject_type_description^.kind <> clc$statistic_code_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$status_type =
      IF subject_type_description^.kind <> clc$status_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$status_code_type =
      IF subject_type_description^.kind <> clc$status_code_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$string_type =
      IF subject_type_description^.kind = clc$string_type THEN
        IF (target_type_description^.min_string_size <= subject_type_description^.min_string_size) AND
              (subject_type_description^.max_string_size <= target_type_description^.max_string_size) AND
              (target_type_description^.literal <= subject_type_description^.literal) THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF (target_type_description^.min_string_size <> subject_type_description^.min_string_size) OR
                  (subject_type_description^.max_string_size <> target_type_description^.max_string_size) THEN
              osp$set_status_condition (cle$string_sizes_dont_match, status);
            ELSEIF (target_type_description^.literal <> subject_type_description^.literal) THEN
              osp$set_status_condition (cle$string_literals_dont_match, status);
            IFEND;
          IFEND;
        ELSE
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$string_sizes_dont_match, status);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$string_pattern_type =
      IF subject_type_description^.kind <> clc$string_pattern_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$time_increment_type =
      IF subject_type_description^.kind <> clc$time_increment_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$time_zone_type =
      IF subject_type_description^.kind <> clc$time_zone_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$type_specification_type =
      IF subject_type_description^.kind <> clc$type_specification_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$union_type =
      IF subject_type_description^.kind = clc$union_type THEN
        IF target_type_description^.member_descriptions = NIL THEN
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF subject_type_description^.member_descriptions <> NIL THEN
              osp$set_status_condition (cle$value_not_union_type, status);
            IFEND;
          IFEND;
        ELSEIF (subject_type_description^.member_descriptions = NIL) OR
              (UPPERBOUND (subject_type_description^.member_descriptions^) >
              UPPERBOUND (target_type_description^.member_descriptions^)) THEN
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$value_not_union_type, status);
          IFEND;
        ELSE
          IF minimum_type_conformance > clc$conforms_to_type THEN
            IF UPPERBOUND (subject_type_description^.member_descriptions^) <>
                  UPPERBOUND (target_type_description^.member_descriptions^) THEN
              osp$set_status_condition (cle$value_not_union_type, status);
            IFEND;
          IFEND;

          FOR i := 1 TO UPPERBOUND (subject_type_description^.member_descriptions^) DO
            IF minimum_type_conformance > clc$conforms_to_type THEN
              clp$validate_type_conformance (^subject_type_description^.member_descriptions^ [i],
                    ^target_type_description^.member_descriptions^ [i], type_conformance);
              IF type_conformance < minimum_type_conformance THEN
                IF type_conformance = clc$conforms_to_type THEN
                  osp$set_status_condition (cle$value_not_union_type, status);
                ELSE
                  clp$validate_type_conformance (^subject_type_description^.member_descriptions^ [i],
                        target_type_description, type_conformance);
                  IF type_conformance < minimum_type_conformance THEN
                    osp$set_status_condition (cle$value_not_union_type, status);
                  IFEND;
                IFEND;
              IFEND;
            ELSEIF minimum_type_conformance = clc$conforms_to_type THEN
              clp$validate_type_conformance (^subject_type_description^.member_descriptions^ [i],
                    target_type_description, type_conformance);
              IF type_conformance < minimum_type_conformance THEN
                osp$set_status_condition (cle$value_not_union_type, status);
              IFEND;
            IFEND;
          FOREND;
        IFEND;
      ELSEIF target_type_description^.member_descriptions = NIL THEN
        IF minimum_type_conformance > clc$conforms_to_type THEN
          osp$set_status_condition (cle$value_not_union_type, status);
        IFEND;
      ELSE
        FOR i := 1 TO UPPERBOUND (target_type_description^.member_descriptions^) DO
          clp$validate_type_conformance (subject_type_description,
                ^target_type_description^.member_descriptions^ [i], type_conformance);
          IF type_conformance < minimum_type_conformance THEN
            osp$set_status_condition (cle$value_not_union_type, status);
            RETURN;
          IFEND;
        FOREND;
      IFEND;
*IF $true(osv$unix)

    = clc$unix_file_type =
      IF subject_type_description^.kind <> clc$unix_file_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;
*IFEND

    ELSE
      ;
    CASEND;

  PROCEND clp$evaluate_type_conformance;
?? TITLE := 'clp$evaluate_value_conformance', EJECT ??

  PROCEDURE [XDCL] clp$evaluate_value_conformance
    (    value: ^clt$data_value;
         type_description: ^clt$type_description;
         minimum_type_conformance: clt$type_conformance;
     VAR status: ost$status);

    VAR
      current_value: ^clt$data_value,
      i: integer,
      local_type_conformance: clt$type_conformance,
      result_keyword: clt$keyword;


    status.normal := TRUE;

    IF value = NIL THEN
      osp$set_status_condition (cle$undefined_value, status);
      RETURN;
    IFEND;

    IF type_description = NIL THEN
      RETURN;
    IFEND;

    CASE type_description^.kind OF

    = clc$application_type =
      IF value^.kind <> clc$application THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$array_type =
      IF value^.kind = clc$array THEN
        IF (value^.array_value <> NIL) AND ((NOT type_description^.array_bounds_defined) OR
              ((type_description^.bounds.lower = LOWERBOUND (value^.array_value^)) AND
              (type_description^.bounds.upper = UPPERBOUND (value^.array_value^)))) THEN
          IF type_description^.array_element_type_description <> NIL THEN

          /check_array_elements/
            FOR i := LOWERBOUND (value^.array_value^) TO UPPERBOUND (value^.array_value^) DO
              clp$evaluate_value_conformance (value^.array_value^ [i],
                    type_description^.array_element_type_description, minimum_type_conformance, status);
              IF (minimum_type_conformance > clc$conforms_to_generic_type) AND NOT status.normal THEN
                IF status.condition = cle$undefined_value THEN
                  status.normal := TRUE;
                ELSE
                  IF status.condition = cle$wrong_kind_of_value THEN
                    status.condition := cle$wrong_kind_of_element_type;
                  IFEND;
                  EXIT /check_array_elements/;
                IFEND;
              IFEND;
            FOREND /check_array_elements/;
          IFEND;
        ELSEIF minimum_type_conformance > clc$conforms_to_generic_type THEN
          osp$set_status_condition (cle$array_bounds_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$boolean_type =
      IF value^.kind <> clc$boolean THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$cobol_name_type =
      IF value^.kind <> clc$cobol_name THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$command_reference_type =
      IF value^.kind <> clc$command_reference THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$data_name_type =
      IF value^.kind <> clc$data_name THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$date_time_type =
      IF value^.kind <> clc$date_time THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$entry_point_reference_type =
      IF value^.kind <> clc$entry_point_reference THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

*IF NOT $true(osv$unix)
    = clc$file_type =
      IF value^.kind <> clc$file THEN
*ELSE
    = clc$nos_ve_file_type =
      IF value^.kind <> clc$nos_ve_file THEN
*IFEND
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$integer_type =
      IF value^.kind = clc$integer THEN
        IF (minimum_type_conformance > clc$conforms_to_generic_type) AND
              NOT ((type_description^.min_integer_value <= value^.integer_value.value) AND
              (value^.integer_value.value <= type_description^.max_integer_value)) THEN
          osp$set_status_condition (cle$integer_ranges_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$keyword_type =
      IF value^.kind = clc$keyword THEN
        clp$check_keyword (value^.keyword_value, type_description^.keyword_specifications, result_keyword);
        IF (minimum_type_conformance > clc$conforms_to_generic_type) AND
              (value^.keyword_value <> result_keyword) THEN
          osp$set_status_abnormal ('CL', cle$unknown_keyword, value^.keyword_value, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$list_type =
      IF value^.kind = clc$list THEN
        IF type_description^.list_element_type_description <> NIL THEN

        /check_list_elements/
          BEGIN
            i := 0;
            current_value := value;
            REPEAT
              IF current_value^.kind <> clc$list THEN
                osp$set_status_condition (cle$wrong_kind_of_element_type, status);
                clp$append_status_type_desc (osc$status_parameter_delimiter,
                      type_description^.list_element_type_description, status);
                clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
                EXIT /check_list_elements/;
              ELSEIF current_value^.element_value = NIL THEN
                IF (i > 0) OR (current_value^.link <> NIL) THEN
                  osp$set_status_condition (cle$undefined_value_in_list, status);
                  EXIT /check_list_elements/;
                IFEND;
              ELSE
                i := i + 1;
                clp$evaluate_value_conformance (current_value^.element_value,
                      type_description^.list_element_type_description, minimum_type_conformance, status);
                IF NOT status.normal THEN
                  IF status.condition = cle$wrong_kind_of_value THEN
                    status.condition := cle$wrong_kind_of_element_type;
                  ELSEIF status.condition = cle$undefined_value THEN
                    status.condition := cle$undefined_value_in_list;
                  IFEND;
                  EXIT /check_list_elements/;
                IFEND;
              IFEND;
              current_value := current_value^.link;
            UNTIL current_value = NIL {/check_list_elements/} ;
            IF NOT ((type_description^.min_list_size <= i) AND (i <= type_description^.max_list_size)) THEN
              IF minimum_type_conformance > clc$conforms_to_generic_type THEN
                osp$set_status_condition (cle$list_sizes_dont_match, status);
              IFEND;
            IFEND;
          END /check_list_elements/;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$lock_type =
      IF value^.kind <> clc$lock THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$name_type =
      IF value^.kind = clc$name THEN
        i := clp$trimmed_string_size (value^.name_value);
        IF (minimum_type_conformance > clc$conforms_to_generic_type) AND
              NOT ((type_description^.min_name_size <= i) AND (i <= type_description^.max_name_size)) THEN
          osp$set_status_condition (cle$name_sizes_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$network_title_type =
      IF value^.kind <> clc$network_title THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$program_name_type =
      IF value^.kind <> clc$program_name THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$range_type =
      IF value^.kind = clc$range THEN
        IF type_description^.range_element_type_description <> NIL THEN
          clp$evaluate_value_conformance (value^.low_value, type_description^.range_element_type_description,
                minimum_type_conformance, status);
          IF status.normal AND (value^.high_value <> value^.low_value) THEN
            clp$evaluate_value_conformance (value^.high_value,
                  type_description^.range_element_type_description, minimum_type_conformance, status);
          IFEND;
          IF NOT status.normal THEN
            IF status.condition = cle$wrong_kind_of_value THEN
              status.condition := cle$range_types_dont_match;
            ELSEIF status.condition = cle$undefined_value THEN
              status.condition := cle$undefined_value_in_range;
            IFEND;
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$real_type =
*IF NOT $true(osv$unix)
      IF value^.kind = clc$real THEN
        IF (minimum_type_conformance > clc$conforms_to_generic_type) AND
              NOT (clp$longreal_compare_le (type_description^.min_real_value.long_real,
              value^.real_value.value) AND clp$longreal_compare_le
              (value^.real_value.value, type_description^.max_real_value.long_real)) THEN
          osp$set_status_condition (cle$real_subranges_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;
*ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
*IFEND

    = clc$record_type =
      IF value^.kind = clc$record THEN
        IF (value^.field_values = NIL) OR (UPPERBOUND (value^.field_values^) >
              type_description^.fields_pdt^.header^.number_of_parameters) THEN
          IF minimum_type_conformance > clc$conforms_to_generic_type THEN
            osp$set_status_condition (cle$number_of_fields_dont_match, status);
          IFEND;
        ELSE

        /check_fields/
          BEGIN
            FOR i := 1 TO UPPERBOUND (value^.field_values^) DO
              IF type_description^.fields_pdt^.names^ [i].name <> value^.field_values^ [i].name THEN
                IF minimum_type_conformance > clc$conforms_to_generic_type THEN
                  osp$set_status_condition (cle$field_names_dont_match, status);
                  EXIT /check_fields/;
                IFEND;
              ELSEIF (value^.field_values^ [i].value = NIL) OR
                    (value^.field_values^ [i].value^.kind = clc$unspecified) THEN
                IF type_description^.fields_pdt^.parameters^ [i].requirement = clc$required_field THEN
                  IF minimum_type_conformance > clc$conforms_to_generic_type THEN
                    osp$set_status_condition (cle$field_requirements_mismatch, status);
                    EXIT /check_fields/;
                  IFEND;
                IFEND;
              ELSE
                clp$evaluate_value_conformance (value^.field_values^ [i].value,
                      ^type_description^.fields_pdt^.type_descriptions^ [i], minimum_type_conformance,
                      status);
                IF NOT status.normal THEN
                  IF status.condition = cle$undefined_value THEN
                    status.normal := TRUE;
                  ELSE
                    IF status.condition = cle$wrong_kind_of_value THEN
                      status.condition := cle$field_types_dont_match;
                      osp$append_status_parameter (osc$status_parameter_delimiter, value^.field_values^ [i].
                            name, status);
                    IFEND;
                    EXIT /check_fields/;
                  IFEND;
                IFEND;
              IFEND;
            FOREND;
            FOR i := UPPERBOUND (value^.field_values^) + 1 TO type_description^.fields_pdt^.header^.
                  number_of_parameters DO
              IF type_description^.fields_pdt^.parameters^ [i].requirement = clc$required_field THEN
                IF minimum_type_conformance > clc$conforms_to_generic_type THEN
                  osp$set_status_condition (cle$field_requirements_mismatch, status);
                  EXIT /check_fields/;
                IFEND;
              IFEND;
            FOREND;
          END /check_fields/;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$scu_line_identifier_type =
      IF value^.kind <> clc$scu_line_identifier THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$statistic_code_type =
      IF value^.kind <> clc$statistic_code THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$status_type =
      IF value^.kind <> clc$status THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$status_code_type =
      IF value^.kind <> clc$status_code THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$string_type =
      IF value^.kind = clc$string THEN
        IF (minimum_type_conformance > clc$conforms_to_generic_type) AND
              NOT ((type_description^.min_string_size <= STRLENGTH (value^.string_value^)) AND
              (STRLENGTH (value^.string_value^) <= type_description^.max_string_size)) THEN
          osp$set_status_condition (cle$string_sizes_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$string_pattern_type =
      IF value^.kind <> clc$string_pattern THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$time_increment_type =
      IF value^.kind <> clc$time_increment THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$time_zone_type =
      IF value^.kind <> clc$time_zone THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$type_specification_type =
      IF value^.kind <> clc$type_specification THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;

    = clc$union_type =
      IF type_description^.member_descriptions <> NIL THEN

      /check_member/
        FOR i := 1 TO UPPERBOUND (type_description^.member_descriptions^) DO
          clp$evaluate_value_conformance (value, ^type_description^.member_descriptions^ [i],
                minimum_type_conformance, status);
          IF status.normal THEN
            RETURN;
          IFEND;
        FOREND /check_member/;
        osp$set_status_condition (cle$value_not_union_type, status);
      IFEND;
*IF $true(osv$unix)

    = clc$unix_file_type =
      IF value^.kind <> clc$unix_file THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, type_description, status);
        clp$append_status_value_type (osc$status_parameter_delimiter, value, status);
      IFEND;
*IFEND

    ELSE
      ;
    CASEND;

  PROCEND clp$evaluate_value_conformance;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$get_type_information', EJECT ??
*copy clh$get_type_information

  PROCEDURE [XDCL, #GATE] clp$get_type_information
    (    type_specification_ptr: ^clt$type_specification;
     VAR work_area {input, output} : ^clt$work_area;
     VAR type_information: clt$type_information;
     VAR status: ost$status);

    VAR
      application_type_qualifier: ^clt$application_type_qualifier,
      array_type_qualifier: ^clt$array_type_qualifier,
      date_time_type_qualifier: ^clt$date_time_type_qualifier,
      element_type_specification: ^clt$type_specification,
      field_specification: ^clt$field_specification,
      field_type_specification: ^clt$type_specification,
      header: ^clt$type_specification_header,
      i: integer,
      integer_type_qualifier: ^clt$integer_type_qualifier,
      keyword_specifications: ^clt$keyword_specifications,
      keyword_type_qualifier: ^clt$keyword_type_qualifier,
      list_type_qualifier: ^clt$list_type_qualifier_v2,
      member_type_specification_size: ^clt$type_specification_size,
      member_type_specification: ^clt$type_specification,
      name_type_qualifier: ^clt$name_type_qualifier,
      range_type_qualifier: ^clt$range_type_qualifier,
      real_type_qualifier: ^clt$real_type_qualifier,
      record_type_qualifier: ^clt$record_type_qualifier,
      string_type_qualifier: ^clt$string_type_qualifier,
      type_name: ^clt$type_name_reference,
      type_specification: ^clt$type_specification,
*IF NOT $true(osv$unix)
      union_type_qualifier: ^clt$union_type_qualifier;
*ELSE
      union_type_qualifier: ^clt$union_type_qualifier_v2;
*IFEND


    status.normal := TRUE;
    type_specification := type_specification_ptr;

  /type_specification_ok/
    BEGIN

    /work_area_ok/
      BEGIN
        IF type_specification = NIL THEN
          EXIT /type_specification_ok/;
        IFEND;
        RESET type_specification;

        NEXT header IN type_specification;
*IF NOT $true(osv$unix)
        IF (header = NIL) OR (header^.version <> clc$declaration_version) OR
*ELSE
        IF (header = NIL) OR (header^.version < 1) OR (header^.version > clc$declaration_version) OR
*IFEND
              (header^.kind < LOWERVALUE (clt$type_kind)) OR (header^.kind > UPPERVALUE (clt$type_kind)) THEN
          EXIT /type_specification_ok/;
        IFEND;
        IF header^.name_size > 0 THEN
          NEXT type_name: [header^.name_size] IN type_specification;
          IF type_name = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
        IFEND;
        type_information.kind := header^.kind;
        CASE header^.kind OF

        = clc$application_type =
          NEXT application_type_qualifier IN type_specification;
          IF application_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_information.balance_brackets := application_type_qualifier^.balance_brackets;

        = clc$array_type =
          NEXT array_type_qualifier IN type_specification;
          IF array_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          IF array_type_qualifier^.array_bounds_defined THEN
            IF (clc$min_array_bound <= array_type_qualifier^.bounds.lower) AND
                  (array_type_qualifier^.bounds.lower <= array_type_qualifier^.bounds.upper) AND
                  (array_type_qualifier^.bounds.upper <= clc$max_array_bound) THEN
              type_information.array_bounds_defined := TRUE;
              type_information.bounds.lower := array_type_qualifier^.bounds.lower;
              type_information.bounds.upper := array_type_qualifier^.bounds.upper;
            ELSE
              EXIT /type_specification_ok/;
            IFEND;
          ELSE
            type_information.array_bounds_defined := FALSE;
          IFEND;
          IF array_type_qualifier^.element_type_specification_size = 0 THEN
            type_information.array_element_type_information := NIL;
          ELSE
            NEXT element_type_specification: [[REP array_type_qualifier^.element_type_specification_size OF
                  cell]] IN type_specification;
            IF element_type_specification = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            NEXT type_information.array_element_type_information IN work_area;
            IF type_information.array_element_type_information = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            clp$get_type_information (element_type_specification, work_area,
                  type_information.array_element_type_information^, status);
            IF NOT status.normal THEN
              RESET work_area TO type_information.array_element_type_information;
              RETURN;
            IFEND;
          IFEND;

        = clc$boolean_type =
          ;

        = clc$cobol_name_type =
          ;

        = clc$command_reference_type =
          ;

        = clc$data_name_type =
          ;

        = clc$date_time_type =
          NEXT date_time_type_qualifier IN type_specification;
          IF date_time_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_information.date_and_or_time := date_time_type_qualifier^.date_and_or_time;
          type_information.tenses := date_time_type_qualifier^.tenses;

        = clc$entry_point_reference_type =
          ;

*IF NOT $true(osv$unix)
        = clc$file_type =
*ELSE
        = clc$nos_ve_file_type =
*IFEND
          ;

        = clc$integer_type =
          NEXT integer_type_qualifier IN type_specification;
          IF integer_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_information.min_integer_value := integer_type_qualifier^.min_integer_value;
          type_information.max_integer_value := integer_type_qualifier^.max_integer_value;
          type_information.default_radix := integer_type_qualifier^.default_radix;

        = clc$keyword_type =
          NEXT keyword_type_qualifier IN type_specification;
          IF (keyword_type_qualifier = NIL) OR (keyword_type_qualifier^.number_of_keywords < 1) OR
                (keyword_type_qualifier^.number_of_keywords > clc$max_keywords) THEN
            EXIT /type_specification_ok/;
          IFEND;
          NEXT keyword_specifications: [1 .. keyword_type_qualifier^.number_of_keywords] IN
                type_specification;
          IF keyword_specifications = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          NEXT type_information.keyword_specifications: [1 .. keyword_type_qualifier^.number_of_keywords] IN
                work_area;
          IF type_information.keyword_specifications = NIL THEN
            EXIT /work_area_ok/;
          IFEND;
          FOR i := 1 TO keyword_type_qualifier^.number_of_keywords DO
            type_information.keyword_specifications^ [i] := keyword_specifications^ [i];
          FOREND;

        = clc$list_type =
          NEXT list_type_qualifier IN type_specification;
          IF (list_type_qualifier = NIL) OR (list_type_qualifier^.min_list_size >
                list_type_qualifier^.max_list_size) OR (list_type_qualifier^.max_list_size >
                clc$max_list_size) THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_information.min_list_size := list_type_qualifier^.min_list_size;
          type_information.max_list_size := list_type_qualifier^.max_list_size;
          type_information.list_rest := list_type_qualifier^.list_rest;
          type_information.defer_expansion := list_type_qualifier^.defer_expansion;
          IF list_type_qualifier^.element_type_specification_size = 0 THEN
            type_information.list_element_type_information := NIL;
          ELSE
            NEXT element_type_specification: [[REP list_type_qualifier^.element_type_specification_size OF
                  cell]] IN type_specification;
            IF element_type_specification = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            NEXT type_information.list_element_type_information IN work_area;
            IF type_information.list_element_type_information = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            clp$get_type_information (element_type_specification, work_area,
                  type_information.list_element_type_information^, status);
            IF NOT status.normal THEN
              RESET work_area TO type_information.list_element_type_information;
              RETURN;
            IFEND;
          IFEND;

        = clc$lock_type =
          ;

        = clc$name_type =
          NEXT name_type_qualifier IN type_specification;
          IF (name_type_qualifier <> NIL) AND (1 <= name_type_qualifier^.min_name_size) AND
                (name_type_qualifier^.min_name_size <= name_type_qualifier^.max_name_size) AND
                (name_type_qualifier^.max_name_size <= osc$max_name_size) THEN
            type_information.min_name_size := name_type_qualifier^.min_name_size;
            type_information.max_name_size := name_type_qualifier^.max_name_size;
          ELSE
            EXIT /type_specification_ok/;
          IFEND;

        = clc$network_title_type =
          ;

        = clc$program_name_type =
          ;

        = clc$range_type =
          NEXT range_type_qualifier IN type_specification;
          IF range_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          IF range_type_qualifier^.element_type_specification_size = 0 THEN
            type_information.range_element_type_information := NIL;
          ELSE
            NEXT element_type_specification: [[REP range_type_qualifier^.element_type_specification_size OF
                  cell]] IN type_specification;
            IF element_type_specification = NIL THEN
              EXIT /type_specification_ok/;
            IFEND;
            NEXT type_information.range_element_type_information IN work_area;
            IF type_information.range_element_type_information = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            clp$get_type_information (element_type_specification, work_area,
                  type_information.range_element_type_information^, status);
            IF NOT status.normal THEN
              RESET work_area TO type_information.range_element_type_information;
              RETURN;
            IFEND;
          IFEND;

        = clc$real_type =
          NEXT real_type_qualifier IN type_specification;
          IF real_type_qualifier = NIL THEN
            EXIT /type_specification_ok/;
          IFEND;
          type_information.min_real_value := real_type_qualifier^.min_real_value.long_real;
          type_information.max_real_value := real_type_qualifier^.max_real_value.long_real;

        = clc$record_type =
          NEXT record_type_qualifier IN type_specification;
          IF (record_type_qualifier = NIL) OR (record_type_qualifier^.number_of_fields < 1) OR
                (record_type_qualifier^.number_of_fields > clc$max_fields) THEN
            EXIT /type_specification_ok/;
          IFEND;
          NEXT type_information.fields_information: [1 .. record_type_qualifier^.number_of_fields] IN
                work_area;
          IF type_information.fields_information = NIL THEN
            EXIT /work_area_ok/;
          IFEND;
          FOR i := 1 TO record_type_qualifier^.number_of_fields DO
            NEXT field_specification IN type_specification;
            IF field_specification = NIL THEN
              RESET work_area TO type_information.fields_information;
              EXIT /type_specification_ok/;
            IFEND;
            NEXT field_type_specification: [[REP field_specification^.type_specification_size OF cell]] IN
                  type_specification;
            IF field_type_specification = NIL THEN
              RESET work_area TO type_information.fields_information;
              EXIT /type_specification_ok/;
            IFEND;
            type_information.fields_information^ [i].name := field_specification^.name;
            type_information.fields_information^ [i].requirement := field_specification^.requirement;
            clp$get_type_information (field_type_specification, work_area,
                  type_information.fields_information^ [i].type_information, status);
            IF NOT status.normal THEN
              RESET work_area TO type_information.fields_information;
              RETURN;
            IFEND;
          FOREND;

        = clc$scu_line_identifier_type =
          ;

        = clc$statistic_code_type =
          ;

        = clc$status_type =
          ;

        = clc$status_code_type =
          ;

        = clc$string_type =
          NEXT string_type_qualifier IN type_specification;
          IF (string_type_qualifier <> NIL) AND (string_type_qualifier^.min_string_size <=
                string_type_qualifier^.max_string_size) AND (string_type_qualifier^.max_string_size <=
                clc$max_string_size) THEN
            type_information.min_string_size := string_type_qualifier^.min_string_size;
            type_information.max_string_size := string_type_qualifier^.max_string_size;
            type_information.literal := string_type_qualifier^.literal;
          ELSE
            EXIT /type_specification_ok/;
          IFEND;

        = clc$string_pattern_type =
          ;

        = clc$time_increment_type =
          ;

        = clc$time_zone_type =
          ;

        = clc$type_specification_type =
          ;

        = clc$union_type =
          NEXT union_type_qualifier IN type_specification;
          IF (union_type_qualifier = NIL) OR (union_type_qualifier^.number_of_members > clc$max_union_members)
                THEN
            EXIT /type_specification_ok/;
          IFEND;
          IF union_type_qualifier^.number_of_members = 0 THEN
            type_information.members_information := NIL;
          ELSE
            NEXT type_information.members_information: [1 .. union_type_qualifier^.number_of_members] IN
                  work_area;
            IF type_information.members_information = NIL THEN
              EXIT /work_area_ok/;
            IFEND;
            FOR i := 1 TO union_type_qualifier^.number_of_members DO
              NEXT member_type_specification_size IN type_specification;
              IF member_type_specification_size = NIL THEN
                RESET work_area TO type_information.members_information;
                EXIT /type_specification_ok/;
              IFEND;
              NEXT member_type_specification: [[REP member_type_specification_size^ OF cell]] IN
                    type_specification;
              IF member_type_specification = NIL THEN
                RESET work_area TO type_information.members_information;
                EXIT /type_specification_ok/;
              IFEND;
              clp$get_type_information (member_type_specification, work_area,
                    type_information.members_information^ [i], status);
              IF NOT status.normal THEN
                RESET work_area TO type_information.members_information;
                RETURN;
              IFEND;
            FOREND;
          IFEND;
*IF $true(osv$unix)

        = clc$unix_file_type =
          ;
*IFEND

        ELSE
          EXIT /type_specification_ok/;
        CASEND;
        RETURN;

      END /work_area_ok/;
      osp$set_status_abnormal ('CL', cle$work_area_overflow, 'clp$get_type_information', status);
      RETURN;

    END /type_specification_ok/;
    osp$set_status_condition (cle$bad_type_specification, status);

  PROCEND clp$get_type_information;
*IFEND
?? TITLE := 'clp$validate_type_conformance', EJECT ??

  PROCEDURE [XDCL] clp$validate_type_conformance
    (    subject_type_description: ^clt$type_description;
         target_type_description: ^clt$type_description;
     VAR type_conformance: clt$type_conformance);

    VAR
      i: integer,
      local_type_conformance: clt$type_conformance,
      max_real_order: mlt$compare,
      min_real_order: mlt$compare,
      subject_keyword: clt$keyword,
      target_keyword: clt$keyword;


    type_conformance := clc$no_conformance_to_type;

    IF (subject_type_description = NIL) OR (target_type_description = NIL) THEN
      RETURN;
    IFEND;

    CASE target_type_description^.kind OF

    = clc$application_type =
      IF subject_type_description^.kind = clc$application_type THEN
        IF (subject_type_description^.balance_brackets <> target_type_description^.balance_brackets) THEN
          type_conformance := clc$conforms_to_generic_type;
          RETURN;
        IFEND;
        IF subject_type_description^.name = NIL THEN
          IF target_type_description^.name = NIL THEN
            type_conformance := clc$identical_types;
            RETURN;
          IFEND;
        ELSEIF target_type_description^.name <> NIL THEN
          IF subject_type_description^.name^ = target_type_description^.name^ THEN
            type_conformance := clc$identical_types;
            RETURN;
          IFEND;
        IFEND;
        type_conformance := clc$conforms_to_generic_type;
      IFEND;

    = clc$array_type =
      IF subject_type_description^.kind = clc$array_type THEN
        IF target_type_description^.array_bounds_defined THEN
          IF subject_type_description^.array_bounds_defined AND
                (subject_type_description^.bounds.lower = target_type_description^.bounds.lower) AND
                (subject_type_description^.bounds.upper = target_type_description^.bounds.upper) THEN
            type_conformance := clc$identical_types;
          ELSE
            type_conformance := clc$conforms_to_generic_type;
          IFEND;
        ELSEIF subject_type_description^.array_bounds_defined THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$identical_types;
        IFEND;
        IF type_conformance >= clc$conforms_to_type THEN
          IF target_type_description^.array_element_type_description = NIL THEN
            IF subject_type_description^.array_element_type_description <> NIL THEN
              type_conformance := clc$conforms_to_generic_type;
            IFEND;
          ELSE
            clp$validate_type_conformance (subject_type_description^.array_element_type_description,
                  target_type_description^.array_element_type_description, local_type_conformance);
            IF local_type_conformance < type_conformance THEN
              type_conformance := local_type_conformance;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

    = clc$boolean_type =
      IF subject_type_description^.kind = clc$boolean_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$cobol_name_type =
      IF subject_type_description^.kind = clc$cobol_name_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$command_reference_type =
      IF subject_type_description^.kind = clc$command_reference_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$data_name_type =
      IF subject_type_description^.kind = clc$data_name_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$date_time_type =
      IF subject_type_description^.kind = clc$date_time_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$entry_point_reference_type =
      IF subject_type_description^.kind = clc$entry_point_reference_type THEN
        type_conformance := clc$identical_types;
      IFEND;

*IF NOT $true(osv$unix)
    = clc$file_type =
      IF subject_type_description^.kind = clc$file_type THEN
*ELSE
    = clc$nos_ve_file_type =
      IF subject_type_description^.kind = clc$nos_ve_file_type THEN
*IFEND
        type_conformance := clc$identical_types;
      IFEND;

    = clc$integer_type =
      IF subject_type_description^.kind = clc$integer_type THEN
        IF (subject_type_description^.min_integer_value = target_type_description^.min_integer_value) AND
              (subject_type_description^.max_integer_value = target_type_description^.max_integer_value) AND
              (subject_type_description^.default_radix = target_type_description^.default_radix) THEN
          type_conformance := clc$identical_types;
        ELSEIF (subject_type_description^.min_integer_value >= target_type_description^.min_integer_value) AND
              (subject_type_description^.max_integer_value <= target_type_description^.max_integer_value) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$keyword_type =
      IF subject_type_description^.kind = clc$keyword_type THEN
        type_conformance := clc$conforms_to_generic_type;

      /check_keyword_conformance/
        BEGIN
          IF UPPERBOUND (subject_type_description^.keyword_specifications^) <=
                UPPERBOUND (target_type_description^.keyword_specifications^) THEN

            IF UPPERBOUND (subject_type_description^.keyword_specifications^) =
                  UPPERBOUND (target_type_description^.keyword_specifications^) THEN

            /check_keyword_specifications/
              BEGIN
                FOR i := 1 TO UPPERBOUND (subject_type_description^.keyword_specifications^) DO
                  IF subject_type_description^.keyword_specifications^ [i] <>
                        target_type_description^.keyword_specifications^ [i] THEN
                    EXIT /check_keyword_specifications/;
                  IFEND;
                FOREND;
                type_conformance := clc$identical_types;
                EXIT /check_keyword_conformance/;
              END /check_keyword_specifications/;
            IFEND;
            FOR i := 1 TO UPPERBOUND (subject_type_description^.keyword_specifications^) DO
              IF subject_type_description^.keyword_specifications^ [i].class = clc$nominal_entry THEN
                subject_keyword := subject_type_description^.keyword_specifications^ [i].keyword;
              ELSE
                clp$check_keyword (subject_type_description^.keyword_specifications^ [i].keyword,
                      subject_type_description^.keyword_specifications, subject_keyword);
              IFEND;
              clp$check_keyword (subject_type_description^.keyword_specifications^ [i].keyword,
                    target_type_description^.keyword_specifications, target_keyword);
              IF subject_keyword <> target_keyword THEN
                EXIT /check_keyword_conformance/;
              IFEND;
            FOREND;
            type_conformance := clc$conforms_to_type;
          IFEND;
        END /check_keyword_conformance/;
      IFEND;

    = clc$list_type =
      IF subject_type_description^.kind = clc$list_type THEN
        IF (target_type_description^.min_list_size = subject_type_description^.min_list_size) AND
              (subject_type_description^.max_list_size = target_type_description^.max_list_size) THEN
          type_conformance := clc$identical_types;
        ELSEIF (target_type_description^.min_list_size <= subject_type_description^.min_list_size) AND
              (subject_type_description^.max_list_size <= target_type_description^.max_list_size) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
        IF type_conformance >= clc$conforms_to_type THEN
          IF target_type_description^.list_element_type_description = NIL THEN
            IF subject_type_description^.list_element_type_description = NIL THEN
              type_conformance := clc$identical_types;
            ELSE
              type_conformance := clc$conforms_to_type;
            IFEND;
          ELSE
            clp$validate_type_conformance (subject_type_description^.list_element_type_description,
                  target_type_description^.list_element_type_description, local_type_conformance);
            IF local_type_conformance < type_conformance THEN
              type_conformance := local_type_conformance;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

    = clc$lock_type =
      IF subject_type_description^.kind = clc$lock_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$name_type =
      IF subject_type_description^.kind = clc$name_type THEN
        IF (target_type_description^.min_name_size = subject_type_description^.min_name_size) AND
              (subject_type_description^.max_name_size = target_type_description^.max_name_size) THEN
          type_conformance := clc$identical_types;
        ELSEIF (target_type_description^.min_name_size <= subject_type_description^.min_name_size) AND
              (subject_type_description^.max_name_size <= target_type_description^.max_name_size) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$network_title_type =
      IF subject_type_description^.kind = clc$network_title_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$program_name_type =
      IF subject_type_description^.kind = clc$program_name_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$range_type =
      IF subject_type_description^.kind = clc$range_type THEN
        IF target_type_description^.range_element_type_description = NIL THEN
          IF subject_type_description^.range_element_type_description = NIL THEN
            type_conformance := clc$identical_types;
          ELSE
            type_conformance := clc$conforms_to_type;
          IFEND;
        ELSE
          clp$validate_type_conformance (subject_type_description^.range_element_type_description,
                target_type_description^.range_element_type_description, type_conformance);
          IF type_conformance = clc$no_conformance_to_type THEN
            type_conformance := clc$conforms_to_generic_type;
          IFEND;
        IFEND;
      IFEND;

    = clc$real_type =
      IF subject_type_description^.kind = clc$real_type THEN
*IF NOT $true(osv$unix)
        max_real_order := clp$longreal_compare (subject_type_description^.max_real_value.long_real,
              target_type_description^.max_real_value.long_real, clc$infinities_equal);
        min_real_order := clp$longreal_compare (subject_type_description^.min_real_value.long_real,
              target_type_description^.min_real_value.long_real, clc$infinities_equal);
        IF (min_real_order = clc$equal) AND (max_real_order = clc$equal) THEN
          type_conformance := clc$identical_types;
        ELSEIF (min_real_order IN $clt$comparison_results [clc$left_is_greater,
              clc$equal]) AND (max_real_order IN $clt$comparison_results [clc$right_is_greater, clc$equal])
              THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
*IFEND
      IFEND;

    = clc$record_type =
      IF subject_type_description^.kind = clc$record_type THEN
        IF subject_type_description^.fields_pdt^.header^.number_of_parameters =
              target_type_description^.fields_pdt^.header^.number_of_parameters THEN
          type_conformance := clc$identical_types;
        ELSEIF subject_type_description^.fields_pdt^.header^.number_of_parameters <=
              target_type_description^.fields_pdt^.header^.number_of_parameters THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
        IF type_conformance >= clc$conforms_to_type THEN

        /check_fields/
          FOR i := 1 TO subject_type_description^.fields_pdt^.header^.number_of_parameters DO
            IF type_conformance >= clc$conforms_to_type THEN
              IF (subject_type_description^.fields_pdt^.names^ [i].name <>
                    target_type_description^.fields_pdt^.names^ [i].name) OR
                    (subject_type_description^.fields_pdt^.parameters^ [i].requirement >
                    target_type_description^.fields_pdt^.parameters^ [i].requirement) THEN
                type_conformance := clc$conforms_to_generic_type;
              ELSEIF (type_conformance = clc$identical_types) AND
                    (subject_type_description^.fields_pdt^.parameters^ [i].requirement <>
                    target_type_description^.fields_pdt^.parameters^ [i].requirement) THEN
                type_conformance := clc$conforms_to_type;
              IFEND;
            IFEND;
            clp$validate_type_conformance (^subject_type_description^.fields_pdt^.type_descriptions^ [i],
                  ^target_type_description^.fields_pdt^.type_descriptions^ [i], local_type_conformance);
            IF local_type_conformance < type_conformance THEN
              type_conformance := local_type_conformance;
            IFEND;
            IF (type_conformance <= clc$conforms_to_generic_type) THEN
              EXIT /check_fields/;
            IFEND;
          FOREND /check_fields/;
        IFEND;
      IFEND;

    = clc$scu_line_identifier_type =
      IF subject_type_description^.kind = clc$scu_line_identifier_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$statistic_code_type =
      IF subject_type_description^.kind = clc$statistic_code_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$status_type =
      IF subject_type_description^.kind = clc$status_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$status_code_type =
      IF subject_type_description^.kind = clc$status_code_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$string_type =
      IF subject_type_description^.kind = clc$string_type THEN
        IF (target_type_description^.min_string_size = subject_type_description^.min_string_size) AND
              (subject_type_description^.max_string_size = target_type_description^.max_string_size) AND
              (target_type_description^.literal = subject_type_description^.literal) THEN
          type_conformance := clc$identical_types;
        ELSEIF (target_type_description^.min_string_size <= subject_type_description^.min_string_size) AND
              (subject_type_description^.max_string_size <= target_type_description^.max_string_size) AND
              (target_type_description^.literal <= subject_type_description^.literal) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$string_pattern_type =
      IF subject_type_description^.kind = clc$string_pattern_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$time_increment_type =
      IF subject_type_description^.kind = clc$time_increment_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$time_zone_type =
      IF subject_type_description^.kind = clc$time_zone_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$type_specification_type =
      IF subject_type_description^.kind = clc$type_specification_type THEN
        type_conformance := clc$identical_types;
      IFEND;

    = clc$union_type =
      IF subject_type_description^.kind = clc$union_type THEN
        IF target_type_description^.member_descriptions = NIL THEN
          IF subject_type_description^.member_descriptions = NIL THEN
            type_conformance := clc$identical_types;
          ELSE
            type_conformance := clc$conforms_to_type;
          IFEND;
        ELSEIF (subject_type_description^.member_descriptions = NIL) OR
              (UPPERBOUND (subject_type_description^.member_descriptions^) >
              UPPERBOUND (target_type_description^.member_descriptions^)) THEN
          type_conformance := clc$conforms_to_generic_type;
        ELSE
          IF UPPERBOUND (subject_type_description^.member_descriptions^) =
                UPPERBOUND (target_type_description^.member_descriptions^) THEN
            type_conformance := clc$identical_types;
          ELSE
            type_conformance := clc$conforms_to_type;
          IFEND;

        /check_members/
          FOR i := 1 TO UPPERBOUND (subject_type_description^.member_descriptions^) DO
            CASE type_conformance OF
            = clc$identical_types =
              clp$validate_type_conformance (^subject_type_description^.member_descriptions^ [i],
                    ^target_type_description^.member_descriptions^ [i], local_type_conformance);
              CASE local_type_conformance OF
              = clc$identical_types =
                ;
              = clc$conforms_to_type =
                type_conformance := clc$conforms_to_type;
              ELSE
                clp$validate_type_conformance (^subject_type_description^.member_descriptions^ [i],
                      target_type_description, type_conformance);
                IF type_conformance = clc$no_conformance_to_type THEN
                  type_conformance := clc$conforms_to_generic_type;
                IFEND;
              CASEND;
            = clc$conforms_to_type =
              clp$validate_type_conformance (^subject_type_description^.member_descriptions^ [i],
                    target_type_description, type_conformance);
              IF type_conformance = clc$no_conformance_to_type THEN
                type_conformance := clc$conforms_to_generic_type;
              IFEND;
            ELSE
              ;
            CASEND;
            IF (type_conformance <= clc$conforms_to_generic_type) THEN
              EXIT /check_members/;
            IFEND;
          FOREND /check_members/;
        IFEND;
      ELSEIF target_type_description^.member_descriptions = NIL THEN
        type_conformance := clc$conforms_to_type;
      ELSE
        FOR i := 1 TO UPPERBOUND (target_type_description^.member_descriptions^) DO
          clp$validate_type_conformance (subject_type_description,
                ^target_type_description^.member_descriptions^ [i], local_type_conformance);
          IF local_type_conformance > type_conformance THEN
            type_conformance := local_type_conformance;
          IFEND;
        FOREND;
      IFEND;
*IF $true(osv$unix)

    = clc$unix_file_type =
      IF subject_type_description^.kind = clc$unix_file_type THEN
        type_conformance := clc$identical_types;
      IFEND;
*IFEND

    ELSE
      ;
    CASEND;

  PROCEND clp$validate_type_conformance;
?? TITLE := 'clp$validate_value_conformance', EJECT ??

  PROCEDURE [XDCL] clp$validate_value_conformance
    (    value: ^clt$data_value;
         type_description: ^clt$type_description;
     VAR type_conformance: clt$type_conformance);

    VAR
      current_value: ^clt$data_value,
      i: integer,
      local_type_conformance: clt$type_conformance,
      result_keyword: clt$keyword;


    type_conformance := clc$no_conformance_to_type;

    IF value = NIL THEN
      RETURN;
    IFEND;

    IF type_description = NIL THEN
      type_conformance := clc$conforms_to_type;
      RETURN;
    IFEND;

    CASE type_description^.kind OF

    = clc$application_type =
      IF value^.kind = clc$application THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$array_type =
      IF value^.kind = clc$array THEN
        IF (value^.array_value <> NIL) AND ((NOT type_description^.array_bounds_defined) OR
              ((type_description^.bounds.lower = LOWERBOUND (value^.array_value^)) AND
              (type_description^.bounds.upper = UPPERBOUND (value^.array_value^)))) THEN
          type_conformance := clc$conforms_to_type;
          IF type_description^.array_element_type_description <> NIL THEN

          /check_array_elements/
            FOR i := LOWERBOUND (value^.array_value^) TO UPPERBOUND (value^.array_value^) DO
              clp$validate_value_conformance (value^.array_value^ [i],
                    type_description^.array_element_type_description, type_conformance);
              IF type_conformance <= clc$conforms_to_generic_type THEN
                type_conformance := clc$conforms_to_generic_type;
                EXIT /check_array_elements/;
              IFEND;
            FOREND /check_array_elements/;
          IFEND;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$boolean_type =
      IF value^.kind = clc$boolean THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$cobol_name_type =
      IF value^.kind = clc$cobol_name THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$command_reference_type =
      IF value^.kind = clc$command_reference THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$data_name_type =
      IF value^.kind = clc$data_name THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$date_time_type =
      IF value^.kind = clc$date_time THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$entry_point_reference_type =
      IF value^.kind = clc$entry_point_reference THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

*IF NOT $true(osv$unix)
    = clc$file_type =
      IF value^.kind = clc$file THEN
*ELSE
    = clc$nos_ve_file_type =
      IF value^.kind = clc$nos_ve_file THEN
*IFEND
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$integer_type =
      IF value^.kind = clc$integer THEN
        IF (type_description^.min_integer_value <= value^.integer_value.value) AND
              (value^.integer_value.value <= type_description^.max_integer_value) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$keyword_type =
      IF value^.kind = clc$keyword THEN
        clp$check_keyword (value^.keyword_value, type_description^.keyword_specifications, result_keyword);
        IF value^.keyword_value = result_keyword THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$list_type =
      IF value^.kind = clc$list THEN
        IF type_description^.list_element_type_description = NIL THEN
          type_conformance := clc$conforms_to_type;
        ELSE

        /check_list_elements/
          BEGIN
            i := 0;
            current_value := value;
            REPEAT
              IF current_value^.kind <> clc$list THEN
                type_conformance := clc$no_conformance_to_type;
                EXIT /check_list_elements/;
              ELSEIF current_value^.element_value = NIL THEN
                IF (i > 0) OR (current_value^.link <> NIL) THEN
                  type_conformance := clc$no_conformance_to_type;
                  EXIT /check_list_elements/;
                IFEND;
              ELSE
                i := i + 1;
                clp$validate_value_conformance (current_value^.element_value,
                      type_description^.list_element_type_description, type_conformance);
                IF type_conformance <= clc$conforms_to_generic_type THEN
                  EXIT /check_list_elements/;
                IFEND;
              IFEND;
              current_value := current_value^.link;
            UNTIL current_value = NIL {/check_list_elements/} ;
            IF (type_description^.min_list_size <= i) AND (i <= type_description^.max_list_size) THEN
              type_conformance := clc$conforms_to_type;
            ELSE
              type_conformance := clc$conforms_to_generic_type;
            IFEND;
          END /check_list_elements/;
        IFEND;
      IFEND;

    = clc$lock_type =
      IF value^.kind = clc$lock THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$name_type =
      IF value^.kind = clc$name THEN
        i := clp$trimmed_string_size (value^.name_value);
        IF (type_description^.min_name_size <= i) AND (i <= type_description^.max_name_size) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$network_title_type =
      IF value^.kind = clc$network_title THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$program_name_type =
      IF value^.kind = clc$program_name THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$range_type =
      IF value^.kind = clc$range THEN
        IF type_description^.range_element_type_description = NIL THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          clp$validate_value_conformance (value^.low_value, type_description^.range_element_type_description,
                type_conformance);
          IF (type_conformance = clc$conforms_to_type) AND (value^.high_value <> value^.low_value) THEN
            clp$validate_value_conformance (value^.high_value,
                  type_description^.range_element_type_description, type_conformance);
          IFEND;
          IF type_conformance = clc$no_conformance_to_type THEN
            type_conformance := clc$conforms_to_generic_type;
          IFEND;
        IFEND;
      IFEND;

    = clc$real_type =
*IF NOT $true(osv$unix)
      IF value^.kind = clc$real THEN
        IF clp$longreal_compare_le (type_description^.min_real_value.long_real,
              value^.real_value.value) AND clp$longreal_compare_le
              (value^.real_value.value, type_description^.max_real_value.long_real) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;
*IFEND


    = clc$record_type =
      IF value^.kind = clc$record THEN
        IF (value^.field_values = NIL) OR (UPPERBOUND (value^.field_values^) >
              type_description^.fields_pdt^.header^.number_of_parameters) THEN
          type_conformance := clc$conforms_to_generic_type;
        ELSE

        /check_fields/
          BEGIN
            FOR i := 1 TO UPPERBOUND (value^.field_values^) DO
              IF type_description^.fields_pdt^.names^ [i].name <> value^.field_values^ [i].name THEN
                type_conformance := clc$conforms_to_generic_type;
                EXIT /check_fields/;
              ELSEIF (value^.field_values^ [i].value = NIL) OR
                    (value^.field_values^ [i].value^.kind = clc$unspecified) THEN
                IF type_description^.fields_pdt^.parameters^ [i].requirement = clc$required_field THEN
                  type_conformance := clc$conforms_to_generic_type;
                  EXIT /check_fields/;
                IFEND;
              ELSE
                clp$validate_value_conformance (value^.field_values^ [i].value,
                      ^type_description^.fields_pdt^.type_descriptions^ [i], type_conformance);
                IF type_conformance <= clc$conforms_to_generic_type THEN
                  type_conformance := clc$conforms_to_generic_type;
                  EXIT /check_fields/;
                IFEND;
              IFEND;
            FOREND;
            FOR i := UPPERBOUND (value^.field_values^) + 1 TO type_description^.fields_pdt^.header^.
                  number_of_parameters DO
              IF type_description^.fields_pdt^.parameters^ [i].requirement = clc$required_field THEN
                type_conformance := clc$conforms_to_generic_type;
                EXIT /check_fields/;
              IFEND;
            FOREND;
          END /check_fields/;
        IFEND;
      IFEND;

    = clc$scu_line_identifier_type =
      IF value^.kind = clc$scu_line_identifier THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$statistic_code_type =
      IF value^.kind = clc$statistic_code THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$status_type =
      IF value^.kind = clc$status THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$status_code_type =
      IF value^.kind = clc$status_code THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$string_type =
      IF value^.kind = clc$string THEN
        IF (type_description^.min_string_size <= STRLENGTH (value^.string_value^)) AND
              (STRLENGTH (value^.string_value^) <= type_description^.max_string_size) THEN
          type_conformance := clc$conforms_to_type;
        ELSE
          type_conformance := clc$conforms_to_generic_type;
        IFEND;
      IFEND;

    = clc$string_pattern_type =
      IF value^.kind = clc$string_pattern THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$time_increment_type =
      IF value^.kind = clc$time_increment THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$time_zone_type =
      IF value^.kind = clc$time_zone THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$type_specification_type =
      IF value^.kind = clc$type_specification THEN
        type_conformance := clc$conforms_to_type;
      IFEND;

    = clc$union_type =
      IF type_description^.member_descriptions = NIL THEN
        type_conformance := clc$conforms_to_type;
      ELSE

      /check_member/
        FOR i := 1 TO UPPERBOUND (type_description^.member_descriptions^) DO
          clp$validate_value_conformance (value, ^type_description^.member_descriptions^ [i],
                local_type_conformance);
          IF local_type_conformance > type_conformance THEN
            type_conformance := local_type_conformance;
          IFEND;
          IF type_conformance = clc$conforms_to_type THEN
            EXIT /check_member/;
          IFEND;
        FOREND /check_member/;
      IFEND;
*IF $true(osv$unix)

    = clc$unix_file_type =
      IF value^.kind = clc$unix_file THEN
        type_conformance := clc$conforms_to_type;
      IFEND;
*IFEND

    ELSE
      ;
    CASEND;

  PROCEND clp$validate_value_conformance;
*IF NOT $true(osv$unix)
?? TITLE := 'clp$validate_var_conformance', EJECT ??

  PROCEDURE [XDCL] clp$validate_var_conformance
    (    subject_type_description: ^clt$type_description;
         target_type_description: ^clt$type_description;
     VAR status: ost$status);

    VAR
      i: integer;


    status.normal := TRUE;

    IF (subject_type_description = NIL) OR (target_type_description = NIL) THEN
      osp$set_status_condition (cle$undefined_type, status);
      RETURN;
    IFEND;

    CASE target_type_description^.kind OF

    = clc$application_type =
      IF (subject_type_description^.kind = clc$application_type) THEN
        IF (subject_type_description^.balance_brackets <> target_type_description^.balance_brackets) THEN
          osp$set_status_condition (cle$balance_brackets_dont_match, status);
          RETURN;
        IFEND;
        IF subject_type_description^.name = NIL THEN
          IF target_type_description^.name = NIL THEN
            RETURN;
          IFEND;
        ELSEIF target_type_description^.name <> NIL THEN
          IF subject_type_description^.name^ = target_type_description^.name^ THEN
            RETURN;
          IFEND;
        IFEND;
        osp$set_status_condition (cle$application_name_mismatch, status);
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$array_type =
      IF subject_type_description^.kind = clc$array_type THEN
        IF target_type_description^.array_bounds_defined THEN
          IF NOT subject_type_description^.array_bounds_defined OR
                (subject_type_description^.bounds.lower <> target_type_description^.bounds.lower) OR
                (subject_type_description^.bounds.upper <> target_type_description^.bounds.upper) THEN
            osp$set_status_condition (cle$array_bounds_dont_match, status);
          IFEND;
        ELSEIF (target_type_description^.array_element_type_description <> NIL) THEN
          clp$validate_var_conformance (subject_type_description^.array_element_type_description,
                target_type_description^.array_element_type_description, status);
          IF NOT status.normal AND (status.condition = cle$wrong_kind_of_value) THEN
            status.condition := cle$wrong_kind_of_element_type;
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$boolean_type =
      IF subject_type_description^.kind <> clc$boolean_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$cobol_name_type =
      IF subject_type_description^.kind <> clc$cobol_name_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$command_reference_type =
      IF subject_type_description^.kind <> clc$command_reference_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$data_name_type =
      IF subject_type_description^.kind <> clc$data_name_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$date_time_type =
      IF (subject_type_description^.kind = clc$date_time_type) THEN
        IF (subject_type_description^.date_and_or_time = target_type_description^.date_and_or_time) THEN
          IF (subject_type_description^.tenses <> target_type_description^.tenses) THEN
            osp$set_status_condition (cle$date_time_tenses_dont_match, status);
          IFEND;
        ELSE
          osp$set_status_condition (cle$date_time_types_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$entry_point_reference_type =
      IF subject_type_description^.kind <> clc$entry_point_reference_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

*IF NOT $true(osv$unix)
    = clc$file_type =
      IF subject_type_description^.kind <> clc$file_type THEN
*ELSE
    = clc$nos_ve_file_type =
      IF subject_type_description^.kind <> clc$nos_ve_file_type THEN
*IFEND
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$integer_type =
      IF (subject_type_description^.kind = clc$integer_type) THEN
        IF (target_type_description^.min_integer_value <> subject_type_description^.min_integer_value) OR
              (subject_type_description^.max_integer_value <> target_type_description^.max_integer_value) THEN
          osp$set_status_condition (cle$integer_ranges_dont_match, status);
        ELSEIF (subject_type_description^.default_radix <> target_type_description^.default_radix) THEN
          osp$set_status_condition (cle$integer_radices_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$keyword_type =
      IF (subject_type_description^.kind = clc$keyword_type) THEN
        IF (UPPERBOUND (subject_type_description^.keyword_specifications^) =
              UPPERBOUND (target_type_description^.keyword_specifications^)) THEN

        /check_keywords/
          BEGIN
            FOR i := 1 TO UPPERBOUND (subject_type_description^.keyword_specifications^) DO
              IF subject_type_description^.keyword_specifications^ [i] <>
                    target_type_description^.keyword_specifications^ [i] THEN
                osp$set_status_condition (cle$keywords_dont_match, status);
                EXIT /check_keywords/;
              IFEND;
            FOREND;
          END /check_keywords/;
        ELSE
          osp$set_status_condition (cle$keywords_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$list_type =
      IF (subject_type_description^.kind = clc$list_type) THEN
        IF (target_type_description^.min_list_size = subject_type_description^.min_list_size) AND
              ((target_type_description^.max_list_size = clc$max_list_size) OR
              (subject_type_description^.max_list_size = target_type_description^.max_list_size)) THEN
          IF (subject_type_description^.list_rest = target_type_description^.list_rest) THEN
            IF (NOT subject_type_description^.defer_expansion) OR
                  target_type_description^.defer_expansion THEN
              IF target_type_description^.list_element_type_description <> NIL THEN
                clp$validate_var_conformance (subject_type_description^.list_element_type_description,
                      target_type_description^.list_element_type_description, status);
                IF NOT status.normal AND (status.condition = cle$wrong_kind_of_value) THEN
                  status.condition := cle$wrong_kind_of_element_type;
                IFEND;
              IFEND;
            ELSE
              osp$set_status_condition (cle$defer_expans_doesnt_match, status);
            IFEND;
          ELSE
            osp$set_status_condition (cle$list_rest_doesnt_match, status);
          IFEND;
        ELSE
          osp$set_status_condition (cle$list_sizes_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$lock_type =
      IF subject_type_description^.kind <> clc$lock_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$name_type =
      IF (subject_type_description^.kind = clc$name_type) THEN
        IF (target_type_description^.min_name_size <> subject_type_description^.min_name_size) OR
              (subject_type_description^.max_name_size <> target_type_description^.max_name_size) THEN
          osp$set_status_condition (cle$name_sizes_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$network_title_type =
      IF subject_type_description^.kind <> clc$network_title_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$program_name_type =
      IF subject_type_description^.kind <> clc$program_name_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$range_type =
      IF subject_type_description^.kind = clc$range_type THEN
        IF target_type_description^.range_element_type_description <> NIL THEN
          clp$validate_var_conformance (subject_type_description^.range_element_type_description,
                target_type_description^.range_element_type_description, status);
          IF NOT status.normal AND (status.condition = cle$wrong_kind_of_value) THEN
            status.condition := cle$range_types_dont_match;
          IFEND;
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$real_type =
      IF (subject_type_description^.kind = clc$real_type) THEN
        IF NOT (clp$longreal_compare_eq (target_type_description^.min_real_value.long_real,
              subject_type_description^.min_real_value.long_real) AND
              clp$longreal_compare_eq (subject_type_description^.max_real_value.long_real,
              target_type_description^.max_real_value.long_real)) THEN
          osp$set_status_condition (cle$real_subranges_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$record_type =
      IF (subject_type_description^.kind = clc$record_type) THEN
        IF (subject_type_description^.fields_pdt^.header^.number_of_parameters =
              target_type_description^.fields_pdt^.header^.number_of_parameters) THEN

        /check_fields/
          FOR i := 1 TO subject_type_description^.fields_pdt^.header^.number_of_parameters DO
            IF (subject_type_description^.fields_pdt^.names^ [i].name <>
                  target_type_description^.fields_pdt^.names^ [i].name) THEN
              osp$set_status_condition (cle$field_names_dont_match, status);
            ELSEIF (subject_type_description^.fields_pdt^.parameters^ [i].requirement <>
                  target_type_description^.fields_pdt^.parameters^ [i].requirement) THEN
              osp$set_status_condition (cle$field_requirements_mismatch, status);
              EXIT /check_fields/;
            IFEND;
            clp$validate_var_conformance (^subject_type_description^.fields_pdt^.type_descriptions^ [i],
                  ^target_type_description^.fields_pdt^.type_descriptions^ [i], status);
            IF NOT status.normal THEN
              IF (status.condition = cle$wrong_kind_of_value) THEN
                status.condition := cle$field_types_dont_match;
                osp$append_status_parameter (osc$status_parameter_delimiter,
                      subject_type_description^.fields_pdt^.names^ [i].name, status);
              IFEND;
              EXIT /check_fields/;
            IFEND;
          FOREND /check_fields/;
        ELSE
          osp$set_status_condition (cle$number_of_fields_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$scu_line_identifier_type =
      IF subject_type_description^.kind <> clc$scu_line_identifier_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$statistic_code_type =
      IF subject_type_description^.kind <> clc$statistic_code_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$status_type =
      IF subject_type_description^.kind <> clc$status_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$status_code_type =
      IF subject_type_description^.kind <> clc$status_code_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$string_type =
      IF (subject_type_description^.kind = clc$string_type) THEN
        IF NOT ((target_type_description^.min_string_size <= subject_type_description^.min_string_size) AND
              (subject_type_description^.max_string_size <= target_type_description^.max_string_size)) THEN
          osp$set_status_condition (cle$string_sizes_dont_match, status);
        ELSEIF (subject_type_description^.literal <> target_type_description^.literal) THEN
          osp$set_status_condition (cle$string_literals_dont_match, status);
        IFEND;
      ELSE
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$string_pattern_type =
      IF subject_type_description^.kind <> clc$string_pattern_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$time_increment_type =
      IF subject_type_description^.kind <> clc$time_increment_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$time_zone_type =
      IF subject_type_description^.kind <> clc$time_zone_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$type_specification_type =
      IF subject_type_description^.kind <> clc$type_specification_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;

    = clc$union_type =
      IF subject_type_description^.kind = clc$union_type THEN
        IF target_type_description^.member_descriptions <> NIL THEN
          IF (subject_type_description^.member_descriptions <> NIL) AND
                (UPPERBOUND (subject_type_description^.member_descriptions^) =
                UPPERBOUND (target_type_description^.member_descriptions^)) THEN

          /check_members_conform/
            FOR i := 1 TO UPPERBOUND (subject_type_description^.member_descriptions^) DO
              clp$validate_var_conformance (^subject_type_description^.member_descriptions^ [i],
                    ^target_type_description^.member_descriptions^ [i], status);
              IF NOT status.normal THEN

{ This routine assumes that its caller will insert the text into the status record for this particular
{ condition.

                osp$set_status_condition (cle$variable_not_union_type, status);
                EXIT /check_members_conform/;
              IFEND;
            FOREND /check_members_conform/;
          ELSE

{ This routine assumes that its caller will insert the text into the status record for this particular
{ condition.

            osp$set_status_condition (cle$variable_not_union_type, status);
          IFEND;
        IFEND;

      ELSEIF target_type_description^.member_descriptions <> NIL THEN

        FOR i := 1 TO UPPERBOUND (target_type_description^.member_descriptions^) DO
          clp$validate_var_conformance (subject_type_description,
                ^target_type_description^.member_descriptions^ [i], status);
          IF status.normal THEN
            RETURN;
          IFEND;
        FOREND;

{ This routine assumes that its caller will insert the text into the status record for this particular
{ condition.

        osp$set_status_condition (cle$variable_not_union_type, status);
      IFEND;
*IF $true(osv$unix)

    = clc$unix_file_type =
      IF subject_type_description^.kind <> clc$unix_file_type THEN
        osp$set_status_condition (cle$wrong_kind_of_value, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, target_type_description, status);
        clp$append_status_type_desc (osc$status_parameter_delimiter, subject_type_description, status);
      IFEND;
*IFEND

    ELSE
      ;
    CASEND;

  PROCEND clp$validate_var_conformance;
*IFEND

MODEND clm$process_data_types;
