module reread (ident = '01') = begin !++ ! ! This module contains the routines for implementing the FORTRAN reread ! statement. ! ! The routine FOR$IO_END, which is called to run down all FORTRAN I/O ! operations is patched to put the address of the current RMS buffer and ! length into global variables REREAD_BUFADR and REREAD_BUFLEN. To implement ! rereading, the user calls REREAD, passing the logical unit to implement ! rereading on. A mailbox is created, and opened on that logical unit. ! A read attention AST is maintained on that mailbox. In order to effect ! a reread operation, the user merely issues a FORTRAN read on that logical ! unit. An AST routine gains control, obtains the unformatted input from the ! RMS buffer and moves it to the mailbox. The user's FORTRAN read then ! obtains this buffer through the mailbox. ! ! To use this routine, the user must link to the objects for reread ! as well as sys$library:starlet/lib. ! The maximum buffer that can be reread is max_length bytes ! (larger buffers are truncated). ! ! Neal Lippman, October, 1980 ! !-- library 'sys$library:lib'; literal max_length=512; !maximum buffer size we can reread global reread_bufadr, !addr of last string read reread_buflen; !length last read own mbox_chan : word; !channel of mailbox external reread_canerr : addressing_mode(long_relative),!error cancelling I/O on channel reread_astset : addressing_mode(long_relative),!error setting ast on mailbox reread_transerr : addressing_mode(long_relative),!error moving text to mailbox reread_jpierr : addressing_mode(long_relative),!error on getjpi reread_mbxcre : addressing_mode(long_relative);!error creating mbox forward routine create_mbox : novalue, ast_handle : novalue, ast_set : novalue, length, cancel_io : novalue; global routine create_mbox (desc_addr) : novalue = begin !++ ! ! This routine creates the mailbox for the reread operation, and returns ! its logical name (character*19) to the caller. ! !-- bind desc = .desc_addr : vector[,long], !descriptor len = desc : vector[,word], !length string = .(desc+4), !string addr log = uplit byte('_REREAD'); !part of log name for mbox local istat; own lognam : vector[63,byte], lognam_desc : vector[2,long] initial(0,lognam), username : vector[13,byte] initial( rep 13 of byte(%c' ')), jpi_buf : vector[4,long] initial( word(12,jpi$_username), username, 0, 0); istat = $getjpi( !get username itmlst=jpi_buf ); if .istat neq ss$_normal then $exit(code = reread_jpierr); ch$move((istat=length(username)), username, lognam); ch$move(7, log, lognam+.istat); lognam_desc[0] = .istat + 7; ch$move(.lognam_desc[0], lognam, string); len[0] = .lognam_desc[0]; istat = $crembx( !create the mbox prmflg=0, !temporary chan=mbox_chan, !channel address maxmsg=max_length, !maximum message size bufquo=max_length, !only allow one message at a time lognam=lognam_desc !logical name ); if .istat neq ss$_normal then $exit(code = reread_mbxcre); return end; global routine ast_handle : novalue = begin !++ ! ! Transfer data from RMS buffer to mailbox. ! !-- local istat; istat = $qiow( !move the text to the mbox chan=.mbox_chan, !channel func=io$_writevblk or io$m_now, !write function, no wait p1=.reread_bufadr, !address of RMS buffer p2= !size of buffer (if .reread_buflen gtr max_length then max_length else .reread_buflen) ); if .istat neq ss$_normal then $exit(code = reread_transerr); ast_set(); return end; global routine ast_set : novalue = begin !++ ! ! Set the read attention AST on the mailbox. ! !-- local istat; istat = $qiow( chan=.mbox_chan, !channel func=io$_setmode or io$m_readattn, !attention function code p1=ast_handle !AST routine ); if .istat neq ss$_normal then $exit(code = reread_astset); return end; routine length (string_addr) = begin !++ ! ! This routine returns the length of a string in a buffer...There must ! be at least one blank at the end of the string, or it will crap out ! badly (infinite loop style). ! !-- bind string = .string_addr : vector[,byte]; local i : signed; i = -1; while 1 do if .string[i=.i+1] eql %c' ' then return .i; 0 end; global routine cancel_io : novalue = begin !++ ! ! This routine cancels outstanding I/O on the mailbox channel. ! !-- local istat; istat = $cancel( !cancel I/O on the channel chan=.mbox_chan !channel number ); if .istat neq ss$_normal then $exit(code=reread_canerr); return end; end eludom