?? NEWTITLE := 'NOS/VE Basic Access Method : Connected File Device' ??
MODULE bam$connected_file_device;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains the processor for subjects of file connections.

?? NEWTITLE := 'Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ame$fap_validation_errors
*copyc ame$open_validation_errors
*copyc ame$unimplemented_request
*copyc amt$fap_declarations
*copyc amt$file_identifier
*copyc clt$connected_file
*copyc fmc$entry_assigned
*copyc ife$error_codes
*copyc ost$status
?? POP ??
*copyc amp$get_file_attributes
*copyc amp$rewind
*copyc amp$set_file_instance_abnormal
*copyc amp$skip
*copyc baf$task_file_entry_p
*copyc bap$close
*copyc bap$enable_close_of_target
*copyc bap$fetch
*copyc bap$force_update_of_targets
*copyc bap$null_device
*copyc bap$record_opened_file_target
*copyc bap$record_opened_subject_file
*copyc bap$record_subject_file_op
*copyc bap$store
*copyc bap$update_opened_subject_file
*copyc bav$last_tft_entry
*copyc bav$task_file_table
*copyc bav$tft_entry_assignment
*copyc clp$find_connected_files
*copyc clv$standard_files
*copyc fsp$close_file
*copyc fsp$convert_to_new_contents
*copyc fsp$open_file
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal

  CONST
    interface_name = 'BAP$CONNECTED_FILE_DEVICE';

  TYPE
    amt$input_requests = set of amc$get_direct_req .. amc$get_partial_req;

?? TITLE := 'bap$verify_file_connection_attr', EJECT ??
*copyc bap$verify_file_connection_attr
?? TITLE := 'bap$connected_file_device', EJECT ??
*copy bah$connected_file_device

  PROCEDURE [XDCL] bap$connected_file_device
    (    subject_file_identifier: amt$file_identifier;
         call_block: amt$call_block;
         layer_number: amt$fap_layer_number;
     VAR status: ost$status);

    VAR
      connected_files: ^clt$connected_files,
      file_is_open: boolean,
      file_position: amt$file_position,
      found_target_index: boolean,
      i: integer,
      index_of_last_target_file_id: clt$connected_file_target_index,
      last_target_file_instance: ^bat$task_file_entry,
      local_call_block: amt$call_block,
      local_status: ost$status,
      open_target: boolean,
      subject_file_attributes: array [1 .. 2] of amt$fetch_item,
      subject_file_instance: ^bat$task_file_entry,
      target_attachment_options: array [1 .. 2] of fst$attachment_option,
      target_default_attributes: array [1 .. 1] of fst$file_cycle_attribute,
      target_file: ^clt$connected_file_target,
      target_file_identifier: amt$file_identifier,
      target_file_index: clt$connected_file_target_index,
      target_file_instance: ^bat$task_file_entry,
      target_file_name: amt$local_file_name,
      target_mandated_attributes: array [1 .. 1] of fst$file_cycle_attribute,
      update_targets: boolean;

?? NEWTITLE := '[INLINE] chk_if_need_to_open_target', EJECT ??

{ PURPOSE:
{     This procedure checks whether or not a particular target file of a file
{     connection needs to be opened.
{
{ DESIGN:
{     A target file does NOT need to be opened if it is found in the task
{     file table.  When this is called:  (1) all obsolete target files
{     have been closed, and (2) if the i'th target is being checked then the
{     previous i-1 have already been opened.  Thus, this function needs to
{     locate the i'th TFT target (if it exists) and compare it to the i'th
{     target in the connected files table (as specified by target_file_path_
{     handle_name).  If they match, the file need not be opened.  If they don't
{     match or the match cannot be performed, the file needs to be opened.
{
{     The operation of this procedure is dependent on the procedure
{     bap$record_opened_file_target which orders a TFT subject's targets.
{
{     This procedure modifies 4 parameters.  Three of these exist so that
{     if we have located the i'th TFT target and then need to locate the
{     i+1'th, we needn't start with the first target but may start with the
{     i'th and look at the next.  The three parameters are:
{
{     1. last_target_file_instance - TFT instance corresponding to
{        last target file id located for the subject.  This is
{        undefined if found_target_index = FALSE.
{
{     2. index_of_last_target_file_id - This represents the position of
{        the 'last_target_file_id' in the TFT target list.
{
{     3. found_target_index - Set to TRUE when first valid target is found
{        for the subject in the TFT.


    PROCEDURE [INLINE] chk_if_need_to_open_target
      (    subject_file_instance: ^bat$task_file_entry;
           target_file_index: clt$connected_file_target_index;
           target_file_path_handle_name: fst$path_handle_name;
       VAR {input, output} last_target_file_instance: ^bat$task_file_entry;
       VAR {input, output} index_of_last_target_file_id: clt$connected_file_target_index;
       VAR {input, output} found_target_index: boolean;
       VAR open_target: boolean);


      VAR
        i: clt$connected_file_target_index,
        target_file_instance: ^bat$task_file_entry;

      open_target := TRUE;

      IF (target_file_index = 1) OR (NOT found_target_index) THEN
        IF subject_file_instance^.first_target.defined THEN
          target_file_instance := baf$task_file_entry_p (subject_file_instance^.first_target.file_identifier);
          IF target_file_instance = NIL THEN
            RETURN; {----->
          ELSE
            last_target_file_instance := target_file_instance;
            index_of_last_target_file_id := 1;
            found_target_index := TRUE;
          IFEND;
        ELSE
          RETURN; {----->
        IFEND;
      ELSE { (target_file_index > 1) AND (index_of_last_target_file_id > 0)
        target_file_instance := last_target_file_instance;
      IFEND;

{  At this point, target_file_instance is valid and corresponds to the
{  index_of_last_target_file_id'th TFT target.

      FOR i := (index_of_last_target_file_id + 1) TO target_file_index DO
        IF target_file_instance^.next_target.defined THEN
          target_file_instance := baf$task_file_entry_p (target_file_instance^.next_target.file_identifier);
          IF target_file_instance = NIL THEN
            RETURN; {----->
          ELSE
            last_target_file_instance := target_file_instance;
            index_of_last_target_file_id := i;
          IFEND;
        ELSE
          RETURN; {----->
        IFEND;
      FOREND;

{  At this point, target_file_instance is valid and corresponds to the
{  target_file_index'th target.

      open_target := target_file_instance^.local_file_name <> target_file_path_handle_name;

    PROCEND chk_if_need_to_open_target;
?? OLDTITLE ??
?? EJECT ??

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

  /fap/
    BEGIN
      subject_file_instance := baf$task_file_entry_p (subject_file_identifier);
      IF subject_file_instance = NIL THEN
        osp$set_status_abnormal (amc$access_method_id, ame$improper_file_id, interface_name, status);
        RETURN; {----->
      IFEND;

      IF call_block.operation = amc$open_req THEN
        IF call_block.open.access_level <> amc$record THEN
          amp$set_file_instance_abnormal (subject_file_identifier, ame$not_virtual_memory_device,
                amc$open_req, 'CONNECTED FILE', local_status);
          EXIT /fap/; {----->
        IFEND;
        bap$record_opened_subject_file (subject_file_identifier);
        update_targets := TRUE;
      ELSE
        clp$find_connected_files (connected_files);

{  Check for a PUSH.  If found, update the task_file_table entry pointers to the
{  connected_files table.  NOTE:  a POP calls bap$update_opened_subject_file for all
{  subjects.

        IF #OFFSET (subject_file_instance^.connected_files) <> #OFFSET (connected_files) THEN
          bap$update_opened_subject_file (subject_file_identifier);
        IFEND;

{  Check to see if it is necessary to synchronize the targets in the connected_files table
{  and the task_file table.
{
{  This is necessary if the connection_levels differ.  Consider the two cases:
{
{  1. subject_file_instance^.connection_level < subject_file_instance^.subject^.connection_level.
{     (the task file table's targets were last updated BEFORE the connected_file table's targets)
{     This can happen if another synchronous task has updated the subject's connections since
{     the last time this task accessed the subject or if this task has created/deleted another file
{     connection from the subject.
{
{  2. subject_file_instance^.connection_level > subject_file_instance^.subject^.connection_level.
{     (the task file table's targets were last updated AFTER the connected_file table's targets)
{     This occurs on a POP where the subject's connections were modified in the pushed
{     environment..

        update_targets := (subject_file_instance^.subject = NIL) OR
              (subject_file_instance^.connection_level <> subject_file_instance^.subject^.connection_level);

        IF update_targets THEN
          close_obsolete_target_files (subject_file_identifier, subject_file_instance, local_status);
        IFEND;
      IFEND;

      file_position := subject_file_instance^.global_file_information^.positioning_info.record_info.
            file_position;


{ Open targets because subject is being opened, or to }
{ bring the connections of the subject_file_instance level with the global }
{ description of connections for the subject file. }

      IF update_targets AND (subject_file_instance^.subject <> NIL) AND
            (subject_file_instance^.subject^.targets <> NIL) AND (call_block.operation <> amc$close_req) THEN

        local_call_block.operation := amc$fetch_req;
        local_call_block.fetch.file_attributes := ^subject_file_attributes;
        subject_file_attributes [1].key := amc$file_contents;
        subject_file_attributes [2].key := amc$file_structure;
        bap$fetch (subject_file_identifier, local_call_block, layer_number, local_status);
        IF NOT local_status.normal THEN
          EXIT /fap/; {----->
        IFEND;

        target_file_index := 1;
        found_target_index := FALSE;

      /prepare_targets/
        FOR i := 1 TO UPPERBOUND (subject_file_instance^.subject^.targets^) DO
          target_file := ^subject_file_instance^.subject^.targets^ [i];
          IF target_file^.connection_active THEN

{  The target is always opened if (1) the subject is being opened, or (2) the connection has
{  not been recorded in the task_file_table.  The latter is detected by comparing the
{  connection levels of the target in the connected_files table and the subject in the task
{  file table.

            open_target := (call_block.operation = amc$open_req) OR
                  (target_file^.connection_level > subject_file_instance^.connection_level);

{  If neither of the above conditions is true, we may still need to open the target.  A scenario
{  where this may arise is closing the target in a pushed environment and then popping.

            IF ((NOT open_target) AND (target_file^.connection_level <
                  subject_file_instance^.connection_level)) THEN

              chk_if_need_to_open_target (subject_file_instance, target_file_index,
                    target_file^.path_handle_name, last_target_file_instance, index_of_last_target_file_id,
                    found_target_index, open_target);
            IFEND;

            IF open_target THEN
              prepare_for_opening_target (subject_file_identifier, subject_file_instance,
                    subject_file_attributes [1].file_contents, subject_file_attributes [2].file_structure,
                    target_file, target_file_name, target_attachment_options, target_default_attributes,
                    target_mandated_attributes, local_status);
              IF local_status.normal THEN
                fsp$open_file (target_file_name, amc$record, ^target_attachment_options,
                      ^target_default_attributes, ^target_mandated_attributes, NIL, NIL,
                      target_file_identifier, local_status);
              IFEND;
              IF NOT local_status.normal THEN
                IF call_block.operation = amc$open_req THEN
                  EXIT /fap/; {----->
                ELSEIF status.normal THEN
                  status := local_status;
                IFEND;
                local_status.normal := TRUE;
                CYCLE /prepare_targets/; {----->
              IFEND;
              bap$record_opened_file_target (subject_file_identifier, target_file_index,
                    target_file_identifier, target_file^.connection_level);
            IFEND;

            target_file_index := target_file_index + 1;
          IFEND;
        FOREND /prepare_targets/;

      IFEND;


      IF NOT subject_file_instance^.first_target.defined THEN

{ If there are no targets, treat as a null_device file. }

        IF call_block.operation = amc$open_req THEN
          ;
        ELSEIF call_block.operation = amc$close_req THEN
          bap$close (subject_file_identifier, local_status);
        ELSE
          bap$null_device (subject_file_identifier, call_block, layer_number, local_status);
          file_position := subject_file_instance^.global_file_information^.positioning_info.record_info.
                file_position;
        IFEND;

        EXIT /fap/; {----->
      IFEND;

{ Process all target files. }

      IF call_block.operation = amc$open_req THEN
        EXIT /fap/; {----->
      IFEND;

      target_file_identifier := subject_file_instance^.first_target.file_identifier;
      target_file_instance := NIL;

    /process_targets/
      WHILE TRUE DO
        target_file_instance := baf$task_file_entry_p (target_file_identifier);
        IF target_file_instance = NIL THEN
          osp$set_status_abnormal (amc$access_method_id, ame$improper_file_id, interface_name, local_status);
          EXIT /fap/; {----->
        IFEND;

      /process_target/
        BEGIN

          { The disposition of the operation is determined by the following
          { case statement. Most operations are actually performed at the
          { end of the case statement. Some require special handling and
          { those are dealt with in the corresponding case selector.

          CASE call_block.operation OF

          = amc$close_req =
            bap$enable_close_of_target (subject_file_identifier, target_file_identifier);
            fsp$close_file (target_file_identifier, local_status);
            EXIT /process_target/; {----->

          = amc$close_volume_req =
            ;

          = amc$delete_req, amc$delete_direct_req, amc$delete_key_req =
            ;

          = amc$fetch_req =
            IF NOT target_file_instance^.next_target.defined THEN
              IF target_file_instance^.local_file_name = clv$standard_files [clc$sf_null_file].
                    path_handle_name THEN
                bap$fetch (subject_file_identifier, call_block, layer_number, local_status);
              ELSE
                target_file_instance^.fap_control_information.first_fap.
                      access_method^ (target_file_identifier, call_block, 0, local_status);
              IFEND;
              EXIT /fap/; {----->
            IFEND;
            EXIT /process_target/; {----->

          = amc$fetch_access_information_rq =
            IF (subject_file_instance^.global_file_information^.last_access_operation IN
                  (-$amt$input_requests [])) OR (NOT target_file_instance^.next_target.defined) THEN
              target_file_instance^.fap_control_information.first_fap.
                    access_method^ (target_file_identifier, call_block, 0, local_status);
              EXIT /fap/; {----->
            IFEND;
            EXIT /process_target/; {----->

          = amc$flush_req =
            ;

          = amc$get_direct_req, amc$get_key_req, amc$get_next_req, amc$get_next_key_req, amc$get_partial_req =
            target_file_instance^.fap_control_information.first_fap.
                  access_method^ (target_file_identifier, call_block, 0, local_status);
            IF target_file_instance^.private_read_information = NIL THEN
              file_position := target_file_instance^.global_file_information^.positioning_info.record_info.
                    file_position;
            ELSE
              file_position := target_file_instance^.private_read_information^.positioning_info.record_info.
                    file_position;
            IFEND;
            EXIT /fap/; {----->

          = amc$get_label_req =
            target_file_instance^.fap_control_information.first_fap.
                  access_method^ (target_file_identifier, call_block, 0, local_status);
            IF local_status.normal THEN
              EXIT /fap/; {----->
            IFEND;
            EXIT /process_target/; {----->

          = amc$open_req =
            {processed above} ;
            EXIT /fap/; {----->

          = amc$put_direct_req, amc$put_key_req, amc$put_label_req, amc$put_next_req, amc$put_partial_req,
                amc$putrep_req, amc$replace_req, amc$replace_direct_req, amc$replace_key_req =
            ;

          = amc$rewind_req =
            amp$rewind (target_file_identifier, osc$wait, local_status);
            EXIT /process_target/; {----->

          = amc$seek_direct_req =
            ;

          = amc$skip_req =
            amp$skip (target_file_identifier, call_block.skp.direction, call_block.skp.unit,
                  call_block.skp.count, call_block.skp.file_position^, local_status);
            EXIT /process_target/; {----->

          = amc$store_req =
            ;

          = amc$write_end_partition_req, amc$write_tape_mark_req =
            ;

          = ifc$fetch_terminal_req =
            target_file_instance^.fap_control_information.first_fap.
                  access_method^ (target_file_identifier, call_block, 0, local_status);
            IF local_status.normal THEN
              EXIT /fap/; {----->
            ELSEIF (local_status.condition = ame$improper_fap_operation) OR
                  (local_status.condition = ame$unimplemented_request) OR
                  (local_status.condition = ife$current_job_not_interactive) THEN
              FOR i := 1 TO UPPERBOUND (call_block.fetch_terminal.terminal_attributes^) DO
                call_block.fetch_terminal.terminal_attributes^ [i].source := ifc$undefined_attribute;
              FOREND;
              IF target_file_instance^.next_target.defined THEN
                local_status.normal := TRUE;
              IFEND;
            IFEND;
            EXIT /process_target/; {----->

          = ifc$store_terminal_req =
            target_file_instance^.fap_control_information.first_fap.
                  access_method^ (target_file_identifier, call_block, 0, local_status);
            IF (NOT local_status.normal) AND ((local_status.condition = ame$improper_fap_operation) OR
                  (local_status.condition = ame$unimplemented_request) OR
                  (local_status.condition = ife$current_job_not_interactive)) THEN
              local_status.normal := TRUE;
            IFEND;
            EXIT /process_target/; {----->

          ELSE
            amp$set_file_instance_abnormal (subject_file_identifier, ame$unimplemented_request,
                  call_block.operation, ' for connected files', local_status);
          CASEND;

{ Common processing for most requests. }

          IF local_status.normal THEN
            target_file_instance^.fap_control_information.first_fap.
                  access_method^ (target_file_identifier, call_block, 0, local_status);
          IFEND;
          IF NOT local_status.normal THEN
            IF status.normal THEN
              status := local_status;
            IFEND;
            local_status.normal := TRUE;
          IFEND;
        END /process_target/;

{ Advance to the next target file. }

        IF NOT target_file_instance^.next_target.defined THEN
          file_position := subject_file_instance^.global_file_information^.positioning_info.record_info.
                file_position;
          EXIT /process_targets/; {----->
        IFEND;

        target_file_identifier := target_file_instance^.next_target.file_identifier;
      WHILEND /process_targets/;

{ Deal with requests that apply to the subject file as well as all targets. }

      IF call_block.operation = amc$close_req THEN
        bap$close (subject_file_identifier, local_status);
      ELSEIF call_block.operation = amc$store_req THEN
        bap$store (subject_file_identifier, call_block, layer_number, local_status);
      IFEND;
    END /fap/;

    IF (call_block.operation = amc$fetch_access_information_rq) THEN
      IF (subject_file_instance^.subject <> NIL) AND (subject_file_instance^.connection_level <
            subject_file_instance^.subject^.connection_level) THEN
        bap$record_subject_file_op (subject_file_identifier, call_block.operation, file_position);
      IFEND;
    ELSEIF (call_block.operation = amc$close_req) OR (call_block.operation = amc$open_req) THEN
      ;
    ELSE
      bap$record_subject_file_op (subject_file_identifier, call_block.operation, file_position);
    IFEND;

    IF (NOT local_status.normal) AND status.normal THEN
      status := local_status;
    IFEND;

  PROCEND bap$connected_file_device;
?? TITLE := 'close_obsolete_target_files', EJECT ??

  PROCEDURE [INLINE] close_obsolete_target_files
    (    subject_file_identifier: amt$file_identifier;
         subject_file_instance: ^bat$task_file_entry;
     VAR status: ost$status);

    VAR
      a_target_file_was_closed: boolean,
      close_status: ost$status,
      close_target: boolean,
      target_file: ^clt$connected_file_target,
      target_file_identifier: amt$file_identifier,
      target_file_instance: ^bat$task_file_entry,
      next_target_defined: boolean,
      next_target_file_identifier: amt$file_identifier,
      i: clt$connected_file_target_index;

    status.normal := TRUE;
    a_target_file_was_closed := FALSE;

    IF NOT subject_file_instance^.first_target.defined THEN
      RETURN; {----->
    IFEND;

    target_file_identifier := subject_file_instance^.first_target.file_identifier;

    WHILE TRUE DO
      target_file_instance := baf$task_file_entry_p (target_file_identifier);
      IF target_file_instance = NIL THEN
        osp$set_status_abnormal (amc$access_method_id, ame$improper_file_id, interface_name, status);
        RETURN; {----->
      IFEND;

      next_target_defined := target_file_instance^.next_target.defined;
      IF next_target_defined THEN
        next_target_file_identifier := target_file_instance^.next_target.file_identifier;
      IFEND;

{  Set close_target initially TRUE because we want to close a target if it is not found in the subject's
{  target array in the connected_files table.

      close_target := TRUE;

{  Search the subject file's target array in the connected_files table for the target file.

      IF (subject_file_instance^.subject <> NIL) AND (subject_file_instance^.subject^.targets <> NIL) THEN

      /find_target_description/
        FOR i := 1 TO UPPERBOUND (subject_file_instance^.subject^.targets^) DO
          target_file := ^subject_file_instance^.subject^.targets^ [i];
          IF target_file^.path_handle_name = target_file_instance^.local_file_name THEN

{  Close the target if the connection is not active or the connections in the task_file table
{  and the connected_files table are not in sync.
{
{  Consider the following 2 forms of the latter condition:
{
{  1. target_file_instance^.target_connection_level > target_file^.connection_level
{     (task_file_table target updated AFTER connected_file table's target)
{     This could occur if a connection inherited by a pushed environment was
{     deleted (closing the file), recreated and referenced, followed by a POP.
{
{  2. target_file_instance^.target_connection_level < target_file^.connection_level
{     (task_file_table target updated BEFORE connected_file table's target)
{     Another task updated the file connection.

            close_target := (NOT target_file^.connection_active) OR
                  (target_file_instance^.target_connection_level <> target_file^.connection_level);

            EXIT /find_target_description/; {----->
          IFEND;
        FOREND /find_target_description/;
      IFEND;

      IF close_target THEN
        bap$enable_close_of_target (subject_file_identifier, target_file_identifier);
        fsp$close_file (target_file_identifier, close_status);
        IF NOT close_status.normal THEN
          IF status.normal THEN
            status := close_status;
          IFEND;
        ELSE
          a_target_file_was_closed := TRUE;
        IFEND;
      IFEND;

      IF NOT next_target_defined THEN

{  If any targets were closed, the subject's targets should be
{  updated the next time the fap is called.

        IF a_target_file_was_closed THEN
          bap$force_update_of_targets (subject_file_identifier);
        IFEND;
        RETURN; {----->
      IFEND;
      target_file_identifier := next_target_file_identifier;
    WHILEND;

  PROCEND close_obsolete_target_files;
?? TITLE := 'prepare_for_opening_target', EJECT ??

  PROCEDURE [INLINE] prepare_for_opening_target
    (    subject_file_identifier: amt$file_identifier;
         subject_file_instance: ^bat$task_file_entry;
         subject_file_contents: amt$file_contents;
         subject_file_structure: amt$file_structure;
         target_file: ^clt$connected_file_target;
     VAR target_file_name: amt$local_file_name;
     VAR target_attachment_options: array [1 .. 2] of fst$attachment_option;
     VAR target_default_attributes: array [1 .. 1] of fst$file_cycle_attribute;
     VAR target_mandated_attributes: array [1 .. 1] of fst$file_cycle_attribute;
     VAR status: ost$status);

    VAR
      access_modes: pft$usage_selections,
      ignore_contains_data: boolean,
      ignore_local_file: boolean,
      ignore_open_position: clt$open_position,
      file_contents_truncated: boolean,
      target_attributes: array [1 .. 5] of amt$get_item,
      target_file_exists: boolean;

    target_file_name := target_file^.path_handle_name;

    target_attributes [1].key := amc$access_mode;
    target_attributes [2].key := amc$open_position;
    target_attributes [3].key := amc$file_contents;
    target_attributes [4].key := amc$file_structure;
    target_attributes [5].key := amc$ring_attributes;
    amp$get_file_attributes (target_file_name, target_attributes, ignore_local_file, target_file_exists,
          ignore_contains_data, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    bap$verify_file_connection_attr (TRUE, subject_file_instance^.local_file_name, target_file_name,
          subject_file_contents, target_attributes [3].file_contents, subject_file_structure,
          target_attributes [4].file_structure, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    target_attachment_options [1].selector := fsc$access_and_share_modes;
    target_attachment_options [1].share_modes.selector := fsc$determine_from_access_modes;
    target_attachment_options [1].access_modes.selector := fsc$specific_access_modes;
    IF target_attributes [1].source = amc$access_method_default THEN
      #UNCHECKED_CONVERSION (subject_file_instance^.instance_attributes.dynamic_label.access_mode,
            target_attachment_options [1].access_modes.value);
    ELSE
      access_modes := subject_file_instance^.instance_attributes.dynamic_label.access_mode *
            target_attributes [1].access_mode;
      IF access_modes = $pft$usage_selections [] THEN
        amp$set_file_instance_abnormal (subject_file_identifier, ame$incompatible_file_connect, amc$open_req,
              target_file_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'ACCESS_MODE', status);
        RETURN; {----->
      IFEND;
      #UNCHECKED_CONVERSION (access_modes, target_attachment_options [1].access_modes.value);
    IFEND;

    IF target_file^.open_position.specified THEN
      target_attachment_options [2].selector := fsc$open_position;
      target_attachment_options [2].open_position := target_file^.open_position.value;
    ELSEIF (subject_file_instance^.instance_attributes.dynamic_label.open_position_source <>
          amc$access_method_default) AND (target_attributes [2].source = amc$access_method_default) THEN
      target_attachment_options [2].selector := fsc$open_position;
      target_attachment_options [2].open_position := subject_file_instance^.instance_attributes.dynamic_label.
            open_position;
    ELSE
      target_attachment_options [2].selector := fsc$null_attachment_option;
    IFEND;

    IF target_file_exists OR (target_attributes [3].source <> amc$access_method_default) OR
          (target_attributes [4].source <> amc$access_method_default) THEN
      target_default_attributes [1].selector := fsc$null_attribute;
    ELSE
      target_default_attributes [1].selector := fsc$file_contents_and_processor;
      fsp$convert_to_new_contents (subject_file_contents, subject_file_structure,
            target_default_attributes [1].file_contents, file_contents_truncated);
      target_default_attributes [1].file_processor := osc$null_name;
    IFEND;

    IF target_file_exists THEN
      target_mandated_attributes [1].selector := fsc$null_attribute;
    ELSE
      target_mandated_attributes [1].selector := fsc$ring_attributes;
      IF target_attributes [5].source = amc$undefined_attribute THEN
        target_mandated_attributes [1].ring_attributes.r1 := target_file^.connection_ring;
        target_mandated_attributes [1].ring_attributes.r2 := target_file^.connection_ring;
        target_mandated_attributes [1].ring_attributes.r3 := target_file^.connection_ring;
      ELSE
        target_mandated_attributes [1].ring_attributes := target_attributes [5].ring_attributes;
        IF target_file^.connection_ring > target_attributes [5].ring_attributes.r1 THEN
          target_mandated_attributes [1].ring_attributes.r1 := target_file^.connection_ring;
        IFEND;
        IF target_file^.connection_ring > target_attributes [5].ring_attributes.r2 THEN
          target_mandated_attributes [1].ring_attributes.r2 := target_file^.connection_ring;
        IFEND;
        IF target_file^.connection_ring > target_attributes [5].ring_attributes.r3 THEN
          target_mandated_attributes [1].ring_attributes.r3 := target_file^.connection_ring;
        IFEND;
      IFEND;
    IFEND;

  PROCEND prepare_for_opening_target;
?? TITLE := 'bap$close_obsolete_target_files', EJECT ??

  PROCEDURE [XDCL] bap$close_obsolete_target_files
    (    connected_files: ^clt$connected_files);

    VAR
      subject_file_identifier: amt$file_identifier,
      subject_file_instance: ^bat$task_file_entry,
      entry_index: integer,
      ignore_status: ost$status;


    IF bav$task_file_table = NIL THEN
      RETURN; {----->
    IFEND;

    FOR entry_index := 1 TO bav$last_tft_entry DO
      IF bav$tft_entry_assignment^ (entry_index) = fmc$entry_assigned THEN
        subject_file_instance := ^bav$task_file_table^ [entry_index];

        IF (subject_file_instance^.device_class = rmc$connected_file_device) THEN

          subject_file_identifier.ordinal := entry_index;
          subject_file_identifier.sequence := subject_file_instance^.sequence_number;

          IF #OFFSET (subject_file_instance^.connected_files) <> #OFFSET (connected_files) THEN
            bap$update_opened_subject_file (subject_file_identifier);
          IFEND;

{  Call <close_obsolete_target_files> if the targets specified in the connected_files table
{  and the task_file_table are out of sync.  Note:  not all targets may be closed.

          IF ((subject_file_instance^.subject = NIL) OR (subject_file_instance^.connection_level <>
                subject_file_instance^.subject^.connection_level)) THEN
            close_obsolete_target_files (subject_file_identifier, subject_file_instance, ignore_status);
          IFEND;

        IFEND;
      IFEND;
    FOREND;

  PROCEND bap$close_obsolete_target_files;

MODEND bam$connected_file_device;
