Trailing-Edge
-
PDP-10 Archives
-
RMS-10_T10_704_FT2_880425
-
10,7/rms10/rmssrc/rmsosb.b36
There are 6 other files named rmsosb.b36 in the archive. Click here to see a list.
MODULE OSCALL =
BEGIN
GLOBAL BIND OSCV = 1^24 + 0^18 + 2; !EDIT DATE: 20-DEC-79
%([
FUNCT: THIS MODULE CONTAINS ALL OPERATING-SYSTEM CALLS EXCEPT
FOR THOSE MODULES WHOSE OVERALL FLOW IS MONITOR-DEPENDENT,
NAMELY RMSOPN AND MORE?.
AUTHOR: S. COHEN, A. UDDIN
THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!COPYRIGHT (C) 1979, 1980 BY DIGITAL EQUIPMENT CORPORATION
********** TABLE OF CONTENTS **************
ROUTINE FUNCTION
======= ========
ABORTFILE ABORTIVELY CLOSES FILE
ADJEOF ADJUST EOF PTR OF FILE
ASCREAD READ STREAM OF BYTES FROM SPEC FILE
ASCWRITE WRITE STREAM OF BYTES TO SPEC FILE
CLOSEFILE CLOSE THE FILE
CREPAGE CREATES A PAGE ON THE TOPS-10(PAGE. UUO)
DATOFILE RETURN DATES (EG. CREATE TIME) OF FILE
DEVCHAR RETURNS DEV CHAR WORD IN TOPS-20 FMT
IOERROR MAP JSYS I/O ERROR TO RMS STATUS CODE
KILLPAGE REMOVE PAGE FROM PROCESS (DO IO ON 10)?
LOFFALL CLEAR ALL THE LOCKS
NEXTPAGE RETS NEXT EXISTING P# IN FILE (IF NONE RETS -1)
PAGEXIST RETS TRUE IF SPECIFIED PAGE EXISTS
PAGIN READS ONE OR MORE PAGES INTO MEMORY
PAGOUT WRITES PAGES TO DISK
POSASCFIL SET THE CURRENT LOC OF FILE TO BEGIN OR END
READTTY READ STREAM OF ASCII BYTES FROM TTY
SIZEFILE RETURNS # OF BYTES IN SPECIFIED FILE
TRUNCFILE DELETE TRAILING PAGES FROM A FILE
*************************************************
* *
* NEW REVISION HISTORY *
* *
*************************************************
****************** Start RMS-10 V1.1 *********************
********************* TOPS-10 ONLY ***********************
PRODUCT MODULE SPR
EDIT EDIT QAR DESCRIPTION
====== ====== ===== ===========
107 2 10-32354 (RMT, 12/2/85) PAGOUT code for TOPS-10 is
wrong. Always output whole page. V3 edit
64.
112 3 Dev (WXD, 3/28/86) When paging in a file, clear
all pages rather than just a single page.
***** END OF REVISION HISTORY *****
])%
%([ FORWARD DECLARATIONS ])%
FORWARD ROUTINE
ABORTFILE: NOVALUE,
ADJEOF: NOVALUE,
CLOSEFILE: NOVALUE,
crepAGE: NOVALUE,
DATOFILE: NOVALUE,
DEVCHAR,
IOERROR: NOVALUE,
KILLPAGE: NOVALUE,
LOFFALL: NOVALUE,
NEXTPAGE,
PAGEXIST,
PAGIN: NOVALUE,
PAGOUT: NOVALUE,
POSASCFIL: NOVALUE,
READTTY,
SIZEFILE,
TRUNCFILE: NOVALUE;
%([ MODULE-LEVEL DECLARATIONS ])%
REQUIRE 'RMSREQ';
REQUIRE 'RMSOSD'; !THIS MODULE IS OS-DEPENDENT
EXTDECLARATIONS;
! ABORTFILE
! ======
! CLOSES A FILE ABORTIVELY
! INPUT: 1. VALUE OF JFN.
! 2. ADDR OF USER'S FAB.
! OUTPUT: NONE
GLOBAL ROUTINE ABORTFILE ( FILE_ID, USER_FAB ) : NOVALUE=
BEGIN
! ARGUMENT ( FILE_ID, VALUE );
! ARGUMENT ( USER_FAB, POINTER );
MAP USER_FAB: POINTER;
REGS;
TRACE ( 'ABORTFILE' );
%IF TOPS10
%THEN
!DO NOT SUPPORT USER JFN ON 10
AC1 = .FILE_ID; !GET FILE TO CLOSE
DO_UUO( RESDV$(AC1));
%FI
%IF TOPS20
%THEN
AC1 = .FILE_ID OR CZ_ABT; ! SET ABORT BIT FOR CLOSF JSYS
IF .USER_FAB [ FABJFN ] ISNT ZERO ! HE GAVE US A JFN
THEN
AC1 = .AC1 OR CO_NRJ; ! DON'T RELEASE JFN
IF JSYS (-1, CLOSF, AC1) IS FALSE !CLOSE THE FILE
THEN BEGIN !OOPS
IF .AC1 ISNT ADDR(CLSX1) !ONLY GTJFN DONE?
THEN RETURN; !NO, BUT IGN ERR SO AS
!NOT TO HIDE ORIG ERR
AC1 = .FILE_ID; !GET JFN AGAIN
JSYS (-1, RLJFN, AC1); !RELEASE JFN
END;
%FI
RETURN;
END; %( OF ABORTFILE ROUTINE )%
! ADJEOF
! ======
!
! ROUTINE TO ADJUST THE FILE'S EOF POINTER IN THE FILE DESCRIPTOR BLOCK (FDB)
! THIS ROUTINE IS CALLED ONLY IF WE HAVE WRITTEN INTO THE FILE
! WITH THE CURRENT STREAM, OR IF THERE WAS A $TRUNCATE DONE ON
! THE STREAM. THIS ROUTINE MUST CHECK THE FILE EOF POINTER IN
! THE FDB AND DETERMINE IF OUR NEW EOF IS GREATER THAN THE
! OLD ONE. IF SO, THE FDB EOF IS CHANGED; IF NOT, NO ACTION
! IS PERFORMED.
!
! INPUT:
! FILE_ID = FILE ID
! OUR_EOFBYTE = THE EOF BYTE THAT WE HAVE WRITTEN INTO
! TRUNC_FLAG = FLAG TO INDICATE IF TRUNCATE WAS DONE
! OUTPUT:
! <NO STATUS RETURNED>
!
! NOTES:
!
! 1. THERE IS CURRENTLY NO SYNCHRONIZATION ON THE OPERATION
! OF UPDATING THE FILE'S EOF POINTER. THUS, BETWEEN THE
! TIME THAT WE CHECK THE FDB VALUE AND THEN WE CHANGE IT,
! SOMEONE ELSE COULD SLIP IN AND CHANGE IT ALSO. HOWEVER,
! THIS IS NOT REALLY A PROBLEM SINCE THE EOF WILL BECOME
! CORRECT AGAIN AS SOON AS SOMEONE WRITES INTO THE FILE.
! ALSO, THE QUEUEING OVERHEAD OF THE LOCK TO ACHIEVE
! MUTUAL EXCLUSION IS EXCESSIVE AND IS NOT DEEMED SUFFICIENT.
!
GLOBAL ROUTINE ADJEOF ( FILE_ID, OUR_EOFBYTE, TRUNC_FLAG ): NOVALUE =
BEGIN
! ARGUMENT ( FILE_ID, VALUE );
! ARGUMENT ( OUR_EOFBYTE, VALUE );
! ARGUMENT ( TRUNC_FLAG, VALUE );
LOCAL
EOFBYTE; ! THE REAL EOF BYTE IN THE FDB
REGS;
TRACE ('ADJEOF');
%IF TOPS10
%THEN
!ON THE 10, THE MONITOR MAINTAINS COMPLETE CONTROL OF EOF
!SO THIS ROUTINE JUST RETURNS ON 10
%FI
%IF TOPS20
%THEN
%([ READ THE FILE FDB EOF POINTER ])%
AC1 = .FILE_ID; ! SET UP ACS FOR GTFDB
AC2 = 1 ^ 18 OR $FBSIZ; ! ONE WORD TO READ, NAMELY EOF
AC3 = ADDR (EOFBYTE); ! PLACE TO READ IT INTO
DO_JSYS ( GTFDB );
%([ SHOULD WE UPDATE IT? ])%
IF ( .OUR_EOFBYTE GTR .EOFBYTE )
OR
( .TRUNC_FLAG ISON ) THEN ! OR IF WE DID A $TRUNCATE
BEGIN
AC1 = .FILE_ID OR CF_NUD; ! FILE ID AND NO UPDATE
AC1 < 18, 9 > = $FBSIZ ; ! DISPLACEMENT IN FDB
AC2 = ALLONES; ! MASK
AC3 = .OUR_EOFBYTE; ! NEW VALUE
DO_JSYS ( CHFDB )
END;
%FI
%([ TELL US ABOUT IT ])%
LOOKAT ( ' HYBYTE = ', OUREOFBYTE );
LOOKAT ( ' EOF # = ', EOFBYTE );
RETURN
END; %(OF ADJEOF)%
! ASCREAD
! =======
! READ IN BUCKET ENCOMPASSED BY SPECIFIED BYTE IN FILE
! INPUT: 1. FILE ID
! 2. NUMBER OF BKT WE WANT TO READ
! 3. ADDRESS OF BUFFER TO READ INTO
! 4. LENGTH OF BUFFER IN CHARS
! OUTPUT: 1. COUNT OF CHARS READ
!
! NOTES: 1. ASSUMES THAT A FILE IS ALWAYS READ WITH SAME SIZE BUFFER
!
!
GLOBAL ROUTINE ASCREAD ( FILE_ID, BKT_TO_USE, BUF_PTR, CH_IN_BUF ) :=
BEGIN
LOCAL
TEMP;
LOCAL
W_IN_BUF, !WORDS IN A BUFFER
COUNT, !# OF WORDS TO READ
FOPBLK: VECTOR[2], !FILOP BLK FOR NON-FILE-MGT TASKS
IOWDLST: VECTOR[2]; !HOW MUCH, WHERE TO DO I/O IN FILE
EXTERNAL
ACC$1, ! GLOBALS USED TO STORE JSYS AC'S
ACC$2,
ACC$3;
REGS;
TRACE ( 'ASCREAD' );
W_IN_BUF = (.CH_IN_BUF+4)/5; !GET BUFF SIZE IN WORDS
IF .BKT_TO_USE NEQ .FST [FSTSEQBKT] !POSIT TO RIGHT PLACE?
THEN BEGIN !NO
%IF TOPS10
%THEN
COUNT = .W_IN_BUF/128; !BLKS/BKT=WDS/BKT / WDS/BLK
FOPBLK[0] = .FILE_ID^18 OR $FOUSI; !FILE AND FUNCTION
FOPBLK[1] = (.COUNT*.BKT_TO_USE) + 1; !CONV BKT# TO BLK# (1ST BLK=1)
AC1=2^18 OR FOPBLK; !PTR TO ARGLST
IF NOT UUO(1, FILOP$(AC1))
THEN
BEGIN
$CALL ( IOERROR, .FILE_ID ); !IF RETS, THEN JUST EOF
RETURN 0; !ENTIRE PAGE BEYOND EOF
END;
END; !END BKT NEW SEQBKT
FOPBLK[0] = .FILE_ID^18 OR $FOINP; !RESET OPERATION CODE
FOPBLK[1] = IOWDLST; !STORE PTR TO IOWD LIST
IOWDLST[0] = (-.W_IN_BUF)^18 !# OF WORDS TO READ
OR .BUF_PTR-1; !PICKUP ADDR OF BLK
IOWDLST[1] = 0; !TERM I/O CMDS
AC1=2^18 OR FOPBLK; !RE-INIT ARG PTR
IF NOT UUO(1, FILOP$(AC1))
THEN
BEGIN
FST [FSTSEQBKT] = -1; !AFT ERR, TREAT FIL POS AS UNDEF
$CALL ( IOERROR, .FILE_ID ); !IF RETS, THEN JUST EOF
RETURN ($CALL (SIZEFILE,.FILE_ID) MOD .CH_IN_BUF);
!SET CHARS IN BUF BY BRUTE FORCE
END;
IF .SIZEOFFILE LSS .W_IN_BUF*(.BKT_TO_USE + 1)
THEN
BEGIN
FST [FSTSEQBKT] = -1; ! AFT EOF,TREAT FIL POS AS UNDEFINED
RETURN ($CALL (SIZEFILE,.FILE_ID) MOD .CH_IN_BUF);
! SET CHARS BY BRUTE FORCE
END
ELSE
TEMP = .CH_IN_BUF;
%FI
%IF TOPS20
%THEN
TEMP = .BKT_TO_USE * .CBD[BKDBKTSIZE] * CH_IN_P; !POS OF 1ST BYTE IN BKT
IF SEQUENCED
THEN
TEMP = (.TEMP+4)/5;
IF NOT TTY
THEN
BEGIN
AC1 = .FILE_ID; ! JFN OF THE FILE
AC2=.TEMP;
DO_JSYS ( SFPTR );
END;
END; !END BKT POS OPTIM
IF SEQUENCED
THEN
BEGIN
TEMP = POINT (.BUF_PTR, 36, 36 );
AC3 = -( .CH_IN_BUF + 4 ) / 5
END %( OF SETUP SOUT STUFF FOR LSA FILE )%
ELSE
BEGIN
TEMP = POINT (.BUF_PTR, 36, 7);
AC3 = -.CH_IN_BUF;
END; %(OF ASCII STREAM )%
AC1 = .FILE_ID; ! SET UP ACS FOR SIN
AC2 = .TEMP; !GET BYTE PTR
AC4 = 0;
IF NOT JSYS ( -1, SIN, AC1, AC2, AC3, AC4 ) THEN
BEGIN
ACC$1 = .AC1; ! SAVE JSYS REGISTERS
ACC$2 = .AC2;
ACC$3 = .AC3;
$CALL ( IOERROR, .FILE_ID ) ! PROCESS JSYS ERROR
END
ELSE
ACC$3 = .AC3; ! NO OF BYTES TO READ
IF SEQUENCED
THEN TEMP = -.ACC$3 * ASCIIBYTPERWORD ! CONVERT WORDS TO CHARACTERS FOR LSA FILE
ELSE TEMP = -.ACC$3; ! GET CHARS READ FOR ASCII FILE
TEMP = .CH_IN_BUF - .TEMP; !CHARS READ = MAX - RESIDUE
%FI
CURRENTFILEPAGE = .BKT_TO_USE*ASCIIBKTSIZE; !KEEP TRACK OF CURR P
FST [FSTSEQBKT] = .CURRENTFILEPAGE + ASCIIBKTSIZE; !NOW AFTER IT
RETURN .TEMP
END; %( OF ASCREAD ROUTINE )%
! ASCWRITE
! =========
! WRITE A STREAM OF BYTES TO THE SPECIFIED FILE
! INPUT: 1. FILE ID
! 2. NUMBER OF BKT WE WANT TO WRITE
! 3. POINTER TO BUFF TO OUTPUT IN CALLERS ADDRESS SPACE
! 3. LENGTH OF STRING TO OUTPUT
! OUTPUT: <NONE>
!
!
!
!
GLOBAL ROUTINE ASCWRITE ( FILE_ID, BKT_TO_USE, BUF_PTR, CH_IN_BUF ) :NOVALUE=
BEGIN
EXTERNAL
ACC$1, ! GLOBALS USED TO STORE JSYS AC'S
ACC$2,
ACC$3;
LOCAL
N, !NUM OF BITS OF CRUFT
LW, !PTR TO LAST PARTIAL WD IN BUF
TEMP;
LOCAL
COUNT, !# OF WORDS TO WRITE
W_IN_BUF, !DATA WORDS IN THIS BUFFER
FOPBLK: VECTOR[2], !FILOP BLK FOR NON-FILE-MGT TASKS
IOWDLST: VECTOR[2]; !HOW MUCH, WHERE TO DO I/O IN FILE
REGS;
TRACE ( 'ASCWRITE' );
%IF TOPS10
%THEN
IF TTY !DO HACK FOR TTY OUTPUT
THEN BEGIN !HERE WE GO
$CALLM (TTYHACK, .BUF_PTR, .CH_IN_BUF);
!DO ACTU OUTSTR
RETURN;
END;
%FI !TOPS10 TTY HACK
W_IN_BUF = (.CH_IN_BUF+4)/5; !GET WORDS OF DATA
IF .BKT_TO_USE NEQ .FST [FSTSEQBKT] !POSIT TO RIGHT PLACE?
THEN BEGIN !NO
%IF TOPS10
%THEN
COUNT = ASCIIBKTSIZE * 4; !BLKS/BKT =P/BKT * BLK/P
FOPBLK[0] = .FILE_ID^18 OR $FOUSO; !FILE AND FUNCTION
FOPBLK[1] = (.COUNT*.BKT_TO_USE) + 1; !CONV BKT# TO BLK# (1ST BLK=1)
AC1=2^18 OR FOPBLK; !PTR TO ARGLST
DO_FILOP; !POSITION THE FILE
END; !END BKT NEW SEQBKT
N = .CH_IN_BUF MOD 5; !0 OR NUM CHARS IN PART USED WD
IF .N NEQ 0 !WORD-ALIGNED?
THEN BEGIN
LW = .BUF_PTR+.W_IN_BUF-1; !SETUP PTR TO LAST PARTIAL WD
N = 36 - .N*7; !PREP TO ELIM CRUFT IN LAST WD
.LW = (..LW^-.N)^.N; !SHIFT CRUFT OUT AND 0'S BK IN
END;
FOPBLK[0] = .FILE_ID^18 OR $FOOUT; !RESET OPERATION CODE
FOPBLK[1] = IOWDLST; !STORE PTR TO IOWD LIST
IOWDLST[0] = (-.W_IN_BUF)^18 !# OF WORDS TO READ
OR .BUF_PTR-1; !PICKUP ADDR OF BLK
IOWDLST[1] = 0; !TERM I/O CMDS
AC1=2^18 OR FOPBLK; !RE-INIT ARG PTR
DO_FILOP; !READ THE PAGE(S)
IF .BKT_TO_USE*.COUNT + .W_IN_BUF GTR .SIZEOFFILE !EXTENDING?
THEN SIZEOFFILE = .BKT_TO_USE*.COUNT + .W_IN_BUF; !YES
%FI
%IF TOPS20
%THEN
TEMP = .BKT_TO_USE * .CBD[BKDBKTSIZE] * CH_IN_P; !POS OF 1ST BYTE IN BKT
IF SEQUENCED
THEN
TEMP = (.TEMP+4)/5;
IF NOT TTY
THEN
BEGIN
AC1 = .FILE_ID; ! JFN OF THE FILE
AC2=.TEMP;
DO_JSYS ( SFPTR );
END;
END; !END BKT POS OPTIM
IF SEQUENCED
THEN BEGIN
TEMP = POINT (.BUF_PTR, 36, 36 );
AC3 = -( .CH_IN_BUF + 4 ) / 5
END %( OF SETUP SOUT STUFF FOR LSA FILE )%
ELSE BEGIN
TEMP = POINT (.BUF_PTR, 36, 7);
AC3 = -.CH_IN_BUF;
END; %(OF ASCII STREAM )%
AC1 = .FILE_ID; ! SET UP ACS FOR SOUT
AC2 = .TEMP; !BYTE PTR
AC4 = ZERO;
IF NOT JSYS ( -1, SOUT, AC1, AC2, AC3, AC4 ) THEN
BEGIN
ACC$1 = .AC1; ! SAVE JSYS REGISTERS
ACC$2 = .AC2;
ACC$3 = .AC3;
$CALL ( IOERROR, .FILE_ID )
END;
%FI
CURRENTFILEPAGE = .BKT_TO_USE*ASCIIBKTSIZE; !KEEP TRACK OF CURR P
FST [FSTSEQBKT] = .CURRENTFILEPAGE + ASCIIBKTSIZE; !NOW AFTER IT
RETURN
END; %( OF ASCWRITE ROUTINE )%
! CLOSEFILE
! =========
! CLOSES A FILE
! INPUT: 1. FILE ID OF THE FILE TO BE CLOSED (JFN ON 20)
! 2. POINTER TO USER'S FAB.
! OUTPUT: 1. TRUE IF MON SUCCEEDED, ELSE ERROR CODE
GLOBAL ROUTINE CLOSEFILE( FILE_ID, USER_FAB) : NOVALUE=
BEGIN
! ARGUMENT ( FILE_ID, VALUE);
! ARGUMENT ( USER_FAB, POINTER);
MAP USER_FAB: POINTER;
LOCAL
TEMP;
REGS;
TRACE ( 'CLOSEFILE' );
%IF TOPS10
%THEN
!USER SUPPLIED JFN NOT SUPPORTED ON 10
TEMP = .FILE_ID^18 OR $FOREL; !RELEASE FILE
AC1 = 1^18 OR TEMP; !ARGPTR
DO_FILOP; !DO THE WORK
%FI
%IF TOPS20
%THEN
%([ WE WILL SET UP THE FLAGS AND THE JFN FOR THE CLOSF JSYS.
THEN, WE WILL CHECK TO SEE IF THE USER WANTS US TO KEEP
HIS JFN FOR HIM WHEN WE CLOSE THE FILE. ])%
TEMP = .FILE_ID OR CZ_NUD OR CO_NRJ; ! SET UP ARG TO CLOSF JSYS
IF .USER_FAB [FABJFN] IS ZERO
THEN ! HE DIDNT WANT TO SAVE THE JFN
CLRFLAG ( TEMP, CO_NRJ );
%([ CLOSE THE FILE ])%
AC1 = .TEMP;
DO_JSYS ( CLOSF );
%FI
RETURN;
END; %( OF CLOSEFILE ROUTINE )%
! CREPAGE
!============
! CREATES A PAGE ON THE TOPS-10. A NO-OP ON THE -20.
!
! INPUT: 1. PAGE NO.OF THE FIRST PAGE OF THE BLOCK TO BE CREATED
! 2. NO OF PAGES IN THE BLOCK
!
!
! OUTPUT: <NONE>
!
!
GLOBAL ROUTINE crepAGE ( PAGE_NUM, PAGES ): NOVALUE=
BEGIN
!
! ARGUMENT ( PAGE_NUM, VALUE);
! ARGUMENT ( PAGES, VALUE );
REGS;
LOCAL
ARG: VECTOR[2]; ! ARGUMENT BLOCK FOR PAGE$ UUO
TRACE ( 'CREPAGE' );
%IF TOPS10
%THEN
ARG[0] = 1; ! ARG=(NO OF ARGS -1)
INCR I FROM .PAGE_NUM TO .PAGE_NUM + .PAGES -1
DO
BEGIN
ARG[1] = .I; ! CREATE FUNC AND PAGE NO.
AC1 = $PAGCD ^ 18 OR ARG; !SET UP AC1
DO_UUO ( PAGE$(AC1));
END;
%FI
%IF TOPS20
%THEN
!WHEREAS THE 10 REQS AN EXPLIC OS CALL TO CRE A PROCESS PAGE,
!THE 20 DOES IT AUTOMATICALLY WHEN YOU ACCESS A WORD IN THE PAGE
%FI
RETURN
END; %( OF crepAGE ROUTINE )%
! DATOFILE
! =========
! RETURNS DATES AND TIMES ASSOCIATED WITH THE SPECIFIED FILE.
! INPUT: 1. FILE ID OF THE FILE IN FST.
! 2. POINTER TO A BLOCK THAT WILL CONTAIN DATES
! 3. SIZE OF THE BLOCK
!
!
!
! OUTPUT: INDIRECTLY, DATES AND TIMES IN THE BLOCK
!
!
!
!
!
GLOBAL ROUTINE DATOFILE ( FST_JFN, DATE_BLK, DATE_BLK_SIZ ) :NOVALUE=
BEGIN
! ARGUMENT ( FST_JFN, VALUE);
! ARGUMENT ( DATE_BLK, BASEADD);
! ARGUMENT ( DATE_BLK_SIZ, VALUE);
MAP DATE_BLK: POINTER;
REGS; ! DECLARE ALL REGISTERS FOR USE BY MON CALLS
TRACE ( 'DATOFILE' );
%IF TOPS10
%THEN
%([** RETURN DATES WHICH WERE SAVED PREVIOUSLY FROM THE LOOKUP BLOCK **])%
DATE_BLK [ 0,wrd ] = DATELASTACC;
DATE_BLK [ 1,wrd ] = CREATIME;
%FI
%IF TOPS20
%THEN
%([ SET UP AC'S FOR RFTAD JSYS ])%
AC1 = .FST_JFN; ! FILE_ID
AC2 = .DATE_BLK; ! ADDR OF DATE BLOCK
AC3 = .DATE_BLK_SIZ; ! AND ITS SIZE
DO_JSYS ( RFTAD ); ! ON RETURN DATE_BLK WILL HAVE DATES AND TIMES
%FI
RETURN
END; %( OF DATOFILE ROUTINE )%
! DEVCHAR
! =========
! RETURNS DEVCHAR FLAGS IN 20 FORMAT
! INPUT: 1. JFN OF THE DESIRED DEVICE
!
! OUTPUT: THE 20-FORMAT FLAG WORD
!
GLOBAL ROUTINE DEVCHAR (FILID) =
BEGIN
ARGUMENT ( FILID, VALUE);
REGS; ! DECLARE ALL REGISTERS FOR USE BY MON CALLS
TRACE ( 'DEVCHAR' );
%IF TOPS10
%THEN
AC1 = .FILID; !PICKUP 6BIT DEV NAME
UUO(0,DEVCHR(AC1)); !DO THE UUO
AC2 = 1^18; !DEFAULT VALUE (ILLEGAL DEV)
IF CHKFLAG(AC1,DV$DSK) ISON THEN AC2<18,9>=DVDSK;
IF CHKFLAG(AC1,DV$MTA) ISON THEN AC2<18,9>=DVMTA;
IF CHKFLAG(AC1,DV$TTY) ISON THEN AC2<18,9>=DVTTY;
IF CHKFLAG(AC1,DV$IN) ISON THEN SETFLAG(AC2,DVIN);
IF CHKFLAG(AC1,DV$OUT) ISON THEN SETFLAG(AC2,DVOUT);
IF CHKFLAG(AC1,DV$DIR) ISON THEN SETFLAG(AC2,DVDIR);
IF CHKFLAG(AC1,DV$ASC) ISON THEN SETFLAG(AC2,DEVASN);
RETURN .AC2;
%FI
%IF TOPS20
%THEN
AC1 = .FILID; !IDENT FILE
AC2 = ZERO;
DO_JSYS ( DVCHR );
RETURN .AC2; !RET DEVICE FLAGS
%FI
END; %( OF DATOFILE ROUTINE )%
! IOERROR
! =========
!
! THIS ROUTINE PROCESSES AN ERROR RETURN FROM EITHER THE SIN JSYS
! OR THE SOUT JSYS. EACH MONITOR ERROR CODE IS MAPPED INTO
! A CORRESPONDING RMS-20 ERROR CODE. THE MAPPING IS AS FOLLOWS:
!
! MONITOR CODE MEANING RMS-20 CODE
! ============ ======= ===========
!
! IOX4 EOF <NO MAPPING DONE>
! IOX5 DATA ERROR ER$RER, ER$WER
! ALL OTHERS INTERNAL BUG ER$BUG
!
!
! INPUT:
! 1. JFN OF FILE THAT HAD IO ERROR
!
! OUTPUT:
! <NONE>
! NOTES:
!
! 1. THE STV FIELD WILL ALWAYS BE SET TO BE THE MONITOR CODE
! RETURNED.
!
! 2. THIS ROUTINE EXITS TO THE USER UNLESS THE ERROR WAS ER$EOF
!
GLOBAL ROUTINE IOERROR (FILE_ID): NOVALUE =
BEGIN
LOCAL
FOPARG: VECTOR[2],
TEMP;
REGS;
TRACE ( 'IOERROR ' );
%IF TOPS10
%THEN
FOPARG[0] = .FILE_ID^18 OR $FOGET; !GET STS
AC1 = 1^18 OR FOPARG; !ARG PTR
DO_FILOP; !RET STATUS
TEMP = .AC1; !PRESERVE STATUS BEF CLEAR IT
FOPARG[0] = .FILE_ID^18 OR $FOSET;
FOPARG[1] = $IODMP; !JUST LEAVE IO MODE
AC1 = 2^18 OR FOPARG; !SETUP TO DO SETSTS
DO_FILOP; !DO IT
IF CHKFLAG(TEMP,IO$EOF) ISON
THEN RETURN; !JUST EOF
USRSTV = .TEMP; !RET STATUS TO USER
IF CHKFLAG(TEMP,IO$DER OR IO$DTE) ISON !DATA ERROR?
%FI
%IF TOPS20
%THEN
AC1 = $FHSLF; ! PROCESS ID
AC2 = 0;
DO_JSYS ( GETER ); ! GET THE LAST ERROR CODE
TEMP = .AC2;
%([ IS THIS AN EOF? IF SO, WE CAN IGNORE IT BECAUSE THE
USER PROBABLY WON'T SEE AN EOF UNTIL HE READS ALL THE
RECORDS IN THE CURRENT BUFFER. ])%
IF .TEMP<RH> IS ADDR (IOX4) ! SUPPRESS BYTE POINTER
THEN RETURN; ! RETURN ON EOF
USRSTV = .TEMP<RH>; ! SAVE CODE IN STV
IF .USRSTV IS ADDR (IOX5 )
%FI
!COMMON 10/20 CODE
THEN %(IT'S A DATA ERROR)%
BEGIN
USRSTS = ER$RER; ! ASSUME READ ERROR
IF CURRENTJSYS IS C$PUT THEN USRSTS = ER$WER
END %(OF IF DATA ERROR)%
ELSE BEGIN
USRSTS = ER$BUG; ! SHOW IT'S A BUG
IF $CALL (PRICHK, .USRSTV) !DISPLAYING INT ERRS?
THEN TXTOUT (RM$IOM, .USRSTV); !YES, STREAM I/O ERR
END;
USEXITERR !DO FAILURE RET TO USER
END; %( OF IOERROR )%
! KILLPAGE
! =======
! UNMAPS (KILLS) A FILE'S PAGES IN A PROCESS.
! INPUT: 1. PAGE NUMBER OF THE FIRST PAGE OF THE BLOCK TO BE KILLED
! 2. NO. OF PAGES TO BE UNMAPPED
! OUTPUT: <NONE>
!
!
!
!
GLOBAL ROUTINE KILLPAGE( PAGE_NUM, PAGES ) :NOVALUE=
BEGIN
! ARGUMENT ( PAGE_NUM, VALUE );
! ARGUMENT ( PAGES, VALUE );
REGS;
LOCAL
ARG: VECTOR[2]; !ARGUMENT BLOCK FOR PAGE$ UUO
TRACE ( 'KILLPAGE' );
%IF TOPS10
%THEN
ARG[0] = 1; ! ARG1 = (NO OF ARGS-1)
INCR I FROM .PAGE_NUM TO .PAGE_NUM+.PAGES-1
DO
BEGIN !KILL 1 PAGE AT A TIME
ARG[1] = BITN(0) OR .I; !IDENT CURR PAGE
AC1 = $PAGCD^18 OR ARG; !ARGBLK PTR
DO_UUO (PAGE$(AC1));
END;
%FI
%IF TOPS20
%THEN %( SET UP AC'S FOR PMAP JSYS )%
AC1 = -1; ! KILL PAGE
AC2 = ($FHSLF ^ 18 OR .PAGE_NUM); ! PROCESS HANDLE & PAGE NO.
AC3 = (BITN ( 0 ) OR .PAGES); ! PAGES TO KILL
DO_JSYS ( PMAP );
%FI
RETURN
END; %( OF KILLPAGE ROUTINE )%
! LOFFALL
! =======
! TURNS OFF ALL LOCKS ON RECORDS OF A STREAM
! INPUT: 1. RESUEST ID. THIS IS THE SAME REQUEST ID USED TO LOCK THE RECORDS
! OUTPUT: <NONE>
!
!
GLOBAL ROUTINE LOFFALL ( REQUEST_ID):NOVALUE =
BEGIN
! ARGUMENT ( REQUEST_ID, POINTER );
REGS;
TRACE ( 'LOFFALL' );
%IF TOPS10
%THEN
AC1 = $DEQID ^ 18 OR .REQUEST_ID;
DO_UUO ( DEQ$(AC1));
%FI
%IF TOPS20
%THEN
AC1 = $DEQID ; !K ID
AC2 = .REQUEST_ID; ! USE STREAM ID
DO_JSYS ( DEQ );
%FI
RETURN;
END; %( OF LOFFALL ROUTINE )%
! NEXTPAGE
! ========
! RETURNS THE NEXT USED PAGE IN THE FILE. APPLIES TO 20 ONLY.
! INPUT: 1. VALUE OF JFN IN FST.
! 2. PAGE NUMBER OF PAGE TO FIND.
! OUTPUT: 1. PAGE NUMBER, IF IT EXISTS
! 2. ELSE, FALSE
!
!
!
!
GLOBAL ROUTINE NEXTPAGE ( FST_JFN, PAGE_NO ) :=
BEGIN
! ARGUMENT ( FST_JFN, VALUE );
! ARGUMENT ( PAGE_NO, VALUE );
REGS;
TRACE ( 'NEXTPAGE' );
%IF TOPS10
%THEN
RETURN FALSE !ALWAYS EOF ON 10
%FI
%IF TOPS20
%THEN
AC1 = .FST_JFN ^ 18 OR .PAGE_NO; !FILE ID AND WHERE TO START SEARCH
RETURN IF JSYS ( -1, FFUFP, AC1, AC2 ) ! DO THE SEARCH
THEN
.AC2 ! RETURN PAGE # FOUND
ELSE
FALSE ! RETURN FALSE FOR EOF
%FI
END; %( OF NEXTPAGE ROUTINE )%
! PAGEXIST
! ========
! CHECKS TO SEE WHETHER A PARTICULAR PAGE OF A FILE EXISTS.
! INPUT: 1. FILE ID
! 2. PAGE NO. TO CHECK
! OUTPUT: 1. TRUE IF THE PAGE EXISTS.
! 2. FALSE OTHERWISE
!
!
!
!
GLOBAL ROUTINE PAGEXIST ( FILE_ID, P_TO_CHK ) :=
BEGIN
! ARGUMENT ( FILE_ID, VALUE );
! ARGUMENT ( P_TO_CHK, VALUE);
LOCAL
ARG; ! ARGUMENT BLOCK FOR DISK$
REGS;
TRACE ( 'PAGEXIST' );
%IF TOPS10
%THEN
ARG = .FILE_ID;
AC1 = $DULEN ^ 18 OR ARG; ! FUNC CODE & CHANNEL NO
DO_UUO ( DISK$(AC1) ); ! UUO RETURNS IN AC1 LAST BLOCK OF FILE
RETURN IF .AC1 GTR (.P_TO_CHK * 4)
THEN
TRUE !AT LEAST 1 BLK OF PAGE EXISTS
ELSE
FALSE
%FI
%IF TOPS20
%THEN
AC1 = .FILE_ID ^ 18 OR .P_TO_CHK; ! JFN OF FILE ,, PAGE NO.
AC2 = 0;
DO_JSYS ( RPACS);
RETURN IF ( CHKFLAG (AC2, PA_PEX) IS OFF)
THEN
FALSE
ELSE
TRUE
%FI
END; %( OF PAGEXIST ROUTINE )%
! PAGIN
! =====
! READ ONE OR MORE CONSECUTIVE PAGES INTO MEMORY
! DOES "IN" ON 10 AND "PMAP" ON 20
! INPUT:
! FILE TO READ (JFN OR CHANNEL)
! PAGE IN FILE TO READ (0 IS 1ST PAGE)
! WHERE TO PUT IT (PAGE NUMBER)
! LEVEL OF ACCESS TO PAGE
! NUMBER OF PAGES (=512 WORDS) TO READ
! OUTPUT: (IMPLICITLY)
! DATA IN MEMORY PAGE(S)
GLOBAL ROUTINE PAGIN (FILID, FILPAGE, MEMPAGE, PAGACC, COUNT):NOVALUE =
BEGIN
! ARGUMENT (FILID,VALUE);
! ARGUMENT (FILPAGE,VALUE);
! ARGUMENT (MEMPAGE,VALUE);
! ARGUMENT (PAGACC,VALUE);
! ARGUMENT (COUNT,VALUE);
LOCAL
FOPBLK: VECTOR[2], !FILOP BLK FOR NON-FILE-MGT TASKS
IOWDLST: VECTOR[2]; !HOW MUCH, WHERE TO DO I/O IN FILE
REGS;
TRACE ( 'PAGIN' );
%IF TOPS10
%THEN
FOPBLK[0] = .FILID^18 OR $FOUSI; !FILE AND FUNCTION
FOPBLK[1] = (.FILPAGE)*4 + 1; !CONV BYTE PTR TO BLK#
AC1=2^18 OR FOPBLK; !PTR TO ARGLST
IF NOT UUO(1, FILOP$(AC1)) !POSIT THE FILE
THEN BEGIN !ENTIRE PAGE BEYOND EOF
$CALL ( IOERROR, .FILID ); !IF RETS, THEN JUST EOF
CLEAR ( .MEMPAGE ^ P2W, .COUNT*512 ); !PUT CANON VALS IN BUFF
RETURN;
END;
IF .FILPAGE GEQ .SIZEOFFILE^W2P !STUPID 10 DOES NOT 0 BUFFER
THEN CLEAR (.MEMPAGE^P2W, .COUNT*512); !PAST LAST USED BLK IN PAGE
FOPBLK[0] = .FILID^18 OR $FOINP; !RESET OPERATION CODE
FOPBLK[1] = IOWDLST; !STORE PTR TO IOWD LIST
IOWDLST[0] = (-.COUNT*PAGESIZE)^18 !# OF WORDS TO READ
OR ((.MEMPAGE^P2W) - 1); !CONVERT P# TO ADDRESS
IOWDLST[1] = 0; !TERM I/O CMDS
AC1=2^18 OR FOPBLK; !RE-INIT ARG PTR
IF NOT UUO(1, FILOP$(AC1)) !READ PAGE
THEN BEGIN !ERR, PROB PARTIAL READ PAST EOF
$CALL(IOERROR, .FILID); !IF RETS, THEN JUST EOF
END;
%FI
%IF TOPS20
%THEN
AC2=$FHSLF^18 OR .MEMPAGE; !FORK & MEM PAGE #
IF (.PAGACC AND AXWRT ) IS ZERO %(IF INPUT MODE )%
THEN
AC3 = PM_RD OR PM_PLD ! READ ACCESS & PRELOAD
ELSE
AC3 = PM_RD OR PM_WR OR PM_PLD; ! ELSE WRITE ACCESS ALSO
AC3 = .AC3 OR .COUNT OR BITN(0); !ACCESS BITS & NUM OF P TO READ
AC1 = .FILID ^ 18 OR .FILPAGE; ! JFN & PAGE #
DO_JSYS(PMAP);
$CALLM (OKCREATE, .MEMPAGE^P2W, .FILPAGE);
!PREV ILL MEM READ
%FI
RETURN
END; %( OF PAGIN ROUTINE )%
! PAGOUT
! ======
!
! UPDATE PAGES OF THE SPECIFIED FILE.
! INPUT:
! -----
! 1. FILE ID
! 2. PAGE NUMBER IN FILE TO BE UPDATED.
! 3. [10 ONLY] THE CORRESPONDING PAGE NO. IN CORE, -1 IMPLIES JUST UPD RIB
! 4. COUNT OF PAGES TO UPDATED
! OUTPUT:
! ------
! <NONE>
!
!
GLOBAL ROUTINE PAGOUT (FILID, FILPAGE, MEMPAGE, COUNT):NOVALUE =
BEGIN
! ARGUMENT (FILID,VALUE);
! ARGUMENT (FILPAGE,VALUE);
! ARGUMENT (MEMPAGE,VALUE);
! ARGUMENT (COUNT,VALUE);
LOCAL
SIZOUT, !# OF WORDS TO ACTU WRITE, ALWAYS BKT
!SIZE UNLESS EXTENDING FILE
FOPBLK: VECTOR[2], !FILOP BLK FOR NON-FILE-MGT TASKS
IOWDLST: VECTOR[2]; !HOW MUCH, WHERE TO DO I/O IN FILE
REGS;
TRACE ( 'PAGOUT' );
%IF TOPS10
%THEN
IF .MEMPAGE GEQ 0 !WRITING A PAGE?
THEN BEGIN !YES
FOPBLK[0] =.FILID^18 OR $FOUSO; !FILE AND FUNCTION
FOPBLK[1] = (.FILPAGE)*4 + 1; !CONV BYTE PTR TO BLK#
AC1=2^18 OR FOPBLK; !PTR TO ARGLST
DO_FILOP; !POSITION THE FILE
! IF (.FILPAGE+.COUNT)^P2W LSS .SIZEOFFILE
! !EXTENDING FILE?
! THEN SIZOUT = .COUNT*PAGESIZE !NO
! ELSE SIZOUT = .SIZEOFFILE - (.FILPAGE^P2W);
! !YES, OUTPUT AMT OF EXTEND ONLY
SIZOUT = .COUNT*PAGESIZE; ! Put out whole pages
IOWDLST[0] = (-.SIZOUT^18) !# OF WORDS TO WRITE
OR .MEMPAGE*PAGESIZE-1; !CONVERT P# TO ADDRESS
IOWDLST[1] = 0; !TERM I/O CMDS
FOPBLK[0] = .FILID^18 OR $FOOUT; !RESET OPERATION CODE
FOPBLK[1] = IOWDLST; !STORE PTR TO IOWD LIST
AC1=2^18 OR FOPBLK; !RE-INIT ARG PTR
DO_FILOP; !READ THE PAGE(S)
END;
IF (.FILPAGE+.COUNT)^P2W LSS .SIZEOFFILE
THEN RETURN; !NOT EXTENDING FILE, SO DONE
FOPBLK[0] = .FILID^18 OR $FORRC; !UPD RIB AS NECES
AC1 = 1^18 OR FOPBLK; !PT TO ARG LIST
DO_FILOP; !DO IT
%FI
%IF TOPS20
%THEN
AC1=.FILID^18 OR .FILPAGE; !JFN & PAGE #
AC2=UF_NOW OR .COUNT; !NUMBER TO PUT OUT
DO_JSYS(UFPGS); !UF_NOW MAKES IT NON-BLKING
%FI
RETURN
END; %( OF PAGOUT ROUTINE )%
! POSASCFIL
! =========
!
! DETERMINE PAGE # OF DESIRED BYTE AND READ IT IN.
! THEN SETUP BYTE PTR TO IT IN MEMORY.
! ALSO SETUP COUNT OF CHARACTERS IN BUFFER
! INPUT: 1. FILE ID
! 2. BYTE NO IN FILE TO POSITION TO
! OUTPUT: <NONE>
GLOBAL ROUTINE POSASCFIL ( FILE_ID, BYTE_NO ) :NOVALUE=
BEGIN
! ARGUMENT ( FILE_ID, VALUE );
! ARGUMENT ( BYTE_NO, VALUE );
LOCAL
BKT_TO_USE, !BKT# IN WHICH DESIRED BYTE IS
CH_PER_BKT, !# OF CHARS IN BUCKET
CC_IN_BUF, !OFFSET OF BYTE_NO(TH) CHAR IN BUFF
TEMP;
TRACE ( 'POSASCFIL' );
CH_PER_BKT = .CBD [BKDBKTSIZE] * CH_IN_P; !CALC BUFF SIZE IN CHARS
CC_IN_BUF = .BYTE_NO MOD .CH_PER_BKT; !OFFSET OF BYTE WITHIN ITS PAGE
BKT_TO_USE = .BYTE_NO / .CH_PER_BKT; !CALC BKT TO POS TO (1ST BKT=0)
TEMP = !READ BKT & RET CHARS IN IT
$CALL (ASCREAD, .FILE_ID, .BKT_TO_USE, .CURENTBUFFERADR, .CH_PER_BKT);
IF ENDOFFILE !IF SO, GETS NO LONGER POSSIB
THEN BEGIN
RST [RSTNRP] = .BKT_TO_USE; !NEXT I/O WILL BE REWRITE OF THIS BKT
RST[RSTBYTECOUNT] = .CC_IN_BUF; !INDIC FULLNESS OF BKT
END
ELSE BEGIN
RST [RSTNRP] = .BKT_TO_USE+1; !NEXT I/O WILL BE READ OF SUBS BKT
RST [RSTBYTECOUNT] = .TEMP - .CC_IN_BUF !CHARS LEFT TO READ
END;
RST [RSTPAGPTR] = CH$PTR(.CURENTBUFFERADR, .CC_IN_BUF, 7);
!PT TO DESIRED BYTE
RETURN
END; %( OF POSASCFIL ROUTINE )%
! READTTY
! =======
! ROUTINE TO READ A LINE FROM THE TTY.
! INPUT: 1. A BYTE POINTER TO AREA IN CALLERS ADDRES SPACE TO MOVE STRING
! 2. NO OF BYTES IN STRING
! OUTPUT: 1. REMAINING BYTE COUNT
!
!
!
!
GLOBAL ROUTINE READTTY ( STRING_PTR, SIZE ) :=
BEGIN
! ARGUMENT ( STRING_PTR, POINTER );
! ARGUMENT ( SIZE, VALUE );
LOCAL
TEMP1,
TEMP2;
REGS;
TRACE ( 'READTTY' );
%IF TOPS10
%THEN
ERROR(ER$DEV); !DONT SUPPORT TTY ON 10
%FI
%IF TOPS20
%THEN
AC1 = POINT (.STRING_PTR,36,7); ! GET BYTE POINTER
AC2 = RD_TOP OR .SIZE; ! BREAK SET & NO OF BYTES
AC3 = ZERO; ! NO CONTROL-R BUFFER
DO_JSYS ( RDTTY ); ! READ IT
TEMP1 = .AC1; ! UPDATED STRING POINTER
TEMP2 = .AC2<RH>; ! AND LENGTH
%([ CHECK FOR CONTROL-Z, WHICH WILL GENERATE AN EOF ])%
LDB ( AC1, TEMP1 ); ! GET THE CHARACTER
IF .AC1 IS CHARCNTZ %( TERMINATING CHARACTER ^Z? )%
THEN USRSTS = ER$EOF;
%FI
RETURN .SIZE - .TEMP2; !CHARS READ = MAX-RESIDUE
END; %( OF READTTY ROUTINE )%
! SIZEFILE
! ======
! RETURNS THE LENGTH OF AN EXISTING FILE
! INPUT: 1. FILE ID
! OUTPUT: 1. NO OF BYTES IN THE FILE:
! WORDS FOR RMS FILES
! CHARS FOR LSA AND ASCII FILES
GLOBAL ROUTINE SIZEFILE ( FILE_ID ):=
BEGIN
! ARGUMENT ( FILE_ID, VALUE );
LOCAL
TEMP;
REGS;
TRACE ( 'SIZEFILE' );
%IF TOPS10
%THEN
TEMP = .SIZEOFFILE; !GET SIZE RETR FROM LOOKUP BLK
IF ASCIIFILE THEN TEMP = .TEMP*5; !!! NOTE: *5 MEANS IMPRECISION
%FI
%IF TOPS20
%THEN
AC1 = .FILE_ID; ! JFN OF FILE
AC2 = 0; ! INITIALIZE AC2 AND AC3
AC3 = 0;
DO_JSYS ( SIZEF );
TEMP = .AC2; ! BYTE COUNT THAT REFERENCED LAST BYTE
IF SEQUENCED THEN TEMP = .TEMP*5; !ON 20, ASCII SIZ ALR IN CHARS
%FI
RETURN .TEMP
END; %( OF SIZEFILE ROUTINE )%
! TRUNCFILE
! =========
! DELETE TRAILING PAGES FROM A FILE
! INPUT: 1. FILE ID OF FILE TO BE TRUNCATED
! 2. PAGE NO OF FIRST PAGE OF A BLOCK OF PAGES TO BE KILLED
! 3. NO OF PAGES TO BE KILLED
! OUTPUT: <NONE>
GLOBAL ROUTINE TRUNCFILE ( FILE_ID, PAGE_NO, NO_OF_PAGES ) : NOVALUE=
BEGIN
! ARGUMENT ( FILE_ID, VALUE );
! ARGUMENT ( PAGE_NO, VALUE );
! ARGUMENT ( NO_OF_PAGES, VALUE );
REGS;
TRACE ( 'TRUNCFILE' );
%IF TOPS10
%THEN
!THERE IS CURRENTLY NO GOOD WAY TO DYNAMICALLY ADJUST FILE SIZE
!ON THE 10. CONSEQUENTLY, $TRUNC IS NOT SUPPORTED ON 10
ERROR ( er$iop);
%FI
%IF TOPS20
%THEN
! TRUNCATION HAS TWO ASPECTS, SETTING EOF PTR AND
! PHYSICALLY DESTROYING PAGES FOR EFFIC'S SAKE.
! UNFORTUNATELY THE 20 ONLY
!HAS FACILITY FOR DESTROYING PAGES LT 777(OCTAL)
AC2 = .FILE_ID ^ 18 OR .PAGE_NO; ! FILE ID & PAGE NO
AC3 = BITN (0) OR .NO_OF_PAGES; ! NO OF PAGES TO KILL
AC1 = -1; ! KILL PAGES
DO_JSYS ( PMAP );
%FI
RETURN
END; %( OF TRUNCFILE ROUTINE )%
END ELUDOM