?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE : Basic Access Methods : Open' ??
MODULE amm$open;
?? RIGHT := 110 ??

*copyc amh$also

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc osd$integer_limits
*copyc cle$ecc_lexical
*copyc fse$get_info_validation_errors
*copyc amt$file_access_selections
*copyc amt$file_identifier
*copyc amt$local_file_name
*copyc ost$caller_identifier
?? POP ??
*copyc amp$validate_attributes
*copyc bap$fetch_art_table_pointer
*copyc bap$get_setfa_dynamic_attrs
*copyc bap$set_local_name_abnormal
*copyc bap$set_return_at_close
*copyc clp$check_name_for_path_handle
*copyc clp$validate_name
*copyc fsp$convert_to_new_contents
*copyc fsp$dtm_structure_from_contents
*copyc fsp$open_file
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc bav$task_file_table
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  TYPE
    access_selections_set = set of amt$file_attribute_keys;

?? TITLE := 'PROCEDURE [XDCL, #GATE] amp$open', EJECT ??
*copyc amh$open
?? EJECT ??

  PROCEDURE [XDCL, #GATE] amp$open
    (    local_file_name: amt$local_file_name;
         access_level: amt$access_level;
         access_selections: amt$file_access_selections;
     VAR file_identifier: amt$file_identifier;
     VAR status: ost$status);

    CONST
      access_mode_selection = 1,
      local_reference = ':$LOCAL.',
      local_reference_size = 8,
      number_of_supported_attachments = 7; {number of attachment options supported by AMP$OPEN.

    VAR
      attached_permanent_file: boolean,
      attached_share_modes: fst$file_access_options,
      attachment_count: ost$non_negative_integers,
      attachment_options: ^fst$attachment_options,
      attribute_count: ost$non_negative_integers,
      caller_id: ost$caller_identifier,
      cl_path_handle: clt$path_handle,
      default_creation_attributes: ^fst$file_cycle_attributes,
      file_reference: string (local_reference_size + osc$max_name_size),
      file_request_attributes: ^amt$file_attributes,
      iteration: (access_selection, file_request_attribute),
      lfn: amt$local_file_name,
      local_access_selections: amt$file_access_selections,
      mandated_creation_attributes: ^fst$file_cycle_attributes,
      specified_return_option: amt$return_option,
      specified_access_selections: access_selections_set,
      temporary_sequence_pointer: ^SEQ ( * ),
      valid_name: boolean;

?? NEWTITLE := 'PROCEDURE [INLINE] process_selections', EJECT ??

    PROCEDURE [INLINE] process_selections
      (    old_attributes: ^amt$file_attributes;
       VAR attachment_count: {i/o} ost$non_negative_integers;
           attachment_options: {i/o} ^fst$attachment_options;
       VAR specified_access_selections: {i/o} access_selections_set;
       VAR attribute_count: ost$non_negative_integers;
           creation_attributes: {output} ^fst$file_cycle_attributes;
       VAR status: ost$status);

      VAR
        i: ost$non_negative_integers,
        old_attribute_p: ^amt$file_item,
        file_contents_truncated: boolean,
        file_processor_index: ost$non_negative_integers,
        specified_file_contents: amt$file_contents,
        specified_file_structure: amt$file_contents;

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

      FOR i := UPPERBOUND (old_attributes^) DOWNTO 1 DO
        old_attribute_p := ^old_attributes^ [i];
        IF (old_attribute_p^.key IN $access_selections_set [amc$collate_table_name, amc$error_exit_name,
              amc$file_access_procedure, amc$label_exit_name]) AND
              (NOT (old_attribute_p^.key IN specified_access_selections)) THEN
          specified_access_selections := specified_access_selections + $access_selections_set
                [old_attribute_p^.key];

          CASE old_attribute_p^.key OF
          = amc$collate_table_name =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$collate_table_name;
            PUSH creation_attributes^ [attribute_count].collate_table_name;
            creation_attributes^ [attribute_count].collate_table_name^.entry_point :=
                  old_attribute_p^.collate_table_name;
            creation_attributes^ [attribute_count].collate_table_name^.object_library := osc$null_name;
          = amc$error_exit_name =
            attachment_count := attachment_count + 1;
            attachment_options^ [attachment_count].selector := fsc$error_exit_procedure_name;
            PUSH attachment_options^ [attachment_count].error_exit_procedure_name;
            attachment_options^ [attachment_count].error_exit_procedure_name^.entry_point :=
                  old_attribute_p^.error_exit_name;
            attachment_options^ [attachment_count].error_exit_procedure_name^.object_library := osc$null_name;
          = amc$file_access_procedure =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$file_access_procedure_name;
            PUSH creation_attributes^ [attribute_count].file_access_procedure_name;
            creation_attributes^ [attribute_count].file_access_procedure_name^.entry_point :=
                  old_attribute_p^.file_access_procedure;
            creation_attributes^ [attribute_count].file_access_procedure_name^.object_library :=
                  osc$null_name;
          = amc$label_exit_name =
            attachment_count := attachment_count + 1;
            attachment_options^ [attachment_count].selector := fsc$label_exit_procedure_name;
            PUSH attachment_options^ [attachment_count].label_exit_procedure_name;
            attachment_options^ [attachment_count].label_exit_procedure_name^.entry_point :=
                  old_attribute_p^.label_exit_name;
            attachment_options^ [attachment_count].label_exit_procedure_name^.object_library := osc$null_name;
          ELSE
          CASEND;
        IFEND;
      FOREND;

      process_unpushed_selections (old_attributes, attachment_count, attachment_options,
            specified_access_selections, attribute_count, creation_attributes, status);

    PROCEND process_selections;

?? OLDTITLE ??
?? NEWTITLE := 'PROCEDURE process_unpushed_selections', EJECT ??

    PROCEDURE process_unpushed_selections
      (    old_attributes: ^amt$file_attributes;
       VAR attachment_count: {i/o} ost$non_negative_integers;
           attachment_options: {i/o} ^fst$attachment_options;
       VAR specified_access_selections: {i/o} access_selections_set;
       VAR attribute_count: {i/o} ost$non_negative_integers;
           creation_attributes: {i/o} ^fst$file_cycle_attributes;
       VAR status: ost$status);

      VAR
        i: ost$non_negative_integers,
        file_contents_truncated: boolean,
        file_processor_index: ost$non_negative_integers,
        old_attribute_p: ^amt$file_item,
        specified_file_contents: amt$file_contents,
        specified_file_structure: amt$file_contents;

      status.normal := TRUE;

      FOR i := UPPERBOUND (old_attributes^) DOWNTO 1 DO
        old_attribute_p := ^old_attributes^ [i];

        IF NOT (old_attribute_p^.key IN specified_access_selections) THEN
          specified_access_selections := specified_access_selections + $access_selections_set
                [old_attribute_p^.key];

          CASE old_attribute_p^.key OF
          = amc$access_mode =
            attachment_options^ [access_mode_selection].access_modes.selector := fsc$specific_access_modes;
            #UNCHECKED_CONVERSION (old_attribute_p^.access_mode,
                  attachment_options^ [access_mode_selection].access_modes.value);
            IF attachment_options^ [access_mode_selection].access_modes.value =
                  $fst$file_access_options [fsc$shorten, fsc$append] THEN
              attachment_count := attachment_count + 1;
              attachment_options^ [attachment_count].selector := fsc$delete_data;
              attachment_options^ [attachment_count].delete_data := TRUE;
            IFEND;
          = amc$average_record_length =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$average_record_length;
            creation_attributes^ [attribute_count].average_record_length :=
                  old_attribute_p^.average_record_length;
          = amc$block_type =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$block_type;
            creation_attributes^ [attribute_count].block_type := old_attribute_p^.block_type;
          = amc$character_conversion =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$character_conversion;
            creation_attributes^ [attribute_count].character_conversion :=
                  old_attribute_p^.character_conversion;
          = amc$clear_space =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$erase_at_deletion;
            creation_attributes^ [attribute_count].erase_at_deletion := old_attribute_p^.clear_space;
          = amc$collate_table_name =

{ processed in PROCESS_SELECTIONS because of PUSHs dependency on INLINE.

          = amc$compression_procedure_name =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$compression_procedure_name;
            creation_attributes^ [attribute_count].compression_procedure_name :=
                  old_attribute_p^.compression_procedure_name;
          = amc$data_padding =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$data_padding;
            creation_attributes^ [attribute_count].data_padding := old_attribute_p^.data_padding;
          = amc$dynamic_home_block_space =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$dynamic_home_block_space;
            creation_attributes^ [attribute_count].dynamic_home_block_space :=
                  old_attribute_p^.dynamic_home_block_space;
          = amc$embedded_key =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$embedded_key;
            creation_attributes^ [attribute_count].embedded_key := old_attribute_p^.embedded_key;
          = amc$error_exit_name =

{ processed in PROCESS_SELECTIONS because of PUSHs dependency on INLINE.

          = amc$error_limit =
            attachment_count := attachment_count + 1;
            attachment_options^ [attachment_count].selector := fsc$error_limit;
            attachment_options^ [attachment_count].error_limit := old_attribute_p^.error_limit;
          = amc$error_options =
            attachment_count := attachment_count + 1;
            attachment_options^ [attachment_count].selector := fsc$tape_error_options;
            attachment_options^ [attachment_count].tape_error_options := old_attribute_p^.error_options;
          = amc$estimated_record_count =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$estimated_record_count;
            creation_attributes^ [attribute_count].estimated_record_count :=
                  old_attribute_p^.estimated_record_count;
          = amc$file_access_procedure =

{ processed in PROCESS_SELECTIONS because of PUSHs dependency on INLINE.

          = amc$file_contents =
            #TRANSLATE (osv$lower_to_upper, old_attribute_p^.file_contents, specified_file_contents);
          = amc$file_limit =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$file_limit;
            creation_attributes^ [attribute_count].file_limit := old_attribute_p^.file_limit;
          = amc$file_organization =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$file_organization;
            creation_attributes^ [attribute_count].file_organization := old_attribute_p^.file_organization;
          = amc$file_processor =
            file_processor_index := i;
          = amc$file_structure =
            #TRANSLATE (osv$lower_to_upper, old_attribute_p^.file_structure, specified_file_structure);
          = amc$forced_write =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$forced_write;
            creation_attributes^ [attribute_count].forced_write := old_attribute_p^.forced_write;
          = amc$hashing_procedure_name =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$hashing_procedure_name;
            creation_attributes^ [attribute_count].hashing_procedure_name :=
                  old_attribute_p^.hashing_procedure_name;
            creation_attributes^ [attribute_count].hashing_procedure_name^.object_library :=
                  old_attribute_p^.hashing_procedure_name^.object_library;
          = amc$index_levels =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$index_levels;
            creation_attributes^ [attribute_count].index_levels := old_attribute_p^.index_levels;
          = amc$index_padding =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$index_padding;
            creation_attributes^ [attribute_count].index_padding := old_attribute_p^.index_padding;
          = amc$initial_home_block_count =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$initial_home_block_count;
            creation_attributes^ [attribute_count].initial_home_block_count :=
                  old_attribute_p^.initial_home_block_count;
          = amc$internal_code =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$internal_code;
            creation_attributes^ [attribute_count].internal_code := old_attribute_p^.internal_code;
          = amc$key_length =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$key_length;
            creation_attributes^ [attribute_count].key_length := old_attribute_p^.key_length;
          = amc$key_position =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$key_position;
            creation_attributes^ [attribute_count].key_position := old_attribute_p^.key_position;
          = amc$key_type =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$key_type;
            creation_attributes^ [attribute_count].key_type := old_attribute_p^.key_type;
          = amc$label_exit_name =

{ processed in PROCESS_SELECTIONS because of PUSHs dependency on INLINE.

          = amc$label_options =

{ UNSUPPORTED by AMP$OPEN and can't be specified on FSP$OPEN_FILE.

          = amc$label_type =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$file_label_type;
            creation_attributes^ [attribute_count].file_label_type := old_attribute_p^.label_type;
          = amc$line_number =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$line_number;
            creation_attributes^ [attribute_count].line_number := old_attribute_p^.line_number;
          = amc$loading_factor =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$loading_factor;
            creation_attributes^ [attribute_count].loading_factor := old_attribute_p^.loading_factor;
          = amc$lock_expiration_time =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$lock_expiration_time;
            creation_attributes^ [attribute_count].lock_expiration_time :=
                  old_attribute_p^.lock_expiration_time;
          = amc$logging_options =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$logging_options;
            creation_attributes^ [attribute_count].logging_options := old_attribute_p^.logging_options;
          = amc$log_residence =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$log_residence;
            creation_attributes^ [attribute_count].log_residence := old_attribute_p^.log_residence;
          = amc$max_block_length =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$max_block_length;
            creation_attributes^ [attribute_count].max_block_length := old_attribute_p^.max_block_length;
          = amc$max_record_length =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$max_record_length;
            creation_attributes^ [attribute_count].max_record_length := old_attribute_p^.max_record_length;
          = amc$message_control =
            attachment_count := attachment_count + 1;
            attachment_options^ [attachment_count].selector := fsc$message_control;
            attachment_options^ [attachment_count].message_control := old_attribute_p^.message_control;
          = amc$min_block_length =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$min_block_length;
            creation_attributes^ [attribute_count].min_block_length := old_attribute_p^.min_block_length;
          = amc$min_record_length =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$min_record_length;
            creation_attributes^ [attribute_count].min_record_length := old_attribute_p^.min_record_length;
          = amc$null_attribute =
            ;
          = amc$open_position =
            attachment_count := attachment_count + 1;
            attachment_options^ [attachment_count].selector := fsc$open_position;
            attachment_options^ [attachment_count].open_position := old_attribute_p^.open_position;
          = amc$padding_character =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$padding_character;
            creation_attributes^ [attribute_count].padding_character := old_attribute_p^.padding_character;
          = amc$page_format =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$page_format;
            creation_attributes^ [attribute_count].page_format := old_attribute_p^.page_format;
          = amc$page_length =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$page_length;
            creation_attributes^ [attribute_count].page_length := old_attribute_p^.page_length;
          = amc$page_width =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$page_width;
            creation_attributes^ [attribute_count].page_width := old_attribute_p^.page_width;
          = amc$preset_value =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$preset_value;
            creation_attributes^ [attribute_count].preset_value := old_attribute_p^.preset_value;
          = amc$record_limit =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$record_limit;
            creation_attributes^ [attribute_count].record_limit := old_attribute_p^.record_limit;
          = amc$record_type =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$record_type;
            creation_attributes^ [attribute_count].record_type := old_attribute_p^.record_type;
          = amc$records_per_block =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$records_per_block;
            creation_attributes^ [attribute_count].records_per_block := old_attribute_p^.records_per_block;
          = amc$return_option =
            specified_return_option := old_attribute_p^.return_option;
          = amc$ring_attributes =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$ring_attributes;
            creation_attributes^ [attribute_count].ring_attributes := old_attribute_p^.ring_attributes;
          = amc$statement_identifier =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$statement_identifier;
            creation_attributes^ [attribute_count].statement_identifier :=
                  old_attribute_p^.statement_identifier;
          = amc$user_info =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$user_information;
            creation_attributes^ [attribute_count].user_information := old_attribute_p^.user_info;
          = amc$vertical_print_density =
            attribute_count := attribute_count + 1;
            creation_attributes^ [attribute_count].selector := fsc$vertical_print_density;
            creation_attributes^ [attribute_count].vertical_print_density :=
                  old_attribute_p^.vertical_print_density;
          ELSE
          CASEND;
        IFEND;
      FOREND;

{ The following block of code is dependent on file_contents, file_structure, and file_processor
{ being removed once the block is finished.

      IF ($access_selections_set [amc$file_contents, amc$file_structure,
            amc$file_processor] * specified_access_selections) <> $access_selections_set [] THEN
        attribute_count := attribute_count + 1;
        creation_attributes^ [attribute_count].selector := fsc$file_contents_and_processor;
        IF amc$file_processor IN specified_access_selections THEN
          creation_attributes^ [attribute_count].file_processor :=
                old_attributes^ [file_processor_index].file_processor;
        ELSE
          creation_attributes^ [attribute_count].file_processor := osc$null_name;
        IFEND;
        IF ($access_selections_set [amc$file_contents, amc$file_structure] * specified_access_selections) <>
              $access_selections_set [] THEN
          IF NOT (amc$file_contents IN specified_access_selections) THEN
            specified_file_contents := amc$unknown_contents;
          ELSEIF NOT (amc$file_structure IN specified_access_selections) THEN
            fsp$dtm_structure_from_contents (specified_file_contents, specified_file_structure);
          IFEND;
          fsp$convert_to_new_contents (specified_file_contents, specified_file_structure,
                creation_attributes^ [attribute_count].file_contents, file_contents_truncated);
          IF file_contents_truncated THEN
            IF iteration = access_selection THEN
              bap$set_local_name_abnormal (lfn, fse$file_contents_truncated, 'AMP$OPEN',
                    specified_file_contents (1, clp$trimmed_string_size (specified_file_contents)), status);
            ELSE
              bap$set_local_name_abnormal (lfn, fse$file_contents_truncated, 'AMP$FILE',
                    specified_file_contents (1, clp$trimmed_string_size (specified_file_contents)), status);
            IFEND;
            osp$append_status_parameter (osc$status_parameter_delimiter,
                  specified_file_structure (1, clp$trimmed_string_size (specified_file_structure)), status);
          IFEND;

        ELSE
          creation_attributes^ [attribute_count].file_contents := osc$null_name;
        IFEND;

{ File_contents, file_structure, and file_processor are removed because amp$open could specify
{ a file_processor and amp$file could specify file_contents and file_structure so both need to
{ be specified.

        specified_access_selections := specified_access_selections - $access_selections_set
              [amc$file_contents, amc$file_processor, amc$file_structure];
      IFEND;

    PROCEND process_unpushed_selections;
?? OLDTITLE ??
?? NEWTITLE := 'PROCEDURE [INLINE] process_setfa_attachments', EJECT ??

    PROCEDURE [INLINE] process_setfa_attachments
      (    lfn: amt$local_file_name;
       VAR attachment_count: {i/o} ost$non_negative_integers;
           attachment_options: {i/o} ^fst$attachment_options;
       VAR specified_access_selections: {i/o} access_selections_set;
       VAR attached_permanent_file: boolean;
       VAR attached_share_modes: fst$file_access_options;
       VAR status: ost$status);

      VAR
        dynamic_attributes: fst$setfa_attachment_options,
        setfa_specified: boolean;

      status.normal := TRUE;

      bap$get_setfa_dynamic_attrs (lfn, attached_permanent_file, attached_share_modes, setfa_specified,
            dynamic_attributes, status);
      IF NOT (status.normal AND setfa_specified) THEN
        RETURN; {----->
      IFEND;

      IF dynamic_attributes.access_modes_specified
{   } AND (NOT (amc$access_mode IN specified_access_selections)) THEN
        specified_access_selections := specified_access_selections + $access_selections_set [amc$access_mode];
        attachment_options^ [access_mode_selection].access_modes.selector := fsc$specific_access_modes;
        attachment_options^ [access_mode_selection].access_modes.value := dynamic_attributes.access_modes;
        IF attachment_options^ [access_mode_selection].access_modes.value =
              $fst$file_access_options [fsc$shorten, fsc$append] THEN
          attachment_count := attachment_count + 1;
          attachment_options^ [attachment_count].selector := fsc$delete_data;
          attachment_options^ [attachment_count].delete_data := TRUE;
        IFEND;
      IFEND;

      IF dynamic_attributes.error_exit_name_specified
{   } AND (NOT (amc$error_exit_name IN specified_access_selections)) THEN
          specified_access_selections := specified_access_selections +
                $access_selections_set [amc$error_exit_name];
          attachment_count := attachment_count + 1;
          attachment_options^ [attachment_count].selector := fsc$error_exit_procedure_name;
          PUSH attachment_options^ [attachment_count].error_exit_procedure_name;
          attachment_options^ [attachment_count].error_exit_procedure_name^.entry_point :=
                dynamic_attributes.error_exit_name;
          attachment_options^ [attachment_count].error_exit_procedure_name^.object_library := osc$null_name;
      IFEND;

      IF dynamic_attributes.error_limit_specified
{   } AND (NOT (amc$error_limit IN specified_access_selections)) THEN
          specified_access_selections := specified_access_selections + $access_selections_set
                [amc$error_limit];
          attachment_count := attachment_count + 1;
          attachment_options^ [attachment_count].selector := fsc$error_limit;
          attachment_options^ [attachment_count].error_limit := dynamic_attributes.error_limit;
      IFEND;

      IF dynamic_attributes.label_exit_name_specified
{   } AND (NOT (amc$label_exit_name IN specified_access_selections)) THEN
          specified_access_selections := specified_access_selections +
                $access_selections_set [amc$label_exit_name];
          attachment_count := attachment_count + 1;
          attachment_options^ [attachment_count].selector := fsc$label_exit_procedure_name;
          PUSH attachment_options^ [attachment_count].label_exit_procedure_name;
          attachment_options^ [attachment_count].label_exit_procedure_name^.entry_point :=
                dynamic_attributes.label_exit_name;
          attachment_options^ [attachment_count].label_exit_procedure_name^.object_library := osc$null_name;
      IFEND;

      IF dynamic_attributes.message_control_specified
{   } AND (NOT (amc$message_control IN specified_access_selections)) THEN
          specified_access_selections := specified_access_selections +
                $access_selections_set [amc$message_control];
          attachment_count := attachment_count + 1;
          attachment_options^ [attachment_count].selector := fsc$message_control;
          attachment_options^ [attachment_count].message_control := dynamic_attributes.message_control;
      IFEND;

      IF dynamic_attributes.open_position_specified
{   } AND (NOT (amc$open_position IN specified_access_selections)) THEN
          specified_access_selections := specified_access_selections +
                $access_selections_set [amc$open_position];
          attachment_count := attachment_count + 1;
          attachment_options^ [attachment_count].selector := fsc$open_position;
          attachment_options^ [attachment_count].open_position := dynamic_attributes.open_position;
      IFEND;

    PROCEND process_setfa_attachments;
?? OLDTITLE ??
?? EJECT ??

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

    mandated_creation_attributes := NIL;
    default_creation_attributes := NIL;
    specified_return_option := amc$return_at_job_exit;

    clp$validate_name (local_file_name, lfn, valid_name);
    IF NOT valid_name THEN
      osp$set_status_abnormal (amc$access_method_id, cle$improper_name, local_file_name, status);
      RETURN; {----->
    IFEND;

    IF access_selections <> NIL THEN
      PUSH local_access_selections: [1 .. UPPERBOUND (access_selections^)];
      local_access_selections^ := access_selections^;
      amp$validate_attributes (lfn, amc$open_req, caller_id.ring, local_access_selections, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    ELSE
      local_access_selections := NIL;
    IFEND;

    bap$fetch_art_table_pointer (lfn, file_request_attributes);

{
{ The previous implementation of AMP$OPEN handled access and share modes in th following manner:
{   1) If the file was not currently attached, fsc$determine_from_access_modes was either explicitly or
{      implicitly specified on the attachment of the file.
{   2) If the file was currently attached, no share validation was done.  This is essentially the same as
{      specifying fsc$required_share_modes.
{ With FSP$OPEN_FILE whether or not the file is attached has no affect on share mode validation.
{   (ie. If access_and_share_modes is not specified, fsc$determine_from_access_modes is used.)
{ In order to replicate AMP$OPENs behavior using FSP$OPEN_FILE access_and_share_modes are always specified
{ in the following manner:
{   1) access_modes of fsc$permitted_access_modes - this is the default value if no access modes are
{      specified.  IF access_modes are specified by amp$file, set_file_attributes, or on the call to
{      amp$open, the appropriate value is used.
{   2) share_modes of fsc$determine_from_access_modes is used for the first selection in order to be
{      compatible with the way AMP$OPEN handled a file that was not currently attached.
{   3) share_modes of the attachment are used for the second selection if the file is currently attached.
{ These choices of share_modes will make the new implementation of AMP$OPEN replicate the old implementation.
{

    PUSH attachment_options: [1 .. number_of_supported_attachments + 2];

{ + 2 is for delete_data specification and double access_mode specification.

    attachment_options^ [access_mode_selection].selector := fsc$access_and_share_modes;
    attachment_options^ [access_mode_selection].access_modes.selector := fsc$permitted_access_modes;
    attachment_options^ [access_mode_selection].share_modes.selector := fsc$determine_from_access_modes;

    attachment_count := access_mode_selection;
    specified_access_selections := $access_selections_set [];

    IF (local_access_selections <> NIL) THEN
      PUSH mandated_creation_attributes: [1 .. UPPERBOUND (local_access_selections^)];
      process_selections (local_access_selections, attachment_count, attachment_options,
            specified_access_selections, attribute_count, mandated_creation_attributes, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      IF attribute_count = 0 THEN
        mandated_creation_attributes := NIL;
      ELSE
        temporary_sequence_pointer := #SEQ (mandated_creation_attributes^);
        RESET temporary_sequence_pointer;
        NEXT mandated_creation_attributes: [1 .. attribute_count] IN temporary_sequence_pointer;
      IFEND;
    IFEND;

{ Prevent SETFA or AMP$FILE from overriding file_reference specification of open_position.

    clp$check_name_for_path_handle (lfn, cl_path_handle);
    IF (cl_path_handle.kind = clc$regular_path_handle) AND
          (cl_path_handle.regular_handle.open_position.specified) THEN
      specified_access_selections := specified_access_selections + $access_selections_set [amc$open_position];
    IFEND;

    process_setfa_attachments (lfn, attachment_count, attachment_options, specified_access_selections,
          attached_permanent_file, attached_share_modes, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    IF (file_request_attributes <> NIL) THEN
      PUSH default_creation_attributes: [1 .. UPPERBOUND (file_request_attributes^)];
      process_selections (file_request_attributes, attachment_count, attachment_options,
            specified_access_selections, attribute_count, default_creation_attributes, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
      IF attribute_count = 0 THEN
        default_creation_attributes := NIL;
      ELSE
        temporary_sequence_pointer := #SEQ (default_creation_attributes^);
        RESET temporary_sequence_pointer;
        NEXT default_creation_attributes: [1 .. attribute_count] IN temporary_sequence_pointer;
      IFEND;
    IFEND;

    IF attached_permanent_file THEN
      attachment_count := attachment_count + 1;
      attachment_options^ [attachment_count] := attachment_options^ [access_mode_selection];
      attachment_options^ [attachment_count].share_modes.selector := fsc$specific_share_modes;
      attachment_options^ [attachment_count].share_modes.value := attached_share_modes;
    IFEND;
    temporary_sequence_pointer := #SEQ (attachment_options^);
    RESET temporary_sequence_pointer;
    NEXT attachment_options: [1 .. attachment_count] IN temporary_sequence_pointer;

{ Prefix local_file_name with ':$LOCAL.' to prevent the local_file_name from being treated as a
{ file variable.

    IF cl_path_handle.kind = clc$not_a_path_handle THEN
      file_reference := local_reference;
      file_reference (local_reference_size + 1, osc$max_name_size) := lfn;
    ELSE
      file_reference := lfn;
    IFEND;

    fsp$open_file (file_reference, access_level, attachment_options, default_creation_attributes,
          mandated_creation_attributes, {attribute_validation=} mandated_creation_attributes,
          {attribute_override=} NIL, file_identifier, status);

    IF status.normal AND (specified_return_option = amc$return_at_close) THEN
      bap$set_return_at_close (file_identifier);
    IFEND;

  PROCEND amp$open;
?? OLDTITLE ??
MODEND amm$open;
