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

{ PURPOSE:
{   This module contains the interface and procedures to write a file
{   from a sequence in memory.
{
{ DESIGN:
{   The compiled module resides in RAF$LIBRARY.
{
{ NOTES:
{

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rae$install_software_cc
?? POP ??
*copyc amp$get_segment_pointer
*copyc amp$set_segment_eoi
*copyc fsp$close_file
*copyc fsp$open_file
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$set_status_abnormal
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] rap$write_file_from_memory', EJECT ??

{ PURPOSE:
{   This interface creates a file and then copies the contents for the file
{   from a memory sequence.
{
{ DESIGN:
{   The memory sequence is copied to the specified file.
{
{ NOTES:
{

  PROCEDURE [XDCL] rap$write_file_from_memory
    (    file: fst$file_reference;
         memory_seq_size: integer;
     VAR memory_seq_p {input} : ^SEQ ( * );
     VAR status: ost$status);


    VAR
      attachment_options: array [1 .. 3] of fst$attachment_option,
      file_contents_p: ^SEQ ( * ),
      file_fid: amt$file_identifier,
      file_opened: boolean,
      local_status: ost$status,
      memory_seq_contents_p: ^SEQ ( * ),
      segment_pointer: amt$segment_pointer;


?? 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 close the file 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;

      fsp$close_file (file_fid, ignore_status);

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??


    status.normal := TRUE;

    attachment_options [1].selector := fsc$access_and_share_modes;
    attachment_options [1].access_modes.selector := fsc$specific_access_modes;
    attachment_options [1].access_modes.value := $fst$file_access_options
          [fsc$read, fsc$shorten, fsc$append, fsc$modify];
    attachment_options [1].share_modes.selector := fsc$determine_from_access_modes;
    attachment_options [2].selector := fsc$create_file;
    attachment_options [2].create_file := TRUE;
    attachment_options [3].selector := fsc$wait_for_attachment;
    attachment_options [3].wait_for_attachment.wait := osc$wait;
    attachment_options [3].wait_for_attachment.wait_time := fsc$longest_wait_time;


    osp$establish_block_exit_hndlr (^abort_handler);

  /main/
    BEGIN

      file_opened := TRUE;
      fsp$open_file (file, amc$segment, ^attachment_options, NIL, NIL, NIL, NIL, file_fid, status);
      IF NOT status.normal THEN
        file_opened := FALSE;
        EXIT /main/;
      IFEND;

      amp$get_segment_pointer (file_fid, amc$sequence_pointer, segment_pointer, status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      { Establish pointers to the memory and file contents as the size of the memory sequence.

      RESET memory_seq_p;
      NEXT memory_seq_contents_p: [[REP memory_seq_size OF cell]] IN memory_seq_p;
      IF memory_seq_contents_p = NIL THEN
        osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'MEMORY SEQUENCE', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'CONTENTS', status);
        EXIT /main/;
      IFEND;

      RESET segment_pointer.sequence_pointer;
      NEXT file_contents_p: [[REP memory_seq_size OF cell]] IN segment_pointer.sequence_pointer;
      IF file_contents_p = NIL THEN
        osp$set_status_abnormal ('RA', rae$accessed_beyond_segment_eoi, 'FILE', status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'CONTENTS', status);
        EXIT /main/;
      IFEND;

      { Copy the processing sequence to the installation control file.

      file_contents_p^ := memory_seq_contents_p^;

      amp$set_segment_eoi (file_fid, segment_pointer, status);

    END /main/;

    IF file_opened THEN
      fsp$close_file (file_fid, local_status);
      IF status.normal AND (NOT local_status.normal) THEN
        status := local_status;
      IFEND;
    IFEND;

    osp$disestablish_cond_handler;

  PROCEND rap$write_file_from_memory;
MODEND ram$write_file_from_memory;
