?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE SCL Interpreter: Copy Command Processor' ??
MODULE clm$copy_command;

{
{ PURPOSE:
{   This module contains the processor for the copy command.
{

?? NEWTITLE := 'Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cle$ecc_parsing
*copyc clt$parameter_list
*copyc nfe$ptf_condition_codes
*copyc ost$status
?? POP ??
*copyc clp$evaluate_file_reference
*copyc clp$evaluate_parameters
*copyc clp$find_current_block
*copyc clp$get_work_area
*copyc fsp$copy_file
*copyc fsp$path_element
*copyc nfp$check_implicit_access
*copyc nfp$perform_implicit_access
*copyc osp$set_status_abnormal
?? TITLE := 'clp$_copy_file', EJECT ??

  PROCEDURE [XDCL] clp$_copy_file
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE (osm$copf) copy_file, copf (
{   input, i: file = $input
{   output, o: file = $output
{   status)

?? PUSH (LISTEXT := ON) ??

    VAR
      pdt: [STATIC, READ, cls$declaration_section] record
        header: clt$pdt_header,
        names: array [1 .. 5] of clt$pdt_parameter_name,
        parameters: array [1 .. 3] of clt$pdt_parameter,
        type1: record
          header: clt$type_specification_header,
          default_value: string (6),
        recend,
        type2: record
          header: clt$type_specification_header,
          default_value: string (7),
        recend,
        type3: record
          header: clt$type_specification_header,
        recend,
      recend := [[1, [87, 10, 20, 12, 30, 50, 281], clc$command, 5, 3, 0, 0, 0, 0, 3, 'OSM$COPF'],
            [['I                              ', clc$abbreviation_entry, 1],
            ['INPUT                          ', clc$nominal_entry, 1],
            ['O                              ', clc$abbreviation_entry, 2],
            ['OUTPUT                         ', clc$nominal_entry, 2],
            ['STATUS                         ', clc$nominal_entry, 3]], [
{ PARAMETER 1
      [2, clc$normal_usage_entry, clc$non_secure_parameter, $clt$parameter_spec_methods
            [clc$specify_by_name, clc$specify_positionally], clc$pass_by_value, clc$immediate_evaluation,
            clc$standard_parameter_checking, 3, clc$optional_default_parameter, 0, 6],
{ PARAMETER 2
      [4, clc$normal_usage_entry, clc$non_secure_parameter, $clt$parameter_spec_methods
            [clc$specify_by_name, clc$specify_positionally], clc$pass_by_value, clc$immediate_evaluation,
            clc$standard_parameter_checking, 3, clc$optional_default_parameter, 0, 7],
{ PARAMETER 3
      [5, clc$normal_usage_entry, clc$non_secure_parameter, $clt$parameter_spec_methods [clc$specify_by_name],
            clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
            clc$optional_parameter, 0, 0]],
{ PARAMETER 1
      [[1, 0, clc$file_type], '$input'],
{ PARAMETER 2
      [[1, 0, clc$file_type], '$output'],
{ PARAMETER 3
      [[1, 0, clc$status_type]]];

?? POP ??

    CONST
      p$input = 1,
      p$output = 2,
      p$status = 3;

    VAR
      pvt: array [1 .. 3] of clt$parameter_value;

    VAR
      block: ^clt$block,
      evaluated_file_reference: fst$evaluated_file_reference,
      input_family: ost$family_name,
      input_remote: boolean,
      output_family: ost$family_name,
      output_remote: boolean,
      work_area: ^^clt$work_area;


    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF (NOT pvt [p$input].specified) AND (NOT pvt [p$output].specified) THEN
      osp$set_status_abnormal ('CL', cle$required_parameter_omitted, 'INPUT or OUTPUT', status);
      RETURN;
    IFEND;

    clp$evaluate_file_reference (pvt [p$input].value^.file_value^, $clt$file_ref_parsing_options [],
          FALSE, evaluated_file_reference, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    input_family := fsp$path_element (^evaluated_file_reference, 1) ^;
    nfp$check_implicit_access (input_family, input_remote, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    clp$evaluate_file_reference (pvt [p$output].value^.file_value^, $clt$file_ref_parsing_options [],
          FALSE, evaluated_file_reference, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    output_family := fsp$path_element (^evaluated_file_reference, 1) ^;
    nfp$check_implicit_access (output_family, output_remote, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF NOT (input_remote OR output_remote) THEN
      fsp$copy_file (pvt [p$input].value^.file_value^, pvt [p$output].value^.file_value^, NIL, NIL, NIL,
            status);
      RETURN;
    IFEND;

    IF input_remote AND output_remote THEN
      osp$set_status_abnormal (nfc$status_id, nfe$both_files_remote, '', status);
      RETURN;
    IFEND;

{
{ One of the files is on a remote family.
{
    clp$find_current_block (block);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    clp$get_work_area (#RING (^work_area), work_area, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF output_remote THEN
      nfp$perform_implicit_access (output_family, pvt [p$input].value^.file_value^, pvt [p$output].
            value^.file_value^, nfc$take, osc$null_name, block^.parameters.unbundled_pdt, ^pvt, NIL,
            work_area^, status);

    ELSE {Input remote
      nfp$perform_implicit_access (input_family, pvt [p$output].value^.file_value^, pvt [p$input].
            value^.file_value^, nfc$give, osc$null_name, block^.parameters.unbundled_pdt, ^pvt, NIL,
            work_area^, status);
    IFEND;

  PROCEND clp$_copy_file;

MODEND clm$copy_command;
