?? NEWTITLE := 'NOS/VE Basic Access Method : Validate Attributes' ??
MODULE fsm$validate_attributes;
?? RIGHT := 110 ??

?? NEWTITLE := 'Global Declarations', EJECT ??

?? PUSH (LISTEXT := ON) ??
*copyc oss$job_paged_literal
*copyc ame$attribute_validation_errors
*copyc ame$ring_validation_errors
*copyc fst$file_cycle_attributes
*copyc fst$status_reporting_procedure
?? POP ??
*copyc clp$convert_integer_to_string
*copyc clp$convert_string_to_file_ref
*copyc clp$only_validate_name
*copyc clp$verify_time_increment
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc pmp$compute_date_time
*copyc pmp$get_compact_date_time
*copyc pmp$verify_compact_date
*copyc pmp$verify_compact_time

?? TITLE := '[XDCL] fsv$attribute_names', EJECT ??

  VAR
    fsv$attribute_names: [XDCL, READ, oss$job_paged_literal] ^array [1 .. * ] of ost$name :=
          ^fs_attribute_names,

    fs_attribute_names: [STATIC, READ, oss$job_paged_literal] array [1 .. 53] of ost$name := [

{fsc$average_record_length ..... = 001} 'AVERAGE_RECORD_LENGTH          ',
{fsc$block_type ................ = 002} 'BLOCK_TYPE                     ',
{fsc$character_conversion ...... = 003} 'CHARACTER_CONVERSION           ',
{fsc$collate_table_name ........ = 004} 'COLLATE_TABLE_NAME             ',
{fsc$compression_procedure_name  = 005} 'COMPRESSION_PROCEDURE_NAME     ',
{fsc$data_padding .............. = 006} 'DATA_PADDING                   ',
{fsc$dynamic_home_block_space .. = 007} 'DYNAMIC_HOME_BLOCK_SPACE       ',
{fsc$embedded_key .............. = 008} 'EMBEDDED_KEY                   ',
{fsc$erase_at_deletion ......... = 009} 'ERASE_AT_DELETION              ',
{fsc$estimated_record_count .... = 010} 'ESTIMATED_RECORD_COUNT         ',
{fsc$file_access_procedure_name. = 011} 'FILE_ACCESS_PROCEDURE_NAME     ',
{fsc$file_contents_and_processor = 012} 'FILE_CONTENTS_AND_PROCESSOR    ',
{fsc$file_label_type ........... = 013} 'FILE_LABEL_TYPE                ',
{fsc$file_limit ................ = 014} 'FILE_LIMIT                     ',
{fsc$file_organization ......... = 015} 'FILE_ORGANIZATION              ',
{fsc$forced_write .............. = 016} 'FORCED_WRITE                   ',
{fsc$hashing_procedure_name .... = 017} 'HASHING_PROCEDURE_NAME         ',
{fsc$index_levels .............. = 018} 'INDEX_LEVELS                   ',
{fsc$index_padding ............. = 019} 'INDEX_PADDING                  ',
{fsc$initial_home_block_count .. = 020} 'INITIAL_HOME_BLOCK_COUNT       ',
{fsc$internal_code ............. = 021} 'INTERNAL_CODE                  ',
{fsc$key_length ................ = 022} 'KEY_LENGTH                     ',
{fsc$key_position .............. = 023} 'KEY_POSITION                   ',
{fsc$key_type .................. = 024} 'KEY_TYPE                       ',
{fsc$line_number ............... = 025} 'LINE_NUMBER                    ',
{fsc$loading_factor ............ = 026} 'LOADING_FACTOR                 ',
{fsc$lock_expiration_time ...... = 027} 'LOCK_EXPIRATION_TIME           ',
{fsc$logging_options ........... = 028} 'LOGGING_OPTIONS                ',
{fsc$log_residence ............. = 029} 'LOG_RESIDENCE                  ',
{fsc$max_block_length .......... = 030} 'MAX_BLOCK_LENGTH               ',
{fsc$max_record_length ......... = 031} 'MAX_RECORD_LENGTH              ',
{fsc$min_block_length .......... = 032} 'MIN_BLOCK_LENGTH               ',
{fsc$min_record_length ......... = 033} 'MIN_RECORD_LENGTH              ',
{fsc$null_attribute ............ = 034} 'NULL_ATTRIBUTE                 ',
{fsc$padding_character ......... = 035} 'PADDING_CHARACTER              ',
{fsc$page_format ............... = 036} 'PAGE_FORMAT                    ',
{fsc$page_length ............... = 037} 'PAGE_LENGTH                    ',
{fsc$page_width ................ = 038} 'PAGE_WIDTH                     ',
{fsc$preset_value .............. = 039} 'PRESET_VALUE                   ',
{fsc$record_delimiting_character = 041} 'RECORD_DELIMITING_CHARACTER    ',
{fsc$record_limit .............. = 040} 'RECORD_LIMIT                   ',
{fsc$record_type ............... = 042} 'RECORD_TYPE                    ',
{fsc$records_per_block ......... = 043} 'RECORDS_PER_BLOCK              ',
{fsc$ring_attributes ........... = 044} 'RING_ATTRIBUTES                ',
{fsc$statement_identifier ...... = 045} 'STATEMENT_IDENTIFIER           ',
{fsc$user_attributes ........... = 046} 'USER_ATTRIBUTES                ',
{fsc$vertical_print_density .... = 047} 'VERTICAL_PRINT_DENSITY         ',
{fsc$user_information .......... = 048} 'USER_INFORMATION               ',
{fsc$retention ................. = 049} 'RETENTION                      ',
{fsc$retreive_option ........... = 050} 'RETRIEVE_OPTION                ',
{fsc$site_backup_option ........ = 051} 'SITE_BACKUP_OPTION             ',
{fsc$site_archive_option ....... = 052} 'SITE_ARCHIVE_OPTION            ',
{fsc$site_release_option ....... = 053} 'SITE_RELEASE_OPTION            '];

  PROCEDURE [INLINE] validate_file_contents
    (    potential_name: amt$file_contents;
     VAR name_is_valid: boolean);

    TYPE
      char_set = set of char;

    VAR
      ignore_scan_found_char: boolean,
      non_name_chars: char_set,
      scan_index: 1 .. osc$max_name_size + 1,
      scan_after_mark_index: 1 .. osc$max_name_size + 1;

    CASE potential_name (1) OF
    = '#', '$', '@', 'A' .. 'Z', 'a' .. 'z', '[', '\', ']', '^', '_', '`', '{', '|', '}', '~' =
      non_name_chars := -$char_set ['#', '$', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '@', 'A', 'B',
            'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
            'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
            'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\', ']', '^', '_', '`', '{',
            '|', '}', '~'];
      #SCAN (non_name_chars, potential_name, scan_index, ignore_scan_found_char);
      IF (scan_index < STRLENGTH (potential_name)) AND (potential_name (scan_index, 1) = $CHAR (200)) THEN
        #SCAN (non_name_chars, potential_name ((scan_index + 1), * ), scan_after_mark_index,
              ignore_scan_found_char);
        IF scan_after_mark_index > 1 THEN
          scan_index := scan_index + scan_after_mark_index;
        IFEND;
      IFEND;
      name_is_valid := potential_name (scan_index, * ) = '';
    ELSE
      name_is_valid := FALSE;
    CASEND;

  PROCEND validate_file_contents;
*copyc osv$lower_to_upper
*copyc amt$file_contents
*copyc ost$name

?? TITLE := '[XDCL] fsp$validate_attributes', EJECT ??

  PROCEDURE [XDCL] fsp$validate_attributes
    (    attributes: ^fst$file_cycle_attributes;
         status_text: string ( * );
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      fsv$logging_options: [STATIC, READ, oss$job_paged_literal] amt$logging_options :=
            [amc$enable_parcels, amc$enable_media_recovery, amc$enable_request_recovery];

    VAR
      attribute_p: ^fst$file_cycle_attribute,
      attribute_key_is_good: boolean,
      attribute_value_is_good: boolean,
      date_time: ost$date_time,
      expiration_date: ost$date_time,
      i: integer,
      ignore_file: fst$parsed_file_reference,
      ignore_status: ost$status;

    status.normal := TRUE;
    IF attributes = NIL THEN
      RETURN; {----->
    IFEND;

    FOR i := 1 TO UPPERBOUND (attributes^) DO
      attribute_key_is_good := TRUE;
      attribute_value_is_good := TRUE;
      attribute_p := ^attributes^ [i];

      CASE attribute_p^.selector OF
      = fsc$average_record_length =
        attribute_value_is_good := (attribute_p^.average_record_length >=
              LOWERVALUE (amt$average_record_length)) AND (attribute_p^.average_record_length <=
              UPPERVALUE (amt$average_record_length));
      = fsc$block_type =
        attribute_value_is_good := (attribute_p^.block_type >= LOWERVALUE (amt$block_type)) AND
              (attribute_p^.block_type <= UPPERVALUE (amt$block_type));
      = fsc$character_conversion =
        attribute_value_is_good := (attribute_p^.character_conversion >= LOWERVALUE (boolean)) AND
              (attribute_p^.character_conversion <= UPPERVALUE (boolean));
      = fsc$collate_table_name =
        IF attribute_p^.collate_table_name <> NIL THEN
          IF attribute_p^.collate_table_name^.entry_point <> osc$null_name THEN
            clp$only_validate_name (attribute_p^.collate_table_name^.entry_point, attribute_value_is_good);
            IF attribute_p^.collate_table_name^.object_library <> osc$null_name THEN
              clp$convert_string_to_file_ref (attribute_p^.collate_table_name^.object_library, ignore_file,
                    status);
              attribute_value_is_good := status.normal;
            IFEND;
          IFEND;
        ELSE
          attribute_value_is_good := FALSE;
        IFEND;
      = fsc$compression_procedure_name =
        IF attribute_p^.compression_procedure_name <> NIL THEN
          IF attribute_p^.compression_procedure_name^.name <> osc$null_name THEN
            clp$only_validate_name (attribute_p^.compression_procedure_name^.name, attribute_value_is_good);
            IF attribute_p^.compression_procedure_name^.object_library <> osc$null_name THEN
              clp$convert_string_to_file_ref (attribute_p^.compression_procedure_name^.object_library,
                    ignore_file, status);
              attribute_value_is_good := status.normal;
            IFEND;
          IFEND;
        ELSE
          attribute_value_is_good := FALSE;
        IFEND;
      = fsc$data_padding =
        attribute_value_is_good := (attribute_p^.data_padding >= LOWERVALUE (amt$data_padding)) AND
              (attribute_p^.data_padding <= UPPERVALUE (amt$data_padding));
      = fsc$dynamic_home_block_space =
        attribute_value_is_good := (attribute_p^.dynamic_home_block_space >= LOWERVALUE (boolean)) AND
              (attribute_p^.dynamic_home_block_space <= UPPERVALUE (boolean));
      = fsc$embedded_key =
        attribute_value_is_good := (attribute_p^.embedded_key >= LOWERVALUE (boolean)) AND
              (attribute_p^.embedded_key <= UPPERVALUE (boolean));
      = fsc$erase_at_deletion =
        attribute_value_is_good := (attribute_p^.erase_at_deletion >= LOWERVALUE (boolean)) AND
              (attribute_p^.erase_at_deletion <= UPPERVALUE (boolean));
      = fsc$estimated_record_count =
        ;
      = fsc$file_access_procedure_name =
        IF attribute_p^.file_access_procedure_name <> NIL THEN
          IF attribute_p^.file_access_procedure_name^.entry_point <> osc$null_name THEN
            clp$only_validate_name (attribute_p^.file_access_procedure_name^.entry_point,
                  attribute_value_is_good);
            IF attribute_p^.file_access_procedure_name^.object_library <> osc$null_name THEN
              clp$convert_string_to_file_ref (attribute_p^.file_access_procedure_name^.object_library,
                    ignore_file, status);
              attribute_value_is_good := status.normal;
            IFEND;
          IFEND;
        ELSE
          attribute_value_is_good := FALSE;
        IFEND;
      = fsc$file_contents_and_processor =
        IF attribute_p^.file_contents <> osc$null_name THEN
          validate_file_contents (attribute_p^.file_contents, attribute_value_is_good);
        IFEND;
        IF attribute_p^.file_processor <> osc$null_name THEN
          clp$only_validate_name (attribute_p^.file_processor, attribute_value_is_good);
        IFEND;
      = fsc$file_label_type =
        attribute_value_is_good := (attribute_p^.file_label_type >= LOWERVALUE (amt$file_label_type)) AND
              (attribute_p^.file_label_type <= UPPERVALUE (amt$file_label_type));
      = fsc$file_limit =
        attribute_value_is_good := (attribute_p^.file_limit >= LOWERVALUE (amt$file_limit)) AND
              (attribute_p^.file_limit <= UPPERVALUE (amt$file_limit));
      = fsc$file_organization =
        attribute_value_is_good := (attribute_p^.file_organization >= LOWERVALUE (amt$file_organization)) AND
              (attribute_p^.file_organization <= UPPERVALUE (amt$file_organization));
      = fsc$forced_write =
        attribute_value_is_good := (attribute_p^.forced_write >= LOWERVALUE (amt$forced_write)) AND
              (attribute_p^.forced_write <= UPPERVALUE (amt$forced_write));
      = fsc$hashing_procedure_name =
        IF attribute_p^.hashing_procedure_name <> NIL THEN
          IF attribute_p^.hashing_procedure_name^.name <> osc$null_name THEN
            clp$only_validate_name (attribute_p^.hashing_procedure_name^.name, attribute_value_is_good);
            IF attribute_p^.hashing_procedure_name^.object_library <> osc$null_name THEN
              clp$convert_string_to_file_ref (attribute_p^.hashing_procedure_name^.object_library,
                    ignore_file, status);
              attribute_value_is_good := status.normal;
            IFEND;
          IFEND;
        ELSE
          attribute_value_is_good := FALSE;
        IFEND;
      = fsc$index_levels =
        attribute_value_is_good := (attribute_p^.index_levels >= LOWERVALUE (amt$index_levels)) AND
              (attribute_p^.index_levels <= UPPERVALUE (amt$index_levels));
      = fsc$index_padding =
        attribute_value_is_good := (attribute_p^.index_padding >= LOWERVALUE (amt$index_padding)) AND
              (attribute_p^.index_padding <= UPPERVALUE (amt$index_padding));
      = fsc$initial_home_block_count =
        attribute_value_is_good := (attribute_p^.initial_home_block_count >=
              LOWERVALUE (amt$initial_home_block_count)) AND (attribute_p^.
              initial_home_block_count <= UPPERVALUE (amt$initial_home_block_count));
      = fsc$internal_code =
        attribute_value_is_good := (attribute_p^.internal_code >= LOWERVALUE (amt$internal_code)) AND
              (attribute_p^.internal_code <= UPPERVALUE (amt$internal_code));
      = fsc$key_length =
        attribute_value_is_good := (attribute_p^.key_length >= LOWERVALUE (amt$key_length)) AND
              (attribute_p^.key_length <= UPPERVALUE (amt$key_length));
      = fsc$key_position =
        attribute_value_is_good := (attribute_p^.key_position >= LOWERVALUE (amt$key_position)) AND
              (attribute_p^.key_position <= UPPERVALUE (amt$key_position));
      = fsc$key_type =
        attribute_value_is_good := (attribute_p^.key_type >= LOWERVALUE (amt$key_type)) AND
              (attribute_p^.key_type <= UPPERVALUE (amt$key_type));
      = fsc$line_number =
        attribute_value_is_good := (attribute_p^.line_number.length >=
              LOWERVALUE (amt$line_number_length)) AND (attribute_p^.line_number.length <=
              UPPERVALUE (amt$line_number_length)) AND (attribute_p^.line_number.location >=
              LOWERVALUE (amt$line_number_location)) AND (attribute_p^.line_number.location <=
              UPPERVALUE (amt$line_number_location));
      = fsc$loading_factor =
        attribute_value_is_good := (attribute_p^.loading_factor >= LOWERVALUE (amt$loading_factor)) AND
              (attribute_p^.loading_factor <= UPPERVALUE (amt$loading_factor));
      = fsc$lock_expiration_time =
        attribute_value_is_good := (attribute_p^.lock_expiration_time >=
              LOWERVALUE (amt$lock_expiration_time)) AND (attribute_p^.lock_expiration_time <=
              UPPERVALUE (amt$lock_expiration_time));
      = fsc$log_residence =
        IF attribute_p^.log_residence <> NIL THEN
          IF attribute_p^.log_residence^ <> osc$null_name THEN
            clp$convert_string_to_file_ref (attribute_p^.log_residence^, ignore_file, status);
            attribute_value_is_good := status.normal;
          IFEND;
        ELSE
          attribute_value_is_good := FALSE;
        IFEND;
      = fsc$logging_options =
        attribute_value_is_good := (attribute_p^.logging_options <= fsv$logging_options);
      = fsc$max_block_length =
        attribute_value_is_good := (attribute_p^.max_block_length >= LOWERVALUE (amt$max_block_length)) AND
              (attribute_p^.max_block_length <= UPPERVALUE (amt$max_block_length));
      = fsc$max_record_length =
        attribute_value_is_good := (attribute_p^.max_record_length >= LOWERVALUE (amt$max_record_length)) AND
              (attribute_p^.max_record_length <= UPPERVALUE (amt$max_record_length));
      = fsc$min_block_length =
        attribute_value_is_good := (attribute_p^.min_block_length >= LOWERVALUE (amt$min_block_length)) AND
              (attribute_p^.min_block_length <= UPPERVALUE (amt$min_block_length));
      = fsc$min_record_length =
        attribute_value_is_good := (attribute_p^.min_record_length >= LOWERVALUE (amt$min_record_length)) AND
              (attribute_p^.min_record_length <= UPPERVALUE (amt$min_record_length));
      = fsc$null_attribute =
        ;
      = fsc$padding_character =
        ;
      = fsc$page_format =
        attribute_value_is_good := (attribute_p^.page_format >= LOWERVALUE (amt$page_format)) AND
              (attribute_p^.page_format <= UPPERVALUE (amt$page_format));
      = fsc$page_length =
        attribute_value_is_good := (attribute_p^.page_length >= LOWERVALUE (amt$page_length)) AND
              (attribute_p^.page_length <= UPPERVALUE (amt$page_length));
      = fsc$page_width =
        attribute_value_is_good := (attribute_p^.page_width >= LOWERVALUE (amt$page_width)) AND
              (attribute_p^.page_width <= UPPERVALUE (amt$page_width));
      = fsc$preset_value =
        ;
      = fsc$record_delimiting_character =
        ;
      = fsc$record_limit =
        attribute_value_is_good := (attribute_p^.record_limit >= LOWERVALUE (amt$record_limit)) AND
              (attribute_p^.record_limit <= UPPERVALUE (amt$record_limit));
      = fsc$record_type =
        attribute_value_is_good := (attribute_p^.record_type >= LOWERVALUE (amt$record_type)) AND
              (attribute_p^.record_type <= UPPERVALUE (amt$record_type));
      = fsc$records_per_block =
        attribute_value_is_good := (attribute_p^.records_per_block >= LOWERVALUE (amt$records_per_block)) AND
              (attribute_p^.records_per_block <= UPPERVALUE (amt$records_per_block));
      = fsc$ring_attributes =
        IF NOT ((1 <= attribute_p^.ring_attributes.r1) AND (attribute_p^.ring_attributes.r1 <=
              attribute_p^.ring_attributes.r2) AND (attribute_p^.ring_attributes.r2 <=
              attribute_p^.ring_attributes.r3) AND (attribute_p^.ring_attributes.r3 <= 13)) THEN
          attribute_value_is_good := FALSE;
        IFEND;
      = fsc$statement_identifier =
        attribute_value_is_good := (attribute_p^.statement_identifier.length >=
              LOWERVALUE (amt$statement_id_length)) AND (attribute_p^.statement_identifier.
              length <= UPPERVALUE (amt$statement_id_length)) AND
              (attribute_p^.statement_identifier.location >= LOWERVALUE (amt$statement_id_location)) AND
              (attribute_p^.statement_identifier.location <= UPPERVALUE (amt$statement_id_location));
      = fsc$user_attribute =
        IF attribute_p^.user_attribute.name <> osc$null_name THEN
          clp$only_validate_name (attribute_p^.user_attribute.name, attribute_value_is_good);
        IFEND;
        attribute_value_is_good := (attribute_p^.user_attribute.selector >=
              LOWERVALUE (fst$user_attribute_type)) AND (attribute_p^.user_attribute.selector <=
              UPPERVALUE (fst$user_attribute_type));
      = fsc$user_information =
        ;
      = fsc$vertical_print_density =
        attribute_value_is_good := (attribute_p^.vertical_print_density >=
              LOWERVALUE (amt$vertical_print_density)) AND (attribute_p^.vertical_print_density <=
              UPPERVALUE (amt$vertical_print_density));
      = fsc$retention =
        CASE attribute_p^.retention.selector OF
        = fsc$retention_day_increment =
          attribute_value_is_good := ((attribute_p^.retention.day_increment >= LOWERVALUE (pft$retention)) AND
                (attribute_p^.retention.day_increment <= UPPERVALUE (pft$retention)));
        = fsc$retention_time_increment =
          clp$verify_time_increment (attribute_p^.retention.time_increment, status);
          IF status.normal THEN
            pmp$get_compact_date_time (date_time, ignore_status);
            pmp$compute_date_time (date_time, attribute_p^.retention.time_increment, expiration_date, status);
          IFEND;
          attribute_value_is_good := status.normal;
        = fsc$retention_expiration_date =
          pmp$verify_compact_date (attribute_p^.retention.expiration_date, status);
          IF status.normal THEN
            pmp$verify_compact_time (attribute_p^.retention.expiration_date, status);
          IFEND;
          attribute_value_is_good := status.normal;
        ELSE
          attribute_value_is_good := FALSE;
        CASEND;
      = fsc$retrieve_option =
        attribute_value_is_good := (((attribute_p^.retrieve_option >= LOWERVALUE (pft$retrieve_option)) AND
              (attribute_p^.retrieve_option <= UPPERVALUE (pft$retrieve_option))));
      = fsc$site_backup_option =
        attribute_value_is_good := (((attribute_p^.site_backup_option >=
              LOWERVALUE (pft$site_backup_option)) AND (attribute_p^.site_backup_option <=
              UPPERVALUE (pft$site_backup_option))));
      = fsc$site_archive_option =
        attribute_value_is_good := (((attribute_p^.site_archive_option >=
              LOWERVALUE (pft$site_archive_option)) AND (attribute_p^.site_archive_option <=
              UPPERVALUE (pft$site_archive_option))));
      = fsc$site_release_option =
        attribute_value_is_good := (((attribute_p^.site_release_option >=
              LOWERVALUE (pft$site_release_option)) AND (attribute_p^.site_release_option <=
              UPPERVALUE (pft$site_release_option))));
      ELSE
        attribute_key_is_good := FALSE;
      CASEND;

      IF NOT attribute_key_is_good THEN
        IF status.normal OR (status.condition <> ame$improper_file_attrib_key) THEN
          status_reporting_procedure_ptr^ (ame$improper_file_attrib_key, status_text, status);
          osp$append_status_integer (osc$status_parameter_delimiter, i, 10, FALSE, status);
        ELSE
          osp$append_status_integer (',', i, 10, FALSE, status);
        IFEND;
      ELSEIF NOT attribute_value_is_good THEN
        IF status.normal THEN
          status_reporting_procedure_ptr^ (ame$improper_file_attrib_value, status_text, status);
          osp$append_status_parameter (osc$status_parameter_delimiter,
                fsv$attribute_names^ [attribute_p^.selector], status);
        ELSEIF status.condition = ame$improper_file_attrib_value THEN
          osp$append_status_parameter (',', fsv$attribute_names^ [attribute_p^.selector], status);
        IFEND;
      IFEND;
    FOREND;

  PROCEND fsp$validate_attributes;

MODEND fsm$validate_attributes;
