?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE : Basic Access Methods : Copy File' ??
MODULE fsm$copy_file;
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ame$access_validation_errors
*copyc ame$lfn_program_actions
*copyc ame$put_validation_errors
*copyc ame$unimplemented_request
*copyc amk$access_method
*copyc amt$file_identifier
*copyc bat$d_record_rcw
*copyc cle$ecc_lexical
*copyc fse$copy_validation_errors
*copyc fsc$maximum_copy_file_push
*copyc fst$attachment_options
*copyc fst$file_cycle_attributes
*copyc fst$file_reference
*copyc fst$copy_control_information
*copyc fst$copy_types
*copyc osd$integer_limits
*copyc oss$job_paged_literal
*copyc ost$caller_identifier
*copyc ost$status
?? POP ??

*copyc amp$fetch
*copyc amp$fetch_access_information
*copyc amp$get_next
*copyc amp$get_partial
*copyc amp$put_next
*copyc amp$put_partial
*copyc amp$write_end_partition
*copyc bap$byte_move
*copyc bap$delete_data
*copyc bap$get_default_attributes
*copyc bap$v_to_t_record_conversion
*copyc clp$check_name_for_path_handle
*copyc clp$include_line
*copyc clp$trimmed_string_size
*copyc clp$validate_name
*copyc fsc$copf_input_attachment_size
*copyc fsc$copf_output_attachment_size
*copyc fsp$close_file
*copyc fsp$contents_is_legible
*copyc fsp$get_open_information
*copyc fsp$open_file
*copyc fsp$set_file_reference_abnormal
*copyc i#move
*copyc mmp$create_scratch_segment
*copyc mmp$delete_scratch_segment
*copyc osp$append_status_file
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$enforce_exception_policies
*copyc osp$establish_block_exit_hndlr
*copyc osp$file_access_condition
*copyc osp$generate_log_message
*copyc osp$set_status_abnormal
*copyc pmp$log

*copyc amv$aam_file_organizations
*copyc amv$nil_file_identifier
*copyc amv$record_type_names
*copyc bav$last_tft_entry
*copyc bav$task_file_table
*copyc bav$tft_entry_assignment
*copyc osv$initial_exception_context

?? TITLE := 'Declarations Defined This Module', EJECT ??
  CONST
    input_access_mode_selection = 1;

  VAR
    fsv$copf_input_file_attachment: [XDCL, #GATE, READ, oss$job_paged_literal]
          array [1 .. fsc$copf_input_attachment_size] of fst$attachment_option := [
      {} [fsc$access_and_share_modes,
      {}       [fsc$specific_access_modes, $fst$file_access_options [fsc$read]],
      {}       [fsc$specific_share_modes, $fst$file_access_options [fsc$read, fsc$execute]]],
      {} [fsc$create_file, FALSE],
      {} [fsc$private_read, TRUE],
      {} [fsc$sequential_access, TRUE]],

    fsv$copf_output_file_attachment: [XDCL, #GATE, READ, oss$job_paged_literal]
          array [1 .. fsc$copf_output_attachment_size] of fst$attachment_option := [
      {} [fsc$access_and_share_modes,
      {}       [fsc$specific_access_modes, $fst$file_access_options [fsc$append, fsc$shorten]],
      {}       [fsc$specific_share_modes, $fst$file_access_options []]],
      {} [fsc$access_and_share_modes,
      {}       [fsc$specific_access_modes, $fst$file_access_options [fsc$append]],
      {}       [fsc$specific_share_modes, $fst$file_access_options []]],
      {} [fsc$open_share_modes, $fst$file_access_options []],
      {} [fsc$open_share_modes, -$fst$file_access_options []],
      {} [fsc$sequential_access, TRUE],
      {} [fsc$delete_data, TRUE]];

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

  PROCEDURE [XDCL, #GATE] amp$copy_file
    (    input_file: amt$local_file_name;
         output_file: amt$local_file_name;
     VAR status: ost$status);

    CONST
      local_reference = ':$LOCAL.',
      local_reference_size = 8;

    VAR
      cl_path_handle: clt$path_handle,
      input_file_reference: string (local_reference_size + osc$max_name_size),
      lfn: amt$local_file_name,
      output_file_reference: string (local_reference_size + osc$max_name_size),
      valid_name: boolean;

    status.normal := TRUE;

{ Prefix local_file_name with ':$LOCAL.' to prevent the local_file_name from being treated as a
{ file variable.
    clp$validate_name (input_file, lfn, valid_name);
    IF NOT valid_name THEN
      osp$set_status_abnormal (amc$access_method_id, cle$improper_name, input_file, status);
      RETURN;
    IFEND;
    clp$check_name_for_path_handle (lfn, cl_path_handle);
    IF cl_path_handle.kind = clc$not_a_path_handle THEN
      input_file_reference := local_reference;
      input_file_reference (local_reference_size + 1, osc$max_name_size) := lfn;
    ELSE
      input_file_reference := lfn;
    IFEND;

{ Prefix local_file_name with ':$LOCAL.' to prevent the local_file_name from being treated as a
{ file variable.
    clp$validate_name (output_file, lfn, valid_name);
    IF NOT valid_name THEN
      osp$set_status_abnormal (amc$access_method_id, cle$improper_name, output_file, status);
      RETURN;
    IFEND;
    clp$check_name_for_path_handle (lfn, cl_path_handle);
    IF cl_path_handle.kind = clc$not_a_path_handle THEN
      output_file_reference := local_reference;
      output_file_reference (local_reference_size + 1, osc$max_name_size) := lfn;
    ELSE
      output_file_reference := lfn;
    IFEND;

    fsp$copy_file (input_file_reference, output_file_reference, NIL, NIL, NIL, status);

  PROCEND amp$copy_file;

?? TITLE := 'PROCEDURE [XDCL, #GATE] fsp$copy_file', EJECT ??
*copyc fsh$copy_file
?? EJECT ??

  PROCEDURE [XDCL, #GATE] fsp$copy_file
    (    input: fst$file_reference;
         output: fst$file_reference;
         input_attribute_validation: ^fst$file_cycle_attributes;
         output_attribute_validation: ^fst$file_cycle_attributes;
         output_creation_attributes: ^fst$file_cycle_attributes;
     VAR status: ost$status);

    VAR
      caller_id: ost$caller_identifier,
      input_file_attachment: ^fst$attachment_options;

    #CALLER_ID (caller_id);

    IF caller_id.ring > osc$tsrv_ring THEN
      input_file_attachment := ^fsv$copf_input_file_attachment;
    ELSE
{
{ The following is necessary to submit an executable file - SUBMIT_JOB runs in ring 3}
{
      PUSH input_file_attachment: [1 .. fsc$copf_input_attachment_size + 1];
      i#move (^fsv$copf_input_file_attachment, input_file_attachment,
            #SIZE (fsv$copf_input_file_attachment));
      input_file_attachment^ [fsc$copf_input_attachment_size + 1] :=
            fsv$copf_input_file_attachment [input_access_mode_selection];
      input_file_attachment^ [fsc$copf_input_attachment_size + 1].access_modes.value :=
            $fst$file_access_options [fsc$execute];
    IFEND;
    fsp$subsystem_copy_file (input, output, input_file_attachment, ^fsv$copf_output_file_attachment,
          input_attribute_validation, output_attribute_validation, output_creation_attributes, status);

  PROCEND fsp$copy_file;

?? TITLE := 'PROCEDURE [XDCL, #GATE] fsp$subsystem_copy_file', EJECT ??
*copyc fsh$subsystem_copy_file
?? EJECT ??

  PROCEDURE [XDCL, #GATE] fsp$subsystem_copy_file
    (    input: fst$file_reference;
         output: fst$file_reference;
         input_file_attachment: ^fst$attachment_options;
         output_file_attachment: ^fst$attachment_options;
         input_attribute_validation: ^fst$file_cycle_attributes;
         output_attribute_validation: ^fst$file_cycle_attributes;
         output_creation_attributes: ^fst$file_cycle_attributes;
     VAR status: ost$status);

    VAR
      input_fid: amt$file_identifier,
      output_fid: amt$file_identifier,
      control_information: fst$copy_control_information,
      job_log: pmt$ascii_logset,
      ignore_status: ost$status,
      local_status: ost$status;

?? NEWTITLE := '  PROCEDURE abort_handler ' ??
?? EJECT ??

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

      clean_up;

    PROCEND abort_handler;


?? TITLE := '  PROCEDURE cleanup ' ??
?? EJECT ??

    PROCEDURE [INLINE] clean_up;

      VAR
        clean_up_status: ost$status;

      IF input_fid <> amv$nil_file_identifier THEN
        fsp$close_file (input_fid, clean_up_status);
        input_fid := amv$nil_file_identifier;
        #SPOIL (input_fid);
      IFEND;
      IF output_fid <> amv$nil_file_identifier THEN
        fsp$close_file (output_fid, clean_up_status);
        output_fid := amv$nil_file_identifier;
        #SPOIL (output_fid);
      IFEND;

    PROCEND clean_up;
?? OLDTITLE ??
?? EJECT ??

    status.normal := TRUE;
    local_status.normal := TRUE;
    input_fid := amv$nil_file_identifier;
    #SPOIL (input_fid);
    output_fid := amv$nil_file_identifier;
    #SPOIL (output_fid);
    osp$establish_block_exit_hndlr (^abort_handler);
    fsp$open_and_get_type_of_copy (input, output, input_file_attachment, output_file_attachment,
          input_attribute_validation, output_attribute_validation, output_creation_attributes, input_fid,
          output_fid, control_information, status);
    IF (NOT status.normal) AND (status.condition <> fse$output_structure_truncated) THEN
      clean_up;
    ELSE
      fsp$copy_data_and_close_files (input_fid, output_fid, control_information, local_status);
      input_fid := amv$nil_file_identifier;
      #SPOIL (input_fid);
      output_fid := amv$nil_file_identifier;
      #SPOIL (output_fid);
      IF NOT local_status.normal THEN
        IF NOT status.normal THEN
          job_log := $pmt$ascii_logset [pmc$job_log];
          osp$generate_log_message (job_log, status, ignore_status);
        IFEND;
        status := local_status;
      IFEND;
    IFEND;
    osp$disestablish_cond_handler;

  PROCEND fsp$subsystem_copy_file;

?? TITLE := 'PROCEDURE change_to_public_lock_file', EJECT??
  PROCEDURE change_to_public_lock_file
    (    file_identifier: amt$file_identifier);

    CONST
      maintain_lock_file_table = 11; { This is AAM's value.

    VAR
      call_block: amt$call_block,
      fap_layer_number: amt$fap_layer_number,
      local_status: ost$status,
      lock_file_path: fst$path,
      lock_file_path_p: ^fst$path,
      lock_file_private_p: ^boolean,
      lock_file_residence: array [1 .. 1] of amt$access_info;

    lock_file_residence [1].key := amc$lock_file_residence;
    lock_file_residence [1].lock_file_path := ^lock_file_path;
    amp$fetch_access_information (file_identifier, lock_file_residence, local_status);
    IF (NOT local_status.normal) OR (NOT lock_file_residence [1].item_returned) OR
          (lock_file_residence [1].lock_file_scope <> amc$private_lock_file) THEN
      RETURN;
    IFEND;

    call_block.operation := amc$user_defined_access_request;
    call_block.user_defined_access_request.request_identifier := maintain_lock_file_table;
    PUSH call_block.user_defined_access_request.request_parameters:
          [[REP (#SIZE(fst$path) + #SIZE(boolean)) OF cell]];
    RESET call_block.user_defined_access_request.request_parameters;
    NEXT lock_file_path_p IN call_block.user_defined_access_request.request_parameters;
    lock_file_path_p^ := '$SYSTEM.AAM.AAF$LOCK_FILE';
    NEXT lock_file_private_p IN call_block.user_defined_access_request.request_parameters;
    lock_file_private_p^ := FALSE;
    IF bav$task_file_table^ [file_identifier.ordinal].fap_control_information.fap_array = NIL THEN
      bav$task_file_table^ [file_identifier.ordinal].fap_control_information.first_fap.
            access_method^ (file_identifier, call_block, fap_layer_number, local_status);
    ELSE
      fap_layer_number := UPPERBOUND (bav$task_file_table^ [file_identifier.ordinal].fap_control_information.
            fap_array^);
      bav$task_file_table^ [file_identifier.ordinal].fap_control_information.fap_array^ [fap_layer_number].
            access_method^ (file_identifier, call_block, fap_layer_number, local_status);
    IFEND;

  PROCEND change_to_public_lock_file;

?? TITLE := 'PROCEDURE fsp$open_and_get_type_of_copy' ??
?? EJECT ??
*copyc fsh$open_and_get_type_of_copy
?? EJECT ??

  PROCEDURE [XDCL, #GATE] fsp$open_and_get_type_of_copy
    (    input: fst$file_reference;
         output: fst$file_reference;
         input_file_attachment: ^fst$attachment_options;
         output_file_attachment: ^fst$attachment_options;
         input_attribute_validation: ^fst$file_cycle_attributes;
         output_attribute_validation: ^fst$file_cycle_attributes;
         output_creation_attributes: ^fst$file_cycle_attributes;
     VAR input_fid: amt$file_identifier;
     VAR output_fid: amt$file_identifier;
     VAR control_information: fst$copy_control_information;
     VAR status: ost$status);

    CONST
      number_of_open_attributes = fsc$highest_current_attribute - 2;

    {total number of cycle attributes on fsp$open_file (47) minus
    {fsc$ring_attributes - this is not inherited from the input file by design.
    {fsc$null_attribute - this is only a specification attribute on fsp$open_file.

    TYPE
   {  record_type_set = set of amt$record_type,  **delete if not referenced**
      attribute_information = record
        force_input_defaults: boolean,
        case adjust_default: boolean of
          =TRUE=
           block_type: amt$block_type,
           record_type: amt$record_type,
          =FALSE=,
        casend,
      recend;

    VAR
      input_cycle_attribute_sources: fst$cycle_attribute_sources,
      input_cycle_attribute_values: fst$cycle_attribute_values,
      input_file_access_info: array [1 .. 1] of amt$access_info,
      input_file_attachment_options: ^fst$attachment_options,
      input_file_catalog_info: fst$catalog_information,
      input_file_cpn: amt$compression_procedure_name,
      input_file_hpn: amt$hashing_procedure_name,
      input_file_instance_info: fst$open_instance_information,
      input_file_user_def_attr_size: fst$user_defined_attribute_size,
      input_initial_byte_address: amt$file_byte_address,
      output_cycle_attribute_values: fst$cycle_attribute_values,
      output_default_creation_attr: array [1 .. number_of_open_attributes] of fst$file_cycle_attribute,
      output_default_creation_ptr: ^fst$file_cycle_attributes,
      output_file_access_info: array [1 .. 1] of amt$access_info,
      output_file_attachment_info: fst$attachment_information,
      output_file_attachment_options: ^fst$attachment_options,
      output_file_catalog_info: fst$catalog_information,
      output_file_instance_info: fst$open_instance_information,
      output_file_user_def_attr_size: fst$user_defined_attribute_size,
      output_initial_byte_address: amt$file_byte_address;


?? NEWTITLE := '  PROCEDURE set_status_internal_error' ??
?? EJECT ??

    PROCEDURE set_status_internal_error
      (    error_number: ost$non_negative_integers;
       VAR status: ost$status);

      VAR
        status_text: string (osc$max_string_size),
        text_length: integer;

      STRINGREP (status_text, text_length, 'detected error #', error_number,
            ' in fsp$open_and_get_type_of_copy');
      fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
            path (1, control_information.input_resolved_file_reference.cycle_path_size),
            fse$copy_internal_error, fsc$copy_file_req, status_text (1, text_length), status);

    PROCEND set_status_internal_error;

?? TITLE := '  FUNCTION task_has_exclusive_write_access', EJECT ??
    FUNCTION task_has_exclusive_write_access
      (    file_identifier: amt$file_identifier): boolean;

      VAR
        fid_ordinal: amt$file_id_ordinal;

      task_has_exclusive_write_access := FALSE;
      FOR fid_ordinal := bav$last_tft_entry DOWNTO 1 DO
        IF (bav$tft_entry_assignment^ (fid_ordinal, 1) = fmc$entry_assigned) AND
              (bav$task_file_table^ [fid_ordinal].local_file_name =
              bav$task_file_table^ [file_identifier.ordinal].local_file_name) AND
              (bav$task_file_table^ [fid_ordinal].instance_attributes.dynamic_label.
              open_share_modes <= $fst$file_access_options [fsc$read, fsc$execute]) THEN
          task_has_exclusive_write_access := TRUE;
          RETURN;
        IFEND;
      FOREND;

    FUNCEND task_has_exclusive_write_access;

?? TITLE := '  PROCEDURE set_output_default_creation_att' ??
?? EJECT ??

    PROCEDURE set_output_default_creation_att
      (    device_dependent_info: attribute_information;
       VAR output_default_creation_ptr: ^fst$file_cycle_attributes;
       VAR status: ost$status);

      VAR
        attribute_count: ost$non_negative_integers,
        default_catalog_info: fst$catalog_information,
        default_cycle_attribute_values: fst$cycle_attribute_values,
        i: ost$non_negative_integers,
        temporary_sequence_pointer: ^SEQ ( * );

      { PURPOSE:  This procedure carries the input file's attributes over to the output file's
      {default creation attributes and saves label space by only specifying those
      {attributes which are different from the systems default attributes or those
      {attributes which are by default undefined but have a source value other than default.
      {The exceptions to this policy are the 7 attributes that may vary from one file to the
      {next on a multi-file tape.  These must be explicitly specified so that the attributes
      {of the mass-storage input file may influence the default attributes used for a tape file.
      {When put_label is modified to save label space this routine can be deleted
      {and the fsp$get_open_attributes can be called and the parameter directly passed
      {to fsp$open_file as the default creation attributes.  But undefined attributes
      {will still have to be treated as a special case.

      bap$get_default_attributes (^default_catalog_info, NIL, ^default_cycle_attribute_values, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      attribute_count := 0;
      IF input_cycle_attribute_sources.average_record_length <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$average_record_length;
        output_default_creation_attr [attribute_count].average_record_length :=
              input_cycle_attribute_values.average_record_length;
      IFEND;
      IF device_dependent_info.force_input_defaults AND device_dependent_info.adjust_default THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$block_type;
        output_default_creation_attr [attribute_count].block_type := device_dependent_info.block_type;
      ELSEIF (default_cycle_attribute_values.block_type <> input_cycle_attribute_values.block_type) OR
            device_dependent_info.force_input_defaults THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$block_type;
        output_default_creation_attr [attribute_count].block_type := input_cycle_attribute_values.block_type;
      IFEND;
      IF (default_cycle_attribute_values.character_conversion <>
            input_cycle_attribute_values.character_conversion) OR
            device_dependent_info.force_input_defaults THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$character_conversion;
        output_default_creation_attr [attribute_count].character_conversion :=
              input_cycle_attribute_values.character_conversion;
      IFEND;
      IF input_cycle_attribute_sources.collate_table_name <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$collate_table_name;
        output_default_creation_attr [attribute_count].collate_table_name :=
              ^input_cycle_attribute_values.collate_table_name;
      IFEND;
      IF input_cycle_attribute_sources.compression_procedure_name <> amc$undefined_attribute THEN
        input_file_cpn.name := input_cycle_attribute_values.compression_procedure_name.entry_point;
        input_file_cpn.object_library := input_cycle_attribute_values.compression_procedure_name.
              object_library;
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$compression_procedure_name;
        output_default_creation_attr [attribute_count].compression_procedure_name := ^input_file_cpn;
      IFEND;
      IF default_cycle_attribute_values.data_padding <> input_cycle_attribute_values.data_padding THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$data_padding;
        output_default_creation_attr [attribute_count].data_padding :=
              input_cycle_attribute_values.data_padding;
      IFEND;
      IF default_cycle_attribute_values.dynamic_home_block_space <>
            input_cycle_attribute_values.dynamic_home_block_space THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$dynamic_home_block_space;
        output_default_creation_attr [attribute_count].dynamic_home_block_space :=
              input_cycle_attribute_values.dynamic_home_block_space;
      IFEND;
      IF default_cycle_attribute_values.embedded_key <> input_cycle_attribute_values.embedded_key THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$embedded_key;
        output_default_creation_attr [attribute_count].embedded_key :=
              input_cycle_attribute_values.embedded_key;
      IFEND;
      IF default_catalog_info.cycle_registration.erase_at_deletion <>
            input_file_catalog_info.cycle_registration.erase_at_deletion THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$erase_at_deletion;
        output_default_creation_attr [attribute_count].erase_at_deletion :=
              input_file_catalog_info.cycle_registration.erase_at_deletion;
      IFEND;
      IF input_cycle_attribute_sources.estimated_record_count <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$estimated_record_count;
        output_default_creation_attr [attribute_count].estimated_record_count :=
              input_cycle_attribute_values.estimated_record_count;
      IFEND;
      IF input_cycle_attribute_sources.file_access_procedure_name <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$file_access_procedure_name;
        output_default_creation_attr [attribute_count].file_access_procedure_name :=
              ^input_cycle_attribute_values.file_access_procedure_name;
      IFEND;
      IF (default_cycle_attribute_values.file_contents <> input_cycle_attribute_values.file_contents) OR
            (default_cycle_attribute_values.file_processor <> input_cycle_attribute_values.file_processor)
            THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$file_contents_and_processor;
        output_default_creation_attr [attribute_count].file_contents :=
              input_cycle_attribute_values.file_contents;
        output_default_creation_attr [attribute_count].file_processor :=
              input_cycle_attribute_values.file_processor;
      IFEND;
      IF default_cycle_attribute_values.file_label_type <> input_cycle_attribute_values.file_label_type THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$file_label_type;
        output_default_creation_attr [attribute_count].file_label_type :=
              input_cycle_attribute_values.file_label_type;
      IFEND;
      IF default_catalog_info.cycle_registration.size_limit <>
            input_file_catalog_info.cycle_registration.size_limit THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$file_limit;
        output_default_creation_attr [attribute_count].file_limit :=
              input_file_catalog_info.cycle_registration.size_limit;
      IFEND;
      IF default_cycle_attribute_values.file_organization <>
            input_cycle_attribute_values.file_organization THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$file_organization;
        output_default_creation_attr [attribute_count].file_organization :=
              input_cycle_attribute_values.file_organization;
      IFEND;
      IF default_cycle_attribute_values.forced_write <> input_cycle_attribute_values.forced_write THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$forced_write;
        output_default_creation_attr [attribute_count].forced_write :=
              input_cycle_attribute_values.forced_write;
      IFEND;
      IF input_cycle_attribute_sources.hashing_procedure_name <> amc$undefined_attribute THEN
        input_file_hpn.name := input_cycle_attribute_values.hashing_procedure_name.entry_point;
        input_file_hpn.object_library := input_cycle_attribute_values.hashing_procedure_name.object_library;
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$hashing_procedure_name;
        output_default_creation_attr [attribute_count].hashing_procedure_name := ^input_file_hpn;
      IFEND;
      IF default_cycle_attribute_values.index_levels <> input_cycle_attribute_values.index_levels THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$index_levels;
        output_default_creation_attr [attribute_count].index_levels :=
              input_cycle_attribute_values.index_levels;
      IFEND;
      IF default_cycle_attribute_values.index_padding <> input_cycle_attribute_values.index_padding THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$index_padding;
        output_default_creation_attr [attribute_count].index_padding :=
              input_cycle_attribute_values.index_padding;
      IFEND;
{ Treat initial_home_block_count as undefined because that is how AAM treats it.
      IF (input_cycle_attribute_sources.initial_home_block_count <> amc$access_method_default) THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$initial_home_block_count;
        output_default_creation_attr [attribute_count].initial_home_block_count :=
              input_cycle_attribute_values.initial_home_block_count;
      IFEND;
      IF (default_cycle_attribute_values.internal_code <> input_cycle_attribute_values.internal_code) OR
            device_dependent_info.force_input_defaults THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$internal_code;
        output_default_creation_attr [attribute_count].internal_code :=
              input_cycle_attribute_values.internal_code;
      IFEND;
      IF input_cycle_attribute_sources.key_length <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$key_length;
        output_default_creation_attr [attribute_count].key_length := input_cycle_attribute_values.key_length;
      IFEND;
      IF default_cycle_attribute_values.key_position <> input_cycle_attribute_values.key_position THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$key_position;
        output_default_creation_attr [attribute_count].key_position :=
              input_cycle_attribute_values.key_position;
      IFEND;
      IF default_cycle_attribute_values.key_type <> input_cycle_attribute_values.key_type THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$key_type;
        output_default_creation_attr [attribute_count].key_type := input_cycle_attribute_values.key_type;
      IFEND;
      IF input_cycle_attribute_sources.line_number <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$line_number;
        output_default_creation_attr [attribute_count].line_number :=
              input_cycle_attribute_values.line_number;
      IFEND;
      IF default_cycle_attribute_values.loading_factor <> input_cycle_attribute_values.loading_factor THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$loading_factor;
        output_default_creation_attr [attribute_count].loading_factor :=
              input_cycle_attribute_values.loading_factor;
      IFEND;
      IF default_cycle_attribute_values.lock_expiration_time <>
            input_cycle_attribute_values.lock_expiration_time THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$lock_expiration_time;
        output_default_creation_attr [attribute_count].lock_expiration_time :=
              input_cycle_attribute_values.lock_expiration_time;
      IFEND;
      IF input_cycle_attribute_sources.log_residence <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$log_residence;
        output_default_creation_attr [attribute_count].log_residence :=
              ^input_cycle_attribute_values.log_residence;
      IFEND;
      IF input_cycle_attribute_sources.logging_options <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$logging_options;
        output_default_creation_attr [attribute_count].logging_options :=
              input_cycle_attribute_values.logging_options;
      IFEND;
{ The following check for amc$access_method_default is because AAM and BAM have different default values.
      IF (default_cycle_attribute_values.max_block_length <> input_cycle_attribute_values.max_block_length) OR
            (input_cycle_attribute_sources.max_block_length <> amc$access_method_default) OR
            device_dependent_info.force_input_defaults THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$max_block_length;
        output_default_creation_attr [attribute_count].max_block_length :=
              input_cycle_attribute_values.max_block_length;
      IFEND;
{ The following check for amc$access_method_default is because AAM requires a max_record_length be specified.
      IF (default_cycle_attribute_values.max_record_length <>
            input_cycle_attribute_values.max_record_length) OR
            (input_cycle_attribute_sources.max_record_length <> amc$access_method_default) OR
            device_dependent_info.force_input_defaults THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$max_record_length;
        output_default_creation_attr [attribute_count].max_record_length :=
              input_cycle_attribute_values.max_record_length;
      IFEND;
      IF default_cycle_attribute_values.min_block_length <> input_cycle_attribute_values.min_block_length THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$min_block_length;
        output_default_creation_attr [attribute_count].min_block_length :=
              input_cycle_attribute_values.min_block_length;
      IFEND;
      IF default_cycle_attribute_values.min_record_length <>
            input_cycle_attribute_values.min_record_length THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$min_record_length;
        output_default_creation_attr [attribute_count].min_record_length :=
              input_cycle_attribute_values.min_record_length;
      IFEND;
      IF (default_cycle_attribute_values.padding_character <>
            input_cycle_attribute_values.padding_character) OR
            device_dependent_info.force_input_defaults THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$padding_character;
        output_default_creation_attr [attribute_count].padding_character :=
              input_cycle_attribute_values.padding_character;
      IFEND;
      IF default_cycle_attribute_values.page_format <> input_cycle_attribute_values.page_format THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$page_format;
        output_default_creation_attr [attribute_count].page_format :=
              input_cycle_attribute_values.page_format;
      IFEND;
      IF default_cycle_attribute_values.page_length <> input_cycle_attribute_values.page_length THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$page_length;
        output_default_creation_attr [attribute_count].page_length :=
              input_cycle_attribute_values.page_length;
      IFEND;
      IF default_cycle_attribute_values.page_width <> input_cycle_attribute_values.page_width THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$page_width;
        output_default_creation_attr [attribute_count].page_width := input_cycle_attribute_values.page_width;
      IFEND;
      IF default_catalog_info.cycle_registration.preset_value <>
            input_file_catalog_info.cycle_registration.preset_value THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$preset_value;
        output_default_creation_attr [attribute_count].preset_value :=
              input_file_catalog_info.cycle_registration.preset_value;
      IFEND;
      IF default_cycle_attribute_values.record_delimiting_character <>
            input_cycle_attribute_values.record_delimiting_character THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$record_delimiting_character;
        output_default_creation_attr [attribute_count].record_delimiting_character :=
              input_cycle_attribute_values.record_delimiting_character;
      IFEND;
      IF input_cycle_attribute_sources.record_limit <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$record_limit;
        output_default_creation_attr [attribute_count].record_limit :=
              input_cycle_attribute_values.record_limit;
      IFEND;
{ The following is because AAM and BAM have different default values.
      IF device_dependent_info.force_input_defaults AND device_dependent_info.adjust_default THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$record_type;
        output_default_creation_attr [attribute_count].record_type :=
              device_dependent_info.record_type;
      ELSEIF ((NOT (input_cycle_attribute_values.file_organization IN amv$aam_file_organizations)) AND
            (input_cycle_attribute_values.record_type <> default_cycle_attribute_values.record_type)) OR
            ((input_cycle_attribute_values.file_organization IN amv$aam_file_organizations) AND
            (input_cycle_attribute_values.record_type <> amc$undefined)) OR
            device_dependent_info.force_input_defaults THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$record_type;
        output_default_creation_attr [attribute_count].record_type :=
              input_cycle_attribute_values.record_type;
      IFEND;
      IF input_cycle_attribute_sources.records_per_block <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$records_per_block;
        output_default_creation_attr [attribute_count].records_per_block :=
              input_cycle_attribute_values.records_per_block;
      IFEND;
      IF input_cycle_attribute_sources.statement_identifier <> amc$undefined_attribute THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$statement_identifier;
        output_default_creation_attr [attribute_count].statement_identifier :=
              input_cycle_attribute_values.statement_identifier;
      IFEND;
      IF default_cycle_attribute_values.user_information <>
            input_cycle_attribute_values.user_information THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$user_information;
        output_default_creation_attr [attribute_count].user_information :=
              input_cycle_attribute_values.user_information;
      IFEND;
      IF default_cycle_attribute_values.vertical_print_density <>
            input_cycle_attribute_values.vertical_print_density THEN
        attribute_count := attribute_count + 1;
        output_default_creation_attr [attribute_count].selector := fsc$vertical_print_density;
        output_default_creation_attr [attribute_count].vertical_print_density :=
              input_cycle_attribute_values.vertical_print_density;
      IFEND;

      IF attribute_count = 0 THEN
        output_default_creation_ptr := NIL;
      ELSE
        temporary_sequence_pointer := #SEQ (output_default_creation_attr);
        RESET temporary_sequence_pointer;
        NEXT output_default_creation_ptr: [1 .. attribute_count] IN temporary_sequence_pointer;
      IFEND;

    PROCEND set_output_default_creation_att;

?? TITLE := '  PROCEDURE validate_line_identifiers' ??
?? EJECT ??

    PROCEDURE validate_line_identifiers
      (VAR status: ost$status);

{ PURPOSE:
{   This procedure validates line number and statement identifier lengths and
{   and locations.  It is called when both the input and output file have
{   file_contents that are considered "LEGIBLE".

      IF input_cycle_attribute_values.line_number <> output_cycle_attribute_values.line_number THEN
        IF (input_cycle_attribute_values.line_number.length <>
              output_cycle_attribute_values.line_number.length) AND
              (input_cycle_attribute_values.line_number.location <>
              output_cycle_attribute_values.line_number.location) THEN
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$line_numbers_unequal, fsc$copy_file_req, 'length and location', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
        ELSEIF input_cycle_attribute_values.line_number.length <>
              output_cycle_attribute_values.line_number.length THEN
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$line_numbers_unequal, fsc$copy_file_req, 'length', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
        ELSE
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$line_numbers_unequal, fsc$copy_file_req, 'location', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
        IFEND;
      ELSEIF input_cycle_attribute_values.statement_identifier <>
            output_cycle_attribute_values.statement_identifier THEN
        IF (input_cycle_attribute_values.statement_identifier.length <>
              output_cycle_attribute_values.statement_identifier.length) AND
              (input_cycle_attribute_values.statement_identifier.location <>
              output_cycle_attribute_values.statement_identifier.location) THEN
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$statement_idents_unequal, fsc$copy_file_req, 'length and location', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
        ELSEIF input_cycle_attribute_values.statement_identifier.length <>
              output_cycle_attribute_values.statement_identifier.length THEN
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$statement_idents_unequal, fsc$copy_file_req, 'length', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
        ELSE
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$statement_idents_unequal, fsc$copy_file_req, 'location', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
        IFEND;
      IFEND;

    PROCEND validate_line_identifiers;

?? TITLE := '  PROCEDURE get_type_of_copy' ??
?? EJECT ??

    PROCEDURE get_type_of_copy
      (VAR type_of_copy: fst$copy_types;
       VAR status: ost$status);

      VAR
        ignore_status: ost$status,
        input_is_legible: boolean,
        output_is_legible: boolean;


      { PURPOSE:  This procedure determines the type of copy that will be performed
      {by fsp$copy_data_and_close_files


      type_of_copy := fsc$error_move;
      input_is_legible := fsp$contents_is_legible (input_cycle_attribute_values.file_contents);
      output_is_legible := fsp$contents_is_legible (output_cycle_attribute_values.file_contents);


      CASE input_cycle_attribute_values.file_organization OF
      = amc$sequential =

        CASE output_cycle_attribute_values.file_organization OF
        = amc$sequential =

          IF (input_file_catalog_info.cycle_registration.residence.device_class = rmc$magnetic_tape_device) OR
                (output_file_catalog_info.cycle_registration.residence.device_class =
                rmc$magnetic_tape_device) THEN
            type_of_copy := fsc$record_move;
          ELSE
            IF output_cycle_attribute_values.file_contents = fsc$list THEN
              IF (output_cycle_attribute_values.record_type = amc$undefined) AND
                    (output_cycle_attribute_values.block_type = amc$system_specified) THEN
                fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size),
                      fse$to_list_output_unsupported, fsc$copy_file_req, '', status);
              ELSEIF (input_cycle_attribute_values.record_type = amc$undefined) AND
                    (input_cycle_attribute_values.block_type = amc$system_specified) THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$to_list_input_unsupported, fsc$copy_file_req, '', status);
                osp$append_status_file (osc$status_parameter_delimiter,
                      control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
              ELSEIF input_cycle_attribute_values.file_contents = fsc$list THEN
                type_of_copy := fsc$record_move;
              ELSEIF input_is_legible OR
                    (input_cycle_attribute_values.file_contents = fsc$data) OR
                    (input_cycle_attribute_values.file_contents = fsc$unknown_contents) THEN
                type_of_copy := fsc$legible_to_list_move;
              ELSE
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$conflicting_file_contents, fsc$copy_file_req, '', status);
                osp$append_status_file (osc$status_parameter_delimiter,
                      control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
              IFEND;
            ELSEIF (output_is_legible OR
                  (output_cycle_attribute_values.file_contents = fsc$data) OR
                  (output_cycle_attribute_values.file_contents = fsc$unknown_contents)) AND
                  (input_cycle_attribute_values.file_contents = fsc$list) THEN
              IF (input_cycle_attribute_values.record_type = amc$undefined) AND
                    (input_cycle_attribute_values.block_type = amc$system_specified) THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$from_list_input_unsupported, fsc$copy_file_req, '', status);
              ELSE
                type_of_copy := fsc$list_to_legible_move;
              IFEND;
            ELSEIF (output_cycle_attribute_values.file_contents =
                  input_cycle_attribute_values.file_contents) OR
                  (output_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_is_legible AND (output_is_legible OR
                  (output_cycle_attribute_values.file_contents = fsc$data))) OR
                  (output_is_legible AND (input_is_legible OR
                  (input_cycle_attribute_values.file_contents = fsc$data))) THEN
              IF output_is_legible AND input_is_legible THEN
                validate_line_identifiers (status);
              IFEND;
              IF status.normal THEN
                IF (input_cycle_attribute_values.record_type = amc$undefined) AND
                      (input_cycle_attribute_values.block_type = amc$system_specified) THEN
                  type_of_copy := fsc$undefined_ss_move;
                ELSE
                  type_of_copy := fsc$record_move;
                IFEND;
              IFEND;
            ELSE
              fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                    path (1, control_information.input_resolved_file_reference.cycle_path_size),
                    fse$conflicting_file_contents, fsc$copy_file_req, '', status);
              osp$append_status_file (osc$status_parameter_delimiter,
                    control_information.output_resolved_file_reference.
                    path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
            IFEND; {IF FC = ?}

            IF status.normal THEN
              IF (input_cycle_attribute_values.block_type = output_cycle_attribute_values.block_type) AND
                    (input_cycle_attribute_values.file_access_procedure_name =
                    output_cycle_attribute_values.file_access_procedure_name) AND
                    (input_file_catalog_info.cycle_registration.residence.device_class =
                    rmc$mass_storage_device) AND (output_file_catalog_info.cycle_registration.residence.
                    device_class = rmc$mass_storage_device) AND (input_file_catalog_info.cycle_registration.
                    size <= output_file_catalog_info.cycle_registration.size_limit) AND
                    (input_initial_byte_address = 0) AND (output_initial_byte_address = 0) AND
                    (fsc$shorten IN output_file_instance_info.attachment_information.access_modes) THEN
                IF (input_cycle_attribute_values.record_type = output_cycle_attribute_values.record_type) AND
                      (input_cycle_attribute_values.file_contents =
                      output_cycle_attribute_values.file_contents) THEN
                  CASE input_cycle_attribute_values.record_type OF
                  = amc$variable =
                    type_of_copy := fsc$byte_move;
                  = amc$ansi_fixed =
                    IF (input_cycle_attribute_values.max_record_length =
                          output_cycle_attribute_values.max_record_length) AND
                          (input_cycle_attribute_values.padding_character =
                          output_cycle_attribute_values.padding_character) THEN
                      type_of_copy := fsc$byte_move;
                    IFEND;
                  = amc$undefined =
                    IF (input_cycle_attribute_values.block_type <> amc$user_specified) OR
                          (input_cycle_attribute_values.max_block_length =
                          output_cycle_attribute_values.max_block_length) THEN
                      type_of_copy := fsc$byte_move;
                    IFEND;
                  = amc$trailing_char_delimited =
                    IF input_cycle_attribute_values.record_delimiting_character =
                          output_cycle_attribute_values.record_delimiting_character THEN
                      type_of_copy := fsc$byte_move;
                    IFEND;
                  ELSE
                    set_status_internal_error (1, status);
                    type_of_copy := fsc$error_move;
                  CASEND;
                ELSEIF (input_cycle_attribute_values.record_type = amc$variable) AND
                      (output_cycle_attribute_values.record_type = amc$trailing_char_delimited) AND
                      (input_cycle_attribute_values.block_type = amc$system_specified) AND
                      (input_cycle_attribute_values.file_access_procedure_name.entry_point = '') AND
                      (type_of_copy = fsc$record_move) THEN
                  type_of_copy := fsc$v_to_t_record_conversion;
                IFEND;
              IFEND;
            IFEND; { IF status.normal }
          IFEND; { IF tape }

        = amc$byte_addressable =
          fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size),
                fse$improper_fo_for_copy, fsc$copy_file_req, '', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size), status);

        = amc$indexed_sequential, amc$direct_access, amc$system_key =
          IF (input_file_catalog_info.cycle_registration.residence.device_class = rmc$magnetic_tape_device)
                THEN
            type_of_copy := fsc$record_move;
          ELSE
            IF (output_is_legible OR
                  (output_cycle_attribute_values.file_contents = fsc$data) OR
                  (output_cycle_attribute_values.file_contents = fsc$unknown_contents)) AND
                  (input_cycle_attribute_values.file_contents = fsc$list) THEN
              IF (input_cycle_attribute_values.record_type = amc$undefined) AND
                    (input_cycle_attribute_values.block_type = amc$system_specified) THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$from_list_input_unsupported, fsc$copy_file_req, '', status);
              ELSE
                type_of_copy := fsc$list_to_legible_move;
              IFEND;
            ELSEIF (output_cycle_attribute_values.file_contents =
                  input_cycle_attribute_values.file_contents) OR
                  (output_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_is_legible AND (output_is_legible OR
                  (output_cycle_attribute_values.file_contents = fsc$data))) OR
                  (output_is_legible AND (input_is_legible OR
                  (input_cycle_attribute_values.file_contents = fsc$data))) THEN
              IF output_is_legible AND input_is_legible THEN
                validate_line_identifiers (status);
              IFEND;
              IF status.normal THEN
                type_of_copy := fsc$record_move;
              IFEND;
            ELSE
              fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                    path (1, control_information.input_resolved_file_reference.cycle_path_size),
                    fse$conflicting_file_contents, fsc$copy_file_req, '', status);
              osp$append_status_file (osc$status_parameter_delimiter,
                    control_information.output_resolved_file_reference.
                    path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
            IFEND; {IF FC = ?}
          IFEND; { IF tape }

        ELSE {all file_organizations (seq, byte_add, isam, da, sys_key) have been cased}
        CASEND;

      = amc$byte_addressable =

        CASE output_cycle_attribute_values.file_organization OF
        = amc$byte_addressable =
          IF input_cycle_attribute_values.block_type <> output_cycle_attribute_values.block_type THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$conflicting_block_types, fsc$copy_file_req, '', status);
            osp$append_status_file (osc$status_parameter_delimiter,
                  control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
          ELSEIF input_cycle_attribute_values.file_access_procedure_name <>
                output_cycle_attribute_values.file_access_procedure_name THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$fap_names_not_identical, fsc$copy_file_req, '', status);
            osp$append_status_file (osc$status_parameter_delimiter,
                  control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
          ELSEIF input_cycle_attribute_values.file_contents <>
                output_cycle_attribute_values.file_contents THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$conflicting_file_contents, fsc$copy_file_req, '', status);
            osp$append_status_file (osc$status_parameter_delimiter,
                  control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
          ELSEIF input_cycle_attribute_values.record_type <> output_cycle_attribute_values.record_type THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$conflicting_record_types, fsc$copy_file_req, '', status);
            osp$append_status_file (osc$status_parameter_delimiter,
                  control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
          ELSEIF input_file_catalog_info.cycle_registration.residence.device_class <>
                rmc$mass_storage_device THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$copy_device_conflict, fsc$copy_file_req, '', status);
          ELSEIF output_file_catalog_info.cycle_registration.residence.device_class <>
                rmc$mass_storage_device THEN
            fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size),
                  fse$copy_device_conflict, fsc$copy_file_req, '', status);
          ELSEIF input_file_catalog_info.cycle_registration.size >
                output_file_catalog_info.cycle_registration.size_limit THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$size_exceeds_output_limits, fsc$copy_file_req, '', status);
            osp$append_status_file (osc$status_parameter_delimiter,
                  control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
          ELSEIF input_initial_byte_address <> output_initial_byte_address THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$conflicting_file_addresses, fsc$copy_file_req, '', status);
            osp$append_status_file (osc$status_parameter_delimiter,
                  control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
          ELSEIF NOT (fsc$shorten IN output_file_instance_info.attachment_information.access_modes) THEN
            fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size),
                  ame$improper_access_attempt, fsc$copy_file_req, ' SHORTEN ', status);
          ELSE
            CASE input_cycle_attribute_values.record_type OF
            = amc$variable =
              type_of_copy := fsc$byte_move;
            = amc$ansi_fixed =
              IF input_cycle_attribute_values.max_record_length <>
                    output_cycle_attribute_values.max_record_length THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$record_lengths_unequal, fsc$copy_file_req, '', status);
                osp$append_status_file (osc$status_parameter_delimiter,
                      control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
              ELSEIF input_cycle_attribute_values.padding_character <>
                    output_cycle_attribute_values.padding_character THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$padding_characters_unequal, fsc$copy_file_req, '', status);
                osp$append_status_file (osc$status_parameter_delimiter,
                      control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
              ELSE
                type_of_copy := fsc$byte_move;
              IFEND;
            = amc$undefined =
              IF (input_cycle_attribute_values.block_type = amc$user_specified) AND
                    (input_cycle_attribute_values.max_block_length <>
                    output_cycle_attribute_values.max_block_length) THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$block_lengths_unequal, fsc$copy_file_req, '', status);
                osp$append_status_file (osc$status_parameter_delimiter,
                      control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
              ELSE
                type_of_copy := fsc$byte_move;
              IFEND;
            = amc$trailing_char_delimited =
              IF input_cycle_attribute_values.record_delimiting_character <>
                    output_cycle_attribute_values.record_delimiting_character THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$trailing_characters_unequal, fsc$copy_file_req, '', status);
                osp$append_status_file (osc$status_parameter_delimiter,
                      control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
              ELSE
                type_of_copy := fsc$byte_move;
              IFEND;
            ELSE
              set_status_internal_error (2, status);
              type_of_copy := fsc$error_move;
            CASEND;
          IFEND;

        = amc$sequential =
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$improper_fo_for_copy, fsc$copy_file_req, '', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);

        = amc$indexed_sequential, amc$direct_access, amc$system_key =
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$improper_fo_for_copy, fsc$copy_file_req, '', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);

        ELSE {all file_organizations (seq, byte_add, isam, da, sys_key) have been cased}
        CASEND;

      = amc$indexed_sequential, amc$direct_access, amc$system_key =

        CASE output_cycle_attribute_values.file_organization OF
        = amc$indexed_sequential, amc$direct_access, amc$system_key =
          IF NOT ((output_cycle_attribute_values.file_contents =
                  input_cycle_attribute_values.file_contents) OR
                  (output_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_is_legible AND (output_is_legible OR
                  (output_cycle_attribute_values.file_contents = fsc$data))) OR
                  (output_is_legible AND (input_is_legible OR
                  (input_cycle_attribute_values.file_contents = fsc$data)))) THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$conflicting_file_contents, fsc$copy_file_req, '', status);
            osp$append_status_file (osc$status_parameter_delimiter,
                  control_information.output_resolved_file_reference.
                  path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
          ELSE
            IF output_is_legible AND input_is_legible THEN
              validate_line_identifiers (status);
            IFEND;
            IF status.normal THEN
              IF (input_file_catalog_info.cycle_registration.residence.device_class <>
                    rmc$mass_storage_device) OR (output_file_catalog_info.cycle_registration.residence.
                    device_class <> rmc$mass_storage_device) THEN
                type_of_copy := fsc$record_move;
              ELSE
                type_of_copy := fsc$copy_keyed_file_move;
                IF (input_cycle_attribute_values.compression_procedure_name =
                      output_cycle_attribute_values.compression_procedure_name) AND
                      (input_cycle_attribute_values.hashing_procedure_name =
                      output_cycle_attribute_values.hashing_procedure_name) AND
                      (input_cycle_attribute_values.collate_table_name =
                      output_cycle_attribute_values.collate_table_name) AND
                      (input_cycle_attribute_values.embedded_key = output_cycle_attribute_values.
                      embedded_key) AND (input_cycle_attribute_values.file_access_procedure_name =
                      output_cycle_attribute_values.file_access_procedure_name) AND
                      (input_cycle_attribute_values.file_contents =
                      output_cycle_attribute_values.file_contents) AND
                      (input_cycle_attribute_values.file_organization =
                      output_cycle_attribute_values.file_organization) AND
                      (input_cycle_attribute_values.initial_home_block_count =
                      output_cycle_attribute_values.initial_home_block_count) AND
                      (input_cycle_attribute_values.key_length = output_cycle_attribute_values.key_length) AND
                      (input_cycle_attribute_values.key_position = output_cycle_attribute_values.
                      key_position) AND (input_cycle_attribute_values.key_type =
                      output_cycle_attribute_values.key_type) AND (input_cycle_attribute_values.
                      max_block_length = output_cycle_attribute_values.max_block_length) AND
                      (input_cycle_attribute_values.max_record_length =
                      output_cycle_attribute_values.max_record_length) AND
                      (input_cycle_attribute_values.min_record_length =
                      output_cycle_attribute_values.min_record_length) AND
                      (input_cycle_attribute_values.record_type = output_cycle_attribute_values.record_type)
                      AND (input_cycle_attribute_values.records_per_block =
                      output_cycle_attribute_values.records_per_block) AND
                      (input_file_catalog_info.cycle_registration.size <=
                      output_file_catalog_info.cycle_registration.size_limit) AND
                      (input_file_instance_info.attachment_information.open_position = amc$open_at_boi) AND
                      (output_file_instance_info.attachment_information.open_position = amc$open_at_boi) AND
                      (output_file_instance_info.attachment_information.open_share_modes =
                      $fst$file_access_options []) AND (fsc$shorten IN
                      output_file_instance_info.attachment_information.access_modes) THEN
                  type_of_copy := fsc$byte_move;
                IFEND;
              IFEND; {device_class}
            IFEND;
          IFEND;

        = amc$sequential =
          IF (output_file_catalog_info.cycle_registration.residence.device_class = rmc$magnetic_tape_device)
                THEN
            type_of_copy := fsc$record_move;
          ELSE
            IF output_cycle_attribute_values.file_contents = fsc$list THEN
              IF (output_cycle_attribute_values.record_type = amc$undefined) AND
                    (output_cycle_attribute_values.block_type = amc$system_specified) THEN
                fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size),
                      fse$to_list_output_unsupported, fsc$copy_file_req, '', status);
              ELSEIF input_is_legible OR
                    (input_cycle_attribute_values.file_contents = fsc$data) OR
                    (input_cycle_attribute_values.file_contents = fsc$unknown_contents) THEN
                type_of_copy := fsc$legible_to_list_move;
              ELSE
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$conflicting_file_contents, fsc$copy_file_req, '', status);
                osp$append_status_file (osc$status_parameter_delimiter,
                      control_information.output_resolved_file_reference.
                      path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
              IFEND;
            ELSEIF (output_cycle_attribute_values.file_contents =
                  input_cycle_attribute_values.file_contents) OR
                  (output_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_cycle_attribute_values.file_contents = fsc$unknown_contents) OR
                  (input_is_legible AND (output_is_legible OR
                  (output_cycle_attribute_values.file_contents = fsc$data))) OR
                  (output_is_legible AND (input_is_legible OR
                  (input_cycle_attribute_values.file_contents = fsc$data))) THEN
              IF output_is_legible AND input_is_legible THEN
                validate_line_identifiers (status);
              IFEND;
              IF status.normal THEN
                type_of_copy := fsc$record_move;
              IFEND;
            ELSE
              fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                    path (1, control_information.input_resolved_file_reference.cycle_path_size),
                    fse$conflicting_file_contents, fsc$copy_file_req, '', status);
              osp$append_status_file (osc$status_parameter_delimiter,
                    control_information.output_resolved_file_reference.
                    path (1, control_information.output_resolved_file_reference.cycle_path_size), status);
            IFEND; {IF FC = ?}
          IFEND; { IF tape }

        = amc$byte_addressable =
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$improper_fo_for_copy, fsc$copy_file_req, '', status);
          osp$append_status_file (osc$status_parameter_delimiter,
                control_information.output_resolved_file_reference.
                path (1, control_information.output_resolved_file_reference.cycle_path_size), status);

        ELSE {all file_organizations (seq, byte_add, isam, da, sys_key) have been cased}
        CASEND;

      ELSE {all file_organizations (seq, byte_add, isam, da, sys_key) have been cased}
      CASEND;

      IF NOT status.normal THEN
        IF type_of_copy <> fsc$error_move THEN
          pmp$log (' FSP$COPY_FILE did not recognize error_move in get_type_of_copy', ignore_status);
        IFEND;
        type_of_copy := fsc$error_move;
        RETURN;
      ELSEIF type_of_copy = fsc$error_move THEN
        set_status_internal_error (3, status);
        RETURN;
      IFEND;

    PROCEND get_type_of_copy;

?? TITLE := '  PROCEDURE calculate_record_info ' ??
?? EJECT ??

    PROCEDURE calculate_record_info
      (VAR control_information: fst$copy_control_information;
       VAR status: ost$status);

      FUNCTION minimum_record_length
        (    input_record_length: integer;
             output_record_length: integer): amt$working_storage_length;

        IF input_record_length < output_record_length THEN
          minimum_record_length := input_record_length;
        ELSE
          minimum_record_length := output_record_length;
        IFEND;
      FUNCEND minimum_record_length;

      CONST
        minimum_sequential_wsl = 100(16); {256 bytes}

      VAR
        required_input_record_length: amt$max_record_length,
        required_output_record_length: amt$max_record_length;

      { PURPOSE:  This procedure determines the necessary information for a       }
      {record_move, list_to_legible_move, legible_to_list_move, undefined_ss_move.}


      control_information.input_file_device_class := input_file_catalog_info.cycle_registration.residence.
            device_class;

      IF control_information.type_of_copy = fsc$legible_to_list_move THEN
        control_information.page_format := output_cycle_attribute_values.page_format;
        control_information.page_length := output_cycle_attribute_values.page_length;
      IFEND;

      IF (output_cycle_attribute_values.record_type = amc$variable) AND
            (output_cycle_attribute_values.file_organization = amc$sequential) THEN
        control_information.output_can_be_partitioned := TRUE;
      ELSE
        control_information.output_can_be_partitioned := FALSE;
      IFEND;

      control_information.output_record_length_is_fixed := FALSE;
      control_information.push_overflow := FALSE;

{  The size of the record header of an ansi_variable file is subtracted from the max_block_length, because
{  the maximum amount of data that can be placed in an ansi_variable block is the max_block_size minus the
{  header size and the calculation of working_storage length and output_record_length is based on the
{  maximum amount of data that can be placed in a record/block.
      IF input_cycle_attribute_values.record_type = amc$ansi_variable THEN
         input_cycle_attribute_values.max_block_length :=
               input_cycle_attribute_values.max_block_length - #SIZE (bat$d_record_rcw);
      IFEND;
      IF output_cycle_attribute_values.record_type = amc$ansi_variable THEN
         output_cycle_attribute_values.max_block_length :=
               output_cycle_attribute_values.max_block_length - #SIZE (bat$d_record_rcw);
      IFEND;

      {See table in ERS for a table of the determination of Working_storage_length}
      IF (input_cycle_attribute_values.file_organization = amc$sequential) AND
            (output_cycle_attribute_values.file_organization = amc$sequential) THEN
        {For a fixed to fixed copy, a working storage area greater than the minimum of the
        {maxrl/maxbl of both files is wasted space. (ie. either truncated of never used.)
        IF (output_cycle_attribute_values.block_type = amc$user_specified) AND
              ((output_cycle_attribute_values.record_type = amc$undefined) OR
              (output_cycle_attribute_values.record_type = amc$ansi_variable)) THEN
          control_information.output_record_length := output_cycle_attribute_values.max_block_length;
          control_information.output_record_length_is_fixed := TRUE;
          IF (input_cycle_attribute_values.block_type = amc$user_specified) AND
                ((input_cycle_attribute_values.record_type = amc$undefined) OR
                (input_cycle_attribute_values.record_type = amc$ansi_variable)) THEN
            control_information.working_storage_length := minimum_record_length
                  (input_cycle_attribute_values.max_block_length,
                  output_cycle_attribute_values.max_block_length);
          ELSEIF input_cycle_attribute_values.record_type = amc$ansi_fixed THEN
            control_information.working_storage_length := minimum_record_length
                  (input_cycle_attribute_values.max_record_length,
                  output_cycle_attribute_values.max_block_length);
          ELSE
            control_information.working_storage_length := output_cycle_attribute_values.max_block_length;
          IFEND;
        ELSEIF output_cycle_attribute_values.record_type = amc$ansi_fixed THEN
          control_information.output_record_length := output_cycle_attribute_values.max_record_length;
          control_information.output_record_length_is_fixed := TRUE;
          IF (input_cycle_attribute_values.block_type = amc$user_specified) AND
                ((input_cycle_attribute_values.record_type = amc$undefined) OR
                (input_cycle_attribute_values.record_type = amc$ansi_variable)) THEN
            control_information.working_storage_length := minimum_record_length
                  (input_cycle_attribute_values.max_block_length,
                  output_cycle_attribute_values.max_record_length);
          ELSEIF input_cycle_attribute_values.record_type = amc$ansi_fixed THEN
            control_information.working_storage_length := minimum_record_length
                  (input_cycle_attribute_values.max_record_length,
                  output_cycle_attribute_values.max_record_length);
          ELSE
            control_information.working_storage_length := output_cycle_attribute_values.max_record_length;
          IFEND;
        ELSEIF (input_cycle_attribute_values.record_type = amc$undefined) AND
              (input_cycle_attribute_values.block_type = amc$system_specified) THEN
          control_information.output_record_length := output_cycle_attribute_values.max_record_length;
          control_information.output_record_length_is_fixed := TRUE;
          control_information.working_storage_length := output_cycle_attribute_values.max_record_length;
        ELSEIF input_cycle_attribute_values.record_type = amc$ansi_fixed THEN
          control_information.working_storage_length := input_cycle_attribute_values.max_record_length;
        ELSE
          control_information.working_storage_length := input_cycle_attribute_values.max_block_length;
        IFEND;
        {The following allows a single get_next and put_next per record if possible when converting.
        IF (control_information.type_of_copy = fsc$list_to_legible_move) OR
              (control_information.type_of_copy = fsc$legible_to_list_move) THEN
          control_information.working_storage_length := control_information.working_storage_length + 1;
        IFEND;

        {The restriction of a maximum push allows for large records without requiring a large
        {working storage area being pushed onto the stack.
        {This is not appropriate for keyed files because they don't support partial gets and puts.
        {The limit for indexed sequential files as of 7/13/86 is a maxrl of approximately 65k.
        {For rt=u bt=us and device_class=rmc$magnetic_tape_device direct i/o can be done on
        {Long record tapes if the working storage area is not restricted, begins on a word
        {boundary (which is true for PUSH and the Scratch segment, and ends on a word boundary.
        {
        IF (input_cycle_attribute_values.record_type = amc$undefined) AND
              (input_cycle_attribute_values.block_type = amc$user_specified) AND
              (input_file_catalog_info.cycle_registration.residence.device_class = rmc$magnetic_tape_device)
              THEN
          control_information.working_storage_length := control_information.working_storage_length +
                ((8 - (control_information.working_storage_length MOD 8)) MOD 8);
        ELSEIF control_information.working_storage_length > fsc$maximum_copy_file_push THEN
          control_information.working_storage_length := fsc$maximum_copy_file_push;
          control_information.push_overflow := TRUE;
        ELSE
          IF (NOT control_information.output_record_length_is_fixed) AND
                (control_information.working_storage_length < minimum_sequential_wsl) THEN
            control_information.working_storage_length := minimum_sequential_wsl;
          IFEND;
        IFEND;
      ELSEIF (input_cycle_attribute_values.file_organization IN amv$aam_file_organizations) AND
            (output_cycle_attribute_values.file_organization = amc$sequential) THEN
        {The case of input file with rt=u bt=ss is not specified because push_overflow is false,
        {therefore output_record_length is irrelevant.
        IF (output_cycle_attribute_values.block_type = amc$user_specified) AND
              ((output_cycle_attribute_values.record_type = amc$undefined) OR
              (output_cycle_attribute_values.record_type = amc$ansi_variable)) THEN
          control_information.output_record_length := output_cycle_attribute_values.max_block_length;
          control_information.output_record_length_is_fixed := TRUE;
        ELSEIF output_cycle_attribute_values.record_type = amc$ansi_fixed THEN
          control_information.output_record_length := output_cycle_attribute_values.max_record_length;
          control_information.output_record_length_is_fixed := TRUE;
        IFEND;
        IF input_cycle_attribute_values.embedded_key THEN
          control_information.working_storage_length := input_cycle_attribute_values.max_record_length;
        ELSE
          control_information.working_storage_length := input_cycle_attribute_values.max_record_length +
                input_cycle_attribute_values.key_length;
        IFEND;
        {The get of an ISAM file MUST be COMPLETE, therefore one is added for legible to list}
        IF (control_information.type_of_copy = fsc$legible_to_list_move) THEN
          control_information.working_storage_length := control_information.working_storage_length + 1;
        IFEND;
      ELSEIF (input_cycle_attribute_values.file_organization = amc$sequential) AND
            (output_cycle_attribute_values.file_organization IN amv$aam_file_organizations) THEN
        IF output_cycle_attribute_values.embedded_key THEN
          control_information.output_record_length := output_cycle_attribute_values.max_record_length;
        ELSE
          control_information.output_record_length := output_cycle_attribute_values.max_record_length +
                output_cycle_attribute_values.key_length;
        IFEND;
        control_information.output_record_length_is_fixed := TRUE;
        control_information.working_storage_length := control_information.output_record_length;
        { The working storage length is increase by one because the format effector is tossed out}
        IF (control_information.type_of_copy = fsc$list_to_legible_move) THEN
          control_information.working_storage_length := control_information.working_storage_length + 1;
        IFEND;
      ELSEIF (input_cycle_attribute_values.file_organization IN amv$aam_file_organizations) AND
            (output_cycle_attribute_values.file_organization IN amv$aam_file_organizations) THEN
{ This is the case where one of the AAM files is the target of a file connection.
        IF output_cycle_attribute_values.embedded_key THEN
          control_information.output_record_length := output_cycle_attribute_values.max_record_length;
        ELSE
          control_information.output_record_length := output_cycle_attribute_values.max_record_length +
                output_cycle_attribute_values.key_length;
        IFEND;
        control_information.output_record_length_is_fixed := TRUE;
        IF input_cycle_attribute_values.embedded_key THEN
          control_information.working_storage_length := input_cycle_attribute_values.max_record_length;
        ELSE
          control_information.working_storage_length := input_cycle_attribute_values.max_record_length +
                input_cycle_attribute_values.key_length;
        IFEND;
      ELSE
        set_status_internal_error (4, status);
      IFEND;

      {  The following lines make sure that the maxrl is large enough for the requested copy. }
      CASE control_information.type_of_copy OF
      = fsc$record_move, fsc$undefined_ss_move =
        required_input_record_length := 1;
        required_output_record_length := 1;
      = fsc$legible_to_list_move =
        required_input_record_length := 1;
        required_output_record_length := 2;
      = fsc$list_to_legible_move =
        required_input_record_length := 2;
        required_output_record_length := 1;
      ELSE
        set_status_internal_error (5, status);
        RETURN;
      CASEND;

      IF control_information.output_record_length_is_fixed AND
            (control_information.output_record_length < required_output_record_length) THEN
        fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
              path (1, control_information.output_resolved_file_reference.cycle_path_size),
              fse$insufficient_record_length, fsc$copy_file_req, '', status);
        RETURN;
      ELSEIF ((input_cycle_attribute_values.record_type = amc$ansi_fixed) AND
            (input_cycle_attribute_values.max_record_length < required_input_record_length)) OR
            ((input_cycle_attribute_values.block_type = amc$user_specified) AND
            ((input_cycle_attribute_values.record_type = amc$undefined) OR
            (input_cycle_attribute_values.record_type = amc$ansi_variable)) AND
            (input_cycle_attribute_values.max_block_length < required_input_record_length)) THEN
        fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
              path (1, control_information.input_resolved_file_reference.cycle_path_size),
              fse$insufficient_record_length, fsc$copy_file_req, '', status);
        RETURN;
      IFEND;

      IF (control_information.working_storage_length < required_input_record_length) OR
            (control_information.working_storage_length < required_output_record_length) THEN
        set_status_internal_error (6, status);
        RETURN;
      IFEND;

    PROCEND calculate_record_info;

?? TITLE := '  PROCEDURE delete_data ' ??
?? EJECT ??

    PROCEDURE delete_data
      (    output: fst$file_reference;
       VAR {input, output} output_fid: amt$file_identifier;
       VAR {input, output} type_of_copy: fst$copy_types;
       VAR status: ost$status);

      VAR
        new_output_attachment_options: ^fst$attachment_options,
        new_output_attribute_validation: array [1 .. 12] of fst$file_cycle_attribute;

      status.normal := TRUE;

      IF (type_of_copy = fsc$byte_move) OR (NOT (output_cycle_attribute_values.file_organization IN
            amv$aam_file_organizations)) THEN
        bap$delete_data (output_fid, status);
        IF NOT status.normal THEN
          type_of_copy := fsc$error_move;
          RETURN;
        IFEND;
      ELSEIF type_of_copy <> fsc$copy_keyed_file_move THEN
        {If a copy_keyed_files is performed, the output file will be deleted in copy_keyed_file.}
        new_output_attribute_validation [1].selector := fsc$block_type;
        new_output_attribute_validation [1].block_type := output_cycle_attribute_values.block_type;
        new_output_attribute_validation [2].selector := fsc$embedded_key;
        new_output_attribute_validation [2].embedded_key := output_cycle_attribute_values.embedded_key;
        new_output_attribute_validation [3].selector := fsc$file_contents_and_processor;
        new_output_attribute_validation [3].file_contents := output_cycle_attribute_values.file_contents;
        new_output_attribute_validation [3].file_processor := output_cycle_attribute_values.file_processor;
        new_output_attribute_validation [4].selector := fsc$file_organization;
        new_output_attribute_validation [4].file_organization :=
              output_cycle_attribute_values.file_organization;
        new_output_attribute_validation [5].selector := fsc$key_length;
        new_output_attribute_validation [5].key_length := output_cycle_attribute_values.key_length;
        new_output_attribute_validation [6].selector := fsc$line_number;
        new_output_attribute_validation [6].line_number := output_cycle_attribute_values.line_number;
        new_output_attribute_validation [7].selector := fsc$max_block_length;
        new_output_attribute_validation [7].max_block_length :=
              output_cycle_attribute_values.max_block_length;
        new_output_attribute_validation [8].selector := fsc$max_record_length;
        new_output_attribute_validation [8].max_record_length :=
              output_cycle_attribute_values.max_record_length;
        new_output_attribute_validation [9].selector := fsc$page_format;
        new_output_attribute_validation [9].page_format := output_cycle_attribute_values.page_format;
        new_output_attribute_validation [10].selector := fsc$page_length;
        new_output_attribute_validation [10].page_length := output_cycle_attribute_values.page_length;
        new_output_attribute_validation [11].selector := fsc$record_type;
        new_output_attribute_validation [11].record_type := output_cycle_attribute_values.record_type;
        new_output_attribute_validation [12].selector := fsc$statement_identifier;
        new_output_attribute_validation [12].statement_identifier :=
              output_cycle_attribute_values.statement_identifier;
        PUSH new_output_attachment_options: [1 .. UPPERBOUND (output_file_attachment^) + 1];
        i#move (output_file_attachment, new_output_attachment_options, #SIZE (output_file_attachment^));
        new_output_attachment_options^ [UPPERBOUND (new_output_attachment_options^)].selector :=
              fsc$create_file;
        new_output_attachment_options^ [UPPERBOUND (new_output_attachment_options^)].create_file := FALSE;
        fsp$close_file (output_fid, status);
        output_fid := amv$nil_file_identifier;
        #SPOIL (output_fid);
        IF NOT status.normal THEN
          type_of_copy := fsc$error_move;
          RETURN;
        IFEND;
        fsp$open_file (output, amc$record, new_output_attachment_options, NIL, NIL,
              ^new_output_attribute_validation, NIL, output_fid, status);
        IF NOT status.normal THEN
          type_of_copy := fsc$error_move;
          RETURN;
        IFEND;
      IFEND;

    PROCEND delete_data;

?? OLDTITLE ??
?? EJECT ??

    CONST
      tfa_bt = 1,
      tfa_cc = 2,
      tfa_ic = 3,
      tfa_maxbl = 4,
      tfa_maxrl = 5,
      tfa_pc = 6,
      tfa_rt = 7;

    TYPE
      attachment_options = set of fst$file_attachment_choices;

    VAR
      allowed_device_classes: fst$device_classes,
      attachment_count: integer,
      delete_data_index: integer,
      delete_output_data: boolean,
      device_dependent_info: attribute_information,
      file_contents_text: ost$string,
      file_contents_truncation_status: ost$status,
      new_default_bt: amt$block_type,
      new_default_rt: amt$record_type,
      option: integer,
      output_file_contents_truncated: boolean,
      specified_options: attachment_options,
      tape_file_attributes: array [tfa_bt .. tfa_rt] of amt$fetch_item;

  /open_and_get_type_of_copy/
    BEGIN

      allowed_device_classes:=-$fst$device_classes[];
      input_fid := amv$nil_file_identifier;
      #SPOIL (input_fid);
      output_fid := amv$nil_file_identifier;
      #SPOIL (output_fid);
      control_information.type_of_copy := fsc$error_move;
      file_contents_truncation_status.normal := TRUE;
      output_file_contents_truncated := FALSE;
      specified_options:=  $attachment_options[];
      status.normal := TRUE;

      IF input_file_attachment <> NIL THEN
         attachment_count:= UPPERBOUND (input_file_attachment^);
         FOR option:= 1 to attachment_count DO
           CASE  input_file_attachment^[option].selector of
             = fsc$open_share_modes =
               specified_options:= specified_options + $attachment_options[fsc$open_share_modes];
           ELSE
           CASEND;
         FOREND;
      ELSE
        attachment_count := 0;
      IFEND;
      IF NOT (fsc$open_share_modes IN specified_options) THEN
        PUSH input_file_attachment_options: [1 .. attachment_count + 2];
        IF attachment_count > 0 THEN
          i#move (input_file_attachment, input_file_attachment_options, #SIZE (input_file_attachment^));
        IFEND;
        input_file_attachment_options^ [attachment_count + 1].selector := fsc$open_share_modes;
        input_file_attachment_options^ [attachment_count + 1].open_share_modes :=
              $fst$file_access_options [fsc$read, fsc$execute];
        input_file_attachment_options^ [attachment_count + 2].selector := fsc$open_share_modes;
        input_file_attachment_options^ [attachment_count + 2].open_share_modes :=
              -$fst$file_access_options [];
      ELSE
        input_file_attachment_options := input_file_attachment;
      IFEND;

      fsp$open_file (input, amc$record, input_file_attachment_options, NIL, NIL, input_attribute_validation,
            NIL, input_fid, status);
      IF NOT status.normal THEN
        IF status.condition = ame$new_file_requires_append THEN
          fsp$set_file_reference_abnormal (input, fse$empty_input_file, fsc$copy_file_req, '', status);
        IFEND;
        RETURN;
      IFEND;

      fsp$get_open_information (input_fid, NIL, ^input_file_catalog_info, ^input_cycle_attribute_sources,
            ^input_cycle_attribute_values, ^input_file_instance_info,
            ^control_information.input_resolved_file_reference, NIL, input_file_user_def_attr_size, status);

      IF NOT status.normal THEN
        IF status.condition = fse$file_contents_truncated THEN
          file_contents_truncation_status := status;
          status.normal := TRUE;
        ELSE
          RETURN;
        IFEND;
      IFEND;

      IF (input_file_catalog_info.cycle_registration.size = 0) AND
            (input_file_catalog_info.cycle_registration.residence.device_class = rmc$mass_storage_device) THEN
        fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
              path (1, control_information.input_resolved_file_reference.cycle_path_size),
              fse$empty_input_file, fsc$copy_file_req, '', status);
        RETURN;
      IFEND;

      IF (input_file_catalog_info.cycle_registration.residence.device_class <> rmc$magnetic_tape_device) AND
            (input_file_catalog_info.cycle_registration.residence.device_class <> rmc$null_device) AND
            (NOT (input_file_instance_info.attachment_information.open_share_modes <=
            $fst$file_access_options [fsc$read, fsc$execute])) AND
            NOT (fsc$open_share_modes IN specified_options) THEN
        IF NOT task_has_exclusive_write_access (input_fid) THEN
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$concurrent_share_conflict, fsc$copy_file_req, 'READ, EXECUTE', status);
          osp$append_status_parameter (osc$status_parameter_delimiter, 'APPEND, SHORTEN, and/or MODIFY',
                status);
          RETURN;
        IFEND;
      IFEND;

      IF input_file_instance_info.attachment_information.open_position = amc$open_at_eoi THEN
        fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
              path (1, control_information.input_resolved_file_reference.cycle_path_size),
              fse$input_file_at_eoi, fsc$copy_file_req, '', status);
        RETURN;
      IFEND;

      device_dependent_info.adjust_default := FALSE;

      {Current byte address is used in determining whether a byte_move can be done}
      IF input_file_catalog_info.cycle_registration.residence.device_class = rmc$mass_storage_device THEN
        IF input_cycle_attribute_values.file_organization IN amv$aam_file_organizations THEN
          input_initial_byte_address := 0;
        ELSE
          input_file_access_info [1].key := amc$current_byte_address;
          amp$fetch_access_information (input_fid, input_file_access_info, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          IF (input_file_access_info [1].current_byte_address =
                input_file_catalog_info.cycle_registration.size) THEN
            fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                  path (1, control_information.input_resolved_file_reference.cycle_path_size),
                  fse$input_file_at_eoi, fsc$copy_file_req, '', status);
            RETURN;
          IFEND;
          input_initial_byte_address := input_file_access_info [1].current_byte_address;
        IFEND;
        allowed_device_classes := -$fst$device_classes[fsc$magnetic_tape_device];
        { SS/F and SS/T block and record combinations are supported on disk but not tape files.
        { Map these combinations to ones that are acceptable for a tape file should the output
        { file turn out to be a tape file; set up allowed device classes to prevent opening a
        { tape file.
        IF (input_cycle_attribute_values.block_type = amc$system_specified) THEN
          IF input_cycle_attribute_values.record_type = amc$ansi_fixed THEN
            device_dependent_info.adjust_default := TRUE;
            new_default_rt := amc$ansi_fixed;
            new_default_bt := amc$user_specified;
          ELSEIF input_cycle_attribute_values.record_type = amc$trailing_char_delimited THEN
            device_dependent_info.adjust_default := TRUE;
            new_default_rt := amc$variable;
            new_default_bt := amc$system_specified;
          IFEND;
        IFEND;
      ELSEIF input_file_catalog_info.cycle_registration.residence.device_class = rmc$magnetic_tape_device THEN

        tape_file_attributes [tfa_bt].key := amc$block_type;
        tape_file_attributes [tfa_cc].key := amc$character_conversion;
        tape_file_attributes [tfa_ic].key := amc$internal_code;
        tape_file_attributes [tfa_maxbl].key := amc$max_block_length;
        tape_file_attributes [tfa_maxrl].key := amc$max_record_length;
        tape_file_attributes [tfa_pc].key := amc$padding_character;
        tape_file_attributes [tfa_rt].key := amc$record_type;

        amp$fetch (input_fid, tape_file_attributes, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        input_cycle_attribute_values.block_type := tape_file_attributes [tfa_bt].block_type;
        input_cycle_attribute_sources.block_type := tape_file_attributes [tfa_bt].source;

        input_cycle_attribute_values.character_conversion :=
              tape_file_attributes [tfa_cc].character_conversion;
        input_cycle_attribute_sources.character_conversion := tape_file_attributes [tfa_cc].source;

        input_cycle_attribute_values.internal_code := tape_file_attributes [tfa_ic].internal_code;
        input_cycle_attribute_sources.internal_code := tape_file_attributes [tfa_ic].source;

        input_cycle_attribute_values.max_block_length := tape_file_attributes [tfa_maxbl].max_block_length;
        input_cycle_attribute_sources.max_block_length := tape_file_attributes [tfa_maxbl].source;

        input_cycle_attribute_values.max_record_length := tape_file_attributes [tfa_maxrl].max_record_length;
        input_cycle_attribute_sources.max_record_length := tape_file_attributes [tfa_maxrl].source;

        input_cycle_attribute_values.padding_character := tape_file_attributes [tfa_pc].padding_character;
        input_cycle_attribute_sources.padding_character := tape_file_attributes [tfa_pc].source;

        input_cycle_attribute_values.record_type := tape_file_attributes [tfa_rt].record_type;
        input_cycle_attribute_sources.record_type := tape_file_attributes [tfa_rt].source;

        { US/D, US/S, and US/V block and record combinations are supported on tape but not disk files.
        { Map these combinations to ones that are acceptable for a disk file should the output
        { file turn out to be a disk file; set up allowed device classes to prevent opening a
        { disk file.
        IF (input_cycle_attribute_values.block_type = amc$user_specified) THEN
          IF (input_cycle_attribute_values.record_type = amc$ansi_variable) OR
             (input_cycle_attribute_values.record_type = amc$ansi_spanned) OR
             (input_cycle_attribute_values.record_type = amc$variable) THEN
            device_dependent_info.adjust_default := TRUE;
            new_default_rt := amc$variable;
            new_default_bt := amc$system_specified;
            allowed_device_classes := -$fst$device_classes[fsc$mass_storage_device];
          IFEND;
        IFEND;
      IFEND;

      device_dependent_info.force_input_defaults := FALSE;
      set_output_default_creation_att (device_dependent_info, output_default_creation_ptr, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      specified_options:=  $attachment_options[];
      delete_output_data:=FALSE;

      IF output_file_attachment <> NIL THEN
        attachment_count := UPPERBOUND (output_file_attachment^);
        FOR option := 1 to attachment_count DO
          CASE  output_file_attachment^[option].selector of
            = fsc$allowed_device_classes =
              specified_options := specified_options + $attachment_options[fsc$allowed_device_classes];
            = fsc$delete_data =
              delete_data_index := option;
              specified_options := specified_options + $attachment_options[fsc$delete_data];
              delete_output_data := output_file_attachment^[option].delete_data;
          ELSE
          CASEND;
        FOREND;
      ELSE
       attachment_count := 0;
      IFEND;
      { If allowed_device_classes was not specified by the caller and there would be
      { a conflict in record/block types when copying disk to tape or vice versa,
      { use allowed_device_classes to cause the open to fail, adjust the
      { default record/block type, and retry the open attempt.
      IF (allowed_device_classes <> -$fst$device_classes[]) AND
         NOT (fsc$allowed_device_classes IN specified_options) THEN
         PUSH output_file_attachment_options: [1 .. (attachment_count+1)];
         IF attachment_count > 0 THEN
           i#move (output_file_attachment, output_file_attachment_options, #SIZE (output_file_attachment^));
         IFEND;
         output_file_attachment_options^[attachment_count+1].selector := fsc$allowed_device_classes;
         output_file_attachment_options^[attachment_count+1].allowed_device_classes := allowed_device_classes;
      ELSEIF delete_output_data THEN
        PUSH output_file_attachment_options: [1 .. attachment_count];
        output_file_attachment_options^ := output_file_attachment^;
      ELSE
        output_file_attachment_options := output_file_attachment;
      IFEND;

      IF delete_output_data THEN
        { Defer the data deletion until after the open as a consideration to AAM.
        output_file_attachment_options^ [delete_data_index].delete_data := FALSE;
      IFEND;

      fsp$open_file (output, amc$record, output_file_attachment_options, output_default_creation_ptr,
            output_creation_attributes, output_attribute_validation, NIL, output_fid, status);
      IF NOT status.normal THEN
        IF (status.condition = fse$device_class_conflict) AND
           (allowed_device_classes <> -$fst$device_classes[]) AND
           NOT (fsc$allowed_device_classes IN specified_options) THEN
          { We are either copying tape->disk or disk->tape and there is
          { a possibility that the record/block type defaults are not appropriate.
          { Adjust them to affect the first instance of open of a new file.
          device_dependent_info.force_input_defaults := TRUE;
          IF device_dependent_info.adjust_default THEN
            device_dependent_info.block_type := new_default_bt;
            device_dependent_info.record_type := new_default_rt;
          IFEND;
          set_output_default_creation_att (device_dependent_info, output_default_creation_ptr, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

          {Allow the open to succeed independent of device class.
          output_file_attachment_options^[attachment_count+1].selector:=fsc$null_attachment_option;
          fsp$open_file (output, amc$record, output_file_attachment_options, output_default_creation_ptr,
            output_creation_attributes, output_attribute_validation, NIL, output_fid, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        ELSE
          RETURN;
        IFEND;
      IFEND; {open succeeded; continue}

      fsp$get_open_information (output_fid, ^output_file_attachment_info, ^output_file_catalog_info, NIL,
            ^output_cycle_attribute_values, ^output_file_instance_info,
            ^control_information.output_resolved_file_reference, NIL, output_file_user_def_attr_size,
            status);
      IF NOT status.normal THEN
        IF status.condition = fse$file_contents_truncated THEN
          output_file_contents_truncated := TRUE;
          status.normal := TRUE;
        ELSE
          RETURN;
        IFEND;
      IFEND;

      {Current byte address is used in determining whether a byte_move can be done}
      IF (input_file_catalog_info.cycle_registration.residence.device_class = rmc$mass_storage_device) AND
            (output_file_catalog_info.cycle_registration.residence.device_class = rmc$mass_storage_device)
            THEN
        IF output_cycle_attribute_values.file_organization IN amv$aam_file_organizations THEN
          output_initial_byte_address := 0;
        ELSE
          output_file_access_info [1].key := amc$current_byte_address;
          amp$fetch_access_information (output_fid, output_file_access_info, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          output_initial_byte_address := output_file_access_info [1].current_byte_address;
        IFEND;
      IFEND;

      IF output_file_catalog_info.cycle_registration.residence.device_class = rmc$magnetic_tape_device THEN

        tape_file_attributes [tfa_bt].key := amc$block_type;
        tape_file_attributes [tfa_cc].key := amc$character_conversion;
        tape_file_attributes [tfa_ic].key := amc$internal_code;
        tape_file_attributes [tfa_maxbl].key := amc$max_block_length;
        tape_file_attributes [tfa_maxrl].key := amc$max_record_length;
        tape_file_attributes [tfa_pc].key := amc$padding_character;
        tape_file_attributes [tfa_rt].key := amc$record_type;

        amp$fetch (output_fid, tape_file_attributes, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        output_cycle_attribute_values.block_type := tape_file_attributes [tfa_bt].block_type;
        output_cycle_attribute_values.character_conversion :=
              tape_file_attributes [tfa_cc].character_conversion;
        output_cycle_attribute_values.internal_code := tape_file_attributes [tfa_ic].internal_code;
        output_cycle_attribute_values.max_block_length := tape_file_attributes [tfa_maxbl].max_block_length;
        output_cycle_attribute_values.max_record_length := tape_file_attributes [tfa_maxrl].max_record_length;
        output_cycle_attribute_values.padding_character := tape_file_attributes [tfa_pc].padding_character;
        output_cycle_attribute_values.record_type := tape_file_attributes [tfa_rt].record_type;

      IFEND;

      get_type_of_copy (control_information.type_of_copy, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF (control_information.type_of_copy = fsc$byte_move) OR
            (control_information.type_of_copy = fsc$v_to_t_record_conversion) THEN
        control_information.initial_byte_address := input_initial_byte_address;
        control_information.input_file_size := input_file_catalog_info.cycle_registration.size;

{ byte_move implies that the input and output file_organizations are the same.

        control_information.input_and_output_are_aam_files := (input_cycle_attribute_values.file_organization
              IN amv$aam_file_organizations);
      ELSEIF control_information.type_of_copy <> fsc$copy_keyed_file_move THEN
        calculate_record_info (control_information, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;

      {The following was added so that copy_file only deletes the output file if necessary.}
      {These restrictions (except size > 0) come from bam$open_file in its determination}
      {of whether to delete the data.  Keyed files recreate the header on the open if}
      {bam$open_file deletes the data.}
      IF delete_output_data AND
            (output_file_catalog_info.cycle_registration.residence.device_class = rmc$mass_storage_device) AND
            (output_file_catalog_info.cycle_registration.size > 0) AND
            (output_file_attachment_info.usage_information.concurrent_open_count = 1) AND
            (output_file_instance_info.attachment_information.open_position = amc$open_at_boi) AND
            (fsc$shorten IN output_file_instance_info.attachment_information.access_modes) AND
            (output_file_attachment_info.administration_information.attached_share_modes =
            $fst$file_access_options []) THEN
        delete_data (control_information.output_resolved_file_reference.
              path (1, control_information.output_resolved_file_reference.complete_path_size),
              output_fid, control_information.type_of_copy, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;
      IFEND;

      IF (NOT file_contents_truncation_status.normal) AND (NOT output_file_contents_truncated) AND
            (input_cycle_attribute_values.file_contents = output_cycle_attribute_values.file_contents) THEN
        status := file_contents_truncation_status;
        status.condition := fse$output_structure_truncated;
      IFEND;

    END /open_and_get_type_of_copy/;

  PROCEND fsp$open_and_get_type_of_copy;

?? TITLE := 'PROCEDURE fsp$copy_data_and_close_files' ??
?? EJECT ??
*copyc fsh$copy_data_and_close_files
?? EJECT ??

  PROCEDURE [XDCL, #GATE] fsp$copy_data_and_close_files
    (    input_fid: amt$file_identifier;
         output_fid: amt$file_identifier;
         control_information: fst$copy_control_information;
     VAR status: ost$status);

    CONST
      maximum_byte_move_data_block = 80000(16),   {512K  =  524288
      {number of bytes that will be moved before an interrupt will be acknowledged}
      page_eject = '1', {page_eject carriage control}
      line_feed = ' ', {line_feed carriage control}
      triple_space = '-'; {triple_space carriage control}

    VAR
      p_scratch_segment: amt$segment_pointer;

?? NEWTITLE := '  PROCEDURE abort_handler ' ??
?? EJECT ??

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

      delete_scratch_segment;

    PROCEND abort_handler;

?? TITLE := '  PROCEDURE delete_scratch_segment' ??
?? EJECT ??

    PROCEDURE [INLINE] delete_scratch_segment;

      VAR
        local_status: ost$status,
        ignore_status: ost$status;

      IF p_scratch_segment.sequence_pointer <> NIL THEN
        mmp$delete_scratch_segment (p_scratch_segment, local_status); {a NIL pointer is returned.}
        IF NOT local_status.normal THEN
          IF NOT status.normal THEN
            osp$generate_log_message ($pmt$ascii_logset [pmc$job_log], local_status, ignore_status);
          ELSE
            status := local_status;
          IFEND;
        IFEND;
      IFEND;

    PROCEND delete_scratch_segment;

?? TITLE := '  PROCEDURE set_status_internal_error' ??
?? EJECT ??

    PROCEDURE set_status_internal_error
      (    error_number: ost$non_negative_integers;
       VAR status: ost$status);

      VAR
        status_text: string (osc$max_string_size),
        text_length: integer;

      STRINGREP (status_text, text_length, 'detected error #', error_number,
            ' in fsp$copy_data_and_close_files');
      fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
            path (1, control_information.input_resolved_file_reference.cycle_path_size),
            fse$copy_internal_error, fsc$copy_file_req, status_text (1, text_length), status);

    PROCEND set_status_internal_error;

?? TITLE := '  PROCEDURE close_files' ??
?? EJECT ??

    PROCEDURE close_files
      (VAR status: ost$status);

      VAR
        close_status: ost$status;

      fsp$close_file (input_fid, close_status);
      IF (NOT close_status.normal) AND status.normal THEN
        status := close_status;
      IFEND;
      fsp$close_file (output_fid, close_status);
      IF (NOT close_status.normal) AND status.normal THEN
        status := close_status;
      IFEND;

    PROCEND close_files;
?? TITLE := '  PROCEDURE perform_v_to_t_conversion ' ??
?? EJECT ??

    PROCEDURE perform_v_to_t_conversion
      (    control_information: fst$copy_control_information;
       VAR status: ost$status);

      VAR
        context: ^ost$ecp_exception_context,
        last_move: boolean,
        file_size_source: amt$file_byte_address,
        current_byte_source: amt$file_byte_address,
        current_byte_destination: amt$file_byte_address;

      status.normal := TRUE;
      context := NIL;
      current_byte_source := control_information.initial_byte_address;
      current_byte_destination := current_byte_source;
      file_size_source := control_information.input_file_size;
      last_move := FALSE;

{ call bap$v_to_t_record_conversion to convert the file.

      WHILE (NOT last_move) AND status.normal DO
        REPEAT
          bap$v_to_t_record_conversion (input_fid, output_fid, file_size_source, current_byte_source,
                current_byte_destination, last_move, status);
          IF NOT status.normal THEN
            IF context = NIL THEN
              PUSH context;
              context^ := osv$initial_exception_context;
              context^.file.selector := osc$ecp_file_identifier;
            IFEND;
            context^.condition_status := status;
            context^.file.file_identifier := input_fid;
            osp$enforce_exception_policies (context^);
            IF context^.condition_status.normal THEN
              context^.file.file_identifier := output_fid;
              osp$enforce_exception_policies (context^);
              status := context^.condition_status;
            ELSE
              status := context^.condition_status;
            IFEND;
          IFEND;
        UNTIL status.normal OR (NOT osp$file_access_condition (status)) OR (NOT context^.wait);
      WHILEND;

    PROCEND perform_v_to_t_conversion;
?? TITLE := '  PROCEDURE perform_byte_move ' ??
?? EJECT ??

    PROCEDURE perform_byte_move
      (    control_information: fst$copy_control_information;
       VAR status: ost$status);

      VAR
        context: ^ost$ecp_exception_context,
        number_of_bytes_to_move: amt$file_byte_address,
        current_byte_address: amt$file_byte_address,
        last_move: boolean;

      status.normal := TRUE;
      context := NIL;
      current_byte_address := control_information.initial_byte_address;

      last_move := (current_byte_address >= control_information.input_file_size);
      number_of_bytes_to_move := maximum_byte_move_data_block;

      WHILE (NOT last_move) AND status.normal DO
        IF (current_byte_address + number_of_bytes_to_move) >= control_information.input_file_size THEN
          number_of_bytes_to_move := control_information.input_file_size - current_byte_address;
          last_move := TRUE;
        IFEND;
        REPEAT
          bap$byte_move (input_fid, output_fid, number_of_bytes_to_move, last_move, current_byte_address,
                status);
          IF NOT status.normal THEN
            IF context = NIL THEN
              PUSH context;
              context^ := osv$initial_exception_context;
              context^.file.selector := osc$ecp_file_identifier;
            IFEND;
            context^.condition_status := status;
            context^.file.file_identifier := input_fid;
            osp$enforce_exception_policies (context^);
            IF context^.condition_status.normal THEN
              context^.file.file_identifier := output_fid;
              osp$enforce_exception_policies (context^);
              status := context^.condition_status;
            ELSE
              status := context^.condition_status;
            IFEND;
          IFEND;
        UNTIL status.normal OR (NOT osp$file_access_condition (status)) OR (NOT context^.wait);
      WHILEND;

      IF control_information.input_and_output_are_aam_files THEN
        change_to_public_lock_file (output_fid);
      IFEND;

    PROCEND perform_byte_move;

?? TITLE := '  PROCEDURE perform_copy_keyed_file_move' ??
?? EJECT ??

    PROCEDURE perform_copy_keyed_file_move
      (    control_information: fst$copy_control_information;
       VAR status: ost$status);

      CONST
        command_part_1 = '$system.copy_keyed_file input=',
        command_part_1_size = 30,
        command_part_2 = ' output=',
        command_part_2_size = 8;

      VAR
        copy_keyed_file_command_ptr: ^string ( * ),
        command_index: integer;

      close_files (status);
      IF status.normal THEN
        PUSH copy_keyed_file_command_ptr: [command_part_1_size + command_part_2_size +
              control_information.input_resolved_file_reference.complete_path_size +
              control_information.output_resolved_file_reference.complete_path_size];
        copy_keyed_file_command_ptr^ (1, command_part_1_size) := command_part_1;
        command_index := command_part_1_size + 1;
        copy_keyed_file_command_ptr^ (command_index, control_information.input_resolved_file_reference.
              complete_path_size) := control_information.input_resolved_file_reference.
              path (1, control_information.input_resolved_file_reference.complete_path_size);
        command_index := command_index + control_information.input_resolved_file_reference.complete_path_size;
        copy_keyed_file_command_ptr^ (command_index, command_part_2_size) := command_part_2;
        command_index := command_index + command_part_2_size;
        copy_keyed_file_command_ptr^ (command_index, control_information.output_resolved_file_reference.
              complete_path_size) := control_information.output_resolved_file_reference.
              path (1, control_information.output_resolved_file_reference.complete_path_size);
        clp$include_line (copy_keyed_file_command_ptr^, FALSE, osc$null_name, status);
      IFEND;

    PROCEND perform_copy_keyed_file_move;

?? TITLE := '  PROCEDURE perform_record_move ' ??
?? EJECT ??

    PROCEDURE perform_record_move
      (    control_information: fst$copy_control_information;
           working_storage_area: ^array [1 .. * ] of char;
       VAR status: ost$status);

      VAR
        ignore_byte_address: amt$file_byte_address,
        file_position: amt$file_position,
        current_record_length: amt$max_record_length,
        transfer_count: amt$transfer_count,
        truncation: boolean,
        first_loop: boolean;

      file_position := amc$boi;
      truncation := FALSE;
      first_loop := TRUE;

      REPEAT
        CASE file_position OF
        = amc$boi, amc$eor, amc$bop, amc$eop =
          amp$get_next (input_fid, working_storage_area, control_information.working_storage_length,
                transfer_count, ignore_byte_address, file_position, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          IF first_loop THEN
            first_loop := FALSE;
            IF file_position = amc$eoi THEN
              IF control_information.input_file_device_class = rmc$magnetic_tape_device THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      ame$input_after_eoi, fsc$copy_file_req, '', status);
              ELSE
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$empty_input_file, fsc$copy_file_req, '', status);
              IFEND;
            IFEND;
          IFEND; {first_loop}
          CASE file_position OF
          = amc$mid_record =
            IF control_information.output_record_length_is_fixed AND
                  (transfer_count >= control_information.output_record_length) THEN
              truncation := TRUE;
              file_position := amc$eor;
              amp$put_next (output_fid, working_storage_area, control_information.output_record_length,
                    ignore_byte_address, status);
            ELSE
              amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                    amc$start, status);
            IFEND;
          = amc$eor =
            IF control_information.output_record_length_is_fixed AND
                  (transfer_count > control_information.output_record_length) THEN
              truncation := TRUE;
              amp$put_next (output_fid, working_storage_area, control_information.output_record_length,
                    ignore_byte_address, status);
            ELSE
              amp$put_next (output_fid, working_storage_area, transfer_count, ignore_byte_address, status);
            IFEND;
          = amc$eop =
            IF control_information.output_can_be_partitioned THEN
              amp$write_end_partition (output_fid, status);
            IFEND;
          = amc$eoi =
          ELSE
            set_status_internal_error (7, status);
          CASEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;

        = amc$mid_record =
          amp$get_partial (input_fid, working_storage_area, control_information.working_storage_length,
                current_record_length, transfer_count, ignore_byte_address, file_position, amc$no_skip,
                status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          IF control_information.output_record_length_is_fixed AND
                (current_record_length > control_information.output_record_length) THEN
            truncation := TRUE;
            file_position := amc$eor;
            {The following line causes copy_file to truncate output record.}
            {This is needed because to rt=u bt=us a put will error rather               than truncate}
            transfer_count := transfer_count - (current_record_length -
                  control_information.output_record_length);
          IFEND;
          CASE file_position OF
          = amc$mid_record =
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                  amc$continue, status);
          = amc$eor =
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                  amc$terminate, status);
          ELSE
            set_status_internal_error (8, status);
          CASEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        = amc$eoi =
        ELSE { a file position error would have occurred in inner case statements if at all. }
        CASEND;

      UNTIL file_position = amc$eoi;

      IF truncation THEN
        fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
              path (1, control_information.output_resolved_file_reference.cycle_path_size),
              fse$output_record_truncated, fsc$copy_file_req, '', status);
      IFEND;

    PROCEND perform_record_move;
?? TITLE := '  PROCEDURE perform_legible_to_list_move' ??
?? EJECT ??

    PROCEDURE perform_legible_to_list_move
      (    control_information: fst$copy_control_information;
           working_storage_area: ^array [1 .. * ] of char;
       VAR status: ost$status);

      VAR
        ignore_byte_address: amt$file_byte_address,
        file_position: amt$file_position,
        current_record_length: amt$max_record_length,
        transfer_count: amt$transfer_count,
        truncation: boolean,
        page_control: char,
        line_number: ost$non_negative_integers,
        first_loop: boolean;

      CASE control_information.page_format OF
      = amc$burstable_form, amc$non_burstable_form =
        page_control := page_eject;
      ELSE
        page_control := line_feed;
      CASEND;

      file_position := amc$boi;
      truncation := FALSE;
      first_loop := TRUE;

      REPEAT
        CASE file_position OF
        = amc$boi, amc$eor, amc$bop, amc$eop =
          amp$get_next (input_fid, ^working_storage_area^ [2], control_information.working_storage_length - 1,
                transfer_count, ignore_byte_address, file_position, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          IF first_loop THEN
            first_loop := FALSE;
            IF file_position = amc$eoi THEN
              IF control_information.input_file_device_class = rmc$magnetic_tape_device THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      ame$input_after_eoi, fsc$copy_file_req, '', status);
              ELSE
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$empty_input_file, fsc$copy_file_req, '', status);
              IFEND;
            IFEND;
            line_number := 1;
            CASE control_information.page_format OF
            = amc$burstable_form, amc$non_burstable_form =
              working_storage_area^ [1] := page_eject;
            = amc$continuous_form =
              working_storage_area^ [1] := triple_space;
            ELSE
              working_storage_area^ [1] := line_feed;
            CASEND;
          ELSE {first_loop}
            IF line_number = control_information.page_length THEN
              line_number := 1;
              working_storage_area^ [1] := page_control;
            ELSE
              line_number := line_number + 1;
              working_storage_area^ [1] := line_feed;
            IFEND;
          IFEND; {first_loop}
          transfer_count := transfer_count + 1; {Adjust for format effector}
          CASE file_position OF
          = amc$mid_record =
            IF control_information.output_record_length_is_fixed AND
                  (transfer_count >= control_information.output_record_length) THEN
              truncation := TRUE;
              file_position := amc$eor;
              amp$put_next (output_fid, working_storage_area, control_information.output_record_length,
                    ignore_byte_address, status);
            ELSE
              amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                    amc$start, status);
            IFEND;
          = amc$eor =
            IF control_information.output_record_length_is_fixed AND
                  (transfer_count > control_information.output_record_length) THEN
              truncation := TRUE;
              amp$put_next (output_fid, working_storage_area, control_information.output_record_length,
                    ignore_byte_address, status);
            ELSE
              amp$put_next (output_fid, working_storage_area, transfer_count, ignore_byte_address, status);
            IFEND;
          = amc$eop =
            IF control_information.output_can_be_partitioned THEN
              amp$write_end_partition (output_fid, status);
            IFEND;
          = amc$eoi =
          ELSE
            set_status_internal_error (9, status);
          CASEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;

        = amc$mid_record =
          amp$get_partial (input_fid, working_storage_area, control_information.working_storage_length,
                current_record_length, transfer_count, ignore_byte_address, file_position, amc$no_skip,
                status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          current_record_length := current_record_length + 1; {Adjust for format effector}
          IF control_information.output_record_length_is_fixed AND
                (current_record_length > control_information.output_record_length) THEN
            truncation := TRUE;
            file_position := amc$eor;
            {The following line causes copy_file to truncate output record.}
            {This is needed because to rt=u bt=us a put will error rather               than truncate}
            transfer_count := transfer_count - (current_record_length -
                  control_information.output_record_length);
          IFEND;
          CASE file_position OF
          = amc$mid_record =
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                  amc$continue, status);
          = amc$eor =
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                  amc$terminate, status);
          ELSE
            set_status_internal_error (10, status);
          CASEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        = amc$eoi =
        ELSE { a file position error would have occurred in inner case statements if at all. }
        CASEND;

      UNTIL file_position = amc$eoi;

      IF truncation THEN
        fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
              path (1, control_information.output_resolved_file_reference.cycle_path_size),
              fse$output_record_truncated, fsc$copy_file_req, '', status);
      IFEND;

    PROCEND perform_legible_to_list_move;
?? TITLE := '  PROCEDURE perform_list_to_legible_move' ??
?? EJECT ??

    PROCEDURE perform_list_to_legible_move
      (    control_information: fst$copy_control_information;
           working_storage_area: ^array [1 .. * ] of char;
       VAR status: ost$status);

      VAR
        ignore_byte_address: amt$file_byte_address,
        file_position: amt$file_position,
        current_record_length: amt$max_record_length,
        transfer_count: amt$transfer_count,
        truncation: boolean,
        first_loop: boolean;

      file_position := amc$boi;
      truncation := FALSE;
      first_loop := TRUE;

      REPEAT
        CASE file_position OF
        = amc$boi, amc$eor, amc$bop, amc$eop =
          amp$get_next (input_fid, working_storage_area, control_information.working_storage_length,
                transfer_count, ignore_byte_address, file_position, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          IF first_loop THEN
            first_loop := FALSE;
            IF file_position = amc$eoi THEN
              IF control_information.input_file_device_class = rmc$magnetic_tape_device THEN
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      ame$input_after_eoi, fsc$copy_file_req, '', status);
              ELSE
                fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                      path (1, control_information.input_resolved_file_reference.cycle_path_size),
                      fse$empty_input_file, fsc$copy_file_req, '', status);
              IFEND;
            IFEND;
          IFEND; {first_loop}
          IF transfer_count > 0 THEN
            transfer_count := transfer_count - 1; {Adjust for loss of format effector}
          IFEND;
          CASE file_position OF
          = amc$mid_record =
            IF control_information.output_record_length_is_fixed AND
                  (transfer_count >= control_information.output_record_length) THEN
              truncation := TRUE;
              file_position := amc$eor;
              amp$put_next (output_fid, ^working_storage_area^ [2], control_information.output_record_length,
                    ignore_byte_address, status);
            ELSE
              amp$put_partial (output_fid, ^working_storage_area^ [2], transfer_count, ignore_byte_address,
                    amc$start, status);
            IFEND;
          = amc$eor =
            IF control_information.output_record_length_is_fixed AND
                  (transfer_count > control_information.output_record_length) THEN
              truncation := TRUE;
              amp$put_next (output_fid, ^working_storage_area^ [2], control_information.output_record_length,
                    ignore_byte_address, status);
            ELSE
              amp$put_next (output_fid, ^working_storage_area^ [2], transfer_count, ignore_byte_address,
                    status);
            IFEND;
          = amc$eop =
            IF control_information.output_can_be_partitioned THEN
              amp$write_end_partition (output_fid, status);
            IFEND;
          = amc$eoi =
          ELSE
            set_status_internal_error (11, status);
          CASEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;

        = amc$mid_record =
          amp$get_partial (input_fid, working_storage_area, control_information.working_storage_length,
                current_record_length, transfer_count, ignore_byte_address, file_position, amc$no_skip,
                status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          current_record_length := current_record_length - 1; {Adjusted for loss of format effector}
          IF control_information.output_record_length_is_fixed AND
                (current_record_length > control_information.output_record_length) THEN
            truncation := TRUE;
            file_position := amc$eor;
            {The following line causes copy_file to truncate output record.}
            {This is needed because to rt=u bt=us a put will error rather         than truncate}
            transfer_count := transfer_count - (current_record_length -
                  control_information.output_record_length);
          IFEND;
          CASE file_position OF
          = amc$mid_record =
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                  amc$continue, status);
          = amc$eor =
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                  amc$terminate, status);
          ELSE
            set_status_internal_error (12, status);
          CASEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        = amc$eoi =
        ELSE { a file position error would have occurred in inner case statements if at all. }
        CASEND;

      UNTIL file_position = amc$eoi;

      IF truncation THEN
        fsp$set_file_reference_abnormal (control_information.output_resolved_file_reference.
              path (1, control_information.output_resolved_file_reference.cycle_path_size),
              fse$output_record_truncated, fsc$copy_file_req, '', status);
      IFEND;

    PROCEND perform_list_to_legible_move;
?? TITLE := '  PROCEDURE perform_undefined_ss_move' ??
?? EJECT ??

    PROCEDURE perform_undefined_ss_move
      (    control_information: fst$copy_control_information;
           working_storage_area: ^array [1 .. * ] of char;
       VAR status: ost$status);

      VAR
        ignore_byte_address: amt$file_byte_address,
        file_position: amt$file_position,
        current_record_length: amt$max_record_length,
        transfer_count: amt$transfer_count;

      amp$get_next (input_fid, working_storage_area, control_information.working_storage_length,
            transfer_count, ignore_byte_address, file_position, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      IF file_position = amc$eoi THEN
        IF control_information.input_file_device_class = rmc$magnetic_tape_device THEN
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                ame$input_after_eoi, fsc$copy_file_req, '', status);
        ELSE
          fsp$set_file_reference_abnormal (control_information.input_resolved_file_reference.
                path (1, control_information.input_resolved_file_reference.cycle_path_size),
                fse$empty_input_file, fsc$copy_file_req, '', status);
        IFEND;
      IFEND;

      IF NOT control_information.push_overflow THEN
        WHILE file_position <> amc$eoi DO
          amp$put_next (output_fid, working_storage_area, transfer_count, ignore_byte_address, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          amp$get_next (input_fid, working_storage_area, control_information.working_storage_length,
                transfer_count, ignore_byte_address, file_position, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        WHILEND;
      ELSE
        current_record_length := 0;
        WHILE file_position <> amc$eoi DO
          IF current_record_length = 0 THEN
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address, amc$start,
                  status);
          ELSE
            amp$put_partial (output_fid, working_storage_area, transfer_count, ignore_byte_address,
                  amc$continue, status);
          IFEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          current_record_length := current_record_length + transfer_count;
          IF current_record_length = control_information.output_record_length THEN
            amp$get_next (input_fid, working_storage_area, control_information.working_storage_length,
                  transfer_count, ignore_byte_address, file_position, status);
            current_record_length := 0;
          ELSEIF (current_record_length + control_information.working_storage_length) >=
                control_information.output_record_length THEN
            amp$get_next (input_fid, working_storage_area, control_information.output_record_length -
                  current_record_length, transfer_count, ignore_byte_address, file_position, status);
          ELSE
            amp$get_next (input_fid, working_storage_area, control_information.working_storage_length,
                  transfer_count, ignore_byte_address, file_position, status);
          IFEND;
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        WHILEND;
      IFEND;

    PROCEND perform_undefined_ss_move;
?? OLDTITLE ??
?? EJECT ??

    VAR
      working_storage_area: ^array [1 .. * ] of char;

  /copy_data_and_close_files/
    BEGIN

      status.normal := TRUE;

      CASE control_information.type_of_copy OF
      = fsc$v_to_t_record_conversion =
        perform_v_to_t_conversion (control_information, status);
      = fsc$byte_move =
        perform_byte_move (control_information, status);
      = fsc$copy_keyed_file_move =
        perform_copy_keyed_file_move (control_information, status);
      = fsc$record_move, fsc$legible_to_list_move, fsc$list_to_legible_move, fsc$undefined_ss_move =
        IF control_information.working_storage_length <= fsc$maximum_copy_file_push THEN
          PUSH working_storage_area: [1 .. control_information.working_storage_length];
          CASE control_information.type_of_copy OF
          = fsc$record_move =
            perform_record_move (control_information, working_storage_area, status);
          = fsc$legible_to_list_move =
            perform_legible_to_list_move (control_information, working_storage_area, status);
          = fsc$list_to_legible_move =
            perform_list_to_legible_move (control_information, working_storage_area, status);
          = fsc$undefined_ss_move =
            perform_undefined_ss_move (control_information, working_storage_area, status);
          ELSE {impossible to go through ELSE}
          CASEND;
        ELSE {use scratch segment when wsl > fsc$maximum_copy_file_push}
          {A scratch segment is used because push is limited to the task's stack size; this}
          {is important in the case of LRT where maxbl can be 2 megabytes or even greater.}

        /use_scratch_segment/
          BEGIN
            p_scratch_segment.sequence_pointer := NIL;
            osp$establish_block_exit_hndlr (^abort_handler);
            mmp$create_scratch_segment (amc$sequence_pointer, mmc$as_sequential, p_scratch_segment, status);
            IF NOT status.normal THEN
              EXIT /use_scratch_segment/;
            IFEND;
            RESET p_scratch_segment.sequence_pointer;
            NEXT working_storage_area: [1 .. control_information.working_storage_length] IN
                  p_scratch_segment.sequence_pointer;
            IF working_storage_area = NIL THEN {User not validated for file that large, but}
              set_status_internal_error (13, status); {this should have been caught in open}
              EXIT /use_scratch_segment/;
            IFEND;
            CASE control_information.type_of_copy OF
            = fsc$record_move =
              perform_record_move (control_information, working_storage_area, status);
            = fsc$legible_to_list_move =
              perform_legible_to_list_move (control_information, working_storage_area, status);
            = fsc$list_to_legible_move =
              perform_list_to_legible_move (control_information, working_storage_area, status);
            = fsc$undefined_ss_move =
              perform_undefined_ss_move (control_information, working_storage_area, status);
            ELSE {impossible to go through ELSE}
            CASEND;
          END /use_scratch_segment/;
          delete_scratch_segment;
          osp$disestablish_cond_handler;
        IFEND;
      ELSE
        set_status_internal_error (14, status);
      CASEND;

      IF (control_information.type_of_copy <> fsc$copy_keyed_file_move) THEN
        close_files (status);
      IFEND;
    END /copy_data_and_close_files/;

  PROCEND fsp$copy_data_and_close_files;

?? OLDTITLE ??

MODEND fsm$copy_file;
