?? RIGHT := 110 ??
?? NEWTITLE := 'INSTALL_SOFTWARE Utility: RAP$INIT_PROCESSING_SEQ Interface.' ??
MODULE ram$init_processing_seq;

{ PURPOSE:
{   This module contains the interface and procedure that initializes the
{   processing sequence and acesses the packing list.
{
{ DESIGN:
{   The compiled module resides in RAF$LIBRARY.
{
{ NOTES:
{

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rac$control_file_name
*copyc rae$install_software_cc
*copyc rat$installation_control_record
*copyc rat$installation_defaults
?? POP ??
*copyc fsp$close_file
*copyc mmp$create_scratch_segment
*copyc mmp$delete_scratch_segment
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$set_status_abnormal
*copyc rap$establish_icr_packlist_ptrs
*copyc rap$establish_icr_subp_ptrs
*copyc rap$open_packing_list_using_icr
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] rap$init_processing_seq', EJECT ??

{ PURPOSE:
{   This interface creates and initializes the processing sequence and
{   accesses the packing list that are used by the installation control
{   record.  The processing sequence holds records that describe how the
{   processing will be done.  In some cases it will also contain a
{   modifiable copy of the packing list.
{
{ DESIGN:
{   A memory scratch segment is created to contain the processing sequence.
{   (The deletion of the segment is the responsibility of the caller.)
{
{   The packing list is accessed and the major data pointers are
{   established.  When installing corrections or updates, the packing list
{   must be modifiable.  This means that a copy of the packing list is
{   placed at the end of the processing sequence.  The pointers are
{   established to the copy and the original packing list is closed.
{
{   The medium and subproduct processing records are established when the
{   packing list is accessed.  The number of subproducts and medium type
{   determine how the records are created.  The job processing record is
{   created when the processing controls are established.
{
{ NOTES:
{   At 1.4.1 only corrections (which must be installed using the
{   INSTALL_CORRECTION command) are supported.  In the future, updates will
{   be supported, at which time the test for when a modifiable packing
{   list is needed will have to be changed.
{

  PROCEDURE [XDCL] rap$init_processing_seq
    (    packing_list_name: ost$name;
         save_previous_cycles: boolean;
         installation_command: rat$installation_commands;
         command_compatible_type: rat$subproduct_type;
         installation_defaults: rat$installation_defaults;
     VAR installation_control_record {input, output} : rat$installation_control_record;
     VAR processing_segment_pointer: amt$segment_pointer;
     VAR packing_list_fid: amt$file_identifier;
     VAR packing_list_opened: boolean;
     VAR status: ost$status);


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


?? NEWTITLE := 'abort_handler', EJECT ??

{ PURPOSE:
{   This procedure cleans up when an abort situation occurs within the
{   block structure.
{
{ DESIGN:
{   The function of this condition handler is to return the scratch
{   segment when an abort condition arises.
{
{ NOTES:
{

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

      VAR
        ignore_status: ost$status;


      IF processing_segment_pointer.sequence_pointer <> NIL THEN
        mmp$delete_scratch_segment (processing_segment_pointer, ignore_status);
        processing_segment_pointer.sequence_pointer := NIL;
      IFEND;

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??


    status.normal := TRUE;
    processing_segment_pointer.kind := amc$sequence_pointer;
    processing_segment_pointer.sequence_pointer := NIL;

    packing_list_opened := FALSE;

    osp$establish_block_exit_hndlr (^abort_handler);

  /main/
    BEGIN

      initialize_seq_and_header (packing_list_name, save_previous_cycles, installation_command,
            command_compatible_type, installation_defaults, installation_control_record,
            processing_segment_pointer, status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      rap$open_packing_list_using_icr (installation_control_record, packing_list_fid, packing_list_opened,
            status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      IF installation_command = rac$install_correction THEN

        { A modifiable copy of the packing list is placed at the end of the processing
        { sequence.  The packing list file is then closed.

        write_packing_list_to_seq (installation_control_record, status);
        IF packing_list_opened THEN
          fsp$close_file (packing_list_fid, local_status);
          packing_list_opened := FALSE;
          IF (NOT status.normal) AND (NOT local_status.normal) THEN
            status := local_status;
          IFEND;
          IF NOT status.normal THEN
            EXIT /main/;
          IFEND;
        IFEND;

      IFEND;

      rap$establish_icr_packlist_ptrs (installation_control_record, status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      establish_processing_records (installation_control_record, status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      rap$establish_icr_subp_ptrs (installation_control_record, status);

    END /main/;

    IF (NOT status.normal) AND (processing_segment_pointer.sequence_pointer <> NIL) THEN
      mmp$delete_scratch_segment (processing_segment_pointer, ignore_status);
      processing_segment_pointer.sequence_pointer := NIL;
    IFEND;

    osp$disestablish_cond_handler;

  PROCEND rap$init_processing_seq;

?? OLDTITLE ??
?? NEWTITLE := 'establish_processing_records', EJECT ??

{ PURPOSE:
{   This procedure establishes the medium and subproduct processing records
{   (which are part of the processing sequence).
{
{ DESIGN:
{   The medium and subproduct processing records provide extended processing
{   information to the information already contained in the packing list.
{   There is a one to one mapping between the subproduct processing records
{   and the subproduct indexer found on the packing list.  Likewise, there
{   is a a one to one mapping between the medium processing records and the
{   tape vsn list (when the order medium is tape).  For non-tape orders the
{   medium processing record is of length one.
{
{ NOTES:
{   Not all of the subproduct processing record fields are set.  The subproduct
{   information pointers are set by rap$establish_icr_subp_ptrs.
{

  PROCEDURE establish_processing_records
    (VAR installation_control_record {input, output} : rat$installation_control_record;
     VAR status: ost$status);


    VAR
      i: rat$subproduct_count,
      medium_record_count: rat$tape_count;


    status.normal := TRUE;

{ Establish the medium processing records.

    IF installation_control_record.packing_list_pointers.order_medium = rac$tape THEN
      medium_record_count := installation_control_record.packing_list_pointers.header_p^.primary_tape_count;
    ELSE {order medium = rac$disk}
      medium_record_count := 1;
    IFEND;

    NEXT installation_control_record.medium_processing_records_p: [1 .. medium_record_count] IN
          installation_control_record.processing_seq_p;
    IF installation_control_record.medium_processing_records_p = NIL THEN
      osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'PROCESSING SEQUENCE', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'JOB PROCESSING RECORDS', status);
      RETURN;
    IFEND;

    installation_control_record.processing_header_p^.medium_processing_rec_rel_p :=
          #REL (installation_control_record.medium_processing_records_p,
          installation_control_record.processing_seq_p^);

    { Initialize the fields of the medium processing records.

    FOR i := 1 TO UPPERBOUND (installation_control_record.medium_processing_records_p^) DO
      installation_control_record.medium_processing_records_p^ [i].job_identifier := osc$null_name;
      installation_control_record.medium_processing_records_p^ [i].subproduct_count := 0;
    FOREND;

{ Establish the subproduct processing records.

    NEXT installation_control_record.subproduct_processing_records_p:
          [1 .. installation_control_record.packing_list_pointers.header_p^.subproduct_count] IN
          installation_control_record.processing_seq_p;
    IF installation_control_record.subproduct_processing_records_p = NIL THEN
      osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'PROCESSING SEQUENCE', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'SUBPRODUCT PROCESSING RECORDS', status);
      RETURN;
    IFEND;

    installation_control_record.processing_header_p^.subproduct_processing_rec_rel_p :=
          #REL (installation_control_record.subproduct_processing_records_p,
          installation_control_record.processing_seq_p^);

    { Initialize the fields of the subproduct processing records.

    FOR i := 1 TO UPPERBOUND (installation_control_record.subproduct_processing_records_p^) DO
      installation_control_record.subproduct_processing_records_p^ [i].job_identifier := osc$null_name;
      installation_control_record.subproduct_processing_records_p^ [i].product_reference :=
            rac$not_referenced;
      installation_control_record.subproduct_processing_records_p^ [i].task_set := $rat$task_selections [];
      installation_control_record.subproduct_processing_records_p^ [i].task := rac$null_task;
      installation_control_record.subproduct_processing_records_p^ [i].task_status := rac$task_started;
      installation_control_record.subproduct_processing_records_p^ [i].installation_catalog_p := NIL;
      installation_control_record.subproduct_processing_records_p^ [i].installation_catalog_rel_p := NIL;
      installation_control_record.subproduct_processing_records_p^ [i].active_level_catalog_rel_p := NIL;
      installation_control_record.subproduct_processing_records_p^ [i].base_level_catalog_rel_p := NIL;
      installation_control_record.subproduct_processing_records_p^ [i].correction_base_catalog_rel_p := NIL;
    FOREND;

  PROCEND establish_processing_records;

?? OLDTITLE ??
?? NEWTITLE := 'initialize_seq_and_header', EJECT ??

{ PURPOSE:
{   This procedure creates and initializes the processing sequence and header.
{
{ DESIGN:
{   The fields in the header record are set.  The PACKING_LIST_NAME,
{   SAVE_PREVIOUS_CYCLES and INSTALLATION_DEFAULTS values were passed in.
{
{ NOTES:
{

  PROCEDURE initialize_seq_and_header
    (    packing_list_name: ost$name;
         save_previous_cycles: boolean;
         installation_command: rat$installation_commands;
         command_compatible_type: rat$subproduct_type;
         installation_defaults: rat$installation_defaults;
     VAR installation_control_record {input, output} : rat$installation_control_record;
     VAR processing_segment_pointer: amt$segment_pointer;
     VAR status: ost$status);



    status.normal := TRUE;

    mmp$create_scratch_segment (amc$sequence_pointer, mmc$as_random, processing_segment_pointer, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    installation_control_record.processing_seq_p := processing_segment_pointer.sequence_pointer;

    RESET installation_control_record.processing_seq_p;

    NEXT installation_control_record.processing_header_p IN installation_control_record.processing_seq_p;
    IF installation_control_record.processing_header_p = NIL THEN
      osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'PROCESSING SEQUENCE', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'HEADER', status);
      RETURN;
    IFEND;

    { Initialize the procesing header values.

    installation_control_record.processing_header_p^.installation_identifier := osc$null_name;
    installation_control_record.processing_header_p^.installation_command := installation_command;
    installation_control_record.processing_header_p^.command_compatible_type := command_compatible_type;
    installation_control_record.processing_header_p^.installation_defaults := installation_defaults;
    installation_control_record.processing_header_p^.packing_list_name := packing_list_name;
    installation_control_record.processing_header_p^.packing_list_seq_rel_p := NIL;
    installation_control_record.processing_header_p^.packing_list_seq_size := 0;
    installation_control_record.processing_header_p^.job_processing_rec_rel_p := NIL;
    installation_control_record.processing_header_p^.medium_processing_rec_rel_p := NIL;
    installation_control_record.processing_header_p^.subproduct_processing_rec_rel_p := NIL;
    installation_control_record.processing_header_p^.number_of_steps := 0;
    installation_control_record.processing_header_p^.step_set := $rat$step_selections [];
    installation_control_record.processing_header_p^.save_previous_cycles := save_previous_cycles;

  PROCEND initialize_seq_and_header;

?? OLDTITLE ??
?? NEWTITLE := 'write_packing_list_to_seq', EJECT ??

{ PURPOSE:
{   This procedure writes the contents of the packing list file to
{   EOI of the processing sequence in memory.
{
{ DESIGN:
{   The file is opened as segment access and a file contents pointer is
{   established.  A sequence contents file is created for the same size and
{   the file contents are assigned to the memory processing sequence
{   contents (using assignment of deferred pointers).
{
{ NOTES:
{

  PROCEDURE write_packing_list_to_seq
    (VAR installation_control_record {input, output} : rat$installation_control_record;
     VAR status: ost$status);


    VAR
      local_status: ost$status,
      packing_list_contents_p: ^SEQ ( * ),
      packing_list_length: integer,
      packing_list_seq_p: ^rat$packing_list_sequence;


    status.normal := TRUE;
    packing_list_seq_p := installation_control_record.packing_list_pointers.sequence_p;

    { Establish the pointer to the control file contents.

    packing_list_length := #SIZE (packing_list_seq_p^);

    RESET packing_list_seq_p;
    NEXT packing_list_contents_p: [[REP packing_list_length OF cell]] IN packing_list_seq_p;
    IF packing_list_contents_p = NIL THEN
      osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'PACKING LIST', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'CONTENTS', status);
      RETURN;
    IFEND;

    { Establish the pointer to create the packing list sequence at EOI of the processing sequence.

    NEXT installation_control_record.packing_list_pointers.sequence_p: [[REP packing_list_length OF cell]] IN
          installation_control_record.processing_seq_p;
    IF installation_control_record.packing_list_pointers.sequence_p = NIL THEN
      osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'PROCESSING SEQUENCE', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'CONTENTS', status);
      RETURN;
    IFEND;

    { Assign the contents of the packing list file to the contents of the packing list sequence
    { found in the processing sequence.

    installation_control_record.packing_list_pointers.sequence_p^ := packing_list_contents_p^;

    { Establish the relative pointer and size to the packing list.

    installation_control_record.processing_header_p^.packing_list_seq_rel_p :=
          #REL (installation_control_record.packing_list_pointers.sequence_p,
          installation_control_record.processing_seq_p^);
    installation_control_record.processing_header_p^.packing_list_seq_size := packing_list_length;

  PROCEND write_packing_list_to_seq;

MODEND ram$init_processing_seq;
