?? NEWTITLE := 'NOS/VE Basic Access Method : File Access Procedure for Logs' ??
MODULE bam$log_device;
?? RIGHT := 110 ??

{
{ PURPOSE:
{   This module contains the procedure (fap) that provides file access to
{   ascii and binary logs.
{

?? NEWTITLE := 'Global Declarations Referenced by this Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ame$access_validation_errors
*copyc ame$get_program_actions
*copyc ame$improper_file_id
*copyc ame$open_validation_errors
*copyc ame$put_validation_errors
*copyc ame$skip_program_actions
*copyc ame$skip_validation_errors
*copyc ame$open_validation_errors
*copyc ame$unimplemented_request
*copyc amt$fap_declarations
*copyc amt$file_identifier
*copyc cyd$string
*copyc ose$heap_full_exceptions
*copyc ost$caller_identifier
*copyc ost$status
*copyc pme$logging_exceptions
?? POP ??
*copyc amp$set_file_instance_abnormal
*copyc amp$validate_caller_privilege
*copyc bap$close
*copyc bap$fetch
*copyc bap$fetch_access_information
*copyc bap$store
*copyc bav$task_file_table
*copyc clv$critical_log_path_handle
*copyc clv$log_name_path_handles
*copyc fmp$get_label_attributes
*copyc i#build_adaptable_seq_pointer
*copyc i#current_sequence_position
*copyc lgp$get_critical_log_read_info
*copyc lgp$get_critical_previous_size
*copyc lgp$get_entry_from_critical_log
*copyc lgp$get_entry_from_global_log
*copyc lgp$get_entry_from_local_log
*copyc lgp$get_global_log_read_info
*copyc lgp$get_global_previous_size
*copyc lgp$get_local_log_read_info
*copyc lgp$get_local_previous_size
*copyc osp$set_status_abnormal
*copyc osv$lower_to_upper
*copyc osv$task_private_heap
*copyc pmp$log_ascii

?? TITLE := 'bap$log_device', EJECT ??
*copy bah$log_device

  PROCEDURE [XDCL, #GATE] bap$log_device
    (    file_identifier: amt$file_identifier;
         call_block: amt$call_block;
         layer_number: amt$fap_layer_number;
     VAR status: ost$status);

    VAR
      local_file_name: amt$local_file_name,
      caller_id: ost$caller_identifier,
      critical_window_log: boolean,
      ignore_structure_pointer: ^cell,
      local_status: ost$status,
      ignore_status: ost$status,
      log_ordinal: pmt$logs,
      log_entry: ^bat$log_entry,
      log_cycle: lgt$log_cycle,
      log_address: ^SEQ ( * ),
      file_instance: ^bat$task_file_entry,
      file_position: amt$file_position,
      current_byte_address: amt$file_byte_address,
      text_ptr: ^string (cyc$max_string_size),
      text_size: cyt$string_size,
      static_label: bat$static_label_attributes,
      previous_length: lgt$log_entry_size,
      current_length: lgt$log_entry_size;

?? NEWTITLE := 'flush', EJECT ??
{
{ PURPOSE:
{   This procedure writes a record to an ascii log.
{   Before the write, the bor_address is established.
{   After the write, record_length, file_position (local and global),
{   current_byte_address (local and global), and eoi_byte_address
{   (local and global) are established.
{

    PROCEDURE [INLINE] flush;

      file_instance^.global_file_information^.positioning_info.record_info.bor_address :=
            file_instance^.global_file_information^.positioning_info.record_info.current_byte_address;
      IF NOT critical_window_log THEN
        pmp$log_ascii (log_entry^.value (1, log_entry^.size), $pmt$ascii_logset [log_ordinal],
              pmc$msg_origin_program, local_status);
        IF NOT local_status.normal THEN
          RETURN; {----->
        IFEND;
      IFEND;
      file_instance^.global_file_information^.positioning_info.record_info.record_length := log_entry^.size;
      file_instance^.global_file_information^.positioning_info.record_info.file_position := amc$eor;
      file_position := amc$eor;
      IF critical_window_log THEN
        lgp$get_critical_log_read_info (0, log_cycle, log_address, current_byte_address, local_status);
      ELSEIF log_ordinal IN -$pmt$global_logset [] THEN
        lgp$get_global_log_read_info (log_ordinal, 0, log_cycle, log_address, current_byte_address,
              local_status);
      ELSE
        lgp$get_local_log_read_info (log_ordinal, 0, log_cycle, log_address, current_byte_address,
              local_status);
      IFEND;
      IF NOT local_status.normal THEN
        RETURN; {----->
      IFEND;
      file_instance^.global_file_information^.positioning_info.record_info.current_byte_address :=
            current_byte_address;
      file_instance^.global_file_information^.eoi_byte_address := current_byte_address;
      log_entry^.size := 0;

    PROCEND flush;
?? TITLE := 'get', EJECT ??
{
{ PURPOSE:
{   This procedure reads a record from a log.
{   Bor_address, current_byte_address (local and global), file_position
{   (local and global), record_length, and eoi_byte_address (local and
{   global - if eoi encountered) are established.
{

    PROCEDURE [INLINE] get
      (    working_storage_area: ^cell;
           working_storage_length: amt$working_storage_length);

      VAR
        bor_address: amt$file_byte_address;

      text_ptr := working_storage_area;
      IF working_storage_length <= cyc$max_string_size THEN
        text_size := working_storage_length;
      ELSE
        text_size := cyc$max_string_size;
      IFEND;

      bor_address := i#current_sequence_position (file_instance^.log_address);

      IF critical_window_log THEN
        lgp$get_entry_from_critical_log (file_instance^.log_cycle, file_instance^.log_address,
              current_length, #SEQ (text_ptr^ (1, text_size)) ^, local_status);
        WHILE (NOT local_status.normal) AND (local_status.condition = lge$log_cycles_do_not_match) DO
          rewind;
          IF local_status.normal THEN
            lgp$get_entry_from_critical_log (file_instance^.log_cycle, file_instance^.log_address,
                  current_length, #SEQ (text_ptr^ (1, text_size)) ^, local_status);
          IFEND;
        WHILEND;
      ELSEIF log_ordinal IN -$pmt$global_logset [] THEN
        lgp$get_entry_from_global_log (log_ordinal, file_instance^.log_cycle, file_instance^.log_address,
              current_length, #SEQ (text_ptr^ (1, text_size)) ^, local_status);
        WHILE (NOT local_status.normal) AND (local_status.condition = lge$log_cycles_do_not_match) DO
          rewind;
          IF local_status.normal THEN
            lgp$get_entry_from_global_log (log_ordinal, file_instance^.log_cycle, file_instance^.log_address,
                  current_length, #SEQ (text_ptr^ (1, text_size)) ^, local_status);
          IFEND;
        WHILEND;
      ELSE
        lgp$get_entry_from_local_log (log_ordinal, file_instance^.log_cycle, file_instance^.log_address,
              current_length, #SEQ (text_ptr^ (1, text_size)) ^, local_status);
        WHILE (NOT local_status.normal) AND (local_status.condition = lge$log_cycles_do_not_match) DO
          rewind;
          IF local_status.normal THEN
            lgp$get_entry_from_local_log (log_ordinal, file_instance^.log_cycle, file_instance^.log_address,
                  current_length, #SEQ (text_ptr^ (1, text_size)) ^, local_status);
          IFEND;
        WHILEND;
      IFEND;

      IF local_status.normal THEN
        file_instance^.global_file_information^.positioning_info.record_info.bor_address := bor_address;
        current_byte_address := i#current_sequence_position (file_instance^.log_address);
        file_instance^.global_file_information^.positioning_info.record_info.current_byte_address :=
              current_byte_address;
        file_position := amc$eor;
        file_instance^.global_file_information^.positioning_info.record_info.record_length := current_length;
        file_instance^.global_file_information^.positioning_info.record_info.file_position := file_position;
      ELSEIF local_status.condition = lge$end_of_log THEN
        local_status.normal := TRUE;
        file_position := amc$eoi;
        file_instance^.global_file_information^.eoi_byte_address := current_byte_address;
        file_instance^.global_file_information^.positioning_info.record_info.file_position := file_position;
      IFEND;

    PROCEND get;
?? TITLE := 'put', EJECT ??
{
{ PURPOSE:
{   This procedure adds characters to the log_entry being constructed.
{   It has no effect on any other file_instance data.
{   It is the responsibility of the processing for the various "put"
{   requests to update other relevant file_instance data.
{   (See the "flush" procedure, above.)
{
{ NOTE:
{   The effect of an amc$put_partial_req is local to the file_instance
{   until the record is terminated, hence global information is not
{   updated for that request.
{

    PROCEDURE [INLINE] put
      (    working_storage_area: ^cell;
           working_storage_length: amt$working_storage_length);

      text_ptr := working_storage_area;
      IF working_storage_length <= cyc$max_string_size THEN
        text_size := working_storage_length;
      ELSE
        text_size := cyc$max_string_size;
      IFEND;
      IF text_size > (STRLENGTH (log_entry^.value) - log_entry^.size) THEN
        text_size := STRLENGTH (log_entry^.value) - log_entry^.size;
      IFEND;
      log_entry^.value (log_entry^.size + 1, text_size) := text_ptr^ (1, text_size);
      log_entry^.size := log_entry^.size + text_size;

    PROCEND put;
?? TITLE := 'rewind', EJECT ??
{
{ PURPOSE:
{   This procedure synchronizes the file_instance with the beginning
{   of the current log cycle; and establishes file_position (local and
{   global), current_byte_address (local and global), and bor_address.
{

    PROCEDURE [INLINE] rewind;

      IF critical_window_log THEN
        lgp$get_critical_log_read_info (0, file_instance^.log_cycle, file_instance^.log_address,
              current_byte_address, local_status);
      ELSEIF log_ordinal IN -$pmt$global_logset [] THEN
        lgp$get_global_log_read_info (log_ordinal, 0, file_instance^.log_cycle, file_instance^.log_address,
              current_byte_address, local_status);
      ELSE
        lgp$get_local_log_read_info (log_ordinal, 0, file_instance^.log_cycle, file_instance^.log_address,
              current_byte_address, local_status);
      IFEND;
      IF NOT local_status.normal THEN
        RETURN; {----->
      IFEND;

      RESET file_instance^.log_address;
      current_byte_address := 0;
      file_position := amc$boi;
      file_instance^.global_file_information^.positioning_info.record_info.bor_address := 0;
      file_instance^.global_file_information^.positioning_info.record_info.current_byte_address := 0;
      file_instance^.global_file_information^.positioning_info.record_info.file_position := amc$boi;

    PROCEND rewind;
?? TITLE := 'seek', EJECT ??
{
{ PURPOSE:
{   This procedure establishes a new current_byte_address (local and
{   global), file_position (local and global), and bor_address.
{

    PROCEDURE [INLINE] seek;

      i#build_adaptable_seq_pointer (#RING (file_instance^.log_address),
            #SEGMENT (file_instance^.log_address), #OFFSET (file_instance^.log_address),
            #SIZE (file_instance^.log_address^), current_byte_address, file_instance^.log_address);

      IF current_byte_address = 0 THEN
        file_position := amc$boi;
      ELSE
        file_position := amc$eor;
      IFEND;
      file_instance^.global_file_information^.positioning_info.record_info.file_position := file_position;
      file_instance^.global_file_information^.positioning_info.record_info.bor_address :=
            current_byte_address;
      file_instance^.global_file_information^.positioning_info.record_info.current_byte_address :=
            current_byte_address;

    PROCEND seek;
?? TITLE := 'skip', EJECT ??
{
{ PURPOSE:
{   This procedure performs forward/backward skips on a log.
{   The log is considerred to consist of a single partition.
{

    PROCEDURE {INLINE} skip;

      VAR
        ignore_text: cell,
        residual_skip_count: amt$skip_count;

      IF log_entry <> NIL THEN
        amp$set_file_instance_abnormal (file_identifier, ame$skip_requires_read_perm, call_block.operation,
              '', local_status);
        RETURN; {----->
      IFEND;

      IF (call_block.skp.count < LOWERVALUE (amt$skip_count)) OR
            (call_block.skp.count > UPPERVALUE (amt$skip_count)) THEN
        amp$set_file_instance_abnormal (file_identifier, ame$improper_skip_count, call_block.operation, '',
              local_status);
        RETURN; {----->
      IFEND;

      CASE call_block.skp.unit OF
      = amc$skip_partition =
        residual_skip_count := UPPERVALUE (amt$skip_count);
      = amc$skip_record =
        residual_skip_count := call_block.skp.count;
      ELSE
        amp$set_file_instance_abnormal (file_identifier, ame$improper_skip_unit, call_block.operation, '',
              local_status);
        RETURN; {----->
      CASEND;

      current_byte_address := i#current_sequence_position (file_instance^.log_address);
      file_position := file_instance^.global_file_information^.positioning_info.record_info.file_position;

      CASE call_block.skp.direction OF

      = amc$forward =
        WHILE (file_position < amc$eoi) AND (residual_skip_count > 0) DO
          get (^ignore_text, 1);
          IF NOT local_status.normal THEN
            RETURN; {----->
          IFEND;
          residual_skip_count := residual_skip_count - 1;
        WHILEND;

        IF call_block.skp.unit = amc$skip_record THEN
          IF file_position = amc$eoi THEN
            residual_skip_count := residual_skip_count + 1;
            amp$set_file_instance_abnormal (file_identifier, ame$skip_encountered_eoi, call_block.operation,
                  'records', local_status);
          IFEND;
        ELSE {amc$skip_partition}
          IF call_block.skp.count > 0 THEN
            amp$set_file_instance_abnormal (file_identifier, ame$skip_encountered_eoi, call_block.operation,
                  'partitions', local_status);
          IFEND;
          residual_skip_count := call_block.skp.count;
        IFEND;

      = amc$backward =
        WHILE (file_position > amc$boi) AND (residual_skip_count > 0) DO
          residual_skip_count := residual_skip_count - 1;
          IF critical_window_log THEN
            lgp$get_critical_previous_size (file_instance^.log_cycle, file_instance^.log_address,
                  previous_length, local_status);
            WHILE (NOT local_status.normal) AND (local_status.condition = lge$log_cycles_do_not_match) DO
              rewind;
              IF local_status.normal THEN
                lgp$get_critical_previous_size (file_instance^.log_cycle, file_instance^.log_address,
                      previous_length, local_status);
              IFEND;
            WHILEND;
          ELSEIF log_ordinal IN -$pmt$global_logset [] THEN
            lgp$get_global_previous_size (log_ordinal, file_instance^.log_cycle, file_instance^.log_address,
                  previous_length, local_status);
            WHILE (NOT local_status.normal) AND (local_status.condition = lge$log_cycles_do_not_match) DO
              rewind;
              IF local_status.normal THEN
                lgp$get_global_previous_size (log_ordinal, file_instance^.log_cycle,
                      file_instance^.log_address, previous_length, local_status);
              IFEND;
            WHILEND;
          ELSE
            lgp$get_local_previous_size (log_ordinal, file_instance^.log_cycle, file_instance^.log_address,
                  previous_length, local_status);
            WHILE (NOT local_status.normal) AND (local_status.condition = lge$log_cycles_do_not_match) DO
              rewind;
              IF local_status.normal THEN
                lgp$get_local_previous_size (log_ordinal, file_instance^.log_cycle,
                      file_instance^.log_address, previous_length, local_status);
              IFEND;
            WHILEND;
          IFEND;
          IF NOT local_status.normal THEN
            RETURN; {----->
          IFEND;
          current_byte_address := current_byte_address - (previous_length + #SIZE (lgt$log_entry_header));
          seek;
          IF NOT local_status.normal THEN
            RETURN; {----->
          IFEND;
        WHILEND;

        IF call_block.skp.unit = amc$skip_record THEN
          IF residual_skip_count > 0 THEN
            amp$set_file_instance_abnormal (file_identifier, ame$skip_encountered_boi, call_block.operation,
                  'records', local_status);
          IFEND;
        ELSE {amc$skip_partition}
          IF call_block.skp.count > 0 THEN
            amp$set_file_instance_abnormal (file_identifier, ame$skip_encountered_boi, call_block.operation,
                  'partitions', local_status);
          IFEND;
          residual_skip_count := call_block.skp.count;
        IFEND;

      ELSE
        amp$set_file_instance_abnormal (file_identifier, ame$improper_skip_direction, call_block.operation,
              '', local_status);
        RETURN; {----->
      CASEND;

      file_instance^.residual_skip_count := residual_skip_count;
      file_instance^.global_file_information^.positioning_info.record_info.file_position := file_position;
      file_instance^.global_file_information^.positioning_info.record_info.current_byte_address :=
            current_byte_address;
      file_instance^.global_file_information^.positioning_info.record_info.bor_address :=
            current_byte_address;
      IF file_position = amc$eoi THEN
        file_instance^.global_file_information^.eoi_byte_address := current_byte_address;
      IFEND;

    PROCEND skip;
?? OLDTITLE, EJECT ??

    #CALLER_ID (caller_id);
    status.normal := TRUE;
    local_status.normal := TRUE;
    critical_window_log := FALSE;
    file_instance := NIL;

  /fap/
    BEGIN
      amp$validate_caller_privilege (file_identifier, call_block, layer_number,
            $pft$usage_selections [pfc$append], caller_id.ring, ignore_structure_pointer, local_status);
      IF NOT local_status.normal THEN
        IF local_status.condition <> ame$improper_file_id THEN
          file_instance := ^bav$task_file_table^ [file_identifier.ordinal];
        IFEND;
        EXIT /fap/; {----->
      IFEND;

      file_instance := ^bav$task_file_table^ [file_identifier.ordinal];

      IF call_block.operation = amc$open_req THEN
        IF call_block.open.access_level <> amc$record THEN
          amp$set_file_instance_abnormal (file_identifier, ame$not_virtual_memory_device, amc$open_req, 'LOG',
                local_status);
          EXIT /fap/; {----->
        IFEND;

      /determine_log_ordinal/
        BEGIN
          #TRANSLATE (osv$lower_to_upper, call_block.open.local_file_name, local_file_name);
          IF local_file_name = clv$critical_log_path_handle THEN
            log_ordinal := pmc$system_log;
            critical_window_log := TRUE;
            EXIT /determine_log_ordinal/; {----->
          ELSE
            FOR log_ordinal := LOWERBOUND (clv$log_name_path_handles)
                  TO UPPERBOUND (clv$log_name_path_handles) DO
              IF local_file_name = clv$log_name_path_handles [log_ordinal] THEN
                EXIT /determine_log_ordinal/; {----->
              IFEND;
            FOREND;
          IFEND;
          osp$set_status_abnormal (amc$access_method_id, pme$name_is_not_name_of_log, local_file_name,
                local_status);
          EXIT /fap/; {----->
        END /determine_log_ordinal/;

        IF critical_window_log THEN
          lgp$get_critical_log_read_info (0, file_instance^.log_cycle, file_instance^.log_address,
                current_byte_address, local_status);
        ELSEIF log_ordinal IN -$pmt$global_logset [] THEN
          lgp$get_global_log_read_info (log_ordinal, 0, file_instance^.log_cycle, file_instance^.log_address,
                current_byte_address, local_status);
        ELSE
          lgp$get_local_log_read_info (log_ordinal, 0, file_instance^.log_cycle, file_instance^.log_address,
                current_byte_address, local_status);
        IFEND;
        IF NOT local_status.normal THEN
          EXIT /fap/; {----->
        IFEND;
        RESET file_instance^.log_address;
        file_instance^.global_file_information^.eoi_byte_address := current_byte_address;

        IF (file_instance^.instance_attributes.dynamic_label.access_mode = $pft$usage_selections [pfc$append])
        { this next check will be taken out when amp$open is eliminated completely and }
        { fsp$open_file is used throughout command language.}
        OR (file_instance^.instance_attributes.dynamic_label.access_mode = $pft$usage_selections
              [pfc$append, pfc$shorten]) THEN
          IF NOT critical_window_log AND NOT (log_ordinal IN -$pmt$ascii_logset []) THEN
            amp$set_file_instance_abnormal (file_identifier, ame$improper_access_attempt,
                  call_block.operation, ' READ ONLY', local_status);
            EXIT /fap/; {----->
          IFEND;
          fmp$get_label_attributes (file_instance^.system_file_label, static_label, local_status);
          IF NOT local_status.normal THEN
            EXIT /fap/; {----->
          IFEND;
          text_size := static_label.page_width;
          IF text_size < osc$max_string_size THEN
            text_size := osc$max_string_size;
          IFEND;
          ALLOCATE log_entry: [text_size] IN osv$task_private_heap^;
          log_entry^.size := 0;
          current_byte_address := file_instance^.global_file_information^.eoi_byte_address;
          file_position := amc$eoi;

        ELSEIF file_instance^.instance_attributes.dynamic_label.access_mode = $pft$usage_selections
              [pfc$read] THEN
          log_entry := NIL;
          current_byte_address := 0;
          file_position := amc$boi;

        ELSE
          IF critical_window_log OR (log_ordinal IN -$pmt$ascii_logset []) THEN
            amp$set_file_instance_abnormal (file_identifier, ame$improper_access_attempt,
                  call_block.operation, ' APPEND ONLY or READ ONLY', local_status);
          ELSE
            amp$set_file_instance_abnormal (file_identifier, ame$improper_access_attempt,
                  call_block.operation, ' READ ONLY', local_status);
          IFEND;
          EXIT /fap/; {----->
        IFEND;

        file_instance^.log_entry := log_entry;
        file_instance^.log_ordinal := log_ordinal;

        file_instance^.global_file_information^.positioning_info.record_info.bor_address :=
              current_byte_address;
        file_instance^.global_file_information^.positioning_info.record_info.current_byte_address :=
              current_byte_address;
        file_instance^.global_file_information^.positioning_info.record_info.file_position := file_position;

      ELSE
        log_ordinal := file_instance^.log_ordinal;
        log_entry := file_instance^.log_entry;
      IFEND;


      CASE call_block.operation OF

      = amc$close_req =
        IF log_entry <> NIL THEN
          IF file_instance^.global_file_information^.positioning_info.record_info.file_position =
                amc$mid_record THEN
            flush;
          IFEND;
          FREE log_entry IN osv$task_private_heap^;
        IFEND;
        IF local_status.normal THEN
          bap$close (file_identifier, local_status);
        ELSE
          bap$close (file_identifier, ignore_status);
        IFEND;

      = amc$fetch_req =
        bap$fetch (file_identifier, call_block, layer_number, local_status);

      = amc$fetch_access_information_rq =
        bap$fetch_access_information (file_identifier, call_block, layer_number, local_status);

      = amc$flush_req, amc$write_end_partition_req =
        IF log_entry <> NIL THEN
          IF file_instance^.global_file_information^.positioning_info.record_info.file_position =
                amc$mid_record THEN
            flush;
          IFEND;
        IFEND;

      = amc$get_direct_req =
        current_byte_address := call_block.getd.byte_address;
        seek;
        IF NOT local_status.normal THEN
          EXIT /fap/; {----->
        IFEND;

        get (call_block.getd.working_storage_area, call_block.getd.working_storage_length);
        IF NOT local_status.normal THEN
          EXIT /fap/; {----->
        IFEND;

        call_block.getd.file_position^ := file_position;
        IF call_block.getd.file_position^ = amc$eoi THEN
          call_block.getd.transfer_count^ := 0;
        ELSEIF current_length <= text_size THEN
          call_block.getd.transfer_count^ := current_length;
        ELSE
          call_block.getd.transfer_count^ := text_size;
        IFEND;

      = amc$get_next_req =
        IF file_instance^.global_file_information^.positioning_info.record_info.file_position = amc$eoi THEN
          amp$set_file_instance_abnormal (file_identifier, ame$input_after_eoi, call_block.operation, '',
                local_status);
          EXIT /fap/; {----->
        IFEND;

        get (call_block.getn.working_storage_area, call_block.getn.working_storage_length);
        IF NOT local_status.normal THEN
          EXIT /fap/; {----->
        IFEND;

        call_block.getn.file_position^ := file_position;
        call_block.getn.byte_address^ := file_instance^.global_file_information^.positioning_info.record_info.
              bor_address;
        IF call_block.getn.file_position^ = amc$eoi THEN
          call_block.getn.transfer_count^ := 0;
        ELSEIF current_length <= text_size THEN
          call_block.getn.transfer_count^ := current_length;
        ELSE
          call_block.getn.transfer_count^ := text_size;
        IFEND;

      = amc$get_partial_req =
        IF file_instance^.global_file_information^.positioning_info.record_info.file_position = amc$eoi THEN
          amp$set_file_instance_abnormal (file_identifier, ame$input_after_eoi, call_block.operation, '',
                local_status);
          EXIT /fap/; {----->
        IFEND;

        get (call_block.getp.working_storage_area, call_block.getp.working_storage_length);
        IF NOT local_status.normal THEN
          EXIT /fap/; {----->
        IFEND;

        call_block.getp.file_position^ := file_position;
        call_block.getp.byte_address^ := file_instance^.global_file_information^.positioning_info.record_info.
              bor_address;
        IF call_block.getp.file_position^ = amc$eoi THEN
          call_block.getp.record_length^ := 0;
          call_block.getp.transfer_count^ := 0;
        ELSE
          call_block.getp.record_length^ := current_length;
          IF current_length <= text_size THEN
            call_block.getp.transfer_count^ := current_length;
          ELSE
            call_block.getp.transfer_count^ := text_size;
          IFEND;
        IFEND;

      = amc$open_req =
        {processed above} ;

      = amc$put_direct_req =
        IF file_instance^.global_file_information^.positioning_info.record_info.file_position =
              amc$mid_record THEN
          flush;
          IF NOT local_status.normal THEN
            EXIT /fap/; {----->
          IFEND;
        IFEND;

        put (call_block.putd.working_storage_area, call_block.putd.working_storage_length);
        flush;

      = amc$put_next_req =
        IF file_instance^.global_file_information^.positioning_info.record_info.file_position =
              amc$mid_record THEN
          flush;
          IF NOT local_status.normal THEN
            EXIT /fap/; {----->
          IFEND;
        IFEND;

        put (call_block.putn.working_storage_area, call_block.putn.working_storage_length);
        flush;
        IF NOT local_status.normal THEN
          EXIT /fap/; {----->
        IFEND;

        call_block.putn.byte_address^ := file_instance^.global_file_information^.positioning_info.record_info.
              bor_address;

      = amc$put_partial_req =
        IF (file_instance^.global_file_information^.positioning_info.record_info.file_position <>
              amc$mid_record) AND (call_block.putp.term_option = amc$continue) THEN
          amp$set_file_instance_abnormal (file_identifier, ame$improper_continue, call_block.operation, '',
                local_status);
          EXIT /fap/; {----->
        IFEND;

        IF (file_instance^.global_file_information^.positioning_info.record_info.file_position =
              amc$mid_record) AND (call_block.putp.term_option = amc$start) THEN
          flush;
          IF NOT local_status.normal THEN
            EXIT /fap/; {----->
          IFEND;
        IFEND;

        put (call_block.putp.working_storage_area, call_block.putp.working_storage_length);

        IF call_block.putp.term_option = amc$terminate THEN
          flush;
          IF NOT local_status.normal THEN
            EXIT /fap/; {----->
          IFEND;
        ELSE
          file_instance^.global_file_information^.positioning_info.record_info.file_position :=
                amc$mid_record;
        IFEND;

        call_block.putn.byte_address^ := file_instance^.global_file_information^.positioning_info.record_info.
              bor_address;

      = amc$rewind_req =
        IF log_entry = NIL THEN
          rewind;
        IFEND;

      = amc$seek_direct_req =
        IF log_entry = NIL THEN
          current_byte_address := call_block.seekd.byte_address;
          seek;
        IFEND;

      = amc$skip_req =
        IF log_entry = NIL THEN
          skip;
          call_block.skp.file_position^ := file_position;
        IFEND;

      = amc$store_req =
        bap$store (file_identifier, call_block, layer_number, local_status);

      ELSE
        amp$set_file_instance_abnormal (file_identifier, ame$unimplemented_request, call_block.operation,
              ' for log device files', local_status);
      CASEND;
    END /fap/;

    IF (file_instance <> NIL) AND (call_block.operation <> amc$close_req) THEN
      IF call_block.operation <> amc$fetch_access_information_rq THEN
        file_instance^.global_file_information^.last_access_operation := call_block.operation;
      IFEND;
      IF local_status.normal THEN
        file_instance^.global_file_information^.error_status := 0;
      ELSE
        file_instance^.global_file_information^.error_status := local_status.condition;
      IFEND;
    IFEND;

    IF NOT local_status.normal THEN
      status := local_status;
    IFEND;

  PROCEND bap$log_device;

MODEND bam$log_device;
