?? RIGHT := 110 ??
?? TITLE := 'PFM$EXTRACT_FILE_LIST' ??
MODULE pfm$extract_file_list;
?? PUSH (LISTEXT := ON) ??
*copyc pfe$error_condition_codes

*copyc amp$get_next
*copyc clp$change_variable
*copyc clp$evaluate_file_reference
*copyc clp$evaluate_parameters
*copyc clp$get_variable
*copyc clp$get_work_area
*copyc clp$make_file_value
*copyc clp$make_list_value
*copyc clp$validate_name
*copyc fsp$close_file
*copyc fsp$open_file
*copyc osp$set_status_condition
?? POP ??

?? OLDTITLE ??
?? NEWTITLE := 'PFP$EXTRACT_FILE_LIST', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$extract_file_list
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);


{ PROCEDURE extract_file_list_pdt (
{   input, i: file = $required
{   catalogs_moved, cm: (VAR, BY_NAME) list 0 .. clc$max_list_size of file = ..
{ $optional
{   catalogs_skipped, cs: (VAR, BY_NAME) list 0 .. clc$max_list_size of file ..
{ = $optional
{   files_moved, fm: (VAR, BY_NAME) list 0 .. clc$max_list_size of file = $op..
{ tional
{   files_skipped, fs: (VAR, BY_NAME) list 0 .. clc$max_list_size of file = $..
{ optional
{   status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 11] of clt$pdt_parameter_name,
      parameters: array [1 .. 6] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
      recend,
      type2: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier_v2,
        element_type_spec: record
          header: clt$type_specification_header,
        recend,
      recend,
      type3: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier_v2,
        element_type_spec: record
          header: clt$type_specification_header,
        recend,
      recend,
      type4: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier_v2,
        element_type_spec: record
          header: clt$type_specification_header,
        recend,
      recend,
      type5: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier_v2,
        element_type_spec: record
          header: clt$type_specification_header,
        recend,
      recend,
      type6: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [92, 5, 13, 14, 4, 5, 402],
    clc$command, 11, 6, 1, 0, 0, 4, 6, ''], [
    ['CATALOGS_MOVED                 ',clc$nominal_entry, 2],
    ['CATALOGS_SKIPPED               ',clc$nominal_entry, 3],
    ['CM                             ',clc$abbreviation_entry, 2],
    ['CS                             ',clc$abbreviation_entry, 3],
    ['FILES_MOVED                    ',clc$nominal_entry, 4],
    ['FILES_SKIPPED                  ',clc$nominal_entry, 5],
    ['FM                             ',clc$abbreviation_entry, 4],
    ['FS                             ',clc$abbreviation_entry, 5],
    ['I                              ',clc$abbreviation_entry, 1],
    ['INPUT                          ',clc$nominal_entry, 1],
    ['STATUS                         ',clc$nominal_entry, 6]],
    [
{ PARAMETER 1
    [10, 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$required_parameter, 0, 0],
{ PARAMETER 2
    [1, 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, 19, clc$optional_parameter, 0, 0],
{ PARAMETER 3
    [2, 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, 19, clc$optional_parameter, 0, 0],
{ PARAMETER 4
    [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, 19, clc$optional_parameter, 0, 0],
{ PARAMETER 5
    [6, 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, 19, clc$optional_parameter, 0, 0],
{ PARAMETER 6
    [11, 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]],
{ PARAMETER 2
    [[1, 0, clc$list_type], [3, 0, clc$max_list_size, 0, FALSE, FALSE],
      [[1, 0, clc$file_type]]
    ],
{ PARAMETER 3
    [[1, 0, clc$list_type], [3, 0, clc$max_list_size, 0, FALSE, FALSE],
      [[1, 0, clc$file_type]]
    ],
{ PARAMETER 4
    [[1, 0, clc$list_type], [3, 0, clc$max_list_size, 0, FALSE, FALSE],
      [[1, 0, clc$file_type]]
    ],
{ PARAMETER 5
    [[1, 0, clc$list_type], [3, 0, clc$max_list_size, 0, FALSE, FALSE],
      [[1, 0, clc$file_type]]
    ],
{ PARAMETER 6
    [[1, 0, clc$status_type]]];

?? FMT (FORMAT := ON) ??
?? POP ??

    CONST
      p$input = 1,
      p$catalogs_moved = 2,
      p$catalogs_skipped = 3,
      p$files_moved = 4,
      p$files_skipped = 5,
      p$status = 6;

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

    VAR
      access_mode: clt$data_access_mode,
      attachment_options_p: ^fst$attachment_options,
      byte_adr: amt$file_byte_address,
      catalog_object: boolean,
      catalogs_moved: ^clt$data_value,
      catalogs_moved_head: ^clt$data_value,
      catalogs_skipped: ^clt$data_value,
      catalogs_skipped_head: ^clt$data_value,
      class: clt$variable_class,
      cycle_released: boolean,
      evaluated_file_reference: fst$evaluated_file_reference,
      evaluation_method: clt$expression_eval_method,
      file_pos: amt$file_position,
      files_moved: ^clt$data_value,
      files_moved_head: ^clt$data_value,
      files_skipped: ^clt$data_value,
      files_skipped_head: ^clt$data_value,
      i: integer,
      input_fid: amt$file_identifier,
      input_line: fst$path,
      j: integer,
      name_valid: boolean,
      object_moved: boolean,
      output_fid: amt$file_identifier,
      output_line: fst$path,
      search_column: 0 .. fsc$max_path_size,
      tran_cnt: amt$transfer_count,
      type_spec: ^clt$type_specification,
      valid_listing: boolean,
      validated_name: ost$name,
      work_area: ^^clt$work_area;

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

    clp$get_work_area (#RING (^work_area), work_area, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    {
    { Get pointers to and initialize specified VAR parameters.
    {
    IF pvt [p$catalogs_moved].specified THEN
      clp$get_variable (pvt [p$catalogs_moved].variable^, work_area^, class, access_mode, evaluation_method,
            type_spec, catalogs_moved, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF catalogs_moved = NIL THEN
        clp$make_list_value (work_area^, catalogs_moved);
      ELSE
        catalogs_moved^.element_value := NIL;
        catalogs_moved^.link := NIL;
      IFEND;
      catalogs_moved_head := catalogs_moved;
    IFEND;

    IF pvt [p$catalogs_skipped].specified THEN
      clp$get_variable (pvt [p$catalogs_skipped].variable^, work_area^, class, access_mode, evaluation_method,
            type_spec, catalogs_skipped, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF catalogs_skipped = NIL THEN
        clp$make_list_value (work_area^, catalogs_skipped);
      ELSE
        catalogs_skipped^.element_value := NIL;
        catalogs_skipped^.link := NIL;
      IFEND;
      catalogs_skipped_head := catalogs_skipped;
    IFEND;

    IF pvt [p$files_moved].specified THEN
      clp$get_variable (pvt [p$files_moved].variable^, work_area^, class, access_mode, evaluation_method,
            type_spec, files_moved, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF files_moved = NIL THEN
        clp$make_list_value (work_area^, files_moved);
      ELSE
        files_moved^.element_value := NIL;
        files_moved^.link := NIL;
      IFEND;
      files_moved_head := files_moved;
    IFEND;

    IF pvt [p$files_skipped].specified THEN
      clp$get_variable (pvt [p$files_skipped].variable^, work_area^, class, access_mode, evaluation_method,
            type_spec, files_skipped, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      IF files_skipped = NIL THEN
        clp$make_list_value (work_area^, files_skipped);
      ELSE
        files_skipped^.element_value := NIL;
        files_skipped^.link := NIL;
      IFEND;
      files_skipped_head := files_skipped;
    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;

    PUSH attachment_options_p: [1 .. 1];
    attachment_options_p^ [1].selector := fsc$create_file;
    attachment_options_p^ [1].create_file := FALSE;

    fsp$open_file (pvt [p$input].value^.file_value^, amc$record, attachment_options_p, NIL, NIL, NIL, NIL,
          input_fid, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    amp$get_next (input_fid, ^input_line, #SIZE (input_line), tran_cnt, byte_adr, file_pos, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    {
    { Verify input file is the correct format. Search for the string 'MOVE_CLASSES Par' as the
    {  first character on one of the first five lines in the file.  Initialize the variable
    { search_column to be the column the "M" in 'MOVE_CLASSES' is found.
    {
    i := 0;
    valid_listing := FALSE;

  /verify_listing/
    WHILE (file_pos <> amc$eoi) AND (i < 5) DO

    /locate_header/
      FOR j := 1 TO tran_cnt DO
        IF input_line (j) <> ' ' THEN
          IF input_line (j) = 'M' THEN
            IF input_line (j, 16) = 'MOVE_CLASSES Par' THEN
              valid_listing := TRUE;
              search_column := j;
              EXIT /verify_listing/;
            IFEND;
          IFEND;
          EXIT /locate_header/;
        IFEND;
      FOREND /locate_header/;
      i := i + 1;
      amp$get_next (input_fid, ^input_line, #SIZE (input_line), tran_cnt, byte_adr, file_pos, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    WHILEND /verify_listing/;

    IF NOT valid_listing THEN
      osp$set_status_condition (pfe$invalid_input_file_format, status);
      RETURN;
    IFEND;

    {
    { Read each line of the input file until eoi is encountered.
    { A path is processed when a colon (i.e. ":") is found in the search_column.
    { If two adjacent periods are detected the path is continued on the next line.
    { The path is reconstructed in the output_line variable exactly as it appears
    { in the listing without any leading blanks or continuation marks.
    {
    WHILE file_pos <> amc$eoi DO
      object_moved := FALSE;
      cycle_released := FALSE;

      IF (input_line (search_column) = ':') THEN
        output_line := ' ';
        i := search_column;
        j := 1;
        WHILE input_line (i) <> ' ' DO
          IF (input_line (i, 2) = '..') THEN
            input_line := ' ';
            amp$get_next (input_fid, ^input_line, #SIZE (input_line), tran_cnt, byte_adr, file_pos, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
            i := search_column;
          ELSE
            output_line (j) := input_line (i);
            i := i + 1;
            j := j + 1;
          IFEND;
        WHILEND;
        j := j - 1;

        {
        { The line following the path will indicate whether the move was successful or not.
        { If successful the "Size:" field will be on the this line, if not, an error
        { message will be found here.  An error message will begin with '--'.
        {
        amp$get_next (input_fid, ^input_line, #SIZE (input_line), tran_cnt, byte_adr, file_pos, status);
        IF NOT status.normal THEN
          RETURN;
        IFEND;

        IF input_line (search_column, 2) = '--' THEN
          WHILE (file_pos <> amc$eoi) AND (input_line (search_column) <> ' ') DO
            input_line := ' ';
            amp$get_next (input_fid, ^input_line, #SIZE (input_line), tran_cnt, byte_adr, file_pos, status);
            IF NOT status.normal THEN
              RETURN;
            IFEND;
          WHILEND;
          object_moved := FALSE;
        ELSEIF input_line (search_column + 3, 5) = 'Size:' THEN
          IF input_line (search_column + 65, 7) = 'OFFLINE' THEN
            cycle_released := TRUE;
          ELSE
            object_moved := TRUE;
          IFEND;
        IFEND;

        {
        { The last element in the path will indicate the type of object involved.
        { A file object will always have a cycle number as the last element and a
        { catalog object will not.  This code will execute clp$validate_name on the
        { last element in the path to determine if it is a catalog.
        {
        catalog_object := FALSE;
        i := j;
        WHILE (i > 0) AND (output_line (i) <> ' ') AND (output_line (i) <> '.') DO
          i := i - 1;
        WHILEND;
        IF output_line (i) = '.' THEN
          clp$validate_name (output_line (i + 1, j - i), validated_name, name_valid);
          IF name_valid THEN
            catalog_object := TRUE;
          IFEND;
        ELSE
          catalog_object := TRUE;
        IFEND;

        {
        { Add the path to the approriate VAR parameter.
        {
        {
        IF catalog_object THEN
          IF pvt [p$catalogs_moved].specified AND object_moved THEN
            IF catalogs_moved^.element_value <> NIL THEN
              clp$make_list_value (work_area^, catalogs_moved^.link);
              catalogs_moved := catalogs_moved^.link;
            IFEND;
            clp$make_file_value (output_line, work_area^, catalogs_moved^.element_value);
          ELSEIF pvt [p$catalogs_skipped].specified AND (NOT object_moved) THEN
            IF catalogs_skipped^.element_value <> NIL THEN
              clp$make_list_value (work_area^, catalogs_skipped^.link);
              catalogs_skipped := catalogs_skipped^.link;
            IFEND;
            clp$make_file_value (output_line, work_area^, catalogs_skipped^.element_value);
          IFEND;
        ELSE
          IF pvt [p$files_moved].specified AND object_moved THEN
            IF files_moved^.element_value <> NIL THEN
              clp$make_list_value (work_area^, files_moved^.link);
              files_moved := files_moved^.link;
            IFEND;
            clp$make_file_value (output_line, work_area^, files_moved^.element_value);
          ELSEIF pvt [p$files_skipped].specified AND (NOT object_moved) AND (NOT cycle_released) THEN
            IF files_skipped^.element_value <> NIL THEN
              clp$make_list_value (work_area^, files_skipped^.link);
              files_skipped := files_skipped^.link;
            IFEND;
            clp$make_file_value (output_line, work_area^, files_skipped^.element_value);
          IFEND;
        IFEND;

      IFEND;

      input_line := ' ';
      amp$get_next (input_fid, ^input_line, #SIZE (input_line), tran_cnt, byte_adr, file_pos, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    WHILEND;

    {
    { Change the values of the SCL variables with the values constructed above.
    {
    IF pvt [p$catalogs_moved].specified THEN
      clp$change_variable (pvt [p$catalogs_moved].variable^, catalogs_moved_head, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    IF pvt [p$catalogs_skipped].specified THEN
      clp$change_variable (pvt [p$catalogs_skipped].variable^, catalogs_skipped_head, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    IF pvt [p$files_moved].specified THEN
      clp$change_variable (pvt [p$files_moved].variable^, files_moved_head, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    IF pvt [p$files_skipped].specified THEN
      clp$change_variable (pvt [p$files_skipped].variable^, files_skipped_head, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

    fsp$close_file (input_fid, status);

  PROCEND pfp$extract_file_list;

MODEND pfm$extract_file_list;

