?? NEWTITLE := 'NOS/VE Basic Access Method : Open File' ??
MODULE bam$open_file;
?? RIGHT := 110 ??

{
{ PURPOSE:
{   This module contains the bulk of the processing needed to open a file.

*copyc fsh$open_file
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ame$attribute_validation_errors
*copyc ame$device_class_validation
*copyc ame$label_validation_errors
*copyc ame$open_validation_errors
*copyc ame$ring_validation_errors
*copyc ame$lfn_program_actions
*copyc ame$tape_program_actions
*copyc bac$minimum_open_ring
*copyc cle$ecc_lexical
*copyc cle$ecc_file_reference
*copyc dme$tape_errors
*copyc fme$file_management_errors
*copyc fsc$file_system_id
*copyc fsc$local
*copyc fse$attach_validation_errors
*copyc fse$open_validation_errors
*copyc fse$path_exception_conditions
*copyc jml$user_id
*copyc lld$loader_execptions
*copyc mme$condition_codes
*copyc ofe$error_codes
*copyc ose$heap_full_exceptions
*copyc rmc$recorded_vsn_size
*copyc rme$creblv_errors
*copyc amt$fap_declarations
*copyc amt$get_attributes
*copyc amt$max_block_length
*copyc amt$max_record_length
*copyc bat$auxilliary_request_table
*copyc bat$block_header
*copyc bat$system_file_attributes
*copyc bat$tape_descriptor
*copyc bat$task_file_table
*copyc clt$path_kind
*copyc fmv$tape_attachment_information
*copyc fst$attachment_options
*copyc fst$ansi_eof1_label
*copyc fst$ansi_eof2_label
*copyc fst$ansi_hdr1_label
*copyc fst$ansi_hdr2_label
*copyc fst$ansi_vol1_label
*copyc fst$device_classes
*copyc fst$file_cycle_attributes
*copyc fst$file_reference
*copyc fst$goi_object_information
*copyc fst$path_element_size
*copyc fst$status_reporting_procedure
*copyc fst$tape_attachment_information
*copyc iiv$interactive_terminated
*copyc osc$status_parameter_delimiter
*copyc osd$code_base_pointer
*copyc osd$virtual_address
*copyc oss$job_paged_literal
*copyc oss$task_private
*copyc ost$caller_identifier
*copyc ost$name
*copyc ost$string
*copyc pfe$error_condition_codes
*copyc pmt$loaded_address
*copyc pmt$program_name
*copyc rmt$device_class
?? POP ??
*copyc amp$get_file_attributes
*copyc mmp$verify_access
*copyc amv$valid_ring
*copyc avp$removable_media_operator
*copyc avp$security_option_active
*copyc bap$connected_file_device
*copyc bap$determine_loaded_ring
*copyc bap$fap_control
*copyc bap$get_tape_label_attributes
*copyc bap$log_device
*copyc bap$merge_open_attributes
*copyc bap$merge_tape_attributes
*copyc bap$null_device

  PROCEDURE hide_xrefs_copied_by_inlines;

{bap$release_tft_entry
*copyc bav$last_tft_entry
*copyc bav$task_file_table
*copyc bav$tft_entry_assignment
  PROCEND hide_xrefs_copied_by_inlines;
*copyc pfe$external_archive_conditions
*copyc pmf$job_mode
*copyc bap$release_tft_entry
*copyc bap$system_tape_label_fap
*copyc clp$construct_path_handle_name
*copyc clp$convert_cyc_ref_to_cyc_sel
*copyc clp$convert_file_ref_to_string
*copyc clp$convert_integer_to_string
*copyc clp$convert_string_to_integer
*copyc clp$get_fs_path_string
*copyc clp$trimmed_string_size
*copyc fmp$cleanup_open
*copyc fmp$create_cycle_description
*copyc fmp$decrement_open_count
*copyc fmp$end_new_open_processing
*copyc fmp$fetch_tape_attachment
*copyc fmp$fetch_tape_label_attributes
*copyc fmp$get_cd_info
*copyc fmp$get_device_class_and_sfid
*copyc fmp$locate_cd_via_path_handle
*copyc fmp$record_open_cycle_info
*copyc fmp$return_file
*copyc fmp$store_tape_attachment
*copyc fsp$convert_device_class_to_fs
*copyc fsp$convert_fs_structure_to_pf
*copyc fsp$convert_to_old_contents
*copyc fsp$locate_tape_label
*copyc fsp$path_element
*copyc fsp$set_evaluated_file_abnormal
*copyc fsp$strictly_null_device
*copyc fsp$validate_attachments
*copyc fsp$validate_attributes
*copyc fsp$ve_wrote_ansi_file
*copyc ifp$fap_control
*copyc ifp$st_fap_control
*copyc iip$xt_is_xterm_file
*copyc iip$xt_xterm_fap
*copyc jmp$job_file_fap
*copyc jmp$system_job
*copyc lop$find_entry_point_residence
*copyc lop$load_entry_point
*copyc mmp$close_segment
*copyc mmp$set_segment_length
*copyc nap$network_fap
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$clear_job_signature_lock
*copyc osp$decrement_locked_variable
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$fetch_locked_variable
*copyc osp$format_message
*copyc osp$generate_log_message
*copyc osp$increment_locked_variable
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osp$test_sig_lock
*copyc osp$verify_system_privilege
*copyc pfp$purge
*copyc pfp$r3_attach_or_create_file
*copyc pfp$r3_get_object_information
*copyc pmp$change_legible_date_format
*copyc pmp$load_module_from_library
*copyc rfp$network_fap
*copyc rmp$enforce_tape_security
*copyc rmp$validate_ansi_string
*copyc rmp$validate_specified_rmg
*copyc sfp$emit_audit_statistic
*copyc sfp$emit_statistic
*copyc i#move

*copyc amv$aam_file_organizations
*copyc amv$block_type_names
*copyc amv$device_class_names
*copyc amv$file_organization_names
*copyc amv$record_type_names
*copyc amv$usage_option_names
*copyc bav$magnetic_tape_device_faps
*copyc bav$mass_storage_device_faps
*copyc bav$rms_library_reference
*copyc clv$processing_phase
*copyc clv$standard_files
*copyc fmv$default_file_attributes
*copyc fmv$entry_assigned_free_select
*copyc fmv$global_file_information
*copyc fmv$null_cd_attachment_options
*copyc fsv$attribute_names
*copyc osv$lower_to_upper
*copyc osv$task_private_heap
*copyc rmv$null_device_set
*copyc sfv$emit_job_open_statistics
*copyc sfv$emit_sys_open_statistics
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

?? FMT (FORMAT := OFF) ??
  CONST
    bac$minimum_load_ring = osc$tsrv_ring;

{ single_choice_attachments
  CONST
    number_of_single_choice_attach = 16;

  TYPE
    single_choice_attachments_keys = (
      sca_allowed_device_classes,
      sca_allowed_exceptions,
      sca_create_file,
      sca_delete_data,
      sca_error_exit_procedure,
      sca_error_exit_procedure_name ,
      sca_error_limit {Advanced Access Method files only},
      sca_label_exit_procedure,
      sca_label_exit_procedure_name,
      sca_message_control {Advanced Access Method files only},
      sca_open_position,
      sca_password,
      sca_tape_error_options,
      sca_validation_ring,
      sca_wait_for_attachment,
      sca_exception_detection),

    single_choice_attachments_type = array [single_choice_attachments_keys] of
          fst$attachment_option;

  TYPE
    t$catalog_cycle_attributes =  record
      retention: fst$retention,
      retrieve_option: pft$retrieve_option,
      site_archive_option: pft$site_archive_option,
      site_backup_option: pft$site_backup_option,
      site_release_option: pft$site_release_option,
    recend;

  VAR
    single_choice_attachments_def: [STATIC, READ, oss$job_paged_literal]
      single_choice_attachments_type := [
      [fsc$allowed_device_classes, -$fst$device_classes []],
      [fsc$allowed_exceptions, [$fst$cycle_damage_symptoms[],
            -$fst$file_access_conditions[fsc$cycle_busy]]],
      { create_file } [fsc$null_attachment_option],
      [fsc$delete_data, FALSE],
      [fsc$error_exit_procedure, NIL],
      [fsc$error_exit_procedure_name, NIL],
      { error_limit } [fsc$null_attachment_option],
      [fsc$label_exit_procedure, NIL],
      [fsc$label_exit_procedure_name, NIL],
      { message_control } [fsc$null_attachment_option],
      { open_position } [fsc$null_attachment_option],
      {password} [fsc$null_attachment_option],
      { tape_error_options } [fsc$null_attachment_option],
      [fsc$validation_ring, * ],
      [fsc$wait_for_attachment, [osc$wait, fsc$longest_wait_time]],
      [fsc$exception_detection, $fst$cycle_damage_symptoms[]]];

{ Default record values
  VAR
    bav$default_tft: [READ, oss$job_paged_literal] bat$task_file_entry
      := [
       {local_file_name}           osc$null_name,
       {sequence_number}           4095,
       {access_level}              amc$record,
       {open_ring}                 * ,
       {close_allowed}             TRUE,
       {next_target}               [FALSE],
       {initial_open}              FALSE,
       {instance_of_open_modified} FALSE,
       {instance_attributes}       *,
       {open_actions}              [FALSE, FALSE, FALSE],
       {previous_get_at_eoi}       FALSE,
       {residual_skip_count}       0,
       {private_read_information}  NIL,
       {global_file_information}   NIL,
       {system_file_label}         NIL,
       {fap_control_information}   *,
       {module_dynamically_loaded} FALSE,
       {target_connection_level}   0,
       {device_class}              rmc$mass_storage_device,
       {= rmc$mass_storage_device =
       {  allowed_access_conditions} $fst$file_access_conditions [],
       {  file_pva}                  NIL,
       {  rollback_procedure}        NIL,
       {  wait}                      TRUE,
       {  wait_time}                 fsc$longest_wait_time
       ],
?? FMT (FORMAT := ON) ??
  bav$default_pri: [READ, oss$job_paged_literal] bat$private_read_information :=
        [0, * , [[1, bac$beginning_of_block, 0, 0, 0, 0], [0, 0, amc$boi, 0, 0, 0, 0]]],
        bav$default_fap_descriptor: [READ, oss$job_paged_literal] bat$fap_descriptor :=
        [NIL, NIL, bac$minimum_load_ring, TRUE];

{ Task file table (TFT) & auxiliary request table (ART)

  VAR
    bav$auxilliary_request_table: [XDCL, oss$task_private] ^bat$auxilliary_request_table := NIL,
    bav$file_id_sequence_number: [XDCL, #GATE, oss$task_private]
          amt$file_id_sequence := LOWERVALUE (amt$file_id_sequence),
    bav$task_file_table: [XDCL, #GATE, oss$task_private] ^bat$task_file_table := NIL,
    bav$last_tft_entry: [XDCL, #GATE, oss$task_private] bat$last_tft_entry := 0,
    bav$tft_entry_assignment: [XDCL, #GATE, oss$task_private] ^bat$tft_entry_assignment := NIL;

{Tape information

  CONST
    tape_attach_choice_limit = fsc$tape_volume_initialization;

  VAR
    tape_attachment_names: [STATIC, READ, oss$job_paged_literal] array
          [fsc$tape_block_type .. tape_attach_choice_limit] of ost$name := [

{    fsc$tape_block_type ........... = 001} 'TAPE_BLOCK_TYPE               ',
{    fsc$tape_buffer_offset ........ = 002} 'TAPE_BUFFER_OFFSET            ',
{    fsc$tape_character_conversion . = 003} 'TAPE_CHARACTER_CONVERSION     ',
{    fsc$tape_character_set ........ = 004} 'TAPE_CHARACTER_SET            ',
{    fsc$tape_creation_date ........ = 005} 'TAPE_CREATION_DATE            ',
{    fsc$tape_expiration_date ...... = 006} 'TAPE_EXPIRATION_DATE          ',
{    fsc$tape_file_accessibility ... = 007} 'TAPE_FILE_ACCESSIBILITY       ',
{    fsc$tape_file_identifier ...... = 008} 'TAPE_FILE_IDENTIFIER          ',
{    fsc$tape_file_sequence_number . = 009} 'TAPE_FILE_SEQUENCE_NUMBER     ',
{    fsc$tape_file_set_identifier .. = 010} 'TAPE_FILE_SET_IDENTIFIER      ',
{    fsc$tape_file_set_position .... = 011} 'TAPE_FILE_SET_POSITION        ',
{    fsc$tape_generation_number .... = 012} 'TAPE_GENERATION_NUMBER        ',
{    fsc$tape_generation_version_num = 013} 'TAPE_GENERATION_VERSION_NUMBER',
{    fsc$tape_max_block_length ..... = 014} 'TAPE_MAX_BLOCK_LENGTH         ',
{    fsc$tape_max_record_length .... = 015} 'TAPE_MAX_RECORD_LENGTH        ',
{    fsc$tape_null_attachment_option = 016} 'TAPE_NULL_ATTACHMENT_OPTION   ',
{    fsc$tape_padding_character .... = 017} 'TAPE_PADDING_CHARACTER        ',
{    fsc$tape_record_type .......... = 018} 'TAPE_RECORD_TYPE              ',
{    fsc$tape_rewrite_labels ....... = 019} 'TAPE_REWRITE_LABELS           ',
{    fsc$tape_removable_media_group  = 020} 'TAPE_REMOVABLE_MEDIA_GROUP    ',
{    fsc$tape_volume_accessibility . = 021} 'TAPE_VOLUME_ACCESSIBILITY     ',
{    fsc$tape_owner_identification . = 022} 'TAPE_OWNER_IDENTIFICATION     ',
{    fsc$tape_label_standard_version = 023} 'TAPE_LABEL_STANDARD_VERSION   ',
{    fsc$tape_implementation_id .... = 024} 'TAPE_IMPLEMENTATION_ID        ',
{    fsc$tape_header_labels ........ = 025} 'TAPE_HEADER_LABELS            ',
{    fsc$tape_trailer_labels ....... = 026} 'TAPE_TRAILER_LABELS           ',
{    fsc$tape_file_section_number .. = 027} 'TAPE_FILE_SECTION_NUMBER      ',
{    fsc$tape_block_count .......... = 028} 'TAPE_BLOCK_COUNT              ',
{    fsc$tape_volume_initialization  = 029} 'TAPE_VOLUME_INITIALIZATION    '];

  VAR
    any_tape_opened_in_task: [STATIC, oss$task_private] boolean := FALSE;

{Get object information request

  VAR
    information_request: [READ, oss$job_paged_literal] fst$goi_information_request :=
          [[fsc$specific_depth, 1], [fsc$goi_cycle_device_info]];

?? OLDTITLE ??
?? NEWTITLE := 'PROCEDURE [XDCL, #GATE] bap$end_new_open_processing', EJECT ??

  PROCEDURE [XDCL, #GATE] bap$end_new_open_processing
    (    path_handle: fmt$path_handle;
     VAR status: ost$status);

    osp$verify_system_privilege;
    fmp$end_new_open_processing (path_handle, status);

  PROCEND bap$end_new_open_processing;
?? OLDTITLE ??
?? NEWTITLE := 'PROCEDURE [XDCL, #GATE] bap$free_static_label', EJECT ??

  PROCEDURE [XDCL, #GATE] bap$free_static_label
    (    path_handle: fmt$path_handle);

    VAR
      open_cleanup_work_list: fmt$open_cleanup_work_list;

    osp$verify_system_privilege;
    open_cleanup_work_list := $fmt$open_cleanup_work_list [fmc$free_static_label];
    fmp$cleanup_open (path_handle, open_cleanup_work_list);

  PROCEND bap$free_static_label;
?? OLDTITLE ??
?? NEWTITLE := 'PROCEDURE [XDCL, #GATE] bap$open_file', EJECT ??
*copyc bah$open_file
?? SKIP := 3 ??

{ evaluated_file_reference should only be updated on a normal status.

  PROCEDURE [XDCL, #GATE] bap$open_file
    (    access_level: amt$access_level;
         file_attachment: ^fst$attachment_options;
         default_creation_attributes: ^fst$file_cycle_attributes;
         mandated_creation_attributes: ^fst$file_cycle_attributes;
         attribute_validation: ^fst$file_cycle_attributes;
         attribute_override: ^fst$file_cycle_attributes;
     VAR evaluated_file_reference: {i/o} fst$evaluated_file_reference;
     VAR contains_data: boolean;
     VAR file_identifier: amt$file_identifier;
     VAR archive_cycle_number: fst$cycle_number;
     VAR status: ost$status);

    CONST
      implicit_detach = TRUE;

    VAR
      access_and_share_modes_count: integer,
      access_mode_includes_write: boolean,
      caller_id: ost$caller_identifier,
      catalog_cycle_attributes: pft$catalog_cycle_attributes,
      cd_attachment_options: fmt$cd_attachment_options,
      device_class: rmt$device_class,
      file_instance_initialized: boolean,
      global_file_information: ^bat$global_file_information,
      instance_access_mode: fst$file_access_options,
      instance_attributes: bat$instance_attributes,
      limit_str: ost$string,
      local_evaluated_file_reference: fst$evaluated_file_reference,
      merged_tape_attributes: fst$tape_attachment_information,
      open_cleanup_work_list: fmt$open_cleanup_work_list,
      open_count: integer,
      open_share_modes_specified: boolean,
      opened_access_modes: bat$access_counts,
      password: pft$password,
      preserved_attributes: bat$system_file_attributes,
      p_tape_descriptor: ^bat$tape_descriptor,
      segment_ptr: ^cell,
      single_choice_attachments: single_choice_attachments_type,
      specified_cd_attachment_options: fmt$cd_attachment_options,
      status_reporting_proc_p: fst$status_reporting_procedure,
      system_file_label: ^fmt$system_file_label,
      tape_attachment_specified: boolean,
      tape_attachment: array [1 .. tape_attach_choice_limit] of fst$attachment_option,
      task_file_index: bat$tft_limit,
      tft_entry_p: ^bat$task_file_entry;

?? NEWTITLE := '    bam_open condition_handler proc', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cyd$run_time_error_condition
*copyc oss$job_paged_literal
*copyc pmt$condition
?? POP ??
*copyc pmp$continue_to_cause

{  PURPOSE:
{     This procedure invokes a clean_up of the established condition in event that
{     its establisher is aborted. Additionally, a call to free the current task_file_entry
{     is invoked.
{
{     Conditions considered to represent an abort are: system, segmt access, cybil runtime,
{     command retry, and interactive terminate breaks.

    PROCEDURE bam_condition_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      VAR
        abort: boolean,
        ignore_status: ost$status;

      handler_status.normal := TRUE;

      CASE condition.selector OF
      = pmc$system_conditions, mmc$segment_access_condition =
        abort := TRUE;
      = pmc$user_defined_condition =
        abort := (condition.user_condition_name = cye$run_time_condition);
      = ifc$interactive_condition =
        abort := condition.interactive_condition = ifc$terminate_break;
      = jmc$job_resource_condition =
        abort := TRUE;
      ELSE
        abort := FALSE;
      CASEND;

      IF abort THEN
        osp$set_status_from_condition (amc$access_method_id, condition, save_area, status, ignore_status);
        #SPOIL (file_instance_initialized);
        IF file_instance_initialized THEN
          cleanup_open;
        IFEND;
        EXIT bap$open_file; {----->
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      IFEND;

    PROCEND bam_condition_handler;

    PROCEDURE cleanup_open;

      VAR
        cleanup_status: ost$status,
        cycle_selector: clt$cycle_selector,
        file_pva: mmt$segment_pointer,
        pf_path: ^pft$path;

      #SPOIL (tft_entry_p, open_cleanup_work_list);
      IF open_cleanup_work_list <> $fmt$open_cleanup_work_list [] THEN
        fmp$cleanup_open (local_evaluated_file_reference.path_handle_info.path_handle,
              open_cleanup_work_list);
{ We should retrieve the static label for a permanent file that isn't
{ being returned.  The following example currently fails:
{ cref $user.x; setfa $user.x fc=george; detf $user.x; attf $user.x
{ open $user.x - failing open
{ open $user.x - successful open but setfa may be lost
      IFEND;

      CASE tft_entry_p^.device_class OF
      = rmc$mass_storage_device =
        IF tft_entry_p^.file_pva <> NIL THEN
          file_pva.kind := mmc$cell_pointer;
          file_pva.cell_pointer := tft_entry_p^.file_pva;
          mmp$close_segment (file_pva, 1, cleanup_status);
          tft_entry_p^.file_pva := NIL;
        IFEND;
      ELSE
        ;
      CASEND;

      bap$release_tft_entry (tft_entry_p, task_file_index);

      IF fsp$path_element (^local_evaluated_file_reference, 1) ^ <> fsc$local THEN
        IF tft_entry_p^.open_actions.open_created_file THEN
          PUSH pf_path: [1 .. local_evaluated_file_reference.number_of_path_elements];
          fsp$convert_fs_structure_to_pf (local_evaluated_file_reference, pf_path);
          clp$convert_cyc_ref_to_cyc_sel (local_evaluated_file_reference.cycle_reference, cycle_selector);
          IF single_choice_attachments [sca_password].selector = fsc$password THEN
            password := single_choice_attachments [sca_password].password;
          ELSE
            password := osc$null_name;
          IFEND;
          pfp$purge (pf_path^, cycle_selector.value, password, cleanup_status);
          fmp$return_file (local_evaluated_file_reference, implicit_detach, {detachment_options} NIL,
                cleanup_status);
        ELSEIF tft_entry_p^.open_actions.open_attached_file THEN
          fmp$return_file (local_evaluated_file_reference, implicit_detach, {detachment_options} NIL,
                cleanup_status);
        IFEND;
      ELSEIF tft_entry_p^.open_actions.open_created_file THEN
        fmp$return_file (local_evaluated_file_reference, NOT implicit_detach, {detachment_options} NIL,
              cleanup_status);
      IFEND;
    PROCEND cleanup_open;

?? TITLE := '    STATUS_REPORTING_PROCEDURE', EJECT ??

    PROCEDURE status_reporting_procedure
      (    condition: ost$status_condition;
           text: string ( * );
       VAR status: ost$status);

      fsp$set_evaluated_file_abnormal (local_evaluated_file_reference, condition, amc$open_req, text, status);

    PROCEND status_reporting_procedure;
?? OLDTITLE ??
?? EJECT ??


    #CALLER_ID (caller_id);
    status.normal := TRUE;

    osp$verify_system_privilege;

    file_instance_initialized := FALSE;
    open_cleanup_work_list := $fmt$open_cleanup_work_list [];
    #SPOIL (file_instance_initialized, open_cleanup_work_list);

    local_evaluated_file_reference := evaluated_file_reference;

    access_and_share_modes_count := 0;
    open_share_modes_specified := FALSE;
    single_choice_attachments := single_choice_attachments_def;
    single_choice_attachments [sca_validation_ring].validation_ring := caller_id.ring;

    tape_attachment_specified := FALSE;
{Note: The initialization of the tape_attachment array is suspended until we need it. This eliminates
{      the overhead for non-tape files.

    osp$establish_condition_handler (^bam_condition_handler, FALSE);

  /main_program/
    BEGIN
      status_reporting_proc_p := ^status_reporting_procedure;
      validate_open_parameters (caller_id.ring, access_level, file_attachment, default_creation_attributes,
            mandated_creation_attributes, attribute_validation, attribute_override, status_reporting_proc_p,
            status);
      IF NOT status.normal THEN
        EXIT /main_program/; {----->
      IFEND;

      initialize_file_instance (access_level, caller_id.ring, task_file_index, status_reporting_proc_p,
            status);
      IF NOT status.normal THEN
        EXIT /main_program/; {----->
      IFEND;

      tft_entry_p := ^bav$task_file_table^ [task_file_index];
      file_instance_initialized := TRUE;
      #SPOIL (tft_entry_p, file_instance_initialized);

      specified_cd_attachment_options := fmv$null_cd_attachment_options;
      IF file_attachment <> NIL THEN

        { Loop through the file_attachment array to find out if certain
        { attachment options were specified by the caller. This is done here
        { to avoid looping through the array each time it is necessary to find
        { out if a particular option was specified and if so what its value is.

        search_file_attachment (local_evaluated_file_reference, file_attachment, single_choice_attachments,
              tape_attachment, tape_attachment_specified, access_and_share_modes_count,
              open_share_modes_specified, specified_cd_attachment_options, status_reporting_proc_p, status);
        IF NOT status.normal THEN
          EXIT /main_program/; {----->
        IFEND;
        IF single_choice_attachments [sca_validation_ring].validation_ring < caller_id.ring THEN
          status_reporting_procedure (ame$ring_validation_error, '', status);
          EXIT /main_program/; {----->
        IFEND;
      IFEND;

      get_catalog_cycle_attributes (mandated_creation_attributes, default_creation_attributes,
            catalog_cycle_attributes);

      attach_or_create_file (task_file_index, access_level, file_attachment, access_and_share_modes_count,
            catalog_cycle_attributes, single_choice_attachments, open_cleanup_work_list,
            local_evaluated_file_reference, preserved_attributes, open_count, device_class,
            opened_access_modes, archive_cycle_number, cd_attachment_options, status_reporting_proc_p,
            status);
      IF NOT status.normal THEN
        EXIT /main_program/; {----->
      IFEND;

      IF device_class = rmc$magnetic_tape_device THEN
        IF open_count > 1 THEN
          status_reporting_procedure (ame$multiple_open_of_tape, '', status);
          EXIT /main_program/; {----->
        IFEND;

{ Get CHATLA specifications

        fmp$fetch_tape_label_attributes (evaluated_file_reference, merged_tape_attributes, status);
        IF NOT status.normal THEN
          EXIT /main_program/; {----->
        IFEND;
        IF tape_attachment_specified THEN

{ Merge CHATLA and tape attachment values into merged_tape_attributes

          fmp$store_tape_attachment (tape_attachment, fsc$tape_open_tape_attachment, ^merged_tape_attributes,
                status);
          IF NOT status.normal THEN
            EXIT /main_program/; {----->
          IFEND;
        IFEND;
      IFEND;

{Update CD Attachment Options
      IF specified_cd_attachment_options.free_behind_specified THEN
        cd_attachment_options.free_behind_specified := TRUE;
        cd_attachment_options.free_behind := specified_cd_attachment_options.free_behind;
      IFEND;
      IF specified_cd_attachment_options.private_read_specified THEN
        cd_attachment_options.private_read_specified := TRUE;
        cd_attachment_options.private_read := specified_cd_attachment_options.private_read;
      IFEND;
      IF specified_cd_attachment_options.sequential_access_specified THEN
        cd_attachment_options.sequential_access_specified := TRUE;
        cd_attachment_options.sequential_access := specified_cd_attachment_options.sequential_access;
      IFEND;
      IF specified_cd_attachment_options.transfer_size_specified THEN
        cd_attachment_options.transfer_size_specified := TRUE;
        cd_attachment_options.transfer_size := specified_cd_attachment_options.transfer_size;
      IFEND;

      process_file_attributes (evaluated_file_reference, access_level, default_creation_attributes,
            mandated_creation_attributes, attribute_validation, attribute_override,
            single_choice_attachments [sca_validation_ring].validation_ring, caller_id.ring,
            NOT tft_entry_p^.initial_open, device_class, merged_tape_attributes, preserved_attributes,
            instance_attributes, access_mode_includes_write, status_reporting_proc_p, status);
      IF NOT status.normal THEN
        EXIT /main_program/; {----->
      IFEND;

      IF (instance_attributes.dynamic_label.access_mode = $pft$usage_selections [pfc$read]) OR
            (instance_attributes.dynamic_label.access_mode = $pft$usage_selections [pfc$read, pfc$execute])
            THEN
        IF ((NOT cd_attachment_options.private_read_specified) OR cd_attachment_options.private_read) AND
              (device_class = rmc$mass_storage_device) THEN
          ALLOCATE tft_entry_p^.private_read_information IN osv$task_private_heap^;
          tft_entry_p^.private_read_information^ := bav$default_pri;
        IFEND;
      ELSEIF (cd_attachment_options.private_read_specified) AND cd_attachment_options.private_read THEN
        status_reporting_procedure (fse$improper_private_read, '', status);
        EXIT /main_program/; {----->
      IFEND;

      IF NOT fsp$strictly_null_device (device_class, fsp$path_element (^evaluated_file_reference, 2) ^) THEN
        enforce_concurrency_rules (file_attachment, cd_attachment_options, device_class,
              open_share_modes_specified, opened_access_modes, open_count,
              instance_attributes.dynamic_label.open_share_modes, status_reporting_proc_p, status);
        IF NOT status.normal THEN
          EXIT /main_program/; {----->
        IFEND;
      IFEND;

      load_all_faps (task_file_index, caller_id, device_class,
            preserved_attributes.static_label.file_access_procedure,
            instance_attributes.static_label.file_label_type,
            instance_attributes.static_label.file_organization, instance_attributes.static_label.block_type,
            instance_attributes.static_label.record_type, access_level,
            local_evaluated_file_reference.path_handle_info.path_handle, status_reporting_proc_p, status);
      IF NOT status.normal THEN
        EXIT /main_program/; {----->
      IFEND;

      IF instance_attributes.dynamic_label.error_exit_name <> osc$null_name THEN
        load_error_exit (instance_attributes.dynamic_label.error_exit_name_source,
              instance_attributes.dynamic_label.error_exit_name, caller_id,
              instance_attributes.dynamic_label.error_exit_procedure,
              instance_attributes.dynamic_label.error_exit_procedure_source, status_reporting_proc_p, status);
        IF NOT status.normal THEN
          EXIT /main_program/; {----->
        IFEND;
      IFEND;

      IF tft_entry_p^.initial_open AND (preserved_attributes.static_label.collate_table_name <> osc$null_name)
            THEN
        load_collate_table (preserved_attributes.static_label.collate_table_name_source,
              preserved_attributes.static_label.collate_table_name, caller_id,
              preserved_attributes.static_label.collate_table_source,
              preserved_attributes.static_label.collate_table, status_reporting_proc_p, status);
        IF NOT status.normal THEN
          EXIT /main_program/; {----->
        IFEND;
      IFEND;

      fmp$record_open_cycle_info (local_evaluated_file_reference.path_handle_info.path_handle, caller_id.ring,
            access_level, preserved_attributes.static_label, instance_attributes, cd_attachment_options,
            open_count, device_class, open_cleanup_work_list, global_file_information, segment_ptr,
            system_file_label, status);
      IF status.normal THEN
        IF device_class = rmc$mass_storage_device THEN
          tft_entry_p^.file_pva := segment_ptr;
          tft_entry_p^.allowed_access_conditions := single_choice_attachments [sca_allowed_exceptions].
                allowed_exceptions.access_conditions;
          tft_entry_p^.wait := (single_choice_attachments [sca_wait_for_attachment].wait_for_attachment.wait =
                osc$wait);
          IF tft_entry_p^.wait THEN
            tft_entry_p^.wait_time := single_choice_attachments [sca_wait_for_attachment].wait_for_attachment.
                  wait_time;
          IFEND;
          IF sfv$emit_job_open_statistics OR sfv$emit_sys_open_statistics THEN
            emit_open_statistics (local_evaluated_file_reference, task_file_index, global_file_information,
                  access_level, status);
            IF NOT status.normal THEN
              EXIT /main_program/; {----->
            IFEND;
          IFEND;
        IFEND;
      ELSE
        IF status.condition = mme$segment_table_is_full THEN
          clp$convert_integer_to_string (bav$last_tft_entry, 10, FALSE, limit_str, status);
          IF status.normal THEN
            status_reporting_procedure (ame$concurrent_open_limit, limit_str.value (1, limit_str.size),
                  status);
            osp$append_status_parameter (osc$status_parameter_delimiter, 'Memory', status);
          IFEND;
        IFEND;
        EXIT /main_program/; {----->
      IFEND;

      IF device_class = rmc$magnetic_tape_device THEN
        RESET global_file_information^.device_dependent_info.tape_descriptor;
        NEXT p_tape_descriptor IN global_file_information^.device_dependent_info.tape_descriptor;
        p_tape_descriptor^.tape_attachment_information := merged_tape_attributes;
      IFEND;

      store_attributes_in_tft (instance_attributes, global_file_information, system_file_label, device_class,
            tft_entry_p^);

      finalize_file_instance (task_file_index, system_file_label^.descriptive_label.internal_cycle_name,
            file_identifier);

      establish_open_position (instance_attributes.dynamic_label.open_position, caller_id,
            instance_attributes.dynamic_label.access_mode, single_choice_attachments [sca_delete_data].
            delete_data, task_file_index, preserved_attributes.descriptive_label.global_share_mode,
            open_count, tft_entry_p^.global_file_information, tft_entry_p^.private_read_information,
            device_class, segment_ptr);

      contains_data := tft_entry_p^.global_file_information^.eoi_byte_address > 0;

{ Clear OPEN's lock on the file, the following two lines assume that this process won't be interrupted.
{ If for some reason an interrupt can occur and the condition handler takes over, the lock could be
{ cleared twice. This would be fatal to the task.

      osp$clear_job_signature_lock (global_file_information^.open_lock);
      open_cleanup_work_list := open_cleanup_work_list - $fmt$open_cleanup_work_list [fmc$clear_open_lock];
      #SPOIL (open_cleanup_work_list);

      evaluated_file_reference := local_evaluated_file_reference;
    END /main_program/;

    IF NOT status.normal AND file_instance_initialized THEN
      cleanup_open;
    IFEND;

{   As long as bap$open_file does not establish a block exit handler, it is not
{   necessary to disestablish the condition handler.
{
{   osp$disestablish_cond_handler;

  PROCEND bap$open_file;

?? NEWTITLE := 'bap$verify_task_file_table', EJECT ??

{for now we simply pass a boolean variable and no other information or a status - might change in the
{future, when we know more.

  PROCEDURE [XDCL, #GATE] bap$verify_task_file_table
    (VAR task_file_table_valid: boolean);

    VAR
      bad_file_count: integer,
      fid_ordinal: amt$file_id_ordinal,
      handle: clt$path_handle,
      i: integer,
      tfte_p: ^bat$task_file_entry;

?? NEWTITLE := '[inline] F$VALID_FAP_DESCRIPTOR', EJECT ??

    FUNCTION [INLINE] f$valid_fap_descriptor
      (    fap: bat$fap_descriptor): boolean;

      f$valid_fap_descriptor := TRUE;
      IF ($INTEGER (fap.layer_closed) <> 0) AND ($INTEGER (fap.layer_closed) <> 1) THEN
        f$valid_fap_descriptor := FALSE;
      IFEND;

      IF fap.layer_closed THEN
        RETURN; {----->
      IFEND;

      IF NOT (fap.loaded_ring IN amv$valid_ring) THEN
        f$valid_fap_descriptor := FALSE;
      IFEND;

{Now, we want to see if we can call the FAP
{     IF NOT mmp$verify_access_for_ring

    FUNCEND f$valid_fap_descriptor;
?? OLDTITLE ??
?? EJECT ??
    task_file_table_valid := TRUE;
    IF bav$task_file_table = NIL THEN
      RETURN; {----->
    IFEND;

    bad_file_count := 0;

  /check_files/
    FOR fid_ordinal := 1 TO bav$last_tft_entry DO
      IF bav$tft_entry_assignment^ (fid_ordinal, 1) = fmc$entry_assigned THEN
        tfte_p := ^bav$task_file_table^ [fid_ordinal];

{local_file_name}
        clp$check_name_for_path_handle (tfte_p^.local_file_name, handle);
        IF handle.kind = clc$not_a_path_handle THEN
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{sequence_number}
        IF (tfte_p^.sequence_number < LOWERVALUE (amt$file_id_sequence))
{     } OR (tfte_p^.sequence_number > UPPERVALUE (amt$file_id_sequence)) THEN
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{access_level}
        IF $INTEGER (tfte_p^.access_level) > $INTEGER (UPPERVALUE (amt$access_level)) THEN
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{open_ring}
        IF NOT (tfte_p^.open_ring IN amv$valid_ring) THEN
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{private_read_information}
        IF (tfte_p^.private_read_information <> NIL)
{     } AND (NOT mmp$verify_access (#LOC (tfte_p^.private_read_information), mmc$va_read)) THEN
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{global_file_information}
        IF (tfte_p^.global_file_information <> NIL)
{     } AND (NOT mmp$verify_access (#LOC (tfte_p^.global_file_information), mmc$va_read)) THEN
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{system_file_label}
        IF (tfte_p^.system_file_label <> NIL)
{     } AND (NOT mmp$verify_access (#LOC (tfte_p^.system_file_label), mmc$va_read)) THEN
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{fap_control_information}
        IF (tfte_p^.fap_control_information.fap_array = NIL) THEN
          IF NOT f$valid_fap_descriptor (tfte_p^.fap_control_information.first_fap) THEN
            bad_file_count := bad_file_count + 1;
            CYCLE /check_files/; {----->
          IFEND;
        ELSEIF mmp$verify_access (#LOC (tfte_p^.fap_control_information.fap_array), mmc$va_read) THEN
          FOR i := LOWERBOUND (tfte_p^.fap_control_information.fap_array^)
                TO UPPERBOUND (tfte_p^.fap_control_information.fap_array^) DO

            IF NOT f$valid_fap_descriptor (tfte_p^.fap_control_information.fap_array^ [i]) THEN
              bad_file_count := bad_file_count + 1;
              CYCLE /check_files/; {----->
            IFEND;
          FOREND;
        ELSE { FAP_ARRAY <> NIL AND Not accessable
          bad_file_count := bad_file_count + 1;
          CYCLE /check_files/; {----->
        IFEND;

{device_class}

      IFEND;
    FOREND /check_files/;

    task_file_table_valid := bad_file_count = 0;

  PROCEND bap$verify_task_file_table;
?? TITLE := 'emit_open_statistics', EJECT ??

  PROCEDURE [INLINE] emit_open_statistics
    (    evaluated_file_reference: fst$evaluated_file_reference;
         task_file_index: bat$tft_limit;
         global_file_information: ^bat$global_file_information;
         access_level: amt$access_level;
     VAR status: ost$status);

    VAR
      counters: array [1 .. 5] of sft$counter,
      data_size: 1 .. sfc$max_descriptive_data_size,
      descriptive_data: string (sfc$max_descriptive_data_size),
      entry: ost$positive_integers,
      ignore_device_class: rmt$device_class,
      object_info_seq: ^SEQ ( * ),
      object_info_seq_size: ost$positive_integers,
      object_information: ^fst$goi_object_information,
      resolved_path: fst$path,
      resolved_path_size: fst$path_size,
      sfid: gft$system_file_identifier,
      sfid_integer: integer;

    status.normal := TRUE;

    clp$convert_file_ref_to_string (evaluated_file_reference, {include_open_position} FALSE, resolved_path,
          resolved_path_size, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    descriptive_data := resolved_path (1, resolved_path_size);
    data_size := resolved_path_size;

    object_info_seq_size := #SIZE (fst$goi_object_information) + #SIZE (fst$goi_object) +
          #SIZE (fst$device_information) + fsc$max_path_size;
    PUSH object_info_seq: [[REP object_info_seq_size OF cell]];
    RESET object_info_seq;
    pfp$r3_get_object_information (evaluated_file_reference, information_request, {validation_criteria} NIL,
          object_info_seq, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;
    RESET object_info_seq;
    IF object_info_seq <> NIL THEN
      NEXT object_information IN object_info_seq;
      IF (object_information^.object <> NIL) AND (object_information^.object^.cycle_device_information <>
            NIL) AND object_information^.object^.cycle_device_information^.mass_storage_device_info.
            resides_online AND (object_information^.object^.cycle_device_information^.
            mass_storage_device_info.volume_list <> NIL) THEN
        descriptive_data (data_size + 1, 3) := ', (';
        data_size := data_size + 3;
        FOR entry := 1 TO UPPERBOUND (object_information^.object^.cycle_device_information^.
              mass_storage_device_info.volume_list^) DO
          descriptive_data (data_size + 1, rmc$recorded_vsn_size) :=
                object_information^.object^.cycle_device_information^.mass_storage_device_info.
                volume_list^ [entry].recorded_vsn;
          data_size := data_size + rmc$recorded_vsn_size + 1;
        FOREND;
        descriptive_data (data_size, 1) := ')';
      IFEND;
    IFEND;

    fmp$get_device_class_and_sfid (bav$task_file_table^ [task_file_index].local_file_name,
          ignore_device_class, sfid, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;
    sfid_integer := (sfid.file_entry_index * 10000(16)) + ($INTEGER (sfid.residence) * 1000(16)) +
          sfid.file_hash;

    counters [1] := sfid_integer;
    counters [2] := $INTEGER (access_level);
    counters [3] := bav$task_file_table^ [task_file_index].open_ring;
    counters [4] := #SEGMENT (bav$task_file_table^ [task_file_index].file_pva);
    counters [5] := global_file_information^.eoi_byte_address;

    sfp$emit_statistic (jml$open_file_statistics, descriptive_data (1, data_size), ^counters, status);

  PROCEND emit_open_statistics;
?? TITLE := 'establish_open_position ', EJECT ??

  PROCEDURE [INLINE] establish_open_position
    (    open_position: amt$open_position;
         caller_id: ost$caller_identifier;
         validated_access_mode: pft$usage_selections;
         delete_data: boolean;
         task_file_index: bat$tft_limit;
         global_share_mode: pft$share_selections;
         open_count: integer;
         global_file_information: ^bat$global_file_information;
         private_read_information: ^bat$private_read_information;
         device_class: rmt$device_class;
     VAR file_ptr: ^cell);

    VAR
      store_status: ost$status;

    CASE open_position OF
    = amc$open_at_eoi =
      IF private_read_information <> NIL THEN
        private_read_information^.positioning_info.record_info.file_position := amc$eoi;
        private_read_information^.positioning_info.record_info.bor_address :=
              global_file_information^.eoi_byte_address;
        private_read_information^.positioning_info.record_info.current_byte_address :=
              global_file_information^.eoi_byte_address;
      ELSE
        global_file_information^.positioning_info.record_info.file_position := amc$eoi;
        global_file_information^.positioning_info.record_info.bor_address :=
              global_file_information^.eoi_byte_address;
        global_file_information^.positioning_info.record_info.record_header_fba :=
              global_file_information^.eoi_byte_address;
        global_file_information^.positioning_info.record_info.current_byte_address :=
              global_file_information^.eoi_byte_address;
        global_file_information^.positioning_info.record_info.record_length := 0;
        global_file_information^.positioning_info.record_info.residual_record_length := 0;
        global_file_information^.positioning_info.record_info.transfer_count := 0;
      IFEND;
    = amc$open_at_boi =
      IF private_read_information <> NIL THEN
        private_read_information^.positioning_info := fmv$global_file_information.positioning_info;
      ELSE
        global_file_information^.positioning_info := fmv$global_file_information.positioning_info;
        IF open_count = 1 THEN
          IF delete_data AND (pfc$shorten IN validated_access_mode) AND
                (global_share_mode = $pft$usage_selections []) THEN
            global_file_information^.eoi_byte_address := 0;
            IF device_class = rmc$mass_storage_device THEN
              mmp$set_segment_length (file_ptr, bac$minimum_open_ring, 0, store_status);
            IFEND;
            bav$task_file_table^ [task_file_index].open_actions.open_deleted_data := TRUE;
          IFEND;
        IFEND;
      IFEND;
    = amc$open_no_positioning, amc$open_at_bop =
      IF private_read_information <> NIL THEN

{ Pick up the address saved by the last close of either private or global.

        private_read_information^.positioning_info.record_info.current_byte_address :=
              global_file_information^.asis_open_address;
        private_read_information^.positioning_info.record_info.bor_address :=
              global_file_information^.asis_bor_address;
        private_read_information^.positioning_info.record_info.file_position :=
              global_file_information^.asis_file_position;
      ELSE
        IF open_count = 1 THEN

{ Pick up the address saved by the last close of either private or global.

          IF global_file_information^.positioning_info.record_info.current_byte_address <>
                global_file_information^.asis_open_address THEN
            global_file_information^.positioning_info.record_info.current_byte_address :=
                  global_file_information^.asis_open_address;
            global_file_information^.positioning_info.record_info.bor_address :=
                  global_file_information^.asis_bor_address;
            global_file_information^.positioning_info.record_info.file_position :=
                  global_file_information^.asis_file_position;
          IFEND;

        IFEND;
      IFEND;
    ELSE
    CASEND;

  PROCEND establish_open_position;

?? TITLE := 'validate_open_parameters ', EJECT ??

  PROCEDURE [INLINE] validate_open_parameters
    (    caller_ring: ost$valid_ring;
         access_level: amt$access_level;
         file_attachment: ^fst$attachment_options;
         default_creation_attributes: ^fst$file_cycle_attributes;
         mandated_creation_attributes: ^fst$file_cycle_attributes;
         attribute_validation: ^fst$file_cycle_attributes;
         attribute_override: ^fst$file_cycle_attributes;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    status.normal := TRUE;

{ Validate_access_level_parameter
    CASE access_level OF
    = amc$record, amc$segment, amc$physical =
    ELSE
      status_reporting_procedure_ptr^ (ame$improper_access_level, '', status);
      RETURN; {----->
    CASEND;

    IF file_attachment <> NIL THEN
      fsp$validate_attachments (file_attachment, status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

    IF default_creation_attributes <> NIL THEN
      fsp$validate_attributes (default_creation_attributes, 'DEFAULT_CREATION_ATTRIBUTES',
            status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

    IF mandated_creation_attributes <> NIL THEN
      fsp$validate_attributes (mandated_creation_attributes, 'MANDATED_CREATION_ATTRIBUTES',
            status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

    IF attribute_validation <> NIL THEN
      fsp$validate_attributes (attribute_validation, 'ATTRIBUTE_VALIDATION', status_reporting_procedure_ptr,
            status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

    IF attribute_override <> NIL THEN
      fsp$validate_attributes (attribute_override, 'ATTRIBUTE_OVERRIDE', status_reporting_procedure_ptr,
            status);
    IFEND;

  PROCEND validate_open_parameters;

?? TITLE := 'initialize_file_instance ', EJECT ??

  PROCEDURE [INLINE] initialize_file_instance
    (    access_level: amt$access_level;
         caller_ring: ost$valid_ring;
     VAR task_file_index: bat$tft_limit;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      free_entry_found: boolean,
      index: integer,
      limit_str: ost$string,
      new_tft_size: bat$tft_limit,
      old_entry_assignment_pointer: ^bat$tft_entry_assignment,
      old_tft_pointer: ^bat$task_file_table,
      old_tft_size: bat$tft_limit,
      text: ost$name,
      tft_entry_p: ^bat$task_file_entry;

    status.normal := TRUE;

{ Locate_tft_entry
    IF bav$task_file_table = NIL THEN
      ALLOCATE bav$tft_entry_assignment: [bac$tft_allocation_size] IN osv$task_private_heap^;
      ALLOCATE bav$task_file_table: [1 .. #SIZE (bav$tft_entry_assignment^)] IN osv$task_private_heap^;
      bav$tft_entry_assignment^ := fmc$entry_free; { ' ' }
    IFEND;

    #SCAN (fmv$entry_free_selector, bav$tft_entry_assignment^, index, free_entry_found);
    IF NOT free_entry_found THEN
      old_tft_size := #SIZE (bav$tft_entry_assignment^);
      IF old_tft_size = bac$maximum_tft_size THEN
        clp$convert_integer_to_string (bac$maximum_tft_size, 10, FALSE, limit_str, {ignore} status);
        status_reporting_procedure_ptr^ (ame$concurrent_open_limit, limit_str.value (1, limit_str.size),
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'File', status);
        RETURN; {----->
      ELSEIF (old_tft_size + bac$tft_allocation_size) < bac$maximum_tft_size THEN
        new_tft_size := old_tft_size + bac$tft_allocation_size;
      ELSE
        new_tft_size := bac$maximum_tft_size;
      IFEND;
      old_entry_assignment_pointer := bav$tft_entry_assignment;
      old_tft_pointer := bav$task_file_table;
      ALLOCATE bav$tft_entry_assignment: [new_tft_size] IN osv$task_private_heap^;
      ALLOCATE bav$task_file_table: [1 .. #SIZE (bav$tft_entry_assignment^)] IN osv$task_private_heap^;
      bav$tft_entry_assignment^ := old_entry_assignment_pointer^;
      i#move (old_tft_pointer, bav$task_file_table, #SIZE (old_tft_pointer^));
      FREE old_tft_pointer IN osv$task_private_heap^;
      FREE old_entry_assignment_pointer IN osv$task_private_heap^;
      index := old_tft_size + 1;
    IFEND;
    task_file_index := index;
    bav$tft_entry_assignment^ (task_file_index, 1) := fmc$entry_assigned; {'A'}
    IF task_file_index > bav$last_tft_entry THEN
      bav$last_tft_entry := task_file_index;
    IFEND;

{ Initialize tft entry
    tft_entry_p := ^bav$task_file_table^ [task_file_index];
    tft_entry_p^ := bav$default_tft;
    tft_entry_p^.access_level := access_level;
    IF caller_ring < bac$minimum_load_ring THEN
      tft_entry_p^.open_ring := bac$minimum_load_ring;
    ELSE
      tft_entry_p^.open_ring := caller_ring;
    IFEND;

{ Initialize_fap_control
    tft_entry_p^.fap_control_information.first_fap := bav$default_fap_descriptor;
    tft_entry_p^.fap_control_information.fap_array := NIL;

  PROCEND initialize_file_instance;

?? TITLE := 'SEARCH_FILE_ATTACHMENT', EJECT ??

{ Evaluated_file_reference is necessary only for call to
{ validate_tape_attachment/bap$get_tape_label_attributes

  PROCEDURE [INLINE] search_file_attachment
    (    evaluated_file_reference: fst$evaluated_file_reference;
         file_attachment: ^fst$attachment_options;
     VAR single_choice_attachments: single_choice_attachments_type;
     VAR tape_attachments: array [1 .. tape_attach_choice_limit] of fst$attachment_option;
     VAR tape_attachment_specified: boolean;
     VAR access_and_share_modes_count: integer;
     VAR open_share_modes_specified: boolean;
     VAR specified_cd_attachment_options: fmt$cd_attachment_options;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      attachment_p: ^fst$attachment_option,
      i: integer,
      j: integer,
      specified: array [1 .. tape_attach_choice_limit] of boolean;

    status.normal := TRUE;
    IF pmf$job_mode () = jmc$batch THEN
      single_choice_attachments [sca_allowed_exceptions].allowed_exceptions.access_conditions :=
            -$fst$file_access_conditions [];
    IFEND;

    FOR i := LOWERBOUND (file_attachment^) TO UPPERBOUND (file_attachment^) DO
      attachment_p := ^file_attachment^ [i];
      CASE attachment_p^.selector OF
      = fsc$access_and_share_modes =
        access_and_share_modes_count := access_and_share_modes_count + 1;
      = fsc$allowed_device_classes =
        single_choice_attachments [sca_allowed_device_classes].allowed_device_classes :=
              attachment_p^.allowed_device_classes;
      = fsc$allowed_exceptions =
        single_choice_attachments [sca_allowed_exceptions].allowed_exceptions :=
              attachment_p^.allowed_exceptions;
      = fsc$create_file =
        single_choice_attachments [sca_create_file].selector := fsc$create_file;
        single_choice_attachments [sca_create_file].create_file := attachment_p^.create_file;
      = fsc$delete_data =
        single_choice_attachments [sca_delete_data].delete_data := attachment_p^.delete_data;
      = fsc$error_exit_procedure =
        single_choice_attachments [sca_error_exit_procedure].error_exit_procedure :=
              attachment_p^.error_exit_procedure;
      = fsc$error_exit_procedure_name =
        IF attachment_p^.error_exit_procedure_name <> NIL THEN
          single_choice_attachments [sca_error_exit_procedure_name].error_exit_procedure_name :=
                attachment_p^.error_exit_procedure_name;
        IFEND;
      = fsc$error_limit =
        single_choice_attachments [sca_error_limit].selector := fsc$error_limit;
        single_choice_attachments [sca_error_limit].error_limit := attachment_p^.error_limit;
      = fsc$exception_detection =
        single_choice_attachments [sca_exception_detection].exception_detection :=
              attachment_p^.exception_detection;
      = fsc$free_behind =
        specified_cd_attachment_options.free_behind_specified := TRUE;
        specified_cd_attachment_options.free_behind := attachment_p^.free_behind;
      = fsc$label_exit_procedure =
        single_choice_attachments [sca_label_exit_procedure].label_exit_procedure :=
              attachment_p^.label_exit_procedure;
      = fsc$label_exit_procedure_name =
        IF attachment_p^.label_exit_procedure_name <> NIL THEN
          single_choice_attachments [sca_label_exit_procedure_name].label_exit_procedure_name :=
                attachment_p^.label_exit_procedure_name;
        IFEND;
      = fsc$message_control =
        single_choice_attachments [sca_message_control].selector := fsc$message_control;
        single_choice_attachments [sca_message_control].message_control := attachment_p^.message_control;
      = fsc$open_position =
        single_choice_attachments [sca_open_position].selector := fsc$open_position;
        single_choice_attachments [sca_open_position].open_position := attachment_p^.open_position;
      = fsc$open_share_modes =
        open_share_modes_specified := TRUE;
      = fsc$password =
        single_choice_attachments [sca_password].selector := fsc$password;
        #TRANSLATE (osv$lower_to_upper, attachment_p^.password,
              single_choice_attachments [sca_password].password);
      = fsc$private_read =
        specified_cd_attachment_options.private_read_specified := TRUE;
        specified_cd_attachment_options.private_read := attachment_p^.private_read;
      = fsc$sequential_access =
        specified_cd_attachment_options.sequential_access_specified := TRUE;
        specified_cd_attachment_options.sequential_access := attachment_p^.sequential_access;
      = fsc$tape_attachment =
        IF NOT tape_attachment_specified THEN
{Need to initialize the tape attachment array
          FOR j := 1 TO tape_attach_choice_limit DO
            specified [j] := FALSE;
            tape_attachments [j].selector := fsc$tape_attachment;
            tape_attachments [j].tape_attachment.selector := fsc$tape_null_attachment_option;
          FOREND;
        IFEND;

        tape_attachment_specified := TRUE;
        specified [attachment_p^.tape_attachment.selector] := TRUE;
        store_tape_attachment (attachment_p^.tape_attachment, tape_attachments,
              status_reporting_procedure_ptr, status);
        IF NOT status.normal THEN
          RETURN; {----->
        IFEND;
      = fsc$tape_error_options =
        single_choice_attachments [sca_tape_error_options].selector := fsc$tape_error_options;
        single_choice_attachments [sca_tape_error_options].tape_error_options :=
              attachment_p^.tape_error_options;
      = fsc$transfer_size =
        specified_cd_attachment_options.transfer_size_specified := TRUE;
        specified_cd_attachment_options.transfer_size := attachment_p^.transfer_size;
      = fsc$validation_ring =
        single_choice_attachments [sca_validation_ring].validation_ring := attachment_p^.validation_ring;
      = fsc$wait_for_attachment =
        single_choice_attachments [sca_wait_for_attachment].wait_for_attachment :=
              attachment_p^.wait_for_attachment;
      ELSE
      CASEND;
    FOREND;

    IF (single_choice_attachments [sca_error_exit_procedure].error_exit_procedure <> NIL) AND
          ((single_choice_attachments [sca_error_exit_procedure_name].error_exit_procedure_name <> NIL) AND
          (single_choice_attachments [sca_error_exit_procedure_name].error_exit_procedure_name^.entry_point <>
          osc$null_name)) THEN
      status_reporting_procedure_ptr^ (fse$redundant_attachment_choice, ' Error_exit_procedure', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'error_exit_procedure_name', status);
      RETURN; {----->
    IFEND;
    IF (single_choice_attachments [sca_label_exit_procedure].label_exit_procedure <> NIL) AND
          ((single_choice_attachments [sca_label_exit_procedure_name].label_exit_procedure_name <> NIL) AND
          (single_choice_attachments [sca_label_exit_procedure_name].label_exit_procedure_name^.entry_point <>
          osc$null_name)) THEN
      status_reporting_procedure_ptr^ (fse$redundant_attachment_choice, ' Label_exit_procedure', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'label_exit_procedure', status);
      RETURN; {----->
    IFEND;

    IF tape_attachment_specified THEN
      validate_tape_attachments (evaluated_file_reference, specified, tape_attachments, status);
      IF NOT status.normal THEN
        status.normal := (status.condition = ame$improper_device_class);
        RETURN; {----->
      IFEND;
    IFEND;

  PROCEND search_file_attachment;
?? TITLE := 'store_tape_attachment', EJECT ??

  PROCEDURE store_tape_attachment
    (    attachment: fst$tape_attachment;
     VAR tape_attachments: array [1 .. tape_attach_choice_limit] of fst$attachment_option;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      dt: ost$date,
      status_parameter_string: string (50),
      string_length: integer;

    status.normal := TRUE;

    CASE attachment.selector OF

    = fsc$tape_block_type =
      IF (attachment.tape_block_type >= LOWERVALUE (amt$block_type)) AND
            (attachment.tape_block_type <= UPPERVALUE (amt$block_type)) THEN
        tape_attachments [fsc$tape_block_type].tape_attachment.selector := fsc$tape_block_type;
        tape_attachments [fsc$tape_block_type].tape_attachment.tape_block_type := attachment.tape_block_type;
        RETURN; {----->
      IFEND;

    = fsc$tape_buffer_offset =
      IF (attachment.tape_buffer_offset >= 0) AND (attachment.tape_buffer_offset <= amc$maximum_block) THEN
        IF attachment.tape_buffer_offset > 0 THEN
          osp$set_status_abnormal ('AM', ame$unimplemented_buffer_offset, ' ', status);
          RETURN; {----->
        IFEND;
        tape_attachments [fsc$tape_buffer_offset].tape_attachment.selector := fsc$tape_buffer_offset;
        tape_attachments [fsc$tape_buffer_offset].tape_attachment.tape_buffer_offset :=
              attachment.tape_buffer_offset;
        RETURN; {----->
      IFEND;

    = fsc$tape_character_conversion =
      IF (attachment.tape_character_conversion >= LOWERVALUE (boolean)) AND
            (attachment.tape_character_conversion <= UPPERVALUE (boolean)) THEN
        tape_attachments [fsc$tape_character_conversion].tape_attachment.selector :=
              fsc$tape_character_conversion;
        tape_attachments [fsc$tape_character_conversion].tape_attachment.tape_character_conversion :=
              attachment.tape_character_conversion;
        RETURN; {----->
      IFEND;

    = fsc$tape_character_set =
      IF (attachment.tape_character_set >= LOWERVALUE (amt$internal_code)) AND
            (attachment.tape_character_set <= UPPERVALUE (amt$internal_code)) THEN
        tape_attachments [fsc$tape_character_set].tape_attachment.selector := fsc$tape_character_set;
        tape_attachments [fsc$tape_character_set].tape_attachment.tape_character_set :=
              attachment.tape_character_set;
        RETURN; {----->
      IFEND;

    = fsc$tape_creation_date =
      dt.date_format := osc$ordinal_date;
      dt.ordinal := attachment.tape_creation_date;
      pmp$change_legible_date_format (osc$ordinal_date, dt, status);
      IF status.normal THEN
        tape_attachments [fsc$tape_creation_date].tape_attachment.selector := fsc$tape_creation_date;
        tape_attachments [fsc$tape_creation_date].tape_attachment.tape_creation_date :=
              attachment.tape_creation_date;
        RETURN; {----->
      IFEND;

    = fsc$tape_expiration_date =
      dt.date_format := osc$ordinal_date;
      dt.ordinal := attachment.tape_expiration_date;
      pmp$change_legible_date_format (osc$ordinal_date, dt, status);
      IF status.normal THEN
        tape_attachments [fsc$tape_expiration_date].tape_attachment.selector := fsc$tape_expiration_date;
        tape_attachments [fsc$tape_expiration_date].tape_attachment.tape_expiration_date :=
              attachment.tape_expiration_date;
        RETURN; {----->
      IFEND;

    = fsc$tape_file_accessibility =
      rmp$validate_ansi_string (attachment.tape_file_accessibility,
            tape_attachments [fsc$tape_file_accessibility].tape_attachment.tape_file_accessibility, status);
      IF status.normal THEN
        tape_attachments [fsc$tape_file_accessibility].tape_attachment.selector :=
              fsc$tape_file_accessibility;
        RETURN; {----->
      IFEND;

    = fsc$tape_file_identifier =
      rmp$validate_ansi_string (attachment.tape_file_identifier,
            tape_attachments [fsc$tape_file_identifier].tape_attachment.tape_file_identifier, status);
      IF status.normal THEN
        tape_attachments [fsc$tape_file_identifier].tape_attachment.selector := fsc$tape_file_identifier;
        RETURN; {----->
      IFEND;

    = fsc$tape_file_sequence_number =
      IF (attachment.tape_file_sequence_number >= 1) AND (attachment.tape_file_sequence_number <= 9999) THEN
        tape_attachments [fsc$tape_file_sequence_number].tape_attachment.selector :=
              fsc$tape_file_sequence_number;
        tape_attachments [fsc$tape_file_sequence_number].tape_attachment.tape_file_sequence_number :=
              attachment.tape_file_sequence_number;
        RETURN; {----->
      IFEND;

    = fsc$tape_file_set_identifier =
      rmp$validate_ansi_string (attachment.tape_file_set_identifier,
            tape_attachments [fsc$tape_file_set_identifier].tape_attachment.tape_file_set_identifier, status);
      IF status.normal THEN
        tape_attachments [fsc$tape_file_set_identifier].tape_attachment.selector :=
              fsc$tape_file_set_identifier;
        RETURN; {----->
      IFEND;

    = fsc$tape_file_set_position =
      IF (attachment.tape_file_set_position.position >= LOWERVALUE (fst$tape_file_set_pos_choices)) AND
            (attachment.tape_file_set_position.position <= UPPERVALUE (fst$tape_file_set_pos_choices)) THEN
        tape_attachments [fsc$tape_file_set_position].tape_attachment.selector := fsc$tape_file_set_position;
        tape_attachments [fsc$tape_file_set_position].tape_attachment.tape_file_set_position :=
              attachment.tape_file_set_position;
        IF attachment.tape_file_set_position.position = fsc$tape_file_identifier_pos THEN
          rmp$validate_ansi_string (attachment.tape_file_set_position.file_identifier,
                tape_attachments [fsc$tape_file_set_position].tape_attachment.tape_file_set_position.
                file_identifier, status);
        IFEND;
        IF status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;

    = fsc$tape_generation_number =
      IF (attachment.tape_generation_number >= 1) AND (attachment.tape_generation_number <= 9999) THEN
        tape_attachments [fsc$tape_generation_number].tape_attachment.selector := fsc$tape_generation_number;
        tape_attachments [fsc$tape_generation_number].tape_attachment.tape_generation_number :=
              attachment.tape_generation_number;
        RETURN; {----->
      IFEND;

    = fsc$tape_generation_version_num =
      IF (attachment.tape_generation_version_num >= 0) AND (attachment.tape_generation_version_num <= 99) THEN
        tape_attachments [fsc$tape_generation_version_num].tape_attachment.selector :=
              fsc$tape_generation_version_num;
        tape_attachments [fsc$tape_generation_version_num].tape_attachment.tape_generation_version_num :=
              attachment.tape_generation_version_num;
        RETURN; {----->
      IFEND;

    = fsc$tape_implementation_id =
      rmp$validate_ansi_string (attachment.tape_implementation_id,
            tape_attachments [fsc$tape_implementation_id].tape_attachment.tape_implementation_id, status);
      IF status.normal THEN
        tape_attachments [fsc$tape_implementation_id].tape_attachment.selector := fsc$tape_implementation_id;
        RETURN; {----->
      IFEND;

    = fsc$tape_label_standard_version =
      IF (attachment.tape_label_standard_version >= 0) AND (attachment.tape_label_standard_version <= 9) THEN
        tape_attachments [fsc$tape_label_standard_version].tape_attachment.selector :=
              fsc$tape_label_standard_version;
        tape_attachments [fsc$tape_label_standard_version].tape_attachment.tape_label_standard_version :=
              attachment.tape_label_standard_version;
        RETURN; {----->
      IFEND;

    = fsc$tape_max_block_length =
      IF (attachment.tape_max_block_length >= LOWERVALUE (amt$max_block_length)) AND
            (attachment.tape_max_block_length <= UPPERVALUE (amt$max_block_length)) THEN
        tape_attachments [fsc$tape_max_block_length].tape_attachment.selector := fsc$tape_max_block_length;
        tape_attachments [fsc$tape_max_block_length].tape_attachment.tape_max_block_length :=
              attachment.tape_max_block_length;
        RETURN; {----->
      IFEND;

    = fsc$tape_max_record_length =
      IF (attachment.tape_max_record_length >= LOWERVALUE (amt$max_record_length)) AND
            (attachment.tape_max_record_length <= UPPERVALUE (amt$max_record_length)) THEN
        tape_attachments [fsc$tape_max_record_length].tape_attachment.selector := fsc$tape_max_record_length;
        tape_attachments [fsc$tape_max_record_length].tape_attachment.tape_max_record_length :=
              attachment.tape_max_record_length;
        RETURN; {----->
      IFEND;

    = fsc$tape_owner_identification =
      rmp$validate_ansi_string (attachment.tape_owner_identification,
            tape_attachments [fsc$tape_owner_identification].tape_attachment.tape_owner_identification,
            status);
      IF status.normal THEN
        tape_attachments [fsc$tape_owner_identification].tape_attachment.selector :=
              fsc$tape_owner_identification;
        RETURN; {----->
      IFEND;

    = fsc$tape_padding_character =
      IF (attachment.tape_padding_character >= LOWERVALUE (amt$padding_character)) AND
            (attachment.tape_padding_character <= UPPERVALUE (amt$padding_character)) THEN
        tape_attachments [fsc$tape_padding_character].tape_attachment.selector := fsc$tape_padding_character;
        tape_attachments [fsc$tape_padding_character].tape_attachment.tape_padding_character :=
              attachment.tape_padding_character;
        RETURN; {----->
      IFEND;

    = fsc$tape_record_type =
      IF (attachment.tape_record_type >= LOWERVALUE (amt$record_type)) AND
            (attachment.tape_record_type <= UPPERVALUE (amt$record_type)) THEN
        tape_attachments [fsc$tape_record_type].tape_attachment.selector := fsc$tape_record_type;
        tape_attachments [fsc$tape_record_type].tape_attachment.tape_record_type :=
              attachment.tape_record_type;
        RETURN; {----->
      IFEND;

    = fsc$tape_removable_media_group =
      rmp$validate_ansi_string (attachment.tape_removable_media_group,
            tape_attachments [fsc$tape_removable_media_group].tape_attachment.tape_removable_media_group,
            status);
      IF status.normal THEN
        tape_attachments [fsc$tape_removable_media_group].tape_attachment.selector :=
              fsc$tape_removable_media_group;
        RETURN; {----->
      IFEND;

    = fsc$tape_rewrite_labels =
      IF (attachment.tape_rewrite_labels >= LOWERVALUE (boolean)) AND
            (attachment.tape_rewrite_labels <= UPPERVALUE (boolean)) THEN
        tape_attachments [fsc$tape_rewrite_labels].tape_attachment.selector := fsc$tape_rewrite_labels;
        tape_attachments [fsc$tape_rewrite_labels].tape_attachment.tape_rewrite_labels :=
              attachment.tape_rewrite_labels;
        RETURN; {----->
      IFEND;

    = fsc$tape_volume_accessibility =
      rmp$validate_ansi_string (attachment.tape_volume_accessibility,
            tape_attachments [fsc$tape_volume_accessibility].tape_attachment.tape_volume_accessibility,
            status);
      IF status.normal THEN
        tape_attachments [fsc$tape_volume_accessibility].tape_attachment.selector :=
              fsc$tape_volume_accessibility;
        RETURN; {----->
      IFEND;

    = fsc$tape_volume_initialization =
      IF attachment.tape_volume_initialization <> NIL THEN
        tape_attachments [fsc$tape_volume_initialization].tape_attachment.selector :=
              fsc$tape_volume_initialization;
        tape_attachments [fsc$tape_volume_initialization].tape_attachment.tape_volume_initialization :=
              attachment.tape_volume_initialization;
        RETURN; {----->
      IFEND;

    = fsc$tape_null_attachment_option, fsc$tape_block_count, fsc$tape_file_section_number,
          fsc$tape_header_labels, fsc$tape_trailer_labels =
      RETURN; {----->

    ELSE
      ;
    CASEND;

    status_reporting_procedure_ptr^ (ame$improper_file_attrib_value, 'FILE_ATTACHMENT', status);
    STRINGREP (status_parameter_string, string_length, 'TAPE_ATTACHMENT - ',
          tape_attachment_names [attachment.selector]);
    osp$append_status_parameter (osc$status_parameter_delimiter, status_parameter_string (1, string_length),
          status);

  PROCEND store_tape_attachment;
?? TITLE := 'validate_tape_attachments', EJECT ??

  PROCEDURE validate_tape_attachments
    (    evaluated_file_reference: fst$evaluated_file_reference;
         specified: array [1 .. tape_attach_choice_limit] of boolean;
     VAR tape_attachments: fst$attachment_options;
     VAR status: ost$status);

    VAR
      authorized_access: fst$file_access_options,
      blank_label_group: ^SEQ ( * ),
      command_attribute: array [1 .. 1] of fst$attachment_option,
      eof1_p: ^fst$ansi_eof1_label,
      eof2_p: ^fst$ansi_eof2_label,
      hdr1_p: ^fst$ansi_hdr1_label,
      hdr2_string: ^string (80),
      ignore_status: ost$status,
      label_identifier: fst$tape_label_identifier,
      label_locator: fst$tape_label_locator,
      label_standard_version_str: string (2),
      length: integer,
      returned_attribute: fst$tla_returned_attributes,
      rewrite_labels: boolean,
      sequence_header: ^fst$tape_label_sequence_header,
      source: fst$tape_attribute_source,
      str: ost$string,
      vol1_p: ^fst$ansi_vol1_label;

    status.normal := TRUE;

    IF NOT specified [fsc$tape_rewrite_labels] THEN
      command_attribute [1].selector := fsc$tape_attachment;
      command_attribute [1].tape_attachment.selector := fsc$tape_rewrite_labels;
      source := fsc$tla_next_position;
      bap$get_tape_label_attributes (evaluated_file_reference, source, command_attribute, returned_attribute,
            status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      rewrite_labels := command_attribute [1].tape_attachment.tape_rewrite_labels;
    ELSE
      rewrite_labels := tape_attachments [fsc$tape_rewrite_labels].tape_attachment.tape_rewrite_labels;
    IFEND;

    {  Validate file_set_position options  }

    IF specified [fsc$tape_file_set_position] THEN
      CASE tape_attachments [fsc$tape_file_set_position].tape_attachment.tape_file_set_position.position OF

      = fsc$tape_file_identifier_pos =

        IF rewrite_labels THEN

          IF specified [fsc$tape_file_sequence_number] THEN
            osp$set_status_abnormal (amc$access_method_id, ame$file_seq_number_illegal, '', status);
            RETURN; {----->
          IFEND;

        ELSE {  rewrite_labels is FALSE  }

          IF specified [fsc$tape_file_identifier] THEN
            IF (tape_attachments [fsc$tape_file_set_position].tape_attachment.tape_file_set_position.
                  file_identifier = tape_attachments [fsc$tape_file_identifier].tape_attachment.
                  tape_file_identifier) THEN
              tape_attachments [fsc$tape_file_identifier].tape_attachment.selector :=
                    fsc$tape_null_attachment_option;
            ELSE
              osp$set_status_abnormal (amc$access_method_id, ame$file_identifier_mismatch,
                    tape_attachments [fsc$tape_file_identifier].tape_attachment.tape_file_identifier, status);
              osp$append_status_parameter (osc$status_parameter_delimiter,
                    tape_attachments [fsc$tape_file_set_position].tape_attachment.tape_file_set_position.
                    file_identifier, status);
              RETURN; {----->
            IFEND;
          IFEND;

          IF specified [fsc$tape_generation_number] THEN
            IF (tape_attachments [fsc$tape_file_set_position].tape_attachment.tape_file_set_position.
                  generation_number = tape_attachments [fsc$tape_generation_number].tape_attachment.
                  tape_generation_number) THEN
              tape_attachments [fsc$tape_generation_number].tape_attachment.selector :=
                    fsc$tape_null_attachment_option;
            ELSE
              str.value := '';
              str.size := 0;
              clp$convert_integer_to_string (tape_attachments [fsc$tape_generation_number].tape_attachment.
                    tape_generation_number, 10, FALSE, str, ignore_status);
              osp$set_status_abnormal (amc$access_method_id, ame$generation_number_mismatch, str.
                    value (1, str.size), status);
              str.value := '';
              str.size := 0;
              clp$convert_integer_to_string (tape_attachments [fsc$tape_file_set_position].tape_attachment.
                    tape_file_set_position.generation_number, 10, FALSE, str, ignore_status);
              osp$append_status_parameter (osc$status_parameter_delimiter, str.value (1, str.size), status);
              RETURN; {----->
            IFEND;
          IFEND;

          IF specified [fsc$tape_file_sequence_number] THEN
            osp$set_status_abnormal (amc$access_method_id, ame$file_seq_number_illegal, '', status);
            RETURN; {----->
          IFEND;
        IFEND;

      = fsc$tape_file_sequence_pos =

        IF specified [fsc$tape_file_sequence_number] THEN
          IF (tape_attachments [fsc$tape_file_set_position].tape_attachment.tape_file_set_position.
                file_sequence_number = tape_attachments [fsc$tape_file_sequence_number].tape_attachment.
                tape_file_sequence_number) THEN
            tape_attachments [fsc$tape_file_sequence_number].tape_attachment.selector :=
                  fsc$tape_null_attachment_option;
          ELSE
            str.value := '';
            str.size := 0;
            clp$convert_integer_to_string (tape_attachments [fsc$tape_file_sequence_number].tape_attachment.
                  tape_file_sequence_number, 10, FALSE, str, ignore_status);
            osp$set_status_abnormal (amc$access_method_id, ame$file_seq_number_mismatch, str.
                  value (1, str.size), status);
            str.value := '';
            str.size := 0;
            clp$convert_integer_to_string (tape_attachments [fsc$tape_file_set_position].tape_attachment.
                  tape_file_set_position.file_sequence_number, 10, FALSE, str, ignore_status);
            osp$append_status_parameter (osc$status_parameter_delimiter, str.value (1, str.size), status);
            RETURN; {----->
          IFEND;
        IFEND;

      ELSE
        ;
      CASEND;

    IFEND;

    IF specified [fsc$tape_implementation_id] OR specified [fsc$tape_label_standard_version] THEN
      IF NOT (avp$removable_media_operator ()) THEN
        osp$set_status_abnormal ('OF', ofe$sou_not_active, 'removable_media_operator', status);
        RETURN; {----->
      IFEND;
    IFEND;

    IF specified [fsc$tape_owner_identification] AND specified [fsc$tape_removable_media_group] THEN
      osp$set_status_abnormal ('AM', rme$ambiguous_specifications, '', status);
      RETURN; {----->
    IFEND;

    IF specified [fsc$tape_volume_initialization] THEN
      IF NOT (avp$removable_media_operator ()) THEN
        osp$set_status_abnormal ('OF', ofe$sou_not_active, 'removable_media_operator', status);
        RETURN; {----->
      IFEND;
      IF tape_attachments [fsc$tape_volume_initialization].tape_attachment.tape_volume_initialization^.
            blank_label_group <> NIL THEN
        blank_label_group := tape_attachments [fsc$tape_volume_initialization].tape_attachment.
              tape_volume_initialization^.blank_label_group;
        IF specified [fsc$tape_character_set] THEN
          RESET blank_label_group;
          NEXT sequence_header IN blank_label_group;
          sequence_header^.character_set := tape_attachments [fsc$tape_character_set].tape_attachment.
                tape_character_set;
        IFEND;

        label_identifier.location_method := fsc$tape_label_locate_by_kind;
        label_identifier.label_kind := fsc$ansi_vol1_label_kind;
        fsp$locate_tape_label (blank_label_group, label_identifier, label_locator);
        IF label_locator.label_found THEN
          NEXT vol1_p IN label_locator.label_block;
          IF specified [fsc$tape_volume_accessibility] THEN
            vol1_p^.accessibility := tape_attachments [fsc$tape_volume_accessibility].tape_attachment.
                  tape_volume_accessibility;
          IFEND;
          IF specified [fsc$tape_implementation_id] THEN
            vol1_p^.implementation_identifier := tape_attachments [fsc$tape_implementation_id].
                  tape_attachment.tape_implementation_id;
          IFEND;
          IF specified [fsc$tape_owner_identification] THEN
            vol1_p^.owner_identifier := tape_attachments [fsc$tape_owner_identification].tape_attachment.
                  tape_owner_identification;
          ELSEIF specified [fsc$tape_removable_media_group] THEN
            vol1_p^.owner_identifier (1, 1) := '&';
            vol1_p^.owner_identifier (2, 13) := tape_attachments [fsc$tape_removable_media_group].
                  tape_attachment.tape_removable_media_group;
          IFEND;
          IF specified [fsc$tape_label_standard_version] THEN
            STRINGREP (label_standard_version_str, length, tape_attachments [fsc$tape_label_standard_version].
                  tape_attachment.tape_label_standard_version);
            vol1_p^.label_standard_version := label_standard_version_str (2, 1);
          IFEND;
        ELSE
          label_identifier.location_method := fsc$tape_label_locate_by_index;
          FOR label_identifier.label_index := 1 TO 3 DO
            fsp$locate_tape_label (blank_label_group, label_identifier, label_locator);
            IF (NOT label_locator.label_found) OR (label_locator.label_block_descriptor^.label_block_type <>
                  fsc$tapemark_tape_label_block) THEN { not unlabeled }
              osp$set_status_condition (ame$vol1_label_missing, status);
              RETURN; {----->
            IFEND;
          FOREND;
        IFEND;

        label_identifier.label_kind := fsc$ansi_hdr1_label_kind;
        fsp$locate_tape_label (blank_label_group, label_identifier, label_locator);
        IF label_locator.label_found THEN
          NEXT hdr1_p IN label_locator.label_block;
        ELSE
          hdr1_p := NIL;
        IFEND;
        IF specified [fsc$tape_file_accessibility] OR specified [fsc$tape_implementation_id] OR
              specified [fsc$tape_removable_media_group] THEN
          IF hdr1_p = NIL THEN
            IF specified [fsc$tape_file_accessibility] THEN
              osp$set_status_abnormal ('RM', ame$hdr1_label_missing, 'FILE_ACCESSIBILITY', status);
            ELSEIF specified [fsc$tape_implementation_id] THEN
              osp$set_status_abnormal ('RM', ame$hdr1_label_missing, 'IMPLEMENTATION_IDENTIFIER', status);
            ELSE { removable_media_group specified }
              osp$set_status_abnormal ('RM', ame$hdr1_label_missing, 'REMOVABLE_MEDIA_GROUP', status);
            IFEND;
            RETURN; {----->
          ELSE
            IF specified [fsc$tape_file_accessibility] THEN
              hdr1_p^.accessibility := tape_attachments [fsc$tape_file_accessibility].tape_attachment.
                    tape_file_accessibility;
            IFEND;
            IF specified [fsc$tape_implementation_id] THEN
              hdr1_p^.system_code := tape_attachments [fsc$tape_implementation_id].tape_attachment.
                    tape_implementation_id;
            IFEND;
            IF specified [fsc$tape_removable_media_group] AND
                  (hdr1_p^.system_code <> fsc$version_two_ve_identifier) THEN
              osp$set_status_abnormal ('RM', rme$rmg_parameter_conflict, 'IMPLEMENTATION_IDENTIFIER', status);
              RETURN; {----->
            IFEND;
          IFEND;

          label_identifier.label_kind := fsc$ansi_eof1_label_kind;
          fsp$locate_tape_label (blank_label_group, label_identifier, label_locator);
          IF label_locator.label_found THEN
            NEXT eof1_p IN label_locator.label_block;
            IF specified [fsc$tape_file_accessibility] THEN
              eof1_p^.accessibility := tape_attachments [fsc$tape_file_accessibility].tape_attachment.
                    tape_file_accessibility;
            IFEND;
            IF specified [fsc$tape_implementation_id] THEN
              eof1_p^.system_code := tape_attachments [fsc$tape_implementation_id].tape_attachment.
                    tape_implementation_id;
            IFEND;
          IFEND;
        IFEND;

        IF (hdr1_p <> NIL) AND fsp$ve_wrote_ansi_file (hdr1_p^.system_code) THEN
          label_identifier.label_kind := fsc$ansi_hdr2_label_kind;
          fsp$locate_tape_label (blank_label_group, label_identifier, label_locator);
          IF NOT label_locator.label_found THEN
            osp$set_status_condition (ame$hdr2_label_missing, status);
          IFEND;
        IFEND;
      IFEND; { blank_label_group <> NIL }

    ELSEIF specified [fsc$tape_removable_media_group] THEN
      rmp$validate_specified_rmg (evaluated_file_reference,
            tape_attachments [fsc$tape_removable_media_group].tape_attachment.tape_removable_media_group,
            authorized_access, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

  PROCEND validate_tape_attachments;
?? TITLE := 'attach_or_create_file', EJECT ??

  PROCEDURE attach_or_create_file
    (    task_file_index: bat$tft_limit;
         access_level: amt$access_level;
         file_attachment: ^fst$attachment_options;
         access_and_share_modes_count: integer;
         catalog_cycle_attributes: pft$catalog_cycle_attributes;
     VAR single_choice_attachments: {i/o} single_choice_attachments_type;
     VAR open_cleanup_work_list: fmt$open_cleanup_work_list;
     VAR evaluated_file_reference: {i/o} fst$evaluated_file_reference;
     VAR preserved_attributes: bat$system_file_attributes;
     VAR open_count: integer;
     VAR device_class: rmt$device_class;
     VAR opened_access_modes: bat$access_counts;
     VAR archive_cycle_number: fst$cycle_number;
     VAR cd_attachment_options: fmt$cd_attachment_options;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      action_taken: pft$attach_or_create_action,
      allowed_access: fst$file_access_options,
      attached_file: boolean,
      attachments: ^fst$attachment_options,
      converted_open_share_modes: pft$usage_selections,
      cycle_description_created: boolean,
      exception_selection_info: pft$exception_selection_info,
      file_previously_opened: boolean,
      fs_device_class: fst$device_class,
      global_file_information: bat$global_file_information,
      i: integer,
      ignore_cycle_description: ^fmt$cycle_description,
      j: integer,
      minimum_number_of_path_elements: 2 .. 3,
      open_position: amt$open_position,
      open_position_source: amt$attribute_source,
      open_share_modes: fst$file_access_options,
      path_ptr: ^fst$path,
      path_size: fst$path_size,
      required_sharing: fst$file_access_options,
      restricted_access_modes: pft$usage_selections,
      selected_access: fst$file_access_options,
      selected_sharing: fst$file_access_options,
      temporary_file: boolean,
      tft_entry_p: ^bat$task_file_entry,
      validation_modes: fst$file_access_options;

    status.normal := TRUE;

    temporary_file := (fsp$path_element (^evaluated_file_reference, 1) ^ = fsc$local);
{ At this point a permanent file ALIAS is considered a temporary file.
    IF temporary_file THEN
      minimum_number_of_path_elements := 2;
    ELSE
      minimum_number_of_path_elements := 3;
    IFEND;

    IF evaluated_file_reference.number_of_path_elements < minimum_number_of_path_elements THEN
      PUSH path_ptr;
      clp$convert_file_ref_to_string (evaluated_file_reference, {include_open_position} FALSE, path_ptr^,
            path_size, status);
      osp$set_status_abnormal (amc$access_method_id, pfe$path_too_short, '', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, path_ptr^ (1, path_size), status);
      osp$append_status_integer (osc$status_parameter_delimiter, minimum_number_of_path_elements, 10, FALSE,
            status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'file', status);
      RETURN; {----->
    IFEND;

    IF single_choice_attachments [sca_open_position].selector = fsc$open_position THEN
      open_position := single_choice_attachments [sca_open_position].open_position;
      open_position_source := amc$open_request;
    ELSEIF evaluated_file_reference.path_handle_info.path_handle.open_position.specified THEN
      open_position := evaluated_file_reference.path_handle_info.path_handle.open_position.value;
      open_position_source := amc$file_reference;
      evaluated_file_reference.path_handle_info.path_handle.open_position.specified := FALSE;
    ELSE
      open_position := amc$open_at_boi;
      open_position_source := amc$access_method_default;
    IFEND;

    tft_entry_p := ^bav$task_file_table^ [task_file_index];

    IF temporary_file THEN {could be an alias
{
{  In addition to resolving and creating a cycle_description for a file,
{  fmp$create_cycle_description also returns the permanent file path of an alias.
{  A cycle_description will not be created, because by definition a permanent file
{  alias already has a cycle_description.
{
      fmp$create_cycle_description ({return_cycle_description=} FALSE, evaluated_file_reference,
            cycle_description_created, ignore_cycle_description, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      IF cycle_description_created THEN
        tft_entry_p^.open_actions.open_created_file := TRUE;
      IFEND;
      temporary_file := (fsp$path_element (^evaluated_file_reference, 1) ^ = fsc$local);
{ At this point a permanent file ALIAS is NOT considered a temporary file.
    IFEND;

    IF NOT temporary_file THEN
      PUSH attachments: [1 .. number_of_single_choice_attach + access_and_share_modes_count];
      i#move (^single_choice_attachments, attachments, #SIZE (single_choice_attachments));
      IF access_and_share_modes_count > 0 THEN
        preserved_attributes.dynamic_label.access_mode_source := amc$open_request;
        j := number_of_single_choice_attach;
        FOR i := 1 TO UPPERBOUND (file_attachment^) DO
          IF file_attachment^ [i].selector = fsc$access_and_share_modes THEN
            j := j + 1;
            attachments^ [j] := file_attachment^ [i];
          IFEND;
        FOREND;
      IFEND;

      exception_selection_info.delete_data := single_choice_attachments [sca_delete_data].delete_data;
      exception_selection_info.open_position := open_position;
      exception_selection_info.open_position_source := open_position_source;
      exception_selection_info.access_level := access_level;

      pfp$r3_attach_or_create_file (single_choice_attachments [sca_validation_ring].validation_ring,
            exception_selection_info, attachments, catalog_cycle_attributes,
            evaluated_file_reference, allowed_access, selected_access, required_sharing, selected_sharing,
            action_taken, device_class, status);
      IF NOT status.normal THEN
        IF status.condition = pfe$invalid_ring_access THEN
          status_reporting_procedure_ptr^ (ame$ring_validation_error, 'attach or create', status);
        ELSEIF status.condition = fse$device_class_conflict THEN
          status_reporting_procedure_ptr^ (fse$device_class_conflict,
                amv$device_class_names [device_class].name, status);
        ELSEIF status.condition = pfe$unknown_permanent_file THEN
          status_reporting_procedure_ptr^ (ame$file_not_known, 'pf attach or create', status);
        ELSEIF (status.condition = pfe$cycle_busy) AND (action_taken <> pfc$cycle_busy_elsewhere) THEN
          { cycle is attached within the current job }
          status_reporting_procedure_ptr^ (fse$redundant_attach_conflict, 'cycle busy within job', status);
        ELSEIF (status.condition = pfe$cycle_data_resides_offline) THEN
          archive_cycle_number := evaluated_file_reference.cycle_reference.cycle_number;
        IFEND;
        RETURN; {----->
      ELSE
        IF action_taken = pfc$cycle_created THEN
          tft_entry_p^.open_actions.open_created_file := TRUE;
        ELSEIF action_taken = pfc$cycle_newly_attached THEN
          tft_entry_p^.open_actions.open_attached_file := TRUE;
        IFEND;
      IFEND;
    IFEND;

    fmp$get_cd_info (evaluated_file_reference, {increment_open_count} TRUE, {lock_path_table} temporary_file,
          open_cleanup_work_list, preserved_attributes, global_file_information, attached_file,
          file_previously_opened, device_class, cd_attachment_options, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF temporary_file THEN
      fsp$convert_device_class_to_fs (device_class, fs_device_class);
      IF NOT (fs_device_class IN single_choice_attachments [sca_allowed_device_classes].
            allowed_device_classes) THEN
        status_reporting_procedure_ptr^ (fse$device_class_conflict, amv$device_class_names [device_class].
              name, status);
        RETURN; {----->
      IFEND;
    IFEND;

    open_count := global_file_information.open_count;
    opened_access_modes := global_file_information.opened_access_modes;
    tft_entry_p^.initial_open := NOT file_previously_opened;

    IF open_position_source <> amc$access_method_default THEN
      preserved_attributes.dynamic_label.open_position := open_position;
      preserved_attributes.dynamic_label.open_position_source := open_position_source;
    IFEND;

    IF (preserved_attributes.dynamic_label.open_position_source = amc$access_method_default) AND
          temporary_file THEN
      IF (fsp$path_element (^evaluated_file_reference, 2) ^ = 'OUTPUT') THEN
        preserved_attributes.dynamic_label.open_position := amc$open_at_eoi;
      IFEND;
    IFEND;

    merge_attachments (single_choice_attachments, preserved_attributes.dynamic_label,
          status_reporting_procedure_ptr, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF attached_file THEN
      IF open_count = 1 THEN
        IF temporary_file THEN
          assign_access_modes (file_attachment, preserved_attributes.descriptive_label.global_access_mode,
                preserved_attributes.dynamic_label.access_mode,
                preserved_attributes.dynamic_label.access_mode_source);
        ELSE
          #UNCHECKED_CONVERSION (selected_access, preserved_attributes.dynamic_label.access_mode);
          preserved_attributes.dynamic_label.access_mode_source := amc$open_request;
        IFEND;

      ELSE
        determine_open_share_modes (global_file_information.prevented_open_access_modes, open_share_modes);
        IF temporary_file THEN
          IF fsp$strictly_null_device (device_class, fsp$path_element (^evaluated_file_reference, 2) ^) THEN
            open_share_modes := -$fst$file_access_options [];
          IFEND;
          #UNCHECKED_CONVERSION (open_share_modes, converted_open_share_modes);
          restricted_access_modes := converted_open_share_modes *
                preserved_attributes.descriptive_label.global_access_mode;
          #UNCHECKED_CONVERSION (restricted_access_modes, validation_modes);
          validate_access_modes (file_attachment, validation_modes,
                preserved_attributes.dynamic_label.access_mode,
                preserved_attributes.dynamic_label.access_mode_source, status_reporting_procedure_ptr,
                status);
          IF NOT status.normal THEN
            RETURN; {----->
          IFEND;
        ELSEIF selected_access <= open_share_modes THEN
          #UNCHECKED_CONVERSION (selected_access, preserved_attributes.dynamic_label.access_mode);
          preserved_attributes.dynamic_label.access_mode_source := amc$open_request;
        ELSE
          access_or_share_conflict (fse$concurrent_access_conflict, (open_share_modes * allowed_access),
                selected_access, status_reporting_procedure_ptr, status);
          RETURN; {----->
        IFEND;
      IFEND;
    ELSE
      { validate creation of a temporary file }
      { (a permanent file should always be attached by this time) }

      IF (device_class = rmc$mass_storage_device) AND (single_choice_attachments [sca_create_file].selector =
            fsc$create_file) AND (NOT single_choice_attachments [sca_create_file].create_file) THEN
        IF tft_entry_p^.open_actions.open_created_file THEN
          status_reporting_procedure_ptr^ (ame$file_not_known,
                'create_file cannot be false for temporary files', status);
        ELSE
          status_reporting_procedure_ptr^ (ame$new_file_requires_append,
                'create_file cannot be false for temporary files', status);
        IFEND;
        RETURN; {----->
      ELSE
        validate_temp_creation (file_attachment, device_class,
              preserved_attributes.descriptive_label.global_access_mode,
              preserved_attributes.dynamic_label.access_mode, preserved_attributes.dynamic_label.
              access_mode_source, status_reporting_procedure_ptr, status);
        IF NOT status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;
    IFEND;

    clp$construct_path_handle_name (evaluated_file_reference.path_handle_info.path_handle,
          tft_entry_p^.local_file_name);

  PROCEND attach_or_create_file;
?? TITLE := 'assign_access_modes', EJECT ??

  PROCEDURE [INLINE] assign_access_modes
    (    file_attachment: ^fst$attachment_options;
         global_access_modes: pft$usage_selections;
     VAR instance_access_modes: pft$usage_selections;
     VAR instance_access_modes_source: amt$attribute_source);

    VAR
      access_modes_found: boolean,
      i: integer;

    i := 1;
    access_modes_found := FALSE;
    IF file_attachment <> NIL THEN
      WHILE (NOT access_modes_found) AND (i <= UPPERBOUND (file_attachment^)) DO
        IF file_attachment^ [i].selector = fsc$access_and_share_modes THEN
          IF file_attachment^ [i].access_modes.selector = fsc$specific_access_modes THEN
            #UNCHECKED_CONVERSION (file_attachment^ [i].access_modes.value, instance_access_modes);
            instance_access_modes_source := amc$open_request;
            access_modes_found := TRUE;
          ELSEIF file_attachment^ [i].access_modes.selector = fsc$permitted_access_modes THEN
            instance_access_modes := global_access_modes;
            instance_access_modes_source := amc$access_method_default;
            access_modes_found := TRUE;
          IFEND;
        IFEND;
        i := i + 1;
      WHILEND;
    IFEND;
  PROCEND assign_access_modes;

?? TITLE := 'determine_open_share_modes', EJECT ??

  PROCEDURE [INLINE] determine_open_share_modes
    (    prevented_open_access_modes: bat$access_counts;
     VAR open_share_modes: fst$file_access_options);

    VAR
      access_mode: fst$file_access_option;

    open_share_modes := $fst$file_access_options [];

    FOR access_mode := LOWERVALUE (fst$file_access_option) TO UPPERVALUE (fst$file_access_option) DO
      IF prevented_open_access_modes [access_mode] = 0 THEN
        open_share_modes := open_share_modes + $fst$file_access_options [access_mode];
      IFEND;
    FOREND;
  PROCEND determine_open_share_modes;

?? TITLE := 'merge_attachments', EJECT ??

  PROCEDURE [INLINE] merge_attachments
    (    single_choice_attachments: single_choice_attachments_type;
     VAR dynamic_label: bat$dynamic_label_attributes;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      i: integer,
      translated_name: pmt$program_name;

    status.normal := TRUE;

    IF single_choice_attachments [sca_error_exit_procedure_name].error_exit_procedure_name <> NIL THEN
      #TRANSLATE (osv$lower_to_upper, single_choice_attachments [sca_error_exit_procedure_name].
            error_exit_procedure_name^.entry_point, translated_name);
    IFEND;
    IF (dynamic_label.error_exit_name_source = amc$file_command) AND
          ((single_choice_attachments [sca_error_exit_procedure].error_exit_procedure <> NIL) OR
          ((single_choice_attachments [sca_error_exit_procedure_name].error_exit_procedure_name <> NIL) AND
          (translated_name <> dynamic_label.error_exit_name))) THEN
      status_reporting_procedure_ptr^ (fse$redundant_attachment_choice, ' Error_exit_procedure', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'error_exit_procedure_name', status);
      RETURN; {----->
    ELSE
      IF single_choice_attachments [sca_error_exit_procedure].error_exit_procedure <> NIL THEN
        dynamic_label.error_exit_procedure := single_choice_attachments [sca_error_exit_procedure].
              error_exit_procedure;
        dynamic_label.error_exit_procedure_source := amc$open_request;
      IFEND;
      IF single_choice_attachments [sca_error_exit_procedure_name].error_exit_procedure_name <> NIL THEN
        dynamic_label.error_exit_name := translated_name;
        dynamic_label.error_exit_name_source := amc$open_request;
      IFEND;
    IFEND;

    IF single_choice_attachments [sca_label_exit_procedure_name].label_exit_procedure_name <> NIL THEN
      #TRANSLATE (osv$lower_to_upper, single_choice_attachments [sca_label_exit_procedure_name].
            label_exit_procedure_name^.entry_point, translated_name);
    IFEND;
    IF (dynamic_label.label_exit_name_source = amc$file_command) AND
          ((single_choice_attachments [sca_label_exit_procedure].label_exit_procedure <> NIL) OR
          ((single_choice_attachments [sca_label_exit_procedure_name].label_exit_procedure_name <> NIL) AND
          (translated_name <> dynamic_label.label_exit_name))) THEN
      status_reporting_procedure_ptr^ (fse$redundant_attachment_choice, ' Label_exit_procedure', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'label_exit_procedure_name', status);
      RETURN; {----->
    ELSE
      IF single_choice_attachments [sca_label_exit_procedure].label_exit_procedure <> NIL THEN
        dynamic_label.label_exit_procedure := single_choice_attachments [sca_label_exit_procedure].
              label_exit_procedure;
        dynamic_label.label_exit_procedure_source := amc$open_request;
      IFEND;
      IF single_choice_attachments [sca_label_exit_procedure_name].label_exit_procedure_name <> NIL THEN
        dynamic_label.label_exit_name := translated_name;
        dynamic_label.label_exit_name_source := amc$open_request;
      IFEND;
    IFEND;

    IF single_choice_attachments [sca_error_limit].selector = fsc$error_limit THEN
      dynamic_label.error_limit := single_choice_attachments [sca_error_limit].error_limit;
      dynamic_label.error_limit_source := amc$open_request;
    IFEND;

    IF single_choice_attachments [sca_message_control].selector = fsc$message_control THEN
      dynamic_label.message_control := single_choice_attachments [sca_message_control].message_control;
      dynamic_label.message_control_source := amc$open_request;
    IFEND;

    IF single_choice_attachments [sca_tape_error_options].selector = fsc$tape_error_options THEN
      dynamic_label.error_options := single_choice_attachments [sca_tape_error_options].tape_error_options;
      dynamic_label.error_options_source := amc$open_request;
    IFEND;

  PROCEND merge_attachments;

?? TITLE := 'validate_access_modes', EJECT ??

  PROCEDURE [INLINE] validate_access_modes
    (    file_attachment: ^fst$attachment_options;
         validation_access_modes: fst$file_access_options;
     VAR instance_access_modes: pft$usage_selections;
     VAR instance_access_modes_source: amt$attribute_source;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      access_and_share_modes_index: integer,
      access_and_share_specified: boolean,
      i: integer,
      setfa_access_modes: fst$file_access_options,
      valid_access_modes_found: boolean;

    status.normal := TRUE;
    i := 0;
    access_and_share_specified := FALSE;
    valid_access_modes_found := FALSE;
    IF file_attachment <> NIL THEN
      REPEAT
        i := i + 1;
        IF file_attachment^ [i].selector = fsc$access_and_share_modes THEN
          access_and_share_specified := TRUE;
          access_and_share_modes_index := i;
          IF file_attachment^ [i].access_modes.selector = fsc$permitted_access_modes THEN
            #UNCHECKED_CONVERSION (validation_access_modes, instance_access_modes);
            instance_access_modes_source := amc$access_method_default;
            valid_access_modes_found := TRUE;
          ELSEIF (file_attachment^ [i].access_modes.selector = fsc$specific_access_modes) AND
                (file_attachment^ [i].access_modes.value <= validation_access_modes) THEN
            #UNCHECKED_CONVERSION (file_attachment^ [i].access_modes.value, instance_access_modes);
            instance_access_modes_source := amc$open_request;
            valid_access_modes_found := TRUE;
          IFEND;
        IFEND;
      UNTIL valid_access_modes_found OR (i = UPPERBOUND (file_attachment^));
    IFEND;

    IF access_and_share_specified THEN
      IF NOT valid_access_modes_found THEN
        access_or_share_conflict (fse$concurrent_access_conflict, validation_access_modes,
              file_attachment^ [access_and_share_modes_index].access_modes.value,
              status_reporting_procedure_ptr, status);
      ELSEIF (instance_access_modes_source = amc$access_method_default) AND
            (instance_access_modes = $pft$usage_selections []) THEN
        status_reporting_procedure_ptr^ (fse$concurrent_access_conflict, 'NONE', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'PERMITTED', status);
      IFEND;
    ELSEIF validation_access_modes = $fst$file_access_options [] THEN
      IF instance_access_modes_source = amc$access_method_default THEN
        status_reporting_procedure_ptr^ (fse$concurrent_access_conflict, 'NONE', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'DEFAULT', status);
      ELSEIF (instance_access_modes_source = amc$file_command) AND
            (instance_access_modes <> $pft$usage_selections []) THEN
        #UNCHECKED_CONVERSION (instance_access_modes, setfa_access_modes);
        access_or_share_conflict (fse$concurrent_access_conflict, validation_access_modes, setfa_access_modes,
              status_reporting_procedure_ptr, status);
      IFEND;
    ELSEIF instance_access_modes_source = amc$access_method_default THEN
      #UNCHECKED_CONVERSION (validation_access_modes, instance_access_modes);
    IFEND;

  PROCEND validate_access_modes;

?? TITLE := 'validate_temp_creation', EJECT ??

  PROCEDURE [INLINE] validate_temp_creation
    (    file_attachment: ^fst$attachment_options;
         device_class: rmt$device_class;
         global_access_modes: pft$usage_selections;
     VAR instance_access_modes: pft$usage_selections;
     VAR instance_access_modes_source: amt$attribute_source;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      access_and_share_specified: boolean,
      i: integer,
      valid_access_modes_found: boolean;

    status.normal := TRUE;
    i := 1;
    access_and_share_specified := FALSE;
    valid_access_modes_found := FALSE;
    IF file_attachment <> NIL THEN
      WHILE (NOT valid_access_modes_found) AND (i <= UPPERBOUND (file_attachment^)) DO
        IF file_attachment^ [i].selector = fsc$access_and_share_modes THEN
          access_and_share_specified := TRUE;
          IF (file_attachment^ [i].access_modes.selector = fsc$specific_access_modes) AND
                ((fsc$append IN file_attachment^ [i].access_modes.value) OR
                (device_class <> rmc$mass_storage_device)) THEN
            #UNCHECKED_CONVERSION (file_attachment^ [i].access_modes.value, instance_access_modes);
            instance_access_modes_source := amc$open_request;
            valid_access_modes_found := TRUE;
          ELSEIF file_attachment^ [i].access_modes.selector = fsc$permitted_access_modes THEN
            instance_access_modes := global_access_modes;
            instance_access_modes_source := amc$open_request;
            valid_access_modes_found := TRUE;
          IFEND;
        IFEND;
        i := i + 1;
      WHILEND;
    IFEND;
    IF access_and_share_specified THEN
      IF NOT valid_access_modes_found THEN
        status_reporting_procedure_ptr^ (ame$new_file_requires_append, 'temporary create', status);
      IFEND;
    ELSEIF instance_access_modes_source = amc$access_method_default THEN
      instance_access_modes := global_access_modes;
    IFEND;

  PROCEND validate_temp_creation;

?? TITLE := 'process_file_attributes', EJECT ??

  PROCEDURE process_file_attributes
    (    evaluated_file_reference: fst$evaluated_file_reference;
         access_level: amt$access_level;
         default_creation_attributes: ^fst$file_cycle_attributes;
         mandated_creation_attributes: ^fst$file_cycle_attributes;
         attribute_validation: ^fst$file_cycle_attributes;
         attribute_override: ^fst$file_cycle_attributes;
         validation_ring: ost$valid_ring;
         caller_ring: ost$valid_ring;
         file_previously_opened: boolean;
         device_class: rmt$device_class;
     VAR merged_tape_attributes {input, output} : fst$tape_attachment_information;
     VAR preserved_attributes {input, output} : bat$system_file_attributes;
     VAR instance_attributes: bat$instance_attributes;
     VAR access_mode_includes_write: boolean;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      attributes_validated: boolean,
      target_exists: boolean,
      target_static_attrs: ^bat$static_label_attributes;

    status.normal := TRUE;
    attributes_validated := FALSE;
    target_exists := FALSE;

    { The following chart shows the action taken with respect to validating
    { attributes:
    { SUBJECT  TARGET         ACTION
    { new      new            no validation
    { new      old            validate target
    { old      new            no validation
    { old      old            validate target
    { new      no connection  no validation
    { old      no connection  validate subject

    IF device_class = rmc$connected_file_device THEN
      PUSH target_static_attrs;
      get_connected_file_attributes (evaluated_file_reference, target_static_attrs^, target_exists, status);
      IF target_exists AND (attribute_validation <> NIL) AND
            (NOT ((evaluated_file_reference.path_handle_info.path_handle.segment_offset =
            clv$standard_files [clc$sf_null_file].path_handle.segment_offset) AND
            (evaluated_file_reference.path_handle_info.path_handle.assignment_counter =
            clv$standard_files [clc$sf_null_file].path_handle.assignment_counter))) THEN
        validate_attributes (attribute_validation, access_mode_includes_write, target_static_attrs^,
              status_reporting_procedure_ptr, status);
        attributes_validated := TRUE;
      IFEND;
    ELSEIF device_class = rmc$magnetic_tape_device THEN
      bap$merge_tape_attributes (default_creation_attributes, mandated_creation_attributes,
            merged_tape_attributes, preserved_attributes.static_label);
      IF merged_tape_attributes.file_set_position_source = fsc$tape_label_attr_command THEN
        IF merged_tape_attributes.file_set_position.position = fsc$tape_file_identifier_pos THEN
          IF (NOT (fsc$fsp_file_identifier IN merged_tape_attributes.supplied_file_set_pos_fields)) AND
                (merged_tape_attributes.file_identifier_source = fsc$tape_label_attr_default) THEN
            bap$set_evaluated_file_abnormal (evaluated_file_reference, ame$file_identifier_required, '', '',
                  status);
            RETURN; {----->
          IFEND;
        ELSEIF merged_tape_attributes.file_set_position.position = fsc$tape_file_sequence_pos THEN
          IF (NOT (fsc$fsp_file_sequence_number IN merged_tape_attributes.supplied_file_set_pos_fields)) AND
                (merged_tape_attributes.file_sequence_number_source = fsc$tape_label_attr_default) THEN
            bap$set_evaluated_file_abnormal (evaluated_file_reference, ame$file_seq_number_required, '', '',
                  status);
            RETURN; {----->
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF file_previously_opened THEN
      validate_access_at_open (validation_ring, caller_ring,
            preserved_attributes.static_label.ring_attributes,
            preserved_attributes.descriptive_label.global_access_mode,
            preserved_attributes.dynamic_label.access_mode_source = amc$access_method_default,
            preserved_attributes.dynamic_label.access_mode, access_mode_includes_write,
            status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      assign_instance_attributes (preserved_attributes, instance_attributes);
    ELSE
      IF mandated_creation_attributes <> NIL THEN
        bap$merge_open_attributes (mandated_creation_attributes, amc$open_request,
              preserved_attributes.static_label, status_reporting_procedure_ptr, status);
        IF NOT status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;
      IF default_creation_attributes <> NIL THEN
        bap$merge_open_attributes (default_creation_attributes, amc$file_request,
              preserved_attributes.static_label, status_reporting_procedure_ptr, status);
        IF NOT status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;
      set_default_attributes (access_level, device_class, validation_ring, preserved_attributes.static_label);
      validate_merged_static_attr (validation_ring, preserved_attributes.static_label, device_class,
            status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      validate_access_at_open (validation_ring, caller_ring,
            preserved_attributes.static_label.ring_attributes,
            preserved_attributes.descriptive_label.global_access_mode,
            preserved_attributes.dynamic_label.access_mode_source = amc$access_method_default,
            preserved_attributes.dynamic_label.access_mode, access_mode_includes_write,
            status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      assign_instance_attributes (preserved_attributes, instance_attributes);
    IFEND;

    IF (NOT attributes_validated) AND (attribute_validation <> NIL) AND (NOT (
    {NOT $NULL
    (evaluated_file_reference.path_handle_info.path_handle.segment_offset =
          clv$standard_files [clc$sf_null_file].path_handle.segment_offset) AND
          (evaluated_file_reference.path_handle_info.path_handle.assignment_counter =
          clv$standard_files [clc$sf_null_file].path_handle.assignment_counter))) THEN
      validate_attributes (attribute_validation, access_mode_includes_write,
            preserved_attributes.static_label, status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

    IF attribute_override <> NIL THEN
      override_attributes (access_level, caller_ring, device_class, attribute_override,
            access_mode_includes_write, preserved_attributes.dynamic_label.access_mode,
            preserved_attributes.dynamic_label.open_position, instance_attributes.static_label,
            status_reporting_procedure_ptr, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    IFEND;

{   validate_fo_access_level
    IF (instance_attributes.static_label.file_organization IN amv$aam_file_organizations) AND
          (access_level <> amc$record) THEN
      status_reporting_procedure_ptr^ (ame$fo_access_level_conflict,
            amv$file_organization_names [instance_attributes.static_label.file_organization].name, status);
      RETURN; {----->
    IFEND;

{   default_open_position
    IF (device_class = rmc$mass_storage_device) AND ((instance_attributes.dynamic_label.open_position_source =
          amc$access_method_default) OR (instance_attributes.dynamic_label.open_position_source =
          amc$undefined_attribute)) AND (instance_attributes.dynamic_label.access_mode =
          $pft$usage_selections [pfc$append]) THEN
      instance_attributes.dynamic_label.open_position := amc$open_at_eoi;
      instance_attributes.dynamic_label.open_position_source := amc$open_request;
    IFEND;

    validate_device_class (device_class, instance_attributes.static_label.file_organization, access_level,
          status_reporting_procedure_ptr, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

  PROCEND process_file_attributes;

?? TITLE := 'PROCEDURE get_catalog_cycle_attributes', EJECT ??

  PROCEDURE [INLINE] get_catalog_cycle_attributes
    (    mandated_creation_attributes: ^fst$file_cycle_attributes;
         default_creation_attributes: ^fst$file_cycle_attributes;
     VAR catalog_cycle_attributes: pft$catalog_cycle_attributes);

    VAR
      attribute_index: integer,
      attribute_p: ^fst$file_cycle_attribute,
      retention_mandated: boolean,
      retention_specified: boolean,
      retrieve_option_mandated: boolean,
      site_archive_option_mandated: boolean,
      site_backup_option_mandated: boolean,
      site_release_option_mandated: boolean;

    retention_mandated := FALSE;
    retention_specified := FALSE;
    retrieve_option_mandated := FALSE;
    site_archive_option_mandated := FALSE;
    site_backup_option_mandated := FALSE;
    site_release_option_mandated := FALSE;

    IF fmv$default_new_retention = NIL THEN
      catalog_cycle_attributes.retention.selector := fsc$retention_day_increment;
      catalog_cycle_attributes.retention.day_increment := 999;
    ELSE
      catalog_cycle_attributes.retention := fmv$default_new_retention^;
    IFEND;

    catalog_cycle_attributes.retrieve_option := pfc$always_retrieve;
    catalog_cycle_attributes.site_backup_option := pfc$null_site_backup_option;
    catalog_cycle_attributes.site_archive_option := pfc$null_site_archive_option;
    catalog_cycle_attributes.site_release_option := pfc$null_site_release_option;

    IF mandated_creation_attributes <> NIL THEN
      FOR attribute_index := 1 TO UPPERBOUND (mandated_creation_attributes^) DO
        attribute_p := ^mandated_creation_attributes^ [attribute_index];
        CASE attribute_p^.selector OF
        = fsc$retention =
          catalog_cycle_attributes.retention := attribute_p^.retention;
          retention_mandated := TRUE;
        = fsc$retrieve_option =
          catalog_cycle_attributes.retrieve_option := attribute_p^.retrieve_option;
          retrieve_option_mandated := TRUE;
        = fsc$site_archive_option =
          catalog_cycle_attributes.site_archive_option := attribute_p^.site_archive_option;
          site_archive_option_mandated := TRUE;
        = fsc$site_backup_option =
          catalog_cycle_attributes.site_backup_option := attribute_p^.site_backup_option;
          site_backup_option_mandated := TRUE;
        = fsc$site_release_option =
          catalog_cycle_attributes.site_release_option := attribute_p^.site_release_option;
          site_release_option_mandated := TRUE;
        ELSE
        CASEND;
      FOREND;
    IFEND;

    IF default_creation_attributes <> NIL THEN
      FOR attribute_index := 1 TO UPPERBOUND (default_creation_attributes^) DO
        attribute_p := ^default_creation_attributes^ [attribute_index];
        CASE attribute_p^.selector OF
        = fsc$retention =
          IF NOT retention_mandated THEN
            catalog_cycle_attributes.retention := attribute_p^.retention;
          IFEND;
        = fsc$retrieve_option =
          IF NOT retrieve_option_mandated THEN
            catalog_cycle_attributes.retrieve_option := attribute_p^.retrieve_option;
          IFEND;
        = fsc$site_archive_option =
          IF NOT site_archive_option_mandated THEN
            catalog_cycle_attributes.site_archive_option := attribute_p^.site_archive_option;
          IFEND;
        = fsc$site_backup_option =
          IF NOT site_backup_option_mandated THEN
            catalog_cycle_attributes.site_backup_option := attribute_p^.site_backup_option;
          IFEND;
        = fsc$site_release_option =
          IF NOT site_release_option_mandated THEN
            catalog_cycle_attributes.site_release_option := attribute_p^.site_release_option;
          IFEND;
        ELSE
        CASEND;
      FOREND;
    IFEND;

  PROCEND get_catalog_cycle_attributes;

?? TITLE := 'get_connected_file_attributes', EJECT ??

  PROCEDURE get_connected_file_attributes
    (    evaluated_file_reference: fst$evaluated_file_reference;
     VAR target_static_attrs: bat$static_label_attributes;
     VAR target_exists: boolean;
     VAR status: ost$status);

    VAR
      get_item_p: ^amt$get_item,
      path: fst$path,
      path_size: fst$path_size,
      target_cpn: amt$compression_procedure_name,
      target_hpn: amt$hashing_procedure_name,
      target_lr: amt$log_residence,
      target_attr: array [1 .. 47] of amt$get_item,
      target_contains_data,
      target_local_file: boolean,
      i: integer;

    target_attr [1].key := amc$average_record_length;
    target_attr [2].key := amc$block_type;
    target_attr [3].key := amc$character_conversion;
    target_attr [4].key := amc$clear_space;
    target_attr [5].key := amc$collate_table_name;
    target_attr [6].key := amc$data_padding;
    target_attr [7].key := amc$embedded_key;
    target_attr [8].key := amc$estimated_record_count;
    target_attr [9].key := amc$file_access_procedure;
    target_attr [10].key := amc$file_contents;
    target_attr [11].key := amc$file_limit;
    target_attr [12].key := amc$file_organization;
    target_attr [13].key := amc$file_processor;
    target_attr [14].key := amc$file_structure;
    target_attr [15].key := amc$forced_write;
    target_attr [16].key := amc$index_levels;
    target_attr [17].key := amc$index_padding;
    target_attr [18].key := amc$internal_code;
    target_attr [19].key := amc$key_length;
    target_attr [20].key := amc$key_position;
    target_attr [21].key := amc$key_type;
    target_attr [22].key := amc$label_type;
    target_attr [23].key := amc$line_number;
    target_attr [24].key := amc$max_block_length;
    target_attr [25].key := amc$max_record_length;
    target_attr [26].key := amc$min_block_length;
    target_attr [27].key := amc$min_record_length;
    target_attr [28].key := amc$padding_character;
    target_attr [29].key := amc$page_format;
    target_attr [30].key := amc$page_length;
    target_attr [31].key := amc$page_width;
    target_attr [32].key := amc$preset_value;
    target_attr [33].key := amc$record_limit;
    target_attr [34].key := amc$records_per_block;
    target_attr [35].key := amc$record_type;
    target_attr [36].key := amc$ring_attributes;
    target_attr [37].key := amc$statement_identifier;
    target_attr [38].key := amc$user_info;
    target_attr [39].key := amc$vertical_print_density;
    target_attr [40].key := amc$compression_procedure_name;
    target_attr [41].key := amc$dynamic_home_block_space;
    target_attr [42].key := amc$hashing_procedure_name;
    target_attr [43].key := amc$initial_home_block_count;
    target_attr [44].key := amc$loading_factor;
    target_attr [45].key := amc$lock_expiration_time;
    target_attr [46].key := amc$logging_options;
    target_attr [47].key := amc$log_residence;

    target_attr [40].compression_procedure_name := ^target_cpn;
    target_attr [42].hashing_procedure_name := ^target_hpn;
    target_attr [47].log_residence := ^target_lr;

    clp$convert_file_ref_to_string (evaluated_file_reference, {include_open_position} FALSE, path, path_size,
          status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    amp$get_file_attributes (path (1, path_size), target_attr, target_local_file, target_exists,
          target_contains_data, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    FOR i := LOWERBOUND (target_attr) TO UPPERBOUND (target_attr) DO
      get_item_p := ^target_attr [i];
      CASE get_item_p^.key OF
      = amc$average_record_length =
        target_static_attrs.average_record_length := get_item_p^.average_record_length;
      = amc$block_type =
        target_static_attrs.block_type := get_item_p^.block_type;
      = amc$character_conversion =
        target_static_attrs.character_conversion := get_item_p^.character_conversion;
      = amc$clear_space =
        target_static_attrs.clear_space := get_item_p^.clear_space;
      = amc$collate_table_name =
        target_static_attrs.collate_table_name := get_item_p^.collate_table_name;
      = amc$data_padding =
        target_static_attrs.data_padding := get_item_p^.data_padding;
      = amc$embedded_key =
        target_static_attrs.embedded_key := get_item_p^.embedded_key;
      = amc$estimated_record_count =
        target_static_attrs.estimated_record_count := get_item_p^.estimated_record_count;
      = amc$file_access_procedure =
        target_static_attrs.file_access_procedure := get_item_p^.file_access_procedure;
      = amc$file_contents =
        target_static_attrs.file_contents := get_item_p^.file_contents;
      = amc$file_limit =
        target_static_attrs.file_limit := get_item_p^.file_limit;
      = amc$file_organization =
        target_static_attrs.file_organization := get_item_p^.file_organization;
      = amc$file_processor =
        target_static_attrs.file_processor := get_item_p^.file_processor;
      = amc$file_structure =
        target_static_attrs.file_structure := get_item_p^.file_structure;
      = amc$forced_write =
        target_static_attrs.forced_write := get_item_p^.forced_write;
      = amc$index_levels =
        target_static_attrs.index_levels := get_item_p^.index_levels;
      = amc$index_padding =
        target_static_attrs.index_padding := get_item_p^.index_padding;
      = amc$internal_code =
        target_static_attrs.internal_code := get_item_p^.internal_code;
      = amc$key_length =
        target_static_attrs.key_length := get_item_p^.key_length;
      = amc$key_position =
        target_static_attrs.key_position := get_item_p^.key_position;
      = amc$key_type =
        target_static_attrs.key_type := get_item_p^.key_type;
      = amc$label_type =
        target_static_attrs.label_type := get_item_p^.label_type;
      = amc$line_number =
        target_static_attrs.line_number := get_item_p^.line_number;
      = amc$max_block_length =
        target_static_attrs.max_block_length := get_item_p^.max_block_length;
      = amc$max_record_length =
        target_static_attrs.max_record_length := get_item_p^.max_record_length;
      = amc$min_block_length =
        target_static_attrs.min_block_length := get_item_p^.min_block_length;
      = amc$min_record_length =
        target_static_attrs.min_record_length := get_item_p^.min_record_length;
      = amc$padding_character =
        target_static_attrs.padding_character := get_item_p^.padding_character;
      = amc$page_format =
        target_static_attrs.page_format := get_item_p^.page_format;
      = amc$page_length =
        target_static_attrs.page_length := get_item_p^.page_length;
      = amc$page_width =
        target_static_attrs.page_width := get_item_p^.page_width;
      = amc$preset_value =
        target_static_attrs.preset_value := get_item_p^.preset_value;
      = amc$record_limit =
        target_static_attrs.record_limit := get_item_p^.record_limit;
      = amc$records_per_block =
        target_static_attrs.records_per_block := get_item_p^.records_per_block;
      = amc$record_type =
        target_static_attrs.record_type := get_item_p^.record_type;
      = amc$ring_attributes =
        target_static_attrs.ring_attributes := get_item_p^.ring_attributes;
      = amc$statement_identifier =
        target_static_attrs.statement_identifier := get_item_p^.statement_identifier;
      = amc$user_info =
        target_static_attrs.user_info := get_item_p^.user_info;
      = amc$vertical_print_density =
        target_static_attrs.vertical_print_density := get_item_p^.vertical_print_density;
      = amc$compression_procedure_name =
        IF get_item_p^.compression_procedure_name <> NIL THEN
          target_static_attrs.compression_procedure_name := get_item_p^.compression_procedure_name^;
        IFEND;
      = amc$dynamic_home_block_space =
        target_static_attrs.dynamic_home_block_space := get_item_p^.dynamic_home_block_space;
      = amc$hashing_procedure_name =
        IF get_item_p^.hashing_procedure_name <> NIL THEN
          target_static_attrs.hashing_procedure_name := get_item_p^.hashing_procedure_name^;
        IFEND;
      = amc$initial_home_block_count =
        target_static_attrs.initial_home_block_count := get_item_p^.initial_home_block_count;
      = amc$loading_factor =
        target_static_attrs.loading_factor := get_item_p^.loading_factor;
      = amc$lock_expiration_time =
        target_static_attrs.lock_expiration_time := get_item_p^.lock_expiration_time;
      = amc$logging_options =
        target_static_attrs.logging_options := get_item_p^.logging_options;
      = amc$log_residence =
        IF get_item_p^.log_residence <> NIL THEN
          target_static_attrs.log_residence := get_item_p^.log_residence^;
        IFEND;
      ELSE
      CASEND;
    FOREND;

  PROCEND get_connected_file_attributes;

?? TITLE := 'override_attributes', EJECT ??

  PROCEDURE override_attributes
    (    access_level: amt$access_level;
         caller_ring: ost$valid_ring;
         device_class: rmt$device_class;
         attribute_override: ^fst$file_cycle_attributes;
         access_mode_includes_write: boolean;
         access_mode: pft$usage_selections;
         open_position: amt$open_position;
     VAR instance_attributes {input, output} : bat$instance_static_attributes;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      overridden_attributes: bat$instance_static_attributes,
      override_from_ring_3: boolean,
      block_type_overridden: boolean,
      file_organization_overridden: boolean,
      label_type_overridden: boolean,
      record_type_overridden: boolean,
      ring_attributes_overridden: boolean,
      i: integer;

    status.normal := TRUE;

    FOR i := 1 TO UPPERBOUND (attribute_override^) DO
      CASE attribute_override^ [i].selector OF
      = fsc$block_type =
        ;
      = fsc$file_organization =
        ;
      = fsc$file_label_type =

        { A call to osp$verify_system_privilege should be added here when 'system privilege' is given to the
        { osf$builtin_library on which the PF utilities reside.  Override of label_type will only be allowed
        { for procedures which have system privilege.
        { This check requires passing the caller's segment number to this procedure.

        ;
      = fsc$null_attribute =
        ;
      = fsc$record_type =
        ;
      = fsc$ring_attributes =
        ;
      ELSE
        IF status.normal THEN
          status_reporting_procedure_ptr^ (ame$improper_override_attempt,
                fsv$attribute_names^ [attribute_override^ [i].selector], status);
        ELSE
          osp$append_status_parameter (',', fsv$attribute_names^ [attribute_override^ [i].selector], status);
        IFEND;
      CASEND;
    FOREND;
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    overridden_attributes := instance_attributes;
    override_from_ring_3 := (caller_ring = 3);
    block_type_overridden := FALSE;
    file_organization_overridden := FALSE;
    label_type_overridden := FALSE;
    record_type_overridden := FALSE;
    ring_attributes_overridden := FALSE;

    merge_overridden_attributes (amc$open_request, attribute_override, overridden_attributes,
          block_type_overridden, file_organization_overridden, label_type_overridden, record_type_overridden,
          ring_attributes_overridden);

    IF (block_type_overridden OR label_type_overridden OR file_organization_overridden OR
          record_type_overridden) THEN
      IF access_level = amc$record THEN

        IF access_mode_includes_write THEN
          IF NOT (override_from_ring_3 AND (open_position = amc$open_at_boi) AND
                (access_mode = $pft$usage_selections [pfc$append, pfc$shorten])) THEN
            status_reporting_procedure_ptr^ (ame$improper_override_access, '', status);
            RETURN; {----->
          IFEND;
          validate_override_for_write (block_type_overridden, file_organization_overridden,
                label_type_overridden, record_type_overridden, overridden_attributes,
                status_reporting_procedure_ptr, status);
        ELSE {not access_mode_includes_write}
          validate_override_for_non_write (block_type_overridden, file_organization_overridden,
                label_type_overridden, record_type_overridden, overridden_attributes,
                status_reporting_procedure_ptr, status);
        IFEND;
        IF NOT status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;
    IFEND;

    IF ring_attributes_overridden AND ((NOT override_from_ring_3) OR access_mode_includes_write) THEN
      status_reporting_procedure_ptr^ (ame$ring_validation_error, '', status);
      RETURN; {----->
    IFEND;
    IF instance_attributes.ring_attributes.r1 > overridden_attributes.ring_attributes.r1 THEN
      status_reporting_procedure_ptr^ (ame$ring_validation_error, '', status);
      RETURN; {----->
    IFEND;

    instance_attributes := overridden_attributes;

  PROCEND override_attributes;
?? TITLE := 'merge_overridden_attributes', EJECT ??

  PROCEDURE [INLINE] merge_overridden_attributes
    (    source: amt$attribute_source;
         attributes: ^fst$file_cycle_attributes;
     VAR overridden_attributes {input, output} : bat$instance_static_attributes;
     VAR block_type_overridden {input, output} : boolean;
     VAR file_organization_overridden {input, output} : boolean;
     VAR label_type_overridden {input, output} : boolean;
     VAR record_type_overridden {input, output} : boolean;
     VAR ring_attributes_overridden {input, output} : boolean);

    VAR
      i: integer;

    FOR i := 1 TO UPPERBOUND (attributes^) DO
      CASE attributes^ [i].selector OF
      = fsc$block_type =
        IF attributes^ [i].block_type <> overridden_attributes.block_type THEN
          overridden_attributes.block_type := attributes^ [i].block_type;
          overridden_attributes.block_type_source := source;
          block_type_overridden := TRUE;
        IFEND;
      = fsc$file_organization =
        IF attributes^ [i].file_organization <> overridden_attributes.file_organization THEN
          overridden_attributes.file_organization := attributes^ [i].file_organization;
          overridden_attributes.file_organization_source := source;
          file_organization_overridden := TRUE;
        IFEND;
      = fsc$file_label_type =
        IF attributes^ [i].file_label_type <> overridden_attributes.file_label_type THEN
          overridden_attributes.file_label_type := attributes^ [i].file_label_type;
          overridden_attributes.file_label_type_source := source;
          label_type_overridden := TRUE;
        IFEND;
      = fsc$record_type =
        IF attributes^ [i].record_type <> overridden_attributes.record_type THEN
          overridden_attributes.record_type := attributes^ [i].record_type;
          overridden_attributes.record_type_source := source;
          record_type_overridden := TRUE;
        IFEND;
      = fsc$ring_attributes =
        IF attributes^ [i].ring_attributes <> overridden_attributes.ring_attributes THEN
          overridden_attributes.ring_attributes := attributes^ [i].ring_attributes;
          overridden_attributes.ring_attributes_source := source;
          ring_attributes_overridden := TRUE;
        IFEND;
      ELSE
        ;
      CASEND;
    FOREND;

  PROCEND merge_overridden_attributes;
?? TITLE := 'validate_override_for_write', EJECT ??

  PROCEDURE [INLINE] validate_override_for_write
    (    block_type_overridden: boolean;
         file_organization_overridden: boolean;
         label_type_overridden: boolean;
         record_type_overridden: boolean;
         override_attributes: bat$instance_static_attributes;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      condition: ost$status_condition;

    status.normal := TRUE;
    condition := 0;

    IF label_type_overridden THEN
      condition := ame$improper_write_override;
    ELSEIF file_organization_overridden AND (override_attributes.file_organization <> amc$sequential) THEN
      condition := ame$improper_write_override;
    ELSEIF block_type_overridden AND (override_attributes.block_type <> amc$system_specified) THEN
      condition := ame$improper_write_override;
    ELSEIF record_type_overridden AND (override_attributes.record_type <> amc$undefined) THEN
      condition := ame$improper_write_override;
    IFEND;

    IF condition <> 0 THEN
      status_reporting_procedure_ptr^ (condition, '', status);
    IFEND;

  PROCEND validate_override_for_write;
?? TITLE := 'validate_override_for_non_write', EJECT ??

  PROCEDURE [INLINE] validate_override_for_non_write
    (    block_type_overridden: boolean;
         file_organization_overridden: boolean;
         label_type_overridden: boolean;
         record_type_overridden: boolean;
         override_attributes: bat$instance_static_attributes;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    TYPE
      record_types = set of amt$record_type;

    VAR
      variable_record_types: record_types,
      condition: ost$status_condition;

    status.normal := TRUE;
    condition := 0;
    variable_record_types := $record_types [amc$variable, amc$ansi_spanned, amc$ansi_variable,
          amc$trailing_char_delimited];

    IF NOT label_type_overridden THEN
      IF file_organization_overridden AND (override_attributes.file_organization IN
            amv$aam_file_organizations) THEN
        condition := ame$improper_fo_override;
      ELSEIF record_type_overridden AND (override_attributes.record_type IN variable_record_types) THEN
        condition := ame$improper_record_override;
      ELSEIF block_type_overridden THEN
        IF override_attributes.block_type = amc$user_specified THEN
          condition := ame$improper_ss_block_override;
        ELSEIF override_attributes.record_type IN variable_record_types THEN
          condition := ame$improper_us_block_override;
        IFEND;
      IFEND;
    IFEND;

    IF condition <> 0 THEN
      status_reporting_procedure_ptr^ (condition, '', status);
    IFEND;

  PROCEND validate_override_for_non_write;
?? TITLE := 'validate_access_at_open', EJECT ??

  PROCEDURE validate_access_at_open
    (    validation_ring: ost$valid_ring;
         caller_ring: ost$valid_ring;
         ring_attributes: amt$ring_attributes;
         global_access_mode: pft$usage_selections;
         access_mode_defaulted: boolean;
     VAR access_mode {input, output} : pft$usage_selections;
     VAR access_mode_includes_write: boolean;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    status.normal := TRUE;
    access_mode_includes_write := ($pft$usage_selections [pfc$append, pfc$modify, pfc$shorten] *
          access_mode) <> $pft$usage_selections [];

    IF access_mode_defaulted THEN

      IF ((pfc$read IN access_mode) AND (validation_ring > ring_attributes.r2)) OR
            (validation_ring > ring_attributes.r3) THEN
        status_reporting_procedure_ptr^ (ame$ring_validation_error, '', status);
        RETURN; {----->
      IFEND;


      IF access_mode_includes_write AND (validation_ring > ring_attributes.r1) THEN
        access_mode := access_mode - $pft$usage_selections [pfc$append, pfc$modify, pfc$shorten];
        access_mode_includes_write := FALSE;
      IFEND;

      IF access_mode = $pft$usage_selections [pfc$execute] THEN
        access_mode := $pft$usage_selections [];
      IFEND;

    ELSE {NOT access_mode_defaulted}

      IF caller_ring <> 3 THEN

        IF NOT (access_mode <= global_access_mode) THEN
          no_permission_for_access (access_mode - global_access_mode, status_reporting_procedure_ptr, status);
          RETURN; {----->
        IFEND;
        IF (access_mode_includes_write AND (validation_ring > ring_attributes.r1)) OR
              ((pfc$read IN access_mode) AND (validation_ring > ring_attributes.r2)) OR
              (validation_ring > ring_attributes.r3) THEN
          status_reporting_procedure_ptr^ (ame$ring_validation_error, '', status);
          RETURN; {----->
        IFEND;

      ELSE {caller_ring = 3}

        IF (access_mode_includes_write AND (validation_ring > ring_attributes.r1)) THEN
          status_reporting_procedure_ptr^ (ame$ring_validation_error, '', status);
          RETURN; {----->
        IFEND;
        IF NOT (access_mode <= global_access_mode) THEN
          IF global_access_mode <> $pft$usage_selections [pfc$execute] THEN
            no_permission_for_access (access_mode - global_access_mode, status_reporting_procedure_ptr,
                  status);
            RETURN; {----->
          IFEND;
          IF access_mode_includes_write THEN
            no_permission_for_access (($pft$usage_selections [pfc$append, pfc$modify,
                  pfc$shorten] * access_mode), status_reporting_procedure_ptr, status);
            RETURN; {----->
          IFEND;
        IFEND;

        IF access_mode = $pft$usage_selections [pfc$execute] THEN
          access_mode := $pft$usage_selections [pfc$read, pfc$execute];
        IFEND;

      IFEND;
    IFEND;

    IF access_mode = $pft$usage_selections [] THEN
      status_reporting_procedure_ptr^ (ame$null_access_mode, '', status);
      RETURN; {----->
    IFEND;

  PROCEND validate_access_at_open;
?? TITLE := 'no_permission_for_access', EJECT ??

  PROCEDURE no_permission_for_access
    (    invalid_access: pft$usage_selections;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      usage: pft$usage_options;

    status.normal := TRUE;
    FOR usage := LOWERVALUE (pft$usage_options) TO UPPERVALUE (pft$usage_options) DO
      IF usage IN invalid_access THEN
        IF status.normal THEN
          status_reporting_procedure_ptr^ (ame$no_permission_for_access, amv$usage_option_names [usage].
                name (1, amv$usage_option_names [usage].size), status);
        ELSE
          osp$append_status_parameter (',', amv$usage_option_names
                [usage].name (1, amv$usage_option_names [usage].size), status);
        IFEND;
      IFEND;
    FOREND;

  PROCEND no_permission_for_access;
?? TITLE := 'store_attributes_in_tft', EJECT ??

  PROCEDURE [INLINE] store_attributes_in_tft
    (    instance_attributes: bat$instance_attributes;
         global_file_information: ^bat$global_file_information;
         system_file_label: ^fmt$system_file_label;
         device_class: rmt$device_class;
     VAR tft_entry {input, output} : bat$task_file_entry);

    tft_entry.instance_attributes := instance_attributes;
    tft_entry.global_file_information := global_file_information;
    tft_entry.system_file_label := system_file_label;
    tft_entry.device_class := device_class;
    CASE device_class OF
    = rmc$connected_file_device =
      tft_entry.subject := NIL;
      tft_entry.connected_files := NIL;
      tft_entry.connection_level := 0;
      tft_entry.first_target.defined := FALSE;
    = rmc$log_device =
      tft_entry.log_ordinal := LOWERVALUE (pmt$logs);
      tft_entry.log_address := NIL;
      tft_entry.log_cycle := LOWERVALUE (lgt$log_cycle);
      tft_entry.log_entry := NIL;
    ELSE
      ;
    CASEND;

  PROCEND store_attributes_in_tft;
?? TITLE := 'set_default_attributes', EJECT ??

  PROCEDURE [INLINE] set_default_attributes
    (    access_level: amt$access_level;
         device_class: rmt$device_class;
         validation_ring: ost$valid_ring;
     VAR static_label {input, output} : bat$static_label_attributes);

    IF static_label.record_type_source = amc$access_method_default THEN
      IF access_level = amc$segment THEN
        static_label.record_type := amc$undefined;
      IFEND;
    IFEND;

    IF static_label.min_record_length_source = amc$access_method_default THEN
      IF static_label.record_type = amc$ansi_fixed THEN
        static_label.min_record_length := static_label.max_record_length;
      ELSEIF (static_label.record_type = amc$undefined) AND
            (static_label.block_type = amc$user_specified) THEN
        static_label.min_record_length := static_label.min_block_length;
      IFEND;
    IFEND;

    IF (static_label.ring_attributes_source = amc$undefined_attribute) OR
          (static_label.ring_attributes_source = amc$access_method_default) THEN
      static_label.ring_attributes.r1 := validation_ring;
      static_label.ring_attributes.r2 := validation_ring;
      static_label.ring_attributes.r3 := validation_ring;
      static_label.ring_attributes_source := amc$access_method_default;
    IFEND;

    IF static_label.page_length_source = amc$access_method_default THEN
      IF static_label.vertical_print_density_source <> amc$access_method_default THEN
        static_label.page_length := static_label.vertical_print_density * 10;
      IFEND;
    IFEND;

  PROCEND set_default_attributes;
?? TITLE := 'validate_merged_static_attr', EJECT ??

  PROCEDURE [INLINE] validate_merged_static_attr
    (    validation_ring: ost$valid_ring;
         static_label: bat$static_label_attributes;
         device_class: rmt$device_class;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    status.normal := TRUE;

    IF NOT ((1 <= static_label.ring_attributes.r1) AND (static_label.ring_attributes.r1 <=
          static_label.ring_attributes.r2) AND (static_label.ring_attributes.r2 <=
          static_label.ring_attributes.r3) AND (static_label.ring_attributes.r3 <= 13)) THEN
      status_reporting_procedure_ptr^ (ame$improper_file_attrib_value, 'CREATION_ATTRIBUTES', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, fsv$attribute_names^ [fsc$ring_attributes],
            status);
      RETURN; {----->
    IFEND;

    IF validation_ring > static_label.ring_attributes.r1 THEN
      status_reporting_procedure_ptr^ (ame$ring_validation_error, '', status);
      RETURN; {----->
    IFEND;

    IF static_label.block_type = amc$user_specified THEN
      IF static_label.max_block_length < static_label.min_block_length THEN
        status_reporting_procedure_ptr^ (ame$mbl_less_than_mibl, '', status);
        RETURN; {----->
      IFEND;

      IF (static_label.record_type = amc$ansi_fixed) AND (static_label.max_record_length >
            static_label.max_block_length) THEN
        status_reporting_procedure_ptr^ (ame$mbl_less_than_mrl, '', status);
        RETURN; {----->
      IFEND;
    IFEND;

  PROCEND validate_merged_static_attr;
?? TITLE := 'validate_device_class', EJECT ??

  PROCEDURE [INLINE] validate_device_class
    (    device_class: rmt$device_class;
         file_organization: amt$file_organization;
         access_level: amt$access_level;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    TYPE
      file_organizations = set of amt$file_organization,
      access_levels = set of amt$access_level;

    VAR
      allowed_file_organizations: file_organizations,
      allowed_access_levels: access_levels;

    status.normal := TRUE;

    CASE device_class OF
    = rmc$mass_storage_device =
      allowed_file_organizations := $file_organizations [amc$sequential, amc$byte_addressable,
            amc$indexed_sequential, amc$direct_access, amc$system_key];
      allowed_access_levels := $access_levels [amc$record, amc$segment, amc$physical];

    = rmc$magnetic_tape_device =
      allowed_file_organizations := $file_organizations [amc$sequential];
      allowed_access_levels := $access_levels [amc$record];
      IF NOT any_tape_opened_in_task THEN
        tape_mount_kludge;
        any_tape_opened_in_task := TRUE;
      IFEND;

    = rmc$network_device =
      allowed_file_organizations := $file_organizations [amc$sequential,
      {
      {TEMPORARY CODE} amc$byte_addressable];
      {
      allowed_access_levels := $access_levels [amc$record];

    = rmc$rhfam_device =
      allowed_file_organizations := $file_organizations [amc$sequential];
      allowed_access_levels := $access_levels [amc$record];

    = rmc$terminal_device =
      allowed_file_organizations := $file_organizations [amc$sequential, amc$byte_addressable];
      allowed_access_levels := $access_levels [amc$record];

    ELSE {NULL DEVICES
      allowed_file_organizations := $file_organizations [amc$sequential, amc$byte_addressable];
      allowed_access_levels := $access_levels [amc$record, amc$segment];
    CASEND;

    IF NOT (file_organization IN allowed_file_organizations) THEN
      status_reporting_procedure_ptr^ (ame$fo_device_class_conflict,
            amv$file_organization_names [file_organization].name, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, amv$device_class_names [device_class].name,
            status);
      RETURN; {----->
    IFEND;

    IF NOT (access_level IN allowed_access_levels) THEN
      IF access_level = amc$segment THEN
        status_reporting_procedure_ptr^ (ame$not_virtual_memory_device,
              amv$device_class_names [device_class].name, status);
      ELSE
        status_reporting_procedure_ptr^ (ame$not_physical_access_device,
              amv$device_class_names [device_class].name, status);
      IFEND;
      RETURN; {----->
    IFEND;

  PROCEND validate_device_class;
?? TITLE := 'tape_mount_kludge', EJECT ??

  PROCEDURE tape_mount_kludge;

    { This is done so that the opening of the library containing the message
    { templates used to action the operator in tapes are not opened in ring 2.
    { This was causing task termination to get a permission not granted for close
    { on these.  Preferable may be close ring 2 files from ring 2 during task
    { termination.

    VAR
      status: ost$status,
      request_status: ost$status,
      p_message: ^ost$status_message;

    osp$set_status_abnormal ('GS', dme$volume, '', status);

    PUSH p_message;
    osp$format_message (status, osc$full_message_level, 80, p_message^, request_status);
  PROCEND tape_mount_kludge;

?? TITLE := 'validate_attributes', EJECT ??

  PROCEDURE validate_attributes
    (    attribute_validation: ^fst$file_cycle_attributes;
         access_mode_includes_write: boolean;
     VAR preserved_static_label {input, output} : bat$static_label_attributes;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

{  This compares the attributes as input to bap$open_file for validation,
{  to the attributes preserved with the file.

    TYPE
      fst$attribute_choices = set of fst$cycle_attribute_choices;

    VAR
      attribute_p: ^fst$file_cycle_attribute,
      file_contents: amt$file_contents,
      file_contents_valid: boolean,
      file_processor_valid: boolean,
      file_structure: amt$file_structure,
      i: integer,
      matches: fst$attribute_choices,
      mismatches: fst$attribute_choices,
      selector: fst$cycle_attribute_choices,
      translated_name: amt$local_file_name;

    matches := $fst$attribute_choices [];
    mismatches := $fst$attribute_choices [];
    status.normal := TRUE;

    FOR i := 1 TO UPPERBOUND (attribute_validation^) DO
      attribute_p := ^attribute_validation^ [i];
      selector := attribute_p^.selector;
      IF NOT (selector IN matches) THEN
        CASE selector OF
        = fsc$average_record_length =
          IF attribute_p^.average_record_length = preserved_static_label.average_record_length THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$block_type =
          IF attribute_p^.block_type = preserved_static_label.block_type THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$character_conversion =
          IF attribute_p^.character_conversion = preserved_static_label.character_conversion THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$collate_table_name =
          IF attribute_p^.collate_table_name <> NIL THEN
            #TRANSLATE (osv$lower_to_upper, attribute_p^.collate_table_name^.entry_point, translated_name);
            IF translated_name = preserved_static_label.collate_table_name THEN
              matches := matches + $fst$attribute_choices [selector];
            ELSE
              mismatches := mismatches + $fst$attribute_choices [selector];
            IFEND;
          IFEND;

        = fsc$compression_procedure_name =
          IF attribute_p^.compression_procedure_name <> NIL THEN
            #TRANSLATE (osv$lower_to_upper, attribute_p^.compression_procedure_name^.name, translated_name);
            IF (translated_name = preserved_static_label.compression_procedure_name.name) AND
                  (attribute_p^.compression_procedure_name^.object_library =
                  preserved_static_label.compression_procedure_name.object_library) THEN
              matches := matches + $fst$attribute_choices [selector];
            ELSE
              mismatches := mismatches + $fst$attribute_choices [selector];
            IFEND;
          IFEND;

        = fsc$data_padding =
          IF attribute_p^.data_padding = preserved_static_label.data_padding THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$dynamic_home_block_space =
          IF attribute_p^.dynamic_home_block_space = preserved_static_label.dynamic_home_block_space THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$embedded_key =
          IF attribute_p^.embedded_key = preserved_static_label.embedded_key THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$erase_at_deletion =
          IF attribute_p^.erase_at_deletion = preserved_static_label.clear_space THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$estimated_record_count =
          IF attribute_p^.estimated_record_count = preserved_static_label.estimated_record_count THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$file_access_procedure_name =
          IF attribute_p^.file_access_procedure_name <> NIL THEN
            #TRANSLATE (osv$lower_to_upper, attribute_p^.file_access_procedure_name^.entry_point,
                  translated_name);
            IF translated_name = preserved_static_label.file_access_procedure THEN
              matches := matches + $fst$attribute_choices [selector];
            ELSE
              mismatches := mismatches + $fst$attribute_choices [selector];
            IFEND;
          IFEND;

        = fsc$file_contents_and_processor =
          IF attribute_p^.file_contents <> osc$null_name THEN
            #TRANSLATE (osv$lower_to_upper, attribute_p^.file_contents, translated_name);
            fsp$convert_to_old_contents (translated_name, file_contents, file_structure);
            { validate file_content }
            file_contents_valid := (file_contents = preserved_static_label.file_contents);
            { validate file_structure }
            file_contents_valid := file_contents_valid AND ((file_structure =
                  preserved_static_label.file_structure) OR (((file_structure = amc$unknown_structure) OR
                  (file_structure = amc$data)) AND ((preserved_static_label.file_structure =
                  amc$unknown_structure) OR (preserved_static_label.file_structure = amc$data))));
          ELSE
            file_contents_valid := TRUE;
          IFEND;
          IF attribute_p^.file_processor <> osc$null_name THEN
            #TRANSLATE (osv$lower_to_upper, attribute_p^.file_processor, translated_name);
            file_processor_valid := (translated_name = preserved_static_label.file_processor)
          ELSE
            file_processor_valid := TRUE;
          IFEND;
          IF file_contents_valid AND file_processor_valid THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$file_label_type =
          IF attribute_p^.file_label_type = preserved_static_label.label_type THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$file_limit =
          IF attribute_p^.file_limit = preserved_static_label.file_limit THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$file_organization =
          IF attribute_p^.file_organization = preserved_static_label.file_organization THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$forced_write =
          IF attribute_p^.forced_write = preserved_static_label.forced_write THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$hashing_procedure_name =
          IF attribute_p^.hashing_procedure_name <> NIL THEN
            #TRANSLATE (osv$lower_to_upper, attribute_p^.hashing_procedure_name^.name, translated_name);
            IF (translated_name = preserved_static_label.hashing_procedure_name.name) AND
                  (attribute_p^.hashing_procedure_name^.object_library =
                  preserved_static_label.hashing_procedure_name.object_library) THEN
              matches := matches + $fst$attribute_choices [selector];
            ELSE
              mismatches := mismatches + $fst$attribute_choices [selector];
            IFEND;
          IFEND;

        = fsc$index_levels =
          IF attribute_p^.index_levels = preserved_static_label.index_levels THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$index_padding =
          IF attribute_p^.index_padding = preserved_static_label.index_padding THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$initial_home_block_count =
          IF attribute_p^.initial_home_block_count = preserved_static_label.initial_home_block_count THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$internal_code =
          IF attribute_p^.internal_code = preserved_static_label.internal_code THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$key_length =
          IF attribute_p^.key_length = preserved_static_label.key_length THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$key_position =
          IF attribute_p^.key_position = preserved_static_label.key_position THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$key_type =
          IF attribute_p^.key_type = preserved_static_label.key_type THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$line_number =
          IF attribute_p^.line_number = preserved_static_label.line_number THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$loading_factor =
          IF attribute_p^.loading_factor = preserved_static_label.loading_factor THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$lock_expiration_time =
          IF attribute_p^.lock_expiration_time = preserved_static_label.lock_expiration_time THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$log_residence =
          IF attribute_p^.log_residence <> NIL THEN
            IF attribute_p^.log_residence^ = preserved_static_label.log_residence THEN
              matches := matches + $fst$attribute_choices [selector];
            ELSE
              mismatches := mismatches + $fst$attribute_choices [selector];
            IFEND;
          IFEND;

        = fsc$logging_options =
          IF attribute_p^.logging_options = preserved_static_label.logging_options THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$max_block_length =
          IF attribute_p^.max_block_length = preserved_static_label.max_block_length THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$max_record_length =
          IF attribute_p^.max_record_length = preserved_static_label.max_record_length THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$min_block_length =
          IF attribute_p^.min_block_length = preserved_static_label.min_block_length THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$min_record_length =
          IF attribute_p^.min_record_length = preserved_static_label.min_record_length THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$padding_character =
          IF attribute_p^.padding_character = preserved_static_label.padding_character THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$page_format =
          IF attribute_p^.page_format = preserved_static_label.page_format THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$page_length =
          IF attribute_p^.page_length = preserved_static_label.page_length THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$page_width =
          IF attribute_p^.page_width = preserved_static_label.page_width THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$preset_value =
          IF attribute_p^.preset_value = preserved_static_label.preset_value THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$record_delimiting_character =
          IF attribute_p^.record_delimiting_character = preserved_static_label.
                record_delimiting_character THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$record_limit =
          IF attribute_p^.record_limit = preserved_static_label.record_limit THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$record_type =
          IF attribute_p^.record_type = preserved_static_label.record_type THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$records_per_block =
          IF attribute_p^.records_per_block = preserved_static_label.records_per_block THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$ring_attributes =
          IF attribute_p^.ring_attributes = preserved_static_label.ring_attributes THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$statement_identifier =
          IF attribute_p^.statement_identifier = preserved_static_label.statement_identifier THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$user_attribute =
          ;

        = fsc$user_information =
          IF attribute_p^.user_information = preserved_static_label.user_info THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;

        = fsc$vertical_print_density =
          IF attribute_p^.vertical_print_density = preserved_static_label.vertical_print_density THEN
            matches := matches + $fst$attribute_choices [selector];
          ELSE
            mismatches := mismatches + $fst$attribute_choices [selector];
          IFEND;
        ELSE
        CASEND;
      IFEND;
    FOREND;

    mismatches := mismatches - matches;
    IF mismatches <> $fst$attribute_choices [] THEN
      FOR i := 1 TO fsc$highest_current_attribute DO
        IF i IN mismatches THEN
          IF status.normal THEN
            status_reporting_procedure_ptr^ (ame$attribute_validation_error, fsv$attribute_names^ [i],
                  status);
          ELSE
            osp$append_status_parameter (',', fsv$attribute_names^ [i], status);
          IFEND;
        IFEND;
      FOREND;
    IFEND;

  PROCEND validate_attributes;
?? TITLE := 'enforce_concurrency_rules ', EJECT ??

  PROCEDURE enforce_concurrency_rules
    (    file_attachment: ^fst$attachment_options;
         cd_attachment_options: fmt$cd_attachment_options;
         device_class: rmt$device_class;
         open_share_modes_specified: boolean;
         opened_access_mode_counts: bat$access_counts;
         open_count: integer;
     VAR instance_open_share_modes: fst$file_access_options;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      i: integer,
      last_choice: integer,
      opened_access_modes: fst$file_access_options,
      valid_open_share_modes_found: boolean;

    status.normal := TRUE;

    IF device_class <> rmc$magnetic_tape_device THEN
      IF open_share_modes_specified THEN
        i := 1;
        valid_open_share_modes_found := FALSE;
        determine_opened_access_modes (opened_access_mode_counts, opened_access_modes);
        WHILE (NOT valid_open_share_modes_found) AND (i <= UPPERBOUND (file_attachment^)) DO
          IF file_attachment^ [i].selector = fsc$open_share_modes THEN
            IF opened_access_modes <= file_attachment^ [i].open_share_modes THEN
              instance_open_share_modes := file_attachment^ [i].open_share_modes;
              valid_open_share_modes_found := TRUE;
            ELSE
              last_choice := i;
            IFEND;
          IFEND;
          i := i + 1;
        WHILEND;
        IF NOT valid_open_share_modes_found THEN
          access_or_share_conflict (fse$concurrent_share_conflict,
                file_attachment^ [last_choice].open_share_modes, opened_access_modes,
                status_reporting_procedure_ptr, status);
        IFEND;
      ELSEIF (cd_attachment_options.job_write_concurrency_specified AND
            (NOT cd_attachment_options.job_write_concurrency)) THEN
        IF open_count = 1 THEN
          instance_open_share_modes := $fst$file_access_options [];
        ELSE
          determine_opened_access_modes (opened_access_mode_counts, opened_access_modes);
          access_or_share_conflict (fse$concurrent_share_conflict, $fst$file_access_options [],
                opened_access_modes, status_reporting_procedure_ptr, status);
        IFEND;
      IFEND;
    IFEND;

  PROCEND enforce_concurrency_rules;
?? TITLE := 'determine_opened_access_modes', EJECT ??

  PROCEDURE [INLINE] determine_opened_access_modes
    (    opened_access_modes: bat$access_counts;
     VAR validation_access_modes: fst$file_access_options);

    VAR
      access_mode: fst$file_access_option;

    validation_access_modes := $fst$file_access_options [];

    FOR access_mode := LOWERVALUE (fst$file_access_option) TO UPPERVALUE (fst$file_access_option) DO
      IF opened_access_modes [access_mode] <> 0 THEN
        validation_access_modes := validation_access_modes + $fst$file_access_options [access_mode];
      IFEND;
    FOREND;
  PROCEND determine_opened_access_modes;

?? TITLE := 'access_or_share_conflict', EJECT ??

  PROCEDURE access_or_share_conflict
    (    condition: ost$status_condition;
         access_options_1: fst$file_access_options;
         access_options_2: fst$file_access_options;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      delimiter: char,
      option: fst$file_access_option,
      usage: pft$usage_options;


    status.normal := TRUE;
    IF access_options_1 = $fst$file_access_options [] THEN
      status_reporting_procedure_ptr^ (condition, 'NONE', status);
    ELSE
      FOR option := LOWERVALUE (fst$file_access_option) TO UPPERVALUE (fst$file_access_option) DO
        IF option IN access_options_1 THEN
          #UNCHECKED_CONVERSION (option, usage);
          IF status.normal THEN
            status_reporting_procedure_ptr^ (condition, amv$usage_option_names [usage].
                  name (1, amv$usage_option_names [usage].size), status);
          ELSE
            osp$append_status_parameter (',', amv$usage_option_names
                  [usage].name (1, amv$usage_option_names [usage].size), status);
          IFEND;
        IFEND;
      FOREND;
    IFEND;

    delimiter := osc$status_parameter_delimiter;
    IF access_options_2 = $fst$file_access_options [] THEN
      osp$append_status_parameter (delimiter, 'NONE', status);
    ELSE
      FOR option := LOWERVALUE (fst$file_access_option) TO UPPERVALUE (fst$file_access_option) DO
        IF option IN access_options_2 THEN
          #UNCHECKED_CONVERSION (option, usage);
          osp$append_status_parameter (delimiter, amv$usage_option_names [usage].
                name (1, amv$usage_option_names [usage].size), status);
          delimiter := ',';
        IFEND;
      FOREND;
    IFEND;

  PROCEND access_or_share_conflict;

?? TITLE := 'load_all_faps', EJECT ??

  PROCEDURE load_all_faps
    (    task_file_index: bat$tft_limit;
         caller_id: ost$caller_identifier;
         device_class: rmt$device_class;
         users_fap_name: ost$name,
         label_type: amt$label_type,
         file_organization: amt$file_organization;
         block_type: amt$block_type;
         record_type: amt$record_type;
         access_level: amt$access_level;
         cd_path_handle: fmt$path_handle;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    CONST
      aam_fap_name = 'AMP$ADVANCED_ACCESS_METHODS    ',
      aam_library_name = 'AAF$44D_LIBRARY                ';

    VAR
      audit_information: sft$audit_information,
      aam_fap_pointer: amt$fap_pointer,
      aam_loaded_ring: ost$valid_ring,
      connected_file_fap_pointer: amt$fap_pointer,
      conversion_fap_name: ost$name,
      cycle_description: ^fmt$cycle_description,
      ignore_status: ost$status,
      file_path_p: ^fst$path,
      file_path_size: fst$path_size,
      job_file_fap_pointer: amt$fap_pointer,
      layer_number: amt$fap_layer_number,
      library_file_path_p: ^fst$path,
      loaded_address: pmt$loaded_address,
      local_status: ost$status,
      module_name_p: ^pmt$program_name,
      max_tape_layers: amt$fap_layer_number,
      path_handle: fmt$path_handle,
      rms_fap_pointer: amt$fap_pointer,
      rms_load_status: ost$status,
      rms_loaded_ring: ost$valid_ring,
      user_fap_loaded_ring: ost$valid_ring,
      user_fap_pointer: amt$fap_pointer;

    status.normal := TRUE;
    layer_number := 0;

    {******* load the user fap if a fap name has been provided *******}
    IF users_fap_name <> osc$null_name THEN
      load_fap (task_file_index, users_fap_name, caller_id, user_fap_loaded_ring, user_fap_pointer,
            status_reporting_procedure_ptr, status);


{ Emit an audit statistic recording the load of the FAP.

      IF avp$security_option_active (avc$vso_security_audit) THEN
        PUSH file_path_p;
        clp$get_fs_path_string (bav$task_file_table^ [task_file_index].local_file_name, file_path_p^,
              file_path_size, path_handle, local_status);
        IF NOT local_status.normal THEN
          file_path_p^ := ' ';
          local_status.normal := TRUE;
        IFEND;
        PUSH module_name_p;
        PUSH library_file_path_p;
        lop$find_entry_point_residence (users_fap_name, user_fap_loaded_ring, module_name_p^,
              library_file_path_p^, local_status);
        IF NOT local_status.normal THEN
          module_name_p^ := osc$null_name;
          library_file_path_p^ := ' ';
          local_status.normal := TRUE;
        IFEND;
        audit_information.audited_operation := sfc$ao_fs_load_fap;
        audit_information.load_fap.file_p := file_path_p;
        audit_information.load_fap.program_name_p := ^users_fap_name;
        audit_information.load_fap.module_name_p := module_name_p;
        audit_information.load_fap.library_name_p := ^library_file_path_p^
              (1, clp$trimmed_string_size (library_file_path_p^));
        audit_information.load_fap.loaded_ring := user_fap_loaded_ring;
        sfp$emit_audit_statistic (audit_information, status);
      IFEND;

      IF status.normal THEN
        store_fap_in_tft (task_file_index, user_fap_loaded_ring, user_fap_pointer, {ignored} 1, layer_number);

      ELSEIF clv$processing_phase >= clc$class_epilog_phase THEN
        osp$generate_log_message ($pmt$ascii_logset [pmc$job_log, pmc$system_log], status, ignore_status);
        status.normal := TRUE;
      ELSE
        RETURN; {----->
      IFEND;
    IFEND;

{ select_system_faps
    CASE device_class OF
    = rmc$mass_storage_device =
      {Max_fap_layers = optional user fap + access method fap}
      IF file_organization IN amv$aam_file_organizations THEN
        load_fap_from_library (task_file_index, aam_fap_name, aam_library_name, caller_id.ring,
              aam_loaded_ring, aam_fap_pointer, status);
        IF status.normal THEN
          store_fap_in_tft (task_file_index, aam_loaded_ring, aam_fap_pointer,
                {max_fap_layers} layer_number + 1, layer_number);
        ELSE
          RETURN; {----->
        IFEND;

      ELSEIF access_level = amc$segment THEN
        store_fap_in_tft (task_file_index, bac$minimum_load_ring, ^bap$fap_control,
              {max_fap_layers} layer_number + 1, layer_number);

      ELSEIF (bav$mass_storage_device_faps [block_type] [record_type] <> NIL) THEN
        store_fap_in_tft (task_file_index, bac$minimum_load_ring,
              bav$mass_storage_device_faps [block_type] [record_type], {max_fap_layers} layer_number + 1,
              layer_number);

      ELSEIF users_fap_name = osc$null_name THEN
        status_reporting_procedure_ptr^ (ame$unsupported_ms_bt_and_rt, amv$block_type_names [block_type].name,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, amv$record_type_names [record_type].name,
              status);
      IFEND;

    = rmc$terminal_device =
      {Max_fap_layers = optional user fap + access method fap}
      bav$task_file_table^ [task_file_index].open_file_dsc_pointer := NIL;
      bav$task_file_table^ [task_file_index].st_open_file_dsc_pointer := NIL;
      CASE iiv$network_identifier OF
      = iic$cdcnet_network =
        store_fap_in_tft (task_file_index, caller_id.ring, ^ifp$st_fap_control,
              {max_fap_layers} layer_number + 1, layer_number);
      = iic$dsiaf_network =
        store_fap_in_tft (task_file_index, caller_id.ring, ^ifp$fap_control,
              {max_fap_layers} layer_number + 1, layer_number);
      ELSE
      CASEND;

    = rmc$magnetic_tape_device =
      {Max_fap_layers = optional user fap + access method fap +
      {    optional RMS site hook + rmp$enforce_tape_security + system tape label fap}
      max_tape_layers := layer_number + 3;
      IF (bav$magnetic_tape_device_faps [block_type] [record_type] <> NIL) THEN
        load_fap_from_library (task_file_index, bav$rms_library_reference.entry_point,
              bav$rms_library_reference.object_library, bac$minimum_load_ring, rms_loaded_ring,
              rms_fap_pointer, rms_load_status);
        IF rms_load_status.normal THEN
          max_tape_layers := max_tape_layers + 1;
        IFEND;
        store_fap_in_tft (task_file_index, caller_id.ring, bav$magnetic_tape_device_faps [block_type]
              [record_type], max_tape_layers, layer_number);
        IF rms_load_status.normal THEN
          store_fap_in_tft (task_file_index, rms_loaded_ring, rms_fap_pointer, max_tape_layers, layer_number);
        IFEND;
        store_fap_in_tft (task_file_index, bac$minimum_load_ring, ^rmp$enforce_tape_security, max_tape_layers,
              layer_number);
        store_fap_in_tft (task_file_index, bac$minimum_load_ring, ^bap$system_tape_label_fap, max_tape_layers,
              layer_number);

      ELSEIF users_fap_name = osc$null_name THEN
        status_reporting_procedure_ptr^ (ame$unsupported_bt_and_rt, amv$block_type_names [block_type].name,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, amv$record_type_names [record_type].name,
              status);
      IFEND;

    = rmc$network_device =
      {Max_fap_layers = optional user fap + access method fap}
      fmp$locate_cd_via_path_handle (cd_path_handle, FALSE {lock_path_table} , cycle_description, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      IF iip$xt_is_xterm_file (^cycle_description^.system_file_label) THEN
        store_fap_in_tft (task_file_index, caller_id.ring, ^iip$xt_xterm_fap,
              {max_fap_layers} layer_number + 1, layer_number);
      ELSE { This is not an xterm file.
        store_fap_in_tft (task_file_index, caller_id.ring, ^nap$network_fap,
              {max_fap_layers} layer_number + 1, layer_number);
      IFEND;

    = rmc$rhfam_device =
      {Max_fap_layers = optional user fap + access method fap}
      store_fap_in_tft (task_file_index, caller_id.ring, ^rfp$network_fap, {max_fap_layers} layer_number + 1,
            layer_number);

    = rmc$connected_file_device =
      {Max_fap_layers = optional user fap + access method fap}
      store_fap_in_tft (task_file_index, caller_id.ring, ^bap$connected_file_device,
            {max_fap_layers} layer_number + 1, layer_number);

    = rmc$log_device =
      {Max_fap_layers = optional user fap + access method fap}
      store_fap_in_tft (task_file_index, bac$minimum_load_ring, ^bap$log_device,
            {max_fap_layers} layer_number + 1, layer_number);

    = rmc$null_device =
      {Max_fap_layers = optional user fap + access method fap}
      IF jmp$system_job () THEN
        job_file_fap_pointer := jmp$job_file_fap (bav$task_file_table^ [task_file_index].local_file_name);
        IF job_file_fap_pointer <> NIL THEN
          store_fap_in_tft (task_file_index, bac$minimum_load_ring, job_file_fap_pointer,
                {max_fap_layers} layer_number + 1, layer_number);
        ELSE
          store_fap_in_tft (task_file_index, bac$minimum_load_ring, ^bap$null_device,
                {max_fap_layers} layer_number + 1, layer_number);
        IFEND;
      ELSE
        store_fap_in_tft (task_file_index, bac$minimum_load_ring, ^bap$null_device,
              {max_fap_layers} layer_number + 1, layer_number);
      IFEND;

    ELSE
      store_fap_in_tft (task_file_index, bac$minimum_load_ring, ^bap$null_device,
            {max_fap_layers} layer_number + 1, layer_number);
    CASEND;

  PROCEND load_all_faps;

?? TITLE := 'load_fap ', EJECT ??

  PROCEDURE load_fap
    (    task_file_index: bat$tft_limit;
         fap_name: ost$name;
         caller_id: ost$caller_identifier;
     VAR loaded_ring: ost$valid_ring;
     VAR fap_pointer: amt$fap_pointer;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      load_address: pmt$loaded_address,
      local_status: ost$status,
      requested_ring: ost$valid_ring,
      r3: ost$valid_ring,
      entry_kind: pmt$loaded_address_kind;

    entry_kind := pmc$procedure_address;

    IF caller_id.ring < bac$minimum_load_ring THEN
      requested_ring := bac$minimum_load_ring;
    ELSE
      requested_ring := caller_id.ring;
    IFEND;

    lop$load_entry_point (fap_name, requested_ring, caller_id.global_key, entry_kind, load_address, status);

    IF status.normal THEN
      bav$task_file_table^ [task_file_index].module_dynamically_loaded := TRUE;
      #CONVERT_POINTER_TO_PROCEDURE (load_address.pointer_to_procedure, fap_pointer);
      bap$determine_loaded_ring (load_address.pointer_to_procedure, loaded_ring, r3);
    ELSE
      status_reporting_procedure_ptr^ (ame$unable_to_load_fap, fap_name, status);
    IFEND;

  PROCEND load_fap;

?? TITLE := 'load_fap_from_library ', EJECT ??

  PROCEDURE load_fap_from_library
    (    task_file_index: bat$tft_limit;
         fap_name: pmt$program_name;
         library: fst$file_reference;
         target_ring: ost$valid_ring;
     VAR loaded_ring: ost$valid_ring;
     VAR fap_pointer: {output} amt$fap_pointer;
     VAR status: ost$status);

    VAR
      file_contains_data: boolean,
      file_exists: boolean,
      file_previously_opened: boolean,
      get_attributes: array [1 .. 1] of amt$get_item,
      ignore_call_bracket_ring: ost$valid_ring,
      loaded_address: pmt$loaded_address,
      referenced_ring: ost$valid_ring;

    IF target_ring < bac$minimum_load_ring THEN
      referenced_ring := bac$minimum_load_ring;
    ELSE
      referenced_ring := target_ring;
    IFEND;

    get_attributes [1].key := amc$null_attribute;
    amp$get_file_attributes (library, get_attributes, file_exists, file_previously_opened, file_contains_data,
          status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;
    IF NOT file_contains_data THEN
      osp$set_status_condition (lle$unable_to_access_load_file, status);
      RETURN; {----->
    IFEND;

    pmp$load_module_from_library (fap_name, referenced_ring, pmc$procedure_address, library, loaded_ring,
          ignore_call_bracket_ring, loaded_address, status);
    IF status.normal THEN
      bav$task_file_table^ [task_file_index].module_dynamically_loaded := TRUE;
      #CONVERT_POINTER_TO_PROCEDURE (loaded_address.pointer_to_procedure, fap_pointer);
    IFEND;

  PROCEND load_fap_from_library;

?? TITLE := 'load_error_exit ', EJECT ??

  PROCEDURE load_error_exit
    (    error_exit_name_source: amt$attribute_source;
         error_exit_name: ost$name;
         caller_id: ost$caller_identifier;
     VAR error_exit: amt$error_exit_procedure;
     VAR error_exit_source: amt$attribute_source;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      entry_kind: pmt$loaded_address_kind,
      load_address: pmt$loaded_address,
      referenced_ring: ost$valid_ring;

    IF caller_id.ring < bac$minimum_load_ring THEN
      referenced_ring := bac$minimum_load_ring;
    ELSE
      referenced_ring := caller_id.ring;
    IFEND;
    entry_kind := pmc$procedure_address;
    lop$load_entry_point (error_exit_name, referenced_ring, caller_id.global_key, entry_kind, load_address,
          status);
    IF NOT status.normal THEN
      status_reporting_procedure_ptr^ (ame$unable_to_load_error_exit, error_exit_name, status);
      RETURN; {----->
    IFEND;
    #CONVERT_POINTER_TO_PROCEDURE (load_address.pointer_to_procedure, error_exit);
    error_exit_source := amc$open_request;

  PROCEND load_error_exit;
?? TITLE := 'load_collate_table ', EJECT ??

  PROCEDURE load_collate_table
    (    collate_table_name_source: amt$attribute_source;
         collate_table_name: ost$name;
         caller_id: ost$caller_identifier;
     VAR collate_table_source: amt$attribute_source;
     VAR collate_entry: amt$collate_table;
         status_reporting_procedure_ptr: fst$status_reporting_procedure;
     VAR status: ost$status);

    VAR
      load_address: pmt$loaded_address,
      p_collate_entry: ^amt$collate_table,
      entry_kind: pmt$loaded_address_kind,
      referenced_ring: ost$valid_ring;

    IF caller_id.ring < bac$minimum_load_ring THEN
      referenced_ring := bac$minimum_load_ring;
    ELSE
      referenced_ring := caller_id.ring;
    IFEND;
    entry_kind := pmc$data_address;
    lop$load_entry_point (collate_table_name, referenced_ring, caller_id.global_key, entry_kind, load_address,
          status);
    IF NOT status.normal THEN
      status_reporting_procedure_ptr^ (ame$unable_to_load_collate_tabl, collate_table_name, status);
      RETURN; {----->
    IFEND;
    p_collate_entry := load_address.pointer_to_data;
    collate_entry := p_collate_entry^;
    collate_table_source := collate_table_name_source;
  PROCEND load_collate_table;
?? TITLE := 'finalize_file_instance', EJECT ??

  PROCEDURE [INLINE] finalize_file_instance
    (    task_file_index: bat$tft_limit;
         global_file_name: ost$binary_unique_name;
     VAR file_identifier: amt$file_identifier);

    VAR
      access_mode: fst$file_access_option,
      entry_p: ^bat$task_file_entry,
      instance_access_modes: fst$file_access_options;

    IF bav$file_id_sequence_number = UPPERVALUE (amt$file_id_sequence) THEN
      bav$file_id_sequence_number := LOWERVALUE (amt$file_id_sequence);
    ELSE
      bav$file_id_sequence_number := bav$file_id_sequence_number + 1;
    IFEND;

    entry_p := ^bav$task_file_table^ [task_file_index];
    entry_p^.sequence_number := bav$file_id_sequence_number;
    file_identifier.ordinal := task_file_index;
    file_identifier.sequence := bav$file_id_sequence_number;

    #UNCHECKED_CONVERSION (entry_p^.instance_attributes.dynamic_label.access_mode, instance_access_modes);
    FOR access_mode := LOWERVALUE (fst$file_access_option) TO UPPERVALUE (fst$file_access_option) DO
      IF access_mode IN instance_access_modes THEN
        entry_p^.global_file_information^.opened_access_modes [access_mode] :=
              entry_p^.global_file_information^.opened_access_modes [access_mode] + 1;
      IFEND;
      IF NOT (access_mode IN entry_p^.instance_attributes.dynamic_label.open_share_modes) THEN
        entry_p^.global_file_information^.prevented_open_access_modes [access_mode] :=
              entry_p^.global_file_information^.prevented_open_access_modes [access_mode] + 1;
      IFEND;
    FOREND;

  PROCEND finalize_file_instance;
?? TITLE := 'assign_instance_attributes', EJECT ??

  PROCEDURE [INLINE] assign_instance_attributes
    (    preserved_attributes: bat$system_file_attributes;
     VAR instance_attributes: bat$instance_attributes);

    instance_attributes.dynamic_label := preserved_attributes.dynamic_label;

    instance_attributes.static_label.block_type := preserved_attributes.static_label.block_type;
    instance_attributes.static_label.block_type_source := preserved_attributes.static_label.block_type_source;
    instance_attributes.static_label.file_label_type := preserved_attributes.static_label.label_type;
    instance_attributes.static_label.file_label_type_source :=
          preserved_attributes.static_label.label_type_source;
    instance_attributes.static_label.file_organization := preserved_attributes.static_label.file_organization;
    instance_attributes.static_label.file_organization_source :=
          preserved_attributes.static_label.file_organization_source;
    instance_attributes.static_label.record_type := preserved_attributes.static_label.record_type;
    instance_attributes.static_label.record_type_source :=
          preserved_attributes.static_label.record_type_source;
    instance_attributes.static_label.ring_attributes := preserved_attributes.static_label.ring_attributes;
    instance_attributes.static_label.ring_attributes_source :=
          preserved_attributes.static_label.ring_attributes_source;

  PROCEND assign_instance_attributes;

?? TITLE := 'store_fap_in_tft ', EJECT ??

  PROCEDURE [INLINE] store_fap_in_tft
    (    task_file_index: bat$tft_limit;
         loaded_ring: ost$valid_ring;
         fap_pointer: amt$fap_pointer;
         maximum_number_of_layers: 1 .. amc$max_fap_layers + 1;
     VAR layer_number: {i/o} amt$fap_layer_number);

    VAR
      fap_control_p: ^bat$fap_control_information,
      layer_to_initialize: amt$fap_layer_number,
      layer: bat$fap_descriptor;

    layer := bav$default_fap_descriptor;
    layer.access_method := fap_pointer;

    IF loaded_ring > bac$minimum_load_ring THEN
      layer.loaded_ring := loaded_ring;
    IFEND;

    fap_control_p := ^bav$task_file_table^ [task_file_index].fap_control_information;
    IF layer_number = 0 THEN
      fap_control_p^.first_fap := layer;

    ELSEIF fap_control_p^.fap_array = NIL THEN
      ALLOCATE fap_control_p^.fap_array: [0 .. maximum_number_of_layers - 1] IN osv$task_private_heap^;
      fap_control_p^.fap_array^ [0] := fap_control_p^.first_fap;
      fap_control_p^.fap_array^ [1] := layer;
      layer_to_initialize := 2;
      WHILE layer_to_initialize <= (maximum_number_of_layers - 1) DO
        fap_control_p^.fap_array^ [layer_to_initialize] := bav$default_fap_descriptor;
        layer_to_initialize := layer_to_initialize + 1;
      WHILEND;

    ELSEIF layer_number <= UPPERBOUND (fap_control_p^.fap_array^) THEN
      fap_control_p^.fap_array^ [layer_number] := layer;
    ELSE
      RETURN; {----->
    IFEND;

    layer_number := layer_number + 1;

  PROCEND store_fap_in_tft;

MODEND bam$open_file;

