Trailing-Edge
-
PDP-10 Archives
-
fortv11
-
forrms.mac
There are 7 other files named forrms.mac in the archive. Click here to see a list.
SEARCH MTHPRM,FORPRM
TV FORRMS RMS INTERFACE, 11(5023)
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1981, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
;TRANSFERRED.
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
;++
; FACILITY: FORTRAN/RMS Interface
;
; ABSTRACT:
;
; Contains all routines which perform RMS I/O.
;
; ENVIRONMENT: FORTRAN Runtime System
;
; AUTHOR: Tom Speer
;
; CREATION DATE: 1-Dec-83
;
; MODIFIED BY:
COMMENT \
***** Begin Revision History *****
4065 JLC 6-Dec-83
Added some new entries for the skeleton.
4066 JLC 11-Jan-84
More new entries for the skeleton.
4072 JLC 24-Jan-84
Begin coding.
4102 JLC 17-Feb-84
Remove a global which was removed from FOROPN.
4122 JLC 2-May-84
Add some more globals.
4131 JLC 12-Jun-84
Add non-skip memory full return to %GTBLK call.
***** Begin Version 11 *****
5000 TGS 1-Jul-85
Implement RMS OPEN.
5001 TGS 1-Aug-85
Implement RMS INQUIRE.
5002 TGS 1-Sep-85
Implement RMS CLOSE.
5003 TGS 24-Oct-85
Implement RMS READ.
5004 TGS 10-Nov-85
Implement RMS WRITE
5007 TGS 4-Jan-86
RMS error-handling
5013 TGS 28-May-86
RMS file-positioning.
5014 MRB 6-JUN-86
Implement RMS UNLOCK statement. Routines %RMCUL, %RMUNL, FREE$
5016 MRB 16-Jun-86
Implement MAXREC keyword in open statements.
5023 TGS 18-Nov-86
Pre-diagnose ER$REX errors to avoid various network problems.
***** End Revision History *****
\
SUBTTL INTERN-EXTERN DECLARATIONS
;If FTEXT is zero, the processor does not support extended addressing
;RMS invocations. Such machines not only do not need the code in
;FORRMS, they can't compile it, since the .REQUIRE files
;for RMS are not on their system.
IF10,< IFNDEF FTEXT,<FTEXT==0> ;Default on -10
> ;End IF20
IF20,< IFNDEF FTEXT,<FTEXT==-1> ;Default on -20
> ;End IF20
;Tell which version we are assembling
IF1,<
IFN FTEXT,<PRINTX [Extended version]>
IFE FTEXT,<PRINTX [Non-Extended version]>
>
DEFINE IFRMS <IFN FTEXT> ;RMS can be invoked
DEFINE IFNRMS <IFE FTEXT> ;RMS cannot be invoked
;%IF20 conditionals are like IF20 ones, except that if FTEXT=0 (non-
; RMS environment) nothing within a %IF20 assembles at all.
; The RMSENT macro defines ENTRY points as POPJ's for a non-RMS
; environment--just enough defined so FOROTS can be compiled without error.
DEFINE %IF20, <
IFRMS> ;End %IF20
DEFINE RMSENT (NAM),<
ENTRY NAM ;;ENTRY on -10/-20
IF20,< ;;If -20
IFE FTEXT < ;;and not RMS-able
IRP <NAM>,<NAM': POPJ P,> ;;Dummy entries
> ;End IFE
> ;End IF20
> ;End RMSENT
%IF20,<
SEARCH RMSINJ
.REQUIRE SYS:RMSZER
.REQUIRE SYS:RTLZNM
.REQUIRE SYS:ZERBOO
.REQUIRE SYS:DYNBOO
> ;End %IF20
SEGMENT CODE
IF20,<
INTERN %ERMIN ;[5007]
ENTRY FNDRMS ;[5000]
RMSENT <%IRMS,%ORMS,%UORMS,%RMOPN,%RMLKP,%RMRFS> ;[5000]
RMSENT <%RMGXF,%RMOSW,%RMISW,%RSISW,%RMCLS,%RMREW,%RMBSR> ;[5000]
RMSENT <%RMEND,%RMSIN,%RMSOU,%RMRDW,%CHKBD> ;[5000]
RMSENT <%RMREN,%RMDSP,%RMEFN,%RMCSY> ;[5002]
RMSENT <%RMERR,%RMECL> ;[5007]
RMSENT <%RMCRW> ;[5004]
RMSENT <%RMCDL,%RMDEL> ;[5013]
RMSENT <%RMCUL,%RMUNL> ;[5014]
> ;End IF20
RMSENT <%RMDAB,%RMASV,%RMKOP,%RMDKB,%RMDFA,%RMCKF> ;[5000]
RMSENT <%RMFND> ;[5004]
RMSENT <%RMECK> ;[5007]
RMSENT <%RSOSW> ;[5000]
EXTERN %POPJ,%POPJ1
IF20,<
;EXTERNS IN FORERR:
EXTERN %RMPDP,ERRPTR,OCTTYP,ASCTYP,%ERNM2,%ERNM3 ;[5007]
EXTERN INICHR,%RMEPT,FOREC2,EMSGT0,%ERPTR,ERRCNT ;[5007]
EXTERN LERRBF ;[5007]
EXTERN %ERIOS ;[5014]
;EXTERNS IN FORIO:
EXTERN %CUNIT ;[5000]
EXTERN SETPTR,%OCLR,RECLEN,PAGNUM ;[5003]
EXTERN A.REC,A.KVL,A.KRL,A.KID,D.KEY,EXPIRB,GETIRB ;[5003]
EXTERN GETORB,ORINI,BYTUSD,%SETAV,A.FMT ;[5004]
EXTERN %CUNIT,%BAKEF ;[5013]
EXTERN A.IOS ;[5014]
;EXTERNS IN FORMEM:
EXTERN %GTBLK,%FREBLK,%GTPGS,%FREPGS ;[5000]
EXTERN %GTSPC ;[5003]
EXTERN %MVBLK ;[5004]
;EXTERNS IN FOROPN:
EXTERN O.KEY,%TXTBF,TXTBF2,OPNSWT,KEYVAL,FNDSWT ;[5000]
EXTERN %ARGNM,SWRECT,FNSPNT,FNSCLR,%GNPNT,FNOJFN ;[5000]
EXTERN ASCFNS,RELJFN,%DOJFNS,RANALC,CHKBSZ,BSTAB ;[5000]
EXTERN %RSEOF,FDB,OPCNF ;[5000]
EXTERN UNKXST ;[5001]
EXTERN DSKREN,%RNAMD,%OLDDB,CLSDDB,SWDISC,JFNBLK ;[5002]
EXTERN ILLOUT,%SOCNT,%SETIN ;[5004]
EXTERN %SETOUT,%SETIN ;[5013]
;EXTERNS IN FOROTS:
EXTERN %FSECT,%ABFLG ;[5007]
EXTERN %DDBTAB,%UDBAD ;[5013]
;EXTERNS IN FORXIT:
EXTERN ABORT. ;[5000]
> ;End IF20
SUBTTL %RMKOP - Setup a FAB/XAB chain
;***************************************************************************
;* *
;* ENTRIES CALLED FROM FOROPN *
;* *
;***************************************************************************
;++
; FUNCTIONAL DESCRIPTION:
;
; This routine allocates a FAB/XAB chain and fills in the XAB(s)
; with KEY specifier data. It is called from OPEN keyword processing
; and from DIAKEY when parsing a /KEY: in DIALOG mode. Deallocates
; any FAB/RAB/XAB which already exists for this (D), then allocates
; a new FAB/XAB chain.
;
; O.KEY points to an argument list of the form:
;
;
; -N,,0 ;N is KSPLEN*number_keys
; xM: IFIW TP%INT,[LB] ;primary key first char
; IFIW TP%INT,[UB] ;primary key last char
; IFIW type,0 ;type is TP%INT or TP%CHR
; .....
; IFIW TP%INT,[LB] ;last key first char
; IFIW TP%INT,[UB] ;last key last char
; IFIW type,0 ;type is integer or character
;
; If the arglist has been constructed in DIALOG, LB and UB values
; are immediate and the left half of each entry except for data
; type is zero.
;
; P1 is the secondary arglist pointer
; P2 is an AOBJN index: -Number_of_specifiers,,key_of_reference
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMKOP
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; O.KEY - Address of secondary argument list
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) - Address of FAB
; XAB(D) - Address of XAB
; POS - Starting byte position of key
; SIZ - Size of key
; DTP - Key's datatype
; REF - Key-of-reference number
; NXT - Pointer to next XAB in chain
; STGFLG(D) - -1 if XAB chain has CHARACTER DTP
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4,P1,P2
; Deallocates any prexisting FAB/RAB/XAB on entry
;
;--
;[5000] New
IF10,<
%RMKOP: $SNH ;Should not get here on -10
> ;End IF10
%IF20,<
MAXCHR==^D255 ;CHARACTER keys must be equal to/less
;than this length
INTLEN==4 ;INTEGER keys must be 4 bytes long
%RMKOP: PUSHJ P,%RMDAB ;Deallocate any arg blocks
PUSHJ P,RMFAB ;Allocate a FAB
MOVEM T1,FAB(D) ;Save its address
SETZM STGFLG(D) ;Clear CHARACTER-in-XAB flag
SETZM PXBADR ;Initialize previous XAB address
MOVE P1,O.KEY ;Get address of secondary arglist
XMOVEI P1,@P1 ; alone
;Initialize AOBJN pointer with -number_of_specifiers,,key_of_reference#
HLRE T1,-1(P1) ;Get argument count
IDIVI T1,KSPLEN ;Get number of specifiers
MOVSI P2,(T1) ;-key_num,,key_ref
;TOP OF KEY_SPECIFIER LOOP
KEYLP: PUSHJ P,RMXAB ;Allocate a XAB
MOVE T4,T1 ;Copy current XAB address
SKIPN PXBADR ;Prime key XAB (no previous)?
MOVEM T4,XAB(D) ;Yes, save start of chain
;Get Lower Bound argument and store
MOVE T2,LBO(P1) ;Get LB argument
TLNE T2,-1 ;Immediate?
MOVE T2,(T2) ;No
MOVEM T2,SAVLB ;Save
PUSHJ P,%CHKBD ;Check validity
JRST KERR ;Bad
SUBI T2,1 ;LB-1: 0 is starting byte
$STORE T2,POS,<(T4)> ;Store starting byte
;Get Upper Bound argument
MOVE T2,UBO(P1)
TLNE T2,-1 ;Immediate?
MOVE T2,(T2) ;No
MOVEM T2,SAVUB ;Save
PUSHJ P,%CHKBD ;Check bound validity
JRST KERR ;Bad
SUBI T2,1 ;Adjust for zero start
$FETCH T1,POS,<(T4)> ;Get lower bound again
CAMGE T2,T1 ;UB greater than/equal to start?
JRST KERR ;No, bad argument
;Calculate key size as UB-LB+1 and store
MOVE T1,SAVLB ;Get user's lower bound
MOVE T2,SAVUB ;and upper
SUBI T2,-1(T1) ;UB-LB+1
$STORE T2,SIZ,<(T4)> ;Store in current XAB
;Get key data type
MOVX T2,XB$STG ;Default to string (CHARACTER)
LDB T1,[POINTR (DTO(P1),ARGTYP)] ;Get type
CAIN T1,TP%INT ;INTEGER?
MOVX T2,XB$IN4 ;Yes
$STORE T2,DTP,<(T4)> ;Store in current XAB
$FETCH T1,SIZ,<(T4)> ;Get key size
CAIE T2,XB$STG ;CHARACTER?
JRST NOTCHR ;No
SETOM STGFLG(D) ;Yes,flag it.
CAILE T1,MAXCHR ;Bigger than RMS max?
JRST KERR ;Yes, error
JRST STFLG ;No, go setup key attributes
NOTCHR: CAIE T2,XB$IN4 ;INTEGER?
$SNH ;No, bad arglist
CAIE T1,INTLEN ;Yes. Is length = 4?
JRST KERR ;No. bad key value
$STORE T1,SIZ,<(T4)>
;Set default DUP/CHG attributes
STFLG: MOVX T1,XB$CHG!XB$DUP ;Default allows DUP/CHG for non-prime
SKIPN PXBADR ;Prime XAB (no previous)?
SETZ T1, ;Yes, no DUP/CHG
$STORE T1,FLG,<(T4)> ;Store in current XAB
;Store the key-of-reference from AOBJN RH
HRRZ T1,P2
$STORE T1,REF,<(T4)>
;If not the first XAB allocated, establish a backward link and fill in
; X$NXT of the previous XAB.
SKIPE T1,PXBADR ;Was there a previous XAB?
$STORE T4,NXT,<(T1)> ;Yes, store the link
MOVEM T4,PXBADR ;Store current XAB address in previous
;BOTTOM OF KEY_SPECIFIER LOOP
ADDI P1,KSPLEN ;Move arg pntr to next section
AOBJN P2,KEYLP ;Increment key_num, key_ref and loop
;Here after all arglist processing. Link in either FAB F$XAB or (if there
; is one) CONFIG XAB X$NXT with start of chain.
PUSHJ P,LNKXAB ;Link to FAB or CONFIG
POPJ P, ;Return
;Here on argument-invalid errors in the arglist. Since we may have allocated
; a XAB but not yet fully linked it in the chain, we must complete the link
; so everything gets properly deallocated.
KERR: SKIPE T1,PXBADR ;Was there a previous XAB?
$STORE T4,NXT,<(T1)> ;Yes, link current to it
PUSHJ P,LNKXAB ;Link FAB or CONFIG
PUSHJ P,%RMDAB ;Deallocate everything
PUSHJ P,%RMDKB ; including the arglist
MOVE T1,KEYVAL ;Get keyword value
MOVEI T2,OPNSWT ;Find ASCII name for keyword
PUSHJ P,FNDSWT
MOVEM T1,%ARGNM ;Save for error
$DCALL IAV ;"?Ilegal value for /KEY:"
SEGMENT DATA
SAVLB: BLOCK 1 ;SAVE LOWER BOUND
SAVUB: BLOCK 1 ;SAVE UPPER BOUND
SEGMENT CODE
> ; End %IF20
SUBTTL %RMECK - Cleanup after failing FOROPN OPEN
;++
; FUNCTIONAL DESCRIPTION:
;
; Called after a failing FOROPN open-by-device call to DOOPEN.
; If the file is an RMS file, performs a dummy $CLOSE to release
; any network link. If TOPS-10 or non-RMS, a no-op.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMECK
; <Return here; always requests DIALOG>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T4.
; If file is RMS, $CLOSEs FAB.
;--
;[5007] New
IF10,<
%RMECK: POPJ P, ;No RMS errors on TOPS10
> ;End IF10
%IF20,<
%RMECK: SKIPN FAB(D) ;RMS involved?
POPJ P, ;No, just return
PJRST RLSLNK ;Yes, go do it
> ;End %IF20
SUBTTL LNKXAB - Link XAB(D)
;++
; FUNCTIONAL DESCRIPTION:
;
; Called on completion of Key XAB processing to link FAB FB$XAB to the
; start of the Key chain XABs. If there is a CONFIG XAB, link its NXT
; field instead.
;
; CALLING SEQUENCE:
;
; PUSHJ P,LNKXAB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; XAB(D) - Address of XAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB F$XAB - Set to start of key chain if file is local
; CONFIG X$NXT - Set to start of key chain if file is remote
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T3.
;
;--
;[5000] New
%IF20,<
LNKXAB: MOVE T1,FAB(D) ;Get FAB's address
MOVE T3,XAB(D) ;Get key chain start
$FETCH T2,XAB,<(T1)> ;Get FAB's link field
JUMPN T2,LNKCFG ;Non-zero if a CONFIG
$STORE T3,XAB,<(T1)> ;store start in FAB FB$XAB
POPJ P, ;Return
LNKCFG: $STORE T3,NXT,<(T2)> ;link start to CONFIG X$NXT
POPJ P, ;Return
> ; End %IF20
SUBTTL %CHKBD - Check KEY= bound validity
;++
; FUNCTIONAL DESCRIPTION:
;
; Checks that a LB or UB KEY= value is valid. LB/UB values
; must be .GE. zero and must not be more than 17 bits.
; (Actually the maximum RMS record size for indexed
; records on TOPS20 results in LB/UB ceilings considerably less than
; 17 bits; this routine checks only that a well-formed XAB chain can
; be handed to RMS).
;
; CALLING SEQUENCE:
;
; PUSHJ P,%CHKBD
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; T2 - Value to be checked
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; T2 - Orginal value returned
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T2.
;
;--
;[5000] New
%IF20,<
%CHKBD: JUMPLE T2,%POPJ ;.LE. zero
TLNN T2,-1 ;Overflow on left?
TRNE T2,(1B0) ;or on right?
POPJ P, ;Yes, error return
JRST %POPJ1 ;OK return
> ; End %IF20
SUBTTL %RMCKF - Check for conflicting RMS OPEN keywords
;++
; FUNCTIONAL DESCRIPTION:
;
; Called from FOROPN CKCONF to check for conflicting OPEN RMS
; keywords. If a conflict is found, an ICA message is issued via
; a call to OPCNF.
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMCKF
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ACC(D) - ACCESS=
; ORGAN(D) - ORGANIZATION=
; O.KEY - KEY= in OPEN
; RECTP(D) - RECORDTYPE=
; RSIZE(D) - RECL=
; SHARE(D) - SHARED
; RO(D) - READONLY
; STAT(D) - STATUS=
;
; ORKYTB - Table by ORGANIZATION of legal/illegal
; KEY= values
; ORACTB - Table by ORGANIZATION of illegal
; /ACCESS codes
; ORRTTB - Table by ORGANIZATION of illegal
; /RECORDTYPE codes
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; If both /SHARED and /READONLY are specified, SHARE(D) and RO(D)
; are cleared.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
IFNRMS,< ;No RMS conditional (also TOPS-10)
%RMCKF: JRST %POPJ1
> ;End IFNRMS
%IF20,<
%RMCKF: SETZM IMPORG ;Clear local flag (implied ORG=)
LOAD T2,ACC(D) ;Get /ACCESS
LOAD T1,ORGAN(D) ;Get /ORGANIZATION
CAIN T1,OR.IDX ;If INDEXED
MOVX T2,AC.KEY ;then ACCESS is KEYED
MOVX T3,OR.IDX ;Assume keyed
CAIE T2,AC.KEY ;If ACCESS='KEYED'
SKIPE O.KEY ;or KEY= given
MOVEM T3,IMPORG ;Flag an implied ORG=INDEXED
SKIPN IMPORG ;If some ORG was given or implied
CAIE T1,OR.UNK
JRST ORKY ;Have to check further
;Here for non-RMS or RSF file
LOAD T1,SHARE(D) ;SHARED?
JUMPE T1,%POPJ1 ;No, all done
PUSHJ P,SHARO ;Check vs READONLY
PJRST %POPJ1 ;and return
;Check /ORGANIZATION vs /KEY (if given)
ORKY: SKIPE O.KEY ;KEY= given?
SKIPL ORKYTB(T1) ;Yes. Allowed with ORG given?
JRST ORAC ;Yes, OK
SETZ T2, ;/KEY has no value (sort of)
MOVEI T3,OK.ORG
MOVEI T4,OK.KEY
CALL OPCNF ;Report error
;Check /ORGANIZATION vs /ACCESS (if given)
ORAC: SKIPN T1,IMPORG ;Get implied ORG if any
LOAD T1,ORGAN(D) ;None, use actual
LOAD T2,ACC(D) ;Get /ACCESS
JUMPE T2,NEWKEY ;None, no check
MOVE T3,ORACTB(T1) ;Get ACCESS/ORG entry for this ORG
PUSHJ P,CKFSRH ;See if this ACCESS is allowed
JRST NEWKEY ;Yes, OK!
SKIPE O.KEY ;No. Did we use implied ORG?
JRST ORAC2 ;Yes, different error message
MOVEI T3,OK.ORG
MOVEI T4,OK.ACC
PUSHJ P,OPCNF
JRST NEWKEY
ORAC2: MOVE T1,T2 ;ACCESS in T1
SETZ T2, ;/KEY has no value
MOVEI T3,OK.ACC
MOVEI T4,OK.KEY
PUSHJ P,OPCNF
;Check for STATUS='NEW' and /KEY.
NEWKEY: LOAD T1,STAT(D) ;Get /STATUS
CAIN T1,ST.SCR ;If SCRATCH
MOVX T1,ST.NEW ;it's really NEW
CAIE T1,ST.NEW ;NEW?
JRST ORRT ;No, no further check
SKIPE O.KEY ;KEY= given?
JRST NEWFIX ;Yes, no conflict
SKIPN T1,IMPORG ;Get implied or actual ORG
LOAD T1,ORGAN(D)
CAIN T1,OR.IDX ;INDEXED?
PUSHJ P,[$DCALL KER] ;?KEY= required
;Check STATUS='NEW' and RECL=. New relative and indexed files
;default to RECORDTYPE='FIXED'.
;In this case, if no RECORDTYPE= has been specified, insist on a RECL=.
;STATUS='UNKNOWN', which may create a new file, is checked for missing
;required RECL= at OPEN time.
;We only come here if STATUS='NEW' or 'SCRATCH'.
NEWFIX: SKIPN T1,IMPORG ;Get implied or actual ORG
LOAD T1,ORGAN(D)
LOAD T2,RSIZE(D) ;Get /RECORDSIZE
JUMPN T2,ORRT ;Got one, no conflict
LOAD T2,RECTP(D) ;Get /RECORDTYPE
JUMPN T2,ORRT ;Got one, no conflict
;Here if STATUS='NEW' and no RECL= and no RECORDTYPE was given.
CAIE T1,OR.REL ;RELATIVE?
CAIN T1,OR.IDX ;or INDEXED?
PUSHJ P,[$DCALL DFR] ;?Default /RECORDT:FIXED requires /RECL
;Check /ORGANIZATION vs RECORDTYPE
ORRT: LOAD T2,RECTP(D) ;Get /RECORDTYPE
JUMPE T2,SHAC ;None
LOAD T1,RSIZE(D) ;Get /RECORDSIZE
JUMPN T1,ORRTA ;Got one, good
CAIN T2,RT.FIX ;FIXED?
PUSHJ P,[$DCALL FRR] ;Yes, requires a size
ORRTA: SKIPN T1,IMPORG ;Get implied or actual ORG
LOAD T1,ORGAN(D)
MOVE T3,ORRTTB(T1) ;Get ORG/RECT table entry for this ORG
PUSHJ P,CKFSRH ;See if legal
JRST SHAC ;OK!
SKIPE IMPORG ;Implied used?
JRST ORRT2 ;Yes, different error message
MOVEI T3,OK.ORG
MOVEI T4,OK.RTP
PUSHJ P,OPCNF
JRST SHAC
ORRT2: MOVEI T3,OK.ACC ;Assume /ACCESS conflict
LOAD T1,ACC(D) ;Get /ACCESS
SKIPN T1 ;If none,
MOVEI T3,OK.KEY ;must be KEY=
MOVEI T4,OK.RTP
PUSHJ P,OPCNF
;Check /SHARED and /ACCESS
SHAC: LOAD T1,SHARE(D) ;Get SHARED bit
JUMPE T1,%POPJ ;none given, all done
LOAD T2,ACC(D) ;Get /ACCESS
MOVE T3,T2 ;Copy it
JUMPE T2,SHARO ;None given
CAIN T2,AC.RIN ;If it's RANDIN
MOVX T2,AC.SIN ;treat like SEQIN for a moment
CAIE T2,AC.SIN ;Some read-onlyness?
JRST SHARO ;No
MOVE T2,T3 ;Retrieve the actual
;/SHARED was specified with an /ACCESS implying read-only.
SETZ T1, ;SHARE has no value
MOVEI T3,OK.SHR
MOVEI T4,OK.ACC
PUSHJ P,OPCNF ;Issue error
;All done
;Check /SHARED vs /READONLY. If both are given, clear both before
;issuing an error. We don't get here unless /SHARED was specified.
SHARO: LOAD T1,RO(D) ;Get /READONLY
JUMPE T1,%POPJ ;None, no conflict
;Here when both were given
SETZB T1,T2
STORE T1,RO(D) ;Clear both
STORE T1,SHARE(D)
MOVEI T3,OK.SHR
MOVEI T4,OK.RO
PJRST OPCNF
;Table for legal KEY= by organization (0 is legal, -1 illegal)
ORKYTB: 0 ;NONE
-1 ;SEQUENTIAL
-1 ;RELATIVE
0 ;INDEXED
SEGMENT DATA
IMPORG: BLOCK 1 ;Implied ORG=INDEXED
SEGMENT CODE
> ;End %IF20
SUBTTL CKFSRH - Search a conflict table
;++
; FUNCTIONAL DESCRIPTION:
;
; Searches a table whose AOBJN pointer is in AC3 for a match against
; the value in AC2.
;
; CALLING SEQUENCE:
;
; PUSHJ P,CKFSRH
; <Return here if no match found>
; <Return here if match found>
;
; INPUT PARAMETERS:
;
; T3 - AOBJN pointer to table
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T2-T4.
;
;--
;[5000] New
%IF20,<
CKFSRH: MOVE T4,(T3) ;Get table entry
CAIN T2,(T4) ;Match our value
JRST %POPJ1 ;Yes, take +2 (error) return
AOBJN T3,CKFSRH ;Keep looking
POPJ P, ;No, match is good
DEFINE TAB (ARGS) <
.ARGN.==0
IRP ARGS,<.ARGN.=.ARGN.+1>
XWD -.ARGN.,[IRP ARGS,<ARGS>]
> ;End TAB
;Table for illegal ACCESS types by ORGANIZATION. A -1 allows any ACCESS
; code. If RMS ever supports direct access to fixed-length sequential
; files, delete AC.RIN and AC.RIO from SEQUENTIAL.
ORACTB: TAB <-1> ;NONE
TAB <AC.KEY,AC.RIN,AC.RIO> ;SEQUENTIAL
TAB <AC.KEY,AC.APP> ;RELATIVE
TAB <AC.APP> ;INDEXED
;Table for illegal RECORDTYPES by ORGANIZATION. A -1 allows any RECORDTYPE.
;Note that any is allowed for SEQUENTIAL, even though RECORDTYPE=STREAM
;is disallowed for TOPS20 RMS files. Since we don't know the operating
;system for a remote file yet, anything goes until the RMS OPEN, when
;a further check is made.
ORRTTB: TAB <-1> ;NONE
TAB <-1> ;SEQUENTIAL
TAB <RT.UND,RT.SCR,RT.SLF> ;RELATIVE
TAB <RT.UND,RT.SCR,RT.SLF> ;INDEXED
PURGE .ARGN.
> ;End %IF20
SUBTTL %RMDFA - Default RMS ACCESS
;++
; FUNCTIONAL DESCRIPTION:
;
; Performs post-OPEN-arg defaulting for /ACCESS to RMS files. If
; ORGANIZATION='INDEXED' has been specified or implied, sets /ACCESS
; to 'KEYED'.
;
; Called from FOROPN DFACC.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMDFA
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ACC(D) - ACCESS=
; ORGAN(D) - ORGANIZATION=
; O.KEY - KEY= arglist
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; ACC(D) - ACCESS=
; ORGAN(D) - ORGANIZATION=
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
IF10,<
%RMDFA: POPJ P, ;No RMS on TOPS10
> ;End IF10
%IF20,<
%RMDFA: LOAD T2,ORGAN(D) ;Get /ORGANIZATION
CAIE T2,OR.SEQ ;If given as SEQUENTIAL
CAIN T2,OR.REL ;or RELATIVE,
POPJ P, ;nothing to do
MOVEI T1,AC.KEY ;Assume ACCESS='KEYED'
SKIPN O.KEY ;Was KEY= given?
CAIN T2,OR.IDX ;or ORG='INDEXED'?
STORE T1,ACC(D) ;Yes. Default to keyed-access
LOAD T2,ACC(D) ;Get access
CAIE T2,AC.KEY ;'KEYED'?
POPJ P,
;Here for ACCESS='KEYED'. Set ORGANIZATION='INDEXED'.
MOVEI T1,OR.IDX ;Yes, /ORGANIZATION is 'INDEXED'
STORE T1,ORGAN(D)
POPJ P, ;Return
> ;End %IF20
SUBTTL %RMOPN - Open an RMS-accessed file
;++
; FUNCTIONAL DESCRIPTION:
;
; This routine opens files with INDX(D) device types of DI.RSF
; (remote stream) or DI.RMS (RMS). It allocates a FAB/CONFIG XAB
; if one does not already exist, sets FAB fields according to
; OPEN specifiers, allocates a RAB and sets its fields, $OPENs
; or $CREATEs the file, and $CONNECTs the RAB to the FAB.
;
; If a USEROPEN user routine has been specified, calls this routine
; instead of performing the $OPEN/$CREATE/$CONNECT.
;
; If cacheing is enabled, allocates a cache.
;
; Updates the DDB on a successful open.
;
; RSF files can cause the following to happen after a successful OPEN:
;
; o Bucket 0, the FDB page, is read in and EOFN calculated.
; o If random-access, a page table is setup.
; o If ACCESS='APPEND', the last page of the file is mapped.
;
; CALLING SEQUENCE:
;
; Called only from FOROPN DOOPEN via OPNTAB.
; Returns +1 on error to enter DIALOG
; Returns +2 on success.
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; SAIDX(D) - STATUS/ACCESS index
; ORGAN(D) - ORGANIZATION
; ORGTAB - Table of RMS organization bits
; INDX(D) - Device index (file type)
; SPAN(D) - Non-zero if NOSPANBLOCKS
; SHAR(D) - SHARED
; RO(D) - READONLY
; MAXREC(D) - MAXREC=
; BUFCT(D) - BUFFERCOUNT (file window
; pages for RSF files; multi-
; buffercount for RMS files)
; UOPN(D) - Address of USEROPEN routine
; UBSIZ(D) - User-specified bytesize
; O.KEY - KEY= arg pointer
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; Updates the following DDB fields before a successful return:
;
; RSIZE(D) - Record size in bytes (formatted) or words
; BSIZ(D) - File bytesize
; IJFN(D) - -1
; WTAB(D) - -1 for RMS relative random-access files,
; a page table for random-access RSF files,
; else zero.
; EOFN(D) - Set to infinity
; IMGFLG(D) - Set for RSF files residing on VAX systems.
; DDB filespec fields - Updated with expanded filespec
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
; Invokes RMS.
; Will establish a network link on successful open of a remote file.
; May call user's USEROPEN routine if present.
; May allocate a cache.
; May set WTAB(D) and allocate a page table
; May cause temporary allocation of 1 page for FDB bucket for
; RSF files
; May cause BUFCT-pages mapped to EOF for RSF files opened
; ACCESS='APPEND'
;
;--
;[5000] New
IF10,<
%RMOPN: $SNH ;Should NOT get here on TOPS-10
> ;End IF10
%IF20,<
LWSIZ==9
PSIZ==1000 ;Words/page
FB$ALL==FB$GET!FB$PUT!FB$DEL!FB$UPD!FB$TRN ;Full access
%RMOPN: SKIPN T1,FAB(D) ;Already have a FAB?
PUSHJ P,RMFAB ;No, allocate one
MOVEM T1,FAB(D) ;Save its address
MOVE T1,[POINT 7,%TXTBF] ;Setup to get DDB filespec
PUSHJ P,%RMFNS ;Get it
MOVE T4,FAB(D) ;Get FAB address again
$STORE T1,FNA,<(T4)> ;Set filespec in FNA
;Initialize NAM block, also scratch argument blocks, and point FAB NAM
; to the NAM block.
PUSHJ P,ABINI ;Initialize some argument blocks
XMOVEI T1,NAMBLK ;Point to NAM blk
$STORE T1,NAM,<(T4)>
;Setup FAC field according to STATUS/ACCESS value.
SETFAC: LOAD T1,SAIDX(D) ;Get STATUS/ACCESS
MOVE T1,FACTAB(T1) ;Get corresponding RMS bits
LOAD T2,RO(D) ;Get READONLY bit
SKIPE T2 ;Set?
MOVX T1,FB$GET ;Yes, set read access only
$STORE T1,FAC,<(T4)> ;in FAC of FAB
;Setup ORG field from ORGANIZATION specified. If no ORGANIZATION was
; specified (RSF file or implicit VAX sequential file), ORGAN(D) is zero
; and we default to OR.SEQ.
SETORG: LOAD T1,ORGAN(D) ;Get ORGANIZATION
HLRZ T1,ORGTAB(T1) ;Get org bits
$STORE T1,ORG,<(T4)>
;If SHARED was specified, set the SHR field to full write sharing, else to
; FB$GET, the RMS default.
SETSHR: MOVX T2,FB$GET ;Assume no SHARE
LOAD T1,SHARE(D) ;Get SHARE bit
SKIPE T1 ;Any specified?
MOVX T2,FB$GET!FB$PUT!FB$DEL!FB$UPD ;Yes, allow lots
$STORE T2,SHR,<(T4)> ;Set in SHR
;Setup MRN field from the MAXREC keyword. If none given, MRN=0 and
; RMS does not check for maximum record number.
MOVE T2,MAXREC(D) ;[5016] Get MAXREC
$STORE T2,MRN,<(T4)> ;[5016] Store into MRS
;Set RAT to NOSPANBLOCKS or zero.
LOAD T1,INDX(D) ;Get file type
CAIE T1,DI.RMS ;RMS?
JRST SETTYP ;No, ignore NOSPANBLOCKS
SETZ T2, ;Assume none
LOAD T1,SPAN(D) ;Get "SPAN" bit
SKIPE T1 ;Set?
MOVX T2,FB$BLK ;Yes
$STORE T2,RAT,<(T4)> ;Store or clear
SETZ T2, ;Clear any TYP link
$STORE T2,TYP,<(T4)>
JRST SETRAB ;Go setup RAB
;For RSF files, point to the TYP block for block-mode I/O.
SETTYP: XMOVEI T2,TYPBLK ;Yes
$STORE T2,TYP,<(T4)> ;Set it, or clear it
;Here after FAB fields are all set. Allocate a RAB and set it up.
SETRAB: SKIPE T1,RAB(D) ;Get a fresh RAB
PUSHJ P,%FREBLK
PUSHJ P,RMRAB ;Declare a RAB
MOVEM T1,RAB(D) ;Save its address
MOVE T4,T1 ;Copy it
MOVE T1,FAB(D) ;Get FAB address
$STORE T1,FAB,<(T4)> ;Link RAB to it
;Here to set RAC (record access) field. For now, just set to RB$SEQ. RMS
; relative file direct READ/WRITEs will set RAC to RB$KEY, as will all indexed
; WRITEs. Indexed READs will set to either SEQ or KEY.
SETRAC: MOVX T2,RB$SEQ ;Default to sequential
$STORE T2,RAC,<(T4)>
;Here when FAB and RAB are all set. If there is a USEROPEN routine, call
; it to $OPEN and $CONNECT the file; otherwise we do.
PUSHJ P,FIXUP ;Do last minute fixup
POPJ P, ;Can't, enter DIALOG
;*NOTE: After FIXUP has been called for remote files, a network link
;is now established and open. Any $DCALL during OPEN processing from
;now on must ensure that the remote link is relinquished. This is
;accomplished by the +1 return out of %RMOPN caused by a $DCALL, which
;returns to DOOPEN and calls %RMECK to perform a dummy $CLOSE on
;the FAB.
PUSHJ P,APPCHK ;Set ROP for ACCESS=APPEND
SKIPN T1,UOPN(D) ;Anything to call?
JRST NOUOPN ;No
PUSHJ P,CALUOP ;Yes, call it
POPJ P, ;Failed, enter DIALOG
JRST RMORET ;Succeeded, go finish up
;Here with no USEROPEN. OPEN/CREATE the file by STATUS/ACCESS index.
; This resolves to 4 courses of action:
;
; 1) $OPEN the file; if this fails, $CREATE it.
; 2) $CREATE the file; if this fails, $OPEN it.
; 3) $OPEN the file; if this fails, abort.
; 4) $CREATE the file (with a new generation if necessary); if
; this fails, abort.
;
NOUOPN: LOAD T1,SAIDX(D) ;Get STATUS/ACCESS index
PUSHJ P,RMOTB(T1) ;Open the file
POPJ P, ;Can't, take error return
PUSHJ P,FABSTV ;Update STV
;Here when the OPEN has succeeded. Check return values, $CONNECT RAB to
; FAB if no USEROPEN, update the DDB, and return.
;Check returned ORG value against what user specified.
RMORET: LOAD T1,ORGAN(D) ;Get user's value
HLRZ T1,ORGTAB(T1) ;Get corresponding RMS bits
MOVE T4,FAB(D) ;Get FAB address
$FETCH T2,ORG,<(T4)> ;Get actual
CAMN T1,T2 ;Same?
JRST UPDDDB ;Yes
XMOVEI T1,[ASCIZ /ORGANIZATION/] ;No
$DCALL ATC ;?File's ORGANIZATION conflicts
; with OPEN statement or default
;Check return BSZ (byte-size). If user specified one, and it conflicts
; with the actual returned size (TOPS files only), complain. If the
; user specified a size and the file is non-TOPS, BYTESIZE must equal 8;
; if no size was specified for a non-TOPS file, set it to 8.
UPDDDB: MOVEI T1,^D8 ;Assume non-TOPS
PUSHJ P,NTTOPS ;Alien environment?
$FETCH T1,BSZ,<(T4)> ;No. Get RMS's size
LOAD T2,UBSIZ(D) ;Get user-specified size
JUMPE T2,RESBSZ ;None given, use returned
LOAD T3,INDX(D) ;Get file type
CAIN T3,DI.RSF ;RSF?
JRST UPDDB2 ;Yes, check later from FDB
CAIE T1,(T2) ;Same?
$ECALL BSC ;No. Give conflict warning
RESBSZ: STORE T1,BSIZ(D) ;Store returned size
PUSHJ P,CHKBSZ ;Update BPW, etc.
UPDDB2: PUSHJ P,CHKRET ;Check other returned RMS values
POPJ P, ;Some conflict, enter DIALOG
;Here to connect RAB to FAB if no USEROPEN.
CONRAB: SKIPE UOPN(D) ;Any USEROPEN
JRST SWTB ;Yes, already $CONNECT'd, presumably
PUSHJ P,CONN$ ;Do $CONNECT
JRST RMOER3 ;Error
SWTB: PUSHJ P,SETWTB ;Setup WTAB, WSIZE, RSF EOF
SETZM O.KEY ;Clear any KEY= pntr
JRST %POPJ1 ;Done with OPEN
RMOTB: JRST OPCRE ;UNKNOWN, READ
JRST CRERX ;UNKNOWN, WRITE
JRST CREOP ;UNKNOWN, READ, WRITE
JRST OPCRE ;UNKNOWN, APPEND
JRST OPERX ;OLD, READ
JRST OPERX ;OLD, WRITE
JRST OPERX ;OLD, READ, WRITE
JRST OPERX ;OLD, APPEND
JRST CRERN ;NEW, WRITE
JRST CRERX ;NEW, SCRATCH
FACTAB: FB$GET ;UNKNOWN, READ
FB$ALL ;UNKNOWN, WRITE
FB$ALL ;UNKNOWN, READ, WRITE
FB$ALL ;UNKNOWN, APPEND
FB$GET ;OLD, READ
FB$ALL ;OLD, WRITE
FB$ALL ;OLD, READ, WRITE
FB$ALL ;OLD, APPEND
FB$ALL ;NEW, WRITE
FB$ALL ;SCRATCH, WRITE
ORGTAB: FB$SEQ,,OR.UNK ;NONE
FB$SEQ,,OR.SEQ ;SEQUENTIAL
FB$REL,,OR.REL ;RELATIVE
FB$IDX,,OR.IDX ;INDEXED
;Table for mapping returned RMS record-format values to FOROTS recordtypes
; for RMS files. RH -1 means "this RMS value not supported by FOROTS for RMS
; files"--the only ones currently being STREAM and LSA records in RMS
; sequential files.
RTTAB: FB$STM,,-1 ;(RT.UNS) NONE
FB$STM,,-1 ;(RT.UND) UNDEFINED
FB$FIX,,RT.FIX ;(RT.FIX) FIXED
FB$VAR,,RT.DEL ;(RT.DEL) VARIABLE
FB$STM,,-1 ;(RT.SEG) SEGMENTED
FB$LSA,,-1 ;LINE-SEQUENCED
-1 ;Table end
;Special table for VAX RMS recordformats. Allows almost all RFMs for RMS
; files
VRTTAB: FB$STM,,RT.UND
FB$STM,,RT.UND
FB$FIX,,RT.FIX
FB$VAR,,RT.DEL
FB$STM,,RT.UND
FB$LSA,,-1
-1
;$OPEN the file. This failing, $CREATE it. That failing, abort.
OPCRE: PUSHJ P,OPEN$ ;Do $OPEN
JRST OPCREX ;Error
JRST %POPJ1 ;Return
;Here after a failing OPEN to $CREATE.
OPCREX: CAIE T2,ER$FNF ;Was error "File not found"?
JRST RMOER3 ;No, this is bad
PUSHJ P,DFRFMN ;Default RFM for new RMS files
POPJ P, ;Some conflict, enter DIALOG
MOVX T1,FB$ALL ;Reset to full access
MOVE T4,FAB(D)
$STORE T1,FAC,<(T4)>
PUSHJ P,CREA$ ;Do $CREATE
JRST RMOERR ;Error
JRST %POPJ1 ;OK
;$CREATE the file. This failing, $OPEN it. That failing, abort.
CREOP: LOAD T1,OSTYPE(D) ;Get OS type
CAIN T1,XA$VMS ;VMS?
JRST OPCRE ;Yes, must do it backwards
PUSHJ P,DFRFMN ;Default RFM for new RMS files
POPJ P, ;Some conflict, enter DIALOG
PUSHJ P,CREA$ ;Do $CREATE
JRST CREOPX ;Error
JRST %POPJ1
;Here when the $CREATE failed. If the error is ER$FEX (file already
; exists), we try to $OPEN it.
CREOPX: CAIE T2,ER$FEX ;Was error "File already exists"?
JRST RMOER3 ;No, this is bad
OPERX: PUSHJ P,OPEN$ ;Do $OPEN
JRST RMOERR ;Error
JRST %POPJ1 ;OK
;Here to $CREATE a new file. Set FAB(D) FOP to FB$SUP to supercede an
; existing file. If an explicit generation was given for STATUS='NEW',
; leave SUP off so the $CREATE will fail if the file exists.
CRERN: HRROI T1,GEN(D) ;STATUS='NEW'. Look at generation
MOVX T3,^D10
NIN% ;See if explicit gen given
ERJMP CRERX ;Assume none
JUMPLE T2,CRERX ;0 or neg means no explicit
SETZ T2,
TRNA
CRERX: MOVX T2,FB$SUP ;Get supercede bits
MOVE T4,FAB(D) ;Get FAB address
$STORE T2,FOP,<(T4)> ;Set SUP
PUSHJ P,DFRFMN ;Default RFM for new RMS files
POPJ P, ;Some conflict, enter DIALOG
PUSHJ P,CREA$ ;Do $CREATE
JRST RMOERR ;Error
$FETCH T1,FOP,<(T4)> ;Turn SUP off
TXZ T1,FB$SUP
$STORE T1,FOP,<(T4)>
JRST %POPJ1
;Here on $OPEN/$CREATE errors.
RMOERR: CAIE T2,ER$REF ;Indexed Key XAB skew?
JRST RMOER3 ;No, something fatal
PUSHJ P,OPEN$ ;Do $OPEN
JRST RMOER3 ;Error
JRST %POPJ1 ;OK
RMOER3: SETZ T2,
$STORE T2,FOP,<(T1)> ;Turn off any FOP bits
PUSHJ P,RMDUXB ;Yes. Deallocate any XAB chain
$DCALL OPN ;Complain
> ; End %IF20
SUBTTL FIXUP - Do last minute pre-$OPEN settings
;++
; FUNCTIONAL DESCRIPTION:
;
; This jacket routine calls last-minute fixup routines to set
; various FAB parameters and check for inconsistencies which
; can only be detected when the target operating system is known.
;
; CALLING SEQUENCE:
;
; PUSHJ P,FIXUP
; <Error return; go release any remote link>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5000] New
%IF20,<
FIXUP: PUSHJ P,GETOST ;Determine OS type, last minute fixup
POPJ P, ;Can't, take error return
PUSHJ P,SETBSZ ;Set/default bytesize
POPJ P, ;Some conflict, take error return
PUSHJ P,SETRFM ;Set/default RECORDTYPE
POPJ P, ;Some conflict, take error return
PJRST %POPJ1 ;OK, take success return
> ; End %IF20
SUBTTL GETOST - Determine OS type
;++
; FUNCTIONAL DESCRIPTION:
;
; This routine is called just prior to any $OPEN or $CREATE (including
; USEROPEN functions) to do a $PARSE with OFP (output file parse) set
; to determine the operating system for remote files. It is a no-op
; for local files. If the remote system is VAX, change INDX(D) to
; DI.RMS (since all VAX files are RMS files) and back out of any RSF
; setup (TYP block links, UDF RFM, etc.) which may already have been
; done on the assumption that the file is RSF.
;
; CALLING SEQUENCE:
;
; PUSHJ P,GETOST
; <Return here for error>
; <Return here on success>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; NODNAM(D) - Node name
; INDX(D) - Device index
; FAB(D) - Address of FAB
; FORM(D) - FORM=
; ORGAN(D) - ORGANIZATION
; CC(U) - CARRIAGECONTROL
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; INDX(D) - Reset to DI.RMS for VAX, DI.RSF is
; TOPS and RECORDTYPE=STREAM, STREAM_CR/LF
; FAB(D) FOP - Set to OFP before the $PARSE.
; ORG - Defaulted to SEQUENTIAL
; RAT - Set to FB$FTN for VAX CC=FORTRAN
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
%IF20,<
GETOST: SKIPN NODNAM(D) ;Is file remote?
JRST %POPJ1 ;No, just return
PUSHJ P,OFPARS ;Do an OFP $PARSE
JRST RMOERR ;Error
PUSHJ P,FETOST ;Get OS type in OSTYPE(D)
PUSHJ P,VALOST ;Do we support it?
JRST UNSOP ;No, abort
CAIE T2,XA$VMS ;Is it VMS?
JRST %POPJ1 ;No, all done
;Here for remote access to VMS. Reset the INDX(D) to DI.RMS, default
; organization to SEQ and check SHR defaulting
MOVEI T1,DI.RMS
STORE T1,INDX(D) ;Yes, it's now an RMS file
SETZ T1, ;Break any TYP link
$STORE T1,TYP,<(T4)>
LOAD T1,ORGAN(D) ;Get ORGANIZATION
JUMPN T1,VAXSHR ;Got one
MOVX T1,FB$SEQ ;If none, default to SEQ
$STORE T1,ORG,<(T4)>
MOVEI T1,OR.SEQ
STORE T1,ORGAN(D)
;If the file is sequential and we want PUT access to it, change the
; default SHR from GET to NIL, since this is the way VAX defaults for
; these files.
VAXSHR: $FETCH T1,ORG,<(T4)> ;Get ORG value
CAIE T1,FB$SEQ ;SEQUENTIAL?
JRST %POPJ1 ;No, all done
$FETCH T2,FAC,<(T4)> ;Get FAC
MOVX T1,FB$NIL ;Assume PUT is on
TXNE T2,FB$PUT ;Was it?
$STORE T1,SHR,<(T4)> ;Yes, SHR=NIL
JRST %POPJ1 ;Done
UNSOP: MOVEI T1,NODNAM(D)
$DCALL URS ;?Unsupported remote system
> ; End %IF20
SUBTTL OFPARS - Do an OFP $PARSE
;++
; FUNCTIONAL DESCRIPTION:
;
; OFP $PARSE to exchange configuration messages.
;
; CALLING SEQUENCE:
;
; PUSHJ P,OFPARS
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; FOP OFP set, cleared on success
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T2,T4.
;
;--
;[5000] New
%IF20,<
OFPARS: MOVE T4,FAB(D) ;Yes. Get FAB address
$FETCH T2,FOP,<(T4)> ;Turn on OFP bit
TXO T2,FB$OFP
$STORE T2,FOP,<(T4)> ; in FOP
PUSHJ P,PARS$ ;Do $PARSE
JFCL ;Ignore errors for a moment
$FETCH T2,FOP,<(T4)> ;Turn off OFP for later OPEN
TXZ T2,FB$OFP
$STORE T2,FOP,<(T4)>
PUSHJ P,RLFJFN ;If RMS gave us a JFN, toss it
LOAD T2,STS(D) ;Get $PARSE status
CAIGE T2,ER$MIN ;Error?
JRST %POPJ1 ;OK return
POPJ P, ;Error return
> ;End %IF20
SUBTTL RLFJFN - Toss an RMS-returned JFN
;++
; FUNCTIONAL DESCRIPTION:
;
; If the FAB's JFN field is non-zero after an RMS $PARSE or
; other service call, toss the JFN and zero the field
;
; CALLING SEQUENCE:
;
; PUSHJ P,RLFJFN
; <Return here>
;
; INPUT PARAMETERS:
;
; T4 - Address of FAB
;
; IMPLICIT INPUTS:
;
; FAB(D) JFN - FAB returned JFN field
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) JFN - Zeroed
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5000] New
%IF20,<
RLFJFN: $FETCH T1,JFN,<(T4)> ;Get JFN,
JUMPE T1,%POPJ ;if any
RLJFN% ;Release it
ERJMP .+1 ;We tried
SETZ T1,
$STORE T1,JFN,<(T4)> ;Clear the field
POPJ P, ;Return
> ;End %IF20
SUBTTL VALOST - Validate a remote operating system
;++
; FUNCTIONAL DESCRIPTION:
;
; Called with the returned OS type code from the CONFIG XAB in T2.
; Returns +1 if the remote system is not supported for Fortran I/O,
; else +2.
;
; CALLING SEQUENCE:
;
; PUSHJ P,VALOST
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; T2 - OS code from CONFIG XAB
;
; IMPLICIT INPUTS:
;
; OSTAB - Table of supported remote systems
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T3.
;
;--
;[5000] New
%IF20,<
VALOST: MOVEI T1,OSTAB ;Point at table of supported OS's.
VALOOP: MOVE T3,(T1) ;Get an entry
JUMPE T3,%POPJ ;End of table and no match
CAME T2,T3 ;Found it?
AOJA T1,VALOOP ;No, keep looking
JRST %POPJ1 ;Yes, return +1
;Table of remote operating systems supported by Fortran
OSTAB: XA$T20 ;TOPS20
XA$VMS ;VAX
0 ;Table end
> ; End %IF20
SUBTTL SETBSZ - Set/default Bytesize
;++
; FUNCTIONAL DESCRIPTION:
;
; If a BYTESIZE= was specified, set the FAB to it and calculate bytes/
; word. If none, default TOPS files by MODE and set non-TOPS files
; to 8. Produce an error for non-TOPS files with BYTESIZE not
; equal to 8. Produce an error for TOPS indexed files with KEY=
; datatype of CHARACTER if BYTESIZE is not equal to 7.
;
; CALLING SEQUENCE:
;
; PUSHJ P,SETBSZ
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; UBSIZ(D) - BYTESIZE=
; MODE(D) - MODE=
; STGFLG(D) - Non-zero if KEY= contains datatype
; CHARACTER
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) BSZ - Bytesize
; BSIZ(D) - File bytesize
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4
;
;--
;[5000] New
%IF20,<
SETBSZ: LOAD T1,UBSIZ(D) ;Did user specify a size?
STORE T1,BSIZ(D)
JUMPN T1,CHKBPW ;Yes, check for non-TOPS size
PUSHJ P,NTTOPS ;No. TOPS file?
JRST TOPBSZ ;Yes, default by MODE
MOVEI T1,^D8 ;Non-TOPS. Default to 8
STORE T1,BSIZ(D)
JRST SETBPW
TOPBSZ: LOAD T1,MODE(D) ;No. Set by mode
LOAD T2,INDX(D) ;If RMS file
CAIN T2,DI.RMS
MOVX T1,MD.ASC ;It's really ascii
MOVE T2,BSTAB(T1) ;Get local byte size by mode
STORE T2,BSIZ(D) ;Save
JRST SETBPW
CHKBPW: PUSHJ P,NTTOPS ;Non-TOPS file?
JRST STGCHK ;TOPS, check for STG datatype
LOAD T1,BSIZ(D) ;Non-TOPS, better be 8
CAIE T1,^D8
$DCALL BME ;?Bytesize must be eight
SETBPW: PUSHJ P,CHKBSZ ;Go setup BPW, etc
LOAD T2,BSIZ(D) ;Get size again
MOVE T4,FAB(D) ;Get FAB address again
$STORE T2,BSZ,<(T4)> ;Store it for RMS
JRST %POPJ1 ;Take success return
STGCHK: SKIPN STGFLG(D) ;XABs have STG datatype?
JRST SETBPW ;No, OK
LOAD T1,BSIZ(D) ;Yes, bytesize must be 7
CAIE T1,7
$DCALL KDB ;"?Key datatype conflicts with BSZ"
JRST SETBPW
> ; End %IF20
SUBTTL SETRFM - Set/default RECORDTYPE/RFM
;++
; FUNCTIONAL DESCRIPTION:
;
; Setup RFM for all RSF files and for RMS files for which a user
; RECORDTYPE= value exists. Set MRS appropriately for file-type.
;
; RSF files always set RFM to UDF (and FAC to BRO) for block-mode
; I/O.
;
; MRS is set to either the user's RECL or, if no RECL, to a
; slightly bogus value of one. MRS must be non-zero
; for RSF files, since if zero RMS will ignore the specified
; bytesize and create a 7-bit file,
;
; RMS files are equally tortuous, in order to conform to the
; VMS RECORDTYPE defaulting scheme. MRS is set according to the
; user's RECL: if the file contains fixed-length records, RECL
; specifies the size of each record; if variable, it specifies
; the maximum record length; if absent, RMS does not check for
; maximum record length. If a RECORDTYPE= exists, we set RFM
; to it now; if it is absent, this routine leaves RFM untouched
; and the RFM is set just before the actual OPEN depending on
; whether the file exists or not. If it exists, the file's
; permanent RFM is used; if a new file, we then default as follows
; (mostly VAX compatibly):
;
; ORGANIZATION=RELATIVE or INDEXED: RFM=FIXED
; All other RMS files: RFM=VARIABLE
;
; Note that RMS-20 does not support random-access to fixed-length
; sequential files.
;
; This routine checks that a specified RECORDTYPE is legal for
; the file type in question.
; CALLING SEQUENCE:
;
; PUSHJ P,SETRFM
; <Error return>
; <Sucess return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; INDX(D) - Device index
; RECTP(D) - RECORDTYPE
; ORGAN(D) - ORGANIZATION
; RSIZ(D) - RECORDSIZE
; FORM(D) - FORM=
; RTTAB - Table of supported TOPS RMS recordtypes
; VRTTAB - Table of supported VMS RMS recordtypes
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) RFM - Set to FB$UDF for all RSF files.
; FAC - Set to BRO for RSF
; MRS - Set to maximum recordsize in bytes
; MBF - Set to user's BUFFERCOUNT for RMS files
; MRSIZE(D) - Set to user's MRS
; FRSIZB(D) - Set to user's MRS
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
%IF20,<
SETRFM: MOVE T4,FAB(D) ;Get FAB address
LOAD T1,INDX(D) ;Get file type
CAIE T1,DI.RSF ;RSF?
JRST RMSRFM ;No, set RMS RFM
LOAD T1,RECTP(D) ;Get user's RECTP
JUMPE T1,RSFUDF ;None
CAIE T1,RT.UND ;If given, must be stream
JRST UNSRFM
;Here for RSF files
RSFUDF: MOVX T1,FB$UDF ;Set to UDF
$STORE T1,RFM,<(T4)>
$FETCH T1,FAC,<(T4)> ;Set BRO in the FAC
TXO T1,FB$BRO
$STORE T1,FAC,<(T4)>
LOAD T1,RSIZE(D) ;Get RECORDSIZE=
JUMPN T1,SETMRS ;Got one
MOVEI T1,1 ;No, fake an MRS
$STORE T1,MRS,<(T4)>
JRST %POPJ1 ;And take success return
RMSRFM: LOAD T1,RECTP(D) ;Get RECORDTYPE
JUMPE T1,SETMRS ;None, set MRS
MOVEI T2,RTTAB ;Point at TOPS table
MOVE T3,OSTYPE(D) ;But check if VMS system
CAIN T3,XA$VMS ;VMS?
MOVEI T2,VRTTAB ;Yes, use non-restrictive table
ADDI T2,(T1) ;Point at correct entry
HRRE T3,(T2) ;Get value
JUMPL T3,UNSRFM ;Not supported
HLRZ T2,(T2) ;OK, get RMS equivalent
$STORE T2,RFM,<(T4)> ;Set RFM
PUSHJ P,RMSCC ;Go check CC form RMS files
SETMRS: LOAD T1,RSIZE(D) ;Get RECORDSIZE
LOAD T2,FORM(D) ;Get FORM=
CAIE T2,FM.FORM ;FORMATTED?
IMUL T1,BPW(D) ;No, convert to bytes
$STORE T1,MRS,<(T4)> ;Set as MRS
JRST %POPJ1 ;Take success return
> ; End %IF20
SUBTTL RMSCC - Check CARRIAGECONTROL for RMS files
;++
; FUNCTIONAL DESCRIPTION:
;
; Called only for RMS files. Checks/defaults CC as follows:
;
; If CC=TRANSLATED, reset it to FORTRAN. TRANSLATED makes no sense
; for RMS files, and VMS can't stand embedded carriagecontrol from
; a TOPS.
;
; Since VMS will convert CC=FORTRAN for RECORDTYPE=STREAM files
; to "implied carriage control" from a remote system, reset
; to VARIABLE if non-TOPS.
;
; If CC=FORTRAN (the default for non-STREAM RMS files), set the
; RAT FTN bit if the remote system is non-TOPS. For VMS and others,
; FTN CC is a record attribute, not a file attribute. RAT FB$FTN
; should never be set for a TOPS RMS file, since the RMSFAL will
; then do its best to convert the RMS file into a STREAM file.
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMSCC
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; CC(U) - CARRIAGECONTROL
; FAB(D) - Address of FAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; CC(U) - Reset to FORTRAN if TRANSLATED
; FAB(D) RAT - Set to FB$FTN is system is non-
; TOPS and CC=FORTRAN
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5000] New
%IF20,<
RMSCC: LOAD T1,CC(U) ;Get CARRIAGECONTROL
CAIN T1,CC.TRN ;TRANSLATED?
MOVX T1,CC.FOR ;Yes, reset to CC=FORTRAN
STORE T1,CC(U)
CAIN T1,CC.FOR ;If not CC=FORTRAN
PUSHJ P,NTTOPS ; or system is TOPS
POPJ P, ; then all done
;System is remote non-TOPS and CC=FORTRAN. The attribute will not be
;honored by most remote systems, so change the RECORDTYPE to VARIABLE.
MOVE T4,FAB(D) ;Get FAB address
$FETCH T1,RAT,<(T4)> ;Get RAT bits
TXO T1,FB$FTN ;Turn on FTN
$STORE T1,RAT,<(T4)> ;Put back
LOAD T1,RECTP(D) ;Get RECORDTYPE
CAIN T1,RT.UNS ;None given, or
MOVX T1,RT.UND ;STREAM?
CAIE T1,RT.UND
POPJ P, ;No
MOVX T2,FB$VAR ;Yes, switch to VARIABLE
$STORE T2,RFM,<(T4)>
MOVX T2,RT.DEL
STORE T2,RECTP(D)
POPJ P,
> ;End %IF20
SUBTTL DFRFMN - Default RMS RFM for new files
;++
; FUNCTIONAL DESCRIPTION:
;
; A no-op for RSF files and for RMS files for which a RECORDTYPE
; has been specified. This routine defaults the RFM just before
; a $CREATE to FIXED for relative or indexed files and for direct-
; access sequential files, and to VARIABLE for all other RMS files.
;
; For STATUS='UNKNOWN' indexed files, check whether a KEY= has
; been specified when $CREATEing a new file.
;
; CALLING SEQUENCE:
;
; PUSHJ P,DFRFMN
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - FAB address
; INDX(D) - File type
; RECTP(D) - RECORDTYPE=
; ORGAN(D) - ORGANIZATION=
; ACC(D) - ACCESS=
; RSIZE(D) - RECORDSIZE=
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) RFM - Default RFM
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5000] New
%IF20,<
DFRFMN: LOAD T1,INDX(D) ;Get file type
CAIE T1,DI.RMS ;RMS file?
JRST %POPJ1 ;No, a no-op
LOAD T1,ORGAN(D) ;Get ORGANIZATION
LOAD T2,RSIZE(D) ;Get RECL
JUMPN T2,DFRFM1 ;Got one
CAIE T1,OR.REL ;RELATIVE?
CAIN T1,OR.IDX ;or INDEXED?
$DCALL RIR ;Yes, must have RECL=
DFRFM1: CAIE T1,OR.IDX ;INDEXED?
JRST DFRFM2 ;No
LOAD T1,SAIDX(D) ;Get STATUS/ACCESS index
CAIN T1,SA.URW ;UNKNOWN R/W (random)?
JRST DFRFM2 ;Yes, don't require XABs
SKIPN XAB(D) ;KEY= given for new file?
JRST NPKERR ;No, give ER$NPK
DFRFM2: LOAD T2,RECTP(D) ;Yes, get RECORDTYPE
JUMPN T2,%POPJ1 ;Got one, RFM already set
;Here to figure out appropriate RFM default based on file and access
CAIE T1,OR.REL ;RELATIVE?
CAIN T1,OR.IDX ;or INDEXED?
JRST FIXRFM ;Yes, default to FIXED
;The following check is unnecessary until RMS implements direct-access
; to fixed-length sequential files.
LOAD T1,ACC(D) ;It's SEQUENTIAL, get access
CAIE T1,AC.RIO ;DIRECT?
CAIN T1,AC.RIN
JRST FIXRFM ;Yes, default is FIXED
SKIPA T2,[FB$VAR]
FIXRFM: MOVX T2,FB$FIX
MOVE T4,FAB(D) ;Get FAB address
$STORE T2,RFM,<(T4)> ;Set in FAB
LOAD T1,RSIZE(D) ;Get RECL
JUMPN T1,%POPJ1 ;Got one
CAIN T2,FB$FIX ;Did we default to FIXED?
$DCALL DFR ;?Default /RECT:FIXED requires /RECL
JRST %POPJ1 ;Return
NPKERR: MOVE T1,FAB(D)
MOVX T2,ER$NPK ;We fake an NPK error
SETZ T3,
PUSHJ P,MAKSTS
JRST RMOER3 ;Go fail
> ; End %IF20
SUBTTL APPCHK - Set ROP for ACCESS='APPEND'
;++
; FUNCTIONAL DESCRIPTION:
;
; This routine sets ROP to EOF for RMS files for which ACCESS=
; 'APPEND'. It is a no-op for RSF files, as block-mode does not
; provide for EOF positioning on an OPEN. Append RSF files have their
; last page mapped in after the OPEN.
;
; Also sets MBF (multibuffercount) from UBUFCT(D), the user's
; BUFFERCOUNT, else defaults to RMS's MBF.
;
; CALLING SEQUENCE:
;
; PUSHJ P,APPCHK
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; INDX(D) - Device type
; ACC(D) - ACCESS=
; RAB(D) - Address of RAB
; UBUFCT(D) - User's BUFFERCOUNT
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; ACC(D) - Set to AC.SOU if ACCESS='APPEND'
; RAB(D) ROP - Set to RB$EOF for append-access RMS
; files
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4.
;
;--
;[5000] New
%IF20,<
APPCHK: LOAD T1,INDX(D) ;Get file type
CAIN T1,DI.RSF ;RSF?
POPJ P, ;Yes, just return
MOVE T4,RAB(D) ;Get RAB address
LOAD T1,UBUFCT(D) ;Get user's BUFFERCOUNT
$STORE T1,MBF,<(T4)>
LOAD T1,ACC(D) ;Get ACCESS
CAIE T1,AC.APP ;'APPEND'?
POPJ P, ;No, don't reset anything
MOVEI T1,AC.SOU ;Yes, set SEQUENTIAL
STORE T1,ACC(D)
PUSHJ P,EOFON ;Turn on EOF
POPJ P,
> ; End %IF20
SUBTTL CHKRET - Check post-OPEN values and update DDB
;++
; FUNCTIONAL DESCRIPTION:
;
; This jacket routine calls routines to check that RMS-returned
; file attributes match those specified in the user's OPEN statement.
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,CHKRET
; <Error return; DIALOG will be entered>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5000] New
%IF20,<
CHKRET: PUSHJ P,RETRCT ;Update returned RFM/RECTP value
POPJ P, ;Conflict, error return
PUSHJ P,RETMRS ;Check returned MRS value
POPJ P, ;Conflict, error return
PUSHJ P,SETIMF ;Set IMGFLG by file type
PUSHJ P,SETCSH ;Setup a cache for RMS sequentials
JRST %POPJ1 ;Success return
> ; End %IF20
SUBTTL RETRCT - Update RECTP(D) from returned RFM
;++
; FUNCTIONAL DESCRIPTION:
;
; Setup RECTP from FAB RFM for RMS files only. The return RFM for RSF
; files must be one of FB$STM, FB$UDF, or FB$LSA; any other value
; probably means the file is actually an RMS file.
;
; Table RTTAB maps returned RFM values into RECTP(D) values for non-
; VMS RMS files; -1 RH means this returned RFM value is not supported
; by FOROTS for RMS files. VMS RMS files (i.e. all VMS files) use
; a non-restrictive VRTTAB table, since VMS Sequential files can have
; recordtype STM. (Non-sequential STM types are trapped before
; the OPEN).
;
; CALLING SEQUENCE:
;
; PUSHJ P,RETRCT
; <Error return; DIALOG>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; INDX(D) - Device index
; FAB(D) RFM - Returned record format value
; OSTYPE(D) - OS type
; RECTP(D) - RECORDTYPE
; RTTAB - RFM-to-RECTP table for non-VMS RMS files
; VRTTAB - " " " VMS files
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RECTP(D) - DDB RECORDTYPE value
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
%IF20,<
RETRCT: MOVE T4,FAB(D) ;Get FAB address
LOAD T2,INDX(D) ;Get file type
$FETCH T1,RFM,<(T4)> ;Get RMS return value
CAIE T2,DI.RMS ;RMS?
JRST RSFRFM ;No, check RSF RFM
MOVEI T2,RTTAB ;Point at normal table
MOVE T3,OSTYPE(D) ;But check if VMS system
CAIN T3,XA$VMS ;VMS?
MOVEI T2,VRTTAB ;Yes, use non-restrictive table
PUSHJ P,RTMAP ;Try to match it
JRST UNSRFM ;Not found or unsupported
LOAD T2,RECTP(D) ;Get user's RECORDTYPE=
JUMPE T2,RSTRCT ;None, use returned
CAMN T3,T2 ;Does user agree with RMS?
JRST RSTRCT ;Yes, go store
XMOVEI T1,[ASCIZ /RECORDTYPE/]
$DCALL ATC ;?File's RECORDTYPE conflicts with
; OPEN statement or default
RSTRCT: STORE T3,RECTP(D) ;Store
JRST %POPJ1
;Here for recordtypes returned for RSF files.
RSFRFM: CAIE T1,FB$UDF ;RMS-UDF?
CAIN T1,FB$STM ;or STREAM?
JRST %POPJ1 ;Yes, OK
CAIN T1,FB$LSA ;or LSA?
JRST %POPJ1 ;Yes, OK
CAIE T1,FB$VAR ;VARIABLE?
CAIN T1,FB$FIX ;or FIXED?
$DCALL RMS
UNSRFM: LOAD T1,RECTP(D) ;Get user's RECORDTYPE
CAIN T1,RT.UNS ;If none given, it's STREAM
MOVX T1,RT.UND
MOVEI T2,SWRECT ;Get address of switch table
PUSHJ P,FNDSWT ;Get switch string
MOVEM T1,%ARGNM
$DCALL URT ;?Recordtype x not supported for
; this file type
> ; End %IF20
SUBTTL RTMAP - Map an RFM to a RECORDTYPE
;++
; FUNCTIONAL DESCRIPTION:
;
; Converts an RFM value to a corresponding RECORDTYPE value. The
; address of a table is passed as an argument. The table determines
; whether a particular RFM value is supported for not.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RTMAP
; <Return here if RFM not matched, or RFM is unsupported>
; <Return here if matched; RECORDTYPE value in T3>
;
; INPUT PARAMETERS:
;
; T1 - RFM value to match
; T2 - Address of RFM/RECORDTYPE table
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; T3 - RECORDTYPE value which matches the RFM. If no
; match, or unsupported RFM, T3 is indeterminate.
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5000] New
%IF20,<
RTMAP: HLRE T3,(T2) ;Get an RMS value
JUMPL T3,%POPJ ;End of table and no match
CAIE T1,(T3) ;Match?
AOJA T2,RTMAP ;No, keep looking
HRRE T3,(T2) ;Yes, get FOROTS value
JUMPL T3,%POPJ ;Unsupported RMS value
JRST %POPJ1 ;Found and supported
> ;End %IF20
SUBTTL RETMRS - Check returned MRS value
;++
; FUNCTIONAL DESCRIPTION:
;
; Set RSIZE(D) to the returned MRS value (recordsize
; in bytes or words) if the user's size agrees with RMS. If
; the user specified no size, use MRS.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RETMRS
; <Error return; DIALOG>
; <Succes return>
;
; INPUT PARAMETERS:U;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) MRS - Returned MRS value
; RFM - Returned RFM
; INDX(D) - Device type
; FORM(D) - FORM=
; BPW(D) - Bytes/word
; RSIZE(D) - RECL=
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RSIZE(D) - Set to MRS if returned and user size
; was specified and RFM=FIXED.
; MRSIZE(D) - Set to MRS for I/O buffer size
; FRSIZB(D) - Set to user's MRS
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
%IF20,<
RETMRS: LOAD T1,INDX(D) ;Get file type
CAIN T1,DI.RSF ;RSF?
JRST %POPJ1 ;Yes, don't bother checking it
MOVE T4,FAB(D) ;Get FAB address
$FETCH T1,MRS,<(T4)> ;Get max rec size
STORE T1,MRSIZE(D) ;Save as MRS buffer size
$FETCH T2,RFM,<(T4)> ;Get RMS recordformat
CAIE T2,FB$VAR ;Set buffersize if fixed
STORE T1,FRSIZB(D)
LOAD T3,ORGAN(D) ;or if INDEXED
CAIN T3,OR.IDX
STORE T1,FRSIZB(D)
JUMPE T1,MRSCMP ;None, see if user specified one
;T1 has MRS
CAIE T2,FB$FIX ;RECORDTYPE FIXED?
CAIN T3,OR.REL ;or ORGANIZATION RELATIVE?
TRNA ;Yes, recalculate RSIZE
JRST %POPJ1 ;No, MRS is just a maximum
LOAD T2,FORM(D) ;Get FORM
CAIN T2,FM.FORM ;FORMATTED?
JRST MRSCMP ;Yes, already in bytes
ADD T1,BPW(D) ;Round up to words
SUBI T1,1
IDIV T1,BPW(D) ;Get words
MRSCMP: LOAD T2,RSIZE(D) ;Get user's RECORDSIZE
JUMPE T2,UPDMRS ;None, use returned
CAMN T1,T2 ;Same?
JRST UPDMRS ;Yes
XMOVEI T1,[ASCIZ /RECORDSIZE/]
$DCALL ATC
UPDMRS: MOVEM T1,RSIZE(D)
JRST %POPJ1
> ; End %IF20
SUBTTL SETIMF - Set IMGFLG(D) by file type
;++
; FUNCTIONAL DESCRIPTION:
;
; Set IMGFLG(D) for all RMS files to prevent processing of LSCWs.
; Also set for RSF files for which MODE='IMAGE'.
;
; CALLING SEQUENCE:
;
; PUSHJ P,SETIMF
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; INDX(D) - Device index
; MODE(D) - MODE
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; IMGFLG(D) - Set for RMS files and image-mode RSF.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5000] New
%IF20,<
SETIMF: LOAD T1,INDX(D)
CAIE T1,DI.RMS ;RMS file?
JRST IMFRSF ;No
SETOM IMGFLG(D) ;Yes, set flag
POPJ P,
IMFRSF: SETZM IMGFLG(D) ;Clear flag
LOAD T1,MODE(D) ;Get Fortran data mode
CAIN T1,MD.IMG ;Image?
SETOM IMGFLG(D) ;Yes. Set flag
POPJ P,
> ; End %IF20
SUBTTL SETCSH - Setup a cache for RMS sequential access files
;++
; FUNCTIONAL DESCRIPTION:
;
; For RMS sequential files, if CACHSZ .NEQ. 0, allocate a cache.
;
; CALLING SEQUENCE:
;
; PUSHJ P,SETCSH
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; INDX(D) - Device index
; ORGAN(D) - Organization
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; CACHE(D) - Address of cache (CASHSZ words)
; CACHPT(D) - Pointer into cache initialized
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
SETCSH: LOAD T1,INDX(D) ;Get file type
CAIE T1,DI.RMS ;If RSF,
POPJ P, ;nothing to do
MOVEI T1,CACHSZ ;Get CACHSZ in words
JUMPE T1,%POPJ ;None, we're done
LOAD T2,ORGAN(D) ;Get organization
CAIE T2,OR.SEQ ;Cache only RMS sequential
POPJ P,
PUSHJ P,%GTBLK ;Allocate a cache
$ACALL MFU ;Can't
MOVEM T1,CACHE(D) ;Save cache address
MOVEM T1,CACHPT(D) ;Initialize pointer
POPJ P, ;Return
> ; End %IF20
SUBTTL SETWTB - Setup WTAB
;++
; FUNCTIONAL DESCRIPTION:
;
; Sets WTAB to minus one for random-access RMS relative files.
; Sets WTAB to a page table for random-access RSF files.
; Sets WTAB to zero for other RMS and RSF files.
;
; Sets WSIZ for all files, WADR and BUFADR for sequential files.
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,SETWTB
; <Return here; errors go to ABORT>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ACC(D) - ACCESS
; INDX(D) - Device index
; ORGAN(D) - ORGANIZATION
; BUFCT(D) - BUFFERCOUNT
; BPW(D) - Bytes-per-word
; WPTR(D) - Page address of buffer pages
; EOFN(D) - EOF byte number
;
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; WTAB(D) - -1 for RMS-relative direct access files
; Page table pointer for random-access RSF
; files
; WPTR(D) - Core page address of buffer pages
; WSIZ(D) - Window size in bytes
; WADR(D) - Address of window
; BUFADR(D) - Synonym for WADR.
; EOFN(D) - Set to infinity for RMS files, to
; EOF byte # for RSF files.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
; Reads in the FDB "page" for all RSF file.
; Allocates a page table for random-access RSF files.
;
;
;--
;[5000] New
%IF20,<
SETWTB: SETZM WTAB(D) ;Clear WTAB
LOAD T1,ACC(D) ;Get ACCESS
CAIE T1,AC.RIO ;ACCESS='DIRECT'?
CAIN T1,AC.RIN
SETOM WTAB(D) ;Yes, flag WTAB
LOAD T1,INDX(D) ;Get file type
CAIN T1,DI.RSF ;RSF?
JRST SETRSF ;Yes, setup for RSF input
HRLOI T1,377777 ;RMS EOFN's are infinite
MOVEM T1,EOFN(D)
POPJ P,
SETRSF: PUSHJ P,RSGFDB ;Setup RSF's EOF, FDB, etc.
LOAD T1,BUFCT(D) ;Get Buffercount
PUSHJ P,%GTPGS ;Get buffer pages
$ACALL MFU ;Can't, memory full
MOVEM T1,WPTR(D) ;Save page address
SKIPGE WTAB(D) ;ACCESS='DIRECT'?
PJRST RANALC ;Yes, setup WTAB with page table
MOVE T1,WPTR(D) ;Get page address
LSH T1,LWSIZ ;Get core address
HRRZM T1,WADR(D) ;Save address
HRRZM T1,BUFADR(D) ;here too
LOAD T1,BUFCT(D) ;Get buffercount again
LSH T1,LWSIZ ;Get # words
IMUL T1,BPW(D) ;Get # bytes in it
MOVEM T1,WSIZ(D) ;Save window size
LOAD T1,ACC(D) ;Get access type
CAIE T1,AC.APP ;Append?
POPJ P, ;No, all done
MOVEI T1,AC.SOU ;Yes, set SEQUENTIAL
STORE T1,ACC(D)
MOVE T2,EOFN(D) ;Get # bytes in file
MOVEM T2,BYTN(D) ;Save as byte number also
PUSHJ P,RMAPW ;Map in EOF page
PJRST SETPTR ;Setup pointers, return
> ; End %IF20
SUBTTL RSGFDB - Get FDB, set EOFN for RSF files
;++
; FUNCTIONAL DESCRIPTION:
;
; Obtains FDB data for an RSF file, storing in FDB for updating
; EOFN(D).
;
; CALLING SEQUENCE:
;
; PUSHJ P,RSGFDB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FDB - FDB block
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Reads an FDB page over the network (!).
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
RSGFDB: PUSHJ P,RSRFDB ;Get the FDB page
$ACALL OPN ;Can't, abort
MOVSI T1,(T1) ;Get source to BLT for EOFSET
MOVEI T2,FDB ;Get destination
HRRI T1,(T2)
ADDI T2,.FBSIZ
BLT T1,(T2) ;BLT upto .FBSIZ
PUSHJ P,FTMPPG ;Free the FDB page
PJRST %RSEOF ;Go set EOFN, etc.
> ; End %IF20
SUBTTL RSRFDB - Get FDB page for an RSF file
;++
; FUNCTIONAL DESCRIPTION:
;
; Reads "bucket 0" from an RSF file, returning a page containing the
; file's FDB.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RSRFDB
; <Error return, page deallocated>
; <Success return, page address in T1>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T1 - Address of FDB data
;
; IMPLICIT OUTPUTS:
;
; RAB(D) USZ - Set to words/page
; UBF - Set to address of core page
; BKT - Set to "bucket 0" for file
; RAC - Set to RB$BLK for block mode
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
; Calls %GTBLK for one page of memory.
;
;--
;[5000] New
%IF20,<
RSRFDB: MOVEI T1,PSIZ ;Get one page for FDB bucket
PUSHJ P,%GTBLK ;Get it, zeroed
$ACALL MFU ;Can't
MOVEM T1,T2 ;Copy for GETBKT
SETZ T1, ;Read bucket 0
PUSHJ P,GETBKT ;$READ it
PJRST FTMPPG ;Can't, deallocate and return+1
$FETCH T1,UBF,<(T4)> ;Get page address
MOVEM T1,T3 ;Copy
ADDI T1,.FBLEN ;Setup to clear rest of page
SETZM (T1)
HRL T2,T1
HRRI T2,1(T1) ;start,,start+1
BLT T2,PSIZ-1(T3)
MOVE T1,T3 ;Return start address
JRST %POPJ1 ;Take success return
> ; End %IF20
SUBTTL FTMPPG - Free a temporary page
;++
; FUNCTIONAL DESCRIPTION:
;
; Calls %FREBLK to return the page to which the "bucket 0" FDB
; has been written.
;
; CALLING SEQUENCE:
;
; PUSHJ P,FTMPPG
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) UBF - Address of page
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5000] New
%IF20,<
FTMPPG: MOVE T4,RAB(D) ;Get RAB address
$FETCH T1,UBF,<(T4)> ;Get page core address
PUSHJ P,%FREBLK ;Free the page
POPJ P,
> ; End %IF20
SUBTTL RSWFDB - Write FDB page for an RSF file
;++
; FUNCTIONAL DESCRIPTION:
;
; Writes "bucket 0" or FDB page for an RSF file. The address of the
; page to write is in T1.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RSWFDB
; <Error return; page is deallocated>
; <Success return>
;
; INPUT PARAMETERS:
;
; T1 - Address of page to write
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) UBF - Set to address of page to write
; RSZ - Set to page size in bytes
; BKT - Set to "bucket 0"
; RAC - Set to RB$BLK
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5000] New
%IF20,<
RSWFDB: MOVE T4,RAB(D) ;Get RAB address
MOVEM T1,T2 ;Copy our buffer address
SETZ T1, ;BKT 0 for FDB
PUSHJ P,PUTBKT ;$WRITE it
PJRST FTMPPG ;Can't, deallocate, error ret
JRST %POPJ1 ;Success
> ; End %IF20
SUBTTL CALUOP - Call a user USEROPEN routine
;++
; FUNCTIONAL DESCRIPTION:
;
; Called with the address of the USEROPEN routine in UOPN(D). Calls
; the USEROPEN routine:
;
; XMOVEI 16,arglist
; PUSHJ 17,useropen
;
; Passes an argument list of the following form:
;
; -3,,0
; IFIW TP%INT,,address of unit
; IFIW TP%LBL,,address of FAB
; IFIW TP%LBL,,address of RAB
;
; The user's routine returns AC0 non-zero on failure, zero on
; success.
;
; CALLING SEQUENCE:
;
; PUSHJ P,CALUOP
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; T1 - Contents of UOPN(D)
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
UOUNT==0 ;Unit arg offset
UOFAB==1 ;FAB address offset
UORAB==2 ;RAB address offset
UOARNM==3 ;Number of USEROPEN args
CALUOP: XMOVEI T1,@T1 ;Get address to call
SKIPN (T1) ;destination valid?
$ACALL MEU ;?Missing EXTERNAL
MOVEM T1,USRADR ;Save it
MOVE T1,FAB(D)
PUSHJ P,RETSUC ;Assume success
MOVE T1,RAB(D)
PUSHJ P,RETSUC
PUSH P,L ;Save L
XMOVEI L,UOPARG ;Point to arglist
HRLI T1,(IFIW TP%INT,) ;Setup unit #
HRRI T1,%CUNIT
MOVEM T1,UOUNT(L) ;Save as unit argument
HRLI T1,(IFIW TP%LBL,) ;Setup FAB address
HRR T1,FAB(D)
MOVEM T1,UOFAB(L) ;Save as FAB arg
HRLI T1,(IFIW TP%LBL,) ;Setup RAB address
HRR T1,RAB(D)
MOVEM T1,UORAB(L) ;Save as RAB arg
PUSHJ P,@USRADR ;Call USEROPEN
POP P,L ;Restore L
JUMPE T0,%POPJ1 ;User says it succeeded
;Since the user says the routine failed, we will believe him/her. The 2
; pathological cases are:
;
; 1) AC0 .EQ.0 but the routine actually failed to $OPEN and $CONNECT.
; This will result in unpredictable failures on subsequent I/O.
; 2) AC0 .NEQ.0 but the routine actually succeeded. This will result
; in an unpredictable FOROTS "error".
PUSHJ P,RABSTV ;Update RAB status first
CAIGE T2,ER$MIN ;Error in RAB?
PUSHJ P,FABSTV ;No, must be in FAB
$DCALL UOF ;USEROPEN failed
;Argument list passed to USEROPEN routine
SEGMENT DATA
-UOARNM,,0
UOPARG: BLOCK UOARNM
USRADR: BLOCK 1 ;Address of USEROPEN routine
SEGMENT CODE
> ; End %IF20
SUBTTL NTTOPS - Determine if remote operating-system is TOPS
;++
; FUNCTIONAL DESCRIPTION:
;
; Checks the OSTYPE(D) to determine whether the remote system is
; TOPS.
;
; CALLING SEQUENCE:
;
; PUSHJ P,NTTOPS
; <Return here if TOPS> ;TOPS is an error condition!
; <Return here if not TOPS>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; NODNAM(D) - Node name
; OSTYPE(D) - OS code from CONFIG XAB
;
; OUTPUT PARAMETERS:
;
; T2 - OSTYPE(D)
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T2.
;
;--
;[5000] New
%IF20,<
NTTOPS: SKIPN NODNAM(D) ;Remote file?
POPJ P, ;No, must be TOPS
MOVE T2,OSTYPE(D) ;Get OS code
CAIE T2,XA$T20 ;TOPS20?
CAIN T2,XA$T10 ;or TOPS10?
POPJ P, ;Yes, return+1
JRST %POPJ1 ;No, return+2
> ; End %IF20
SUBTTL %RMLKP - Lookup an RMS file
;++
; FUNCTIONAL DESCRIPTION:
;
; Does a $PARSE/$SEARCH lookup on the DDB file to determine whether
; the file exists, using a scratch FAB and %TXTBF to receive the FNA
; string; or, if entry RMLKD is called, uses the FAB pointed to
; by FAB(D).
;
; Calls %RMFNS to pull together a filespec string from its DDB
; fields.
;
; For remote files:
; If the lookup succeeds, the expanded filespec string, including
; attributes, if any, is stored in EXFBUF so a later %GTFNS call
; will not have to re-lookup the file.
;
; For all files:
; IJFN is set to -1 if the lookup succeeds.
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMLKP
; <Return here if file not found>
; <Return here if file exists>
;
; INPUT PARAMETERS:
;
; None
;
;
; IMPLICIT INPUTS:
;
; NODNAM(D) - Node name
; DDB filespec fields
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; %TXTBF - Recieves DDB filespec string
; EXFBUF - Resultant expanded filespec, or 0
; if lookup failed
; IJFN(D) - Set to -1 if lookup succeeds
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Invokes RMS.
; Uses T1,T2,T4.
;
;--
;[5001] New
IF10,<
%RMLKP: $SNH ;Should NOT get here on TOPS-10
> ;End IF10
%IF20,<
%RMLKP: XMOVEI T4,SCRFAB ;Enter here to use SCRFAB
MOVEM T4,LKPFAB ;Save as local FAB address
SETOM RLSFLG ;Flag "release link" on exit
JRST RMLKC
RMLKD: MOVE T4,FAB(D) ;Enter here for FAB(D)
MOVEM T4,LKPFAB
SETZM RLSFLG ;Flag "don't release link" on exit
RMLKC: PUSHJ P,ABINI ;Re-init NAM,SCRFAB, TYP
MOVE T1,[POINT 7,EXFBUF] ;Destination for FNA string
MOVEM T1,DESPTR ;Save also for resultant string
PUSHJ P,%RMFNS ;Get DDB filespec string
MOVE T4,LKPFAB
$STORE T1,FNA,<(T4)> ;Save address
XMOVEI T1,NAMBLK ;Get NAMBLK's address
$STORE T1,NAM,<(T4)> ;Link to FAB
$PARSE @LKPFAB,LKPERR ;Lookup the file
$SEARCH @LKPFAB,LKPERR ;Get resultant filespec
MOVE T1,LKPFAB ;Get FAB's address
PUSHJ P,FABST2 ;Update FAB STV
SETOM IJFN(D) ;Flags files exists
MOVE T4,LKPFAB ;Get FAB address
SKIPE RLSFLG ;Release link?
PUSHJ P,RLSLNX ;Yes
PUSHJ P,DRJOFF ;Turn DRJ off
PUSHJ P,RLFJFN ;Toss any RMS-returned JFN
;Save the resultant expanded filespec, with attributes.
SETZM CVFLAG ;Don't ^V anything
PUSHJ P,RETRSA ;
JRST %POPJ1 ;OK, return +2
LKPERR: CAIE T2,ER$FLK ;File locked for some reason?
JRST LKPFNF ;No, not found or ambiguous
;Here for a "File is locked" $SEARCH failure. This is sufficient evidence
;that the file exists, so we clear the error and return to $SEARCH+1.
;Note that even though it failed, $SEARCH has updated the NAM block.
SKIPE T1,FAB(D) ;If a real FAB,
PUSHJ P,RETSUC ; clear the error
$RETURN ;Return from LKPERR error call
LKPFNF: POP P,%RMPDP ;Save error return
SETZM IJFN(D) ;File doesn't exist
SETZM EXFBUF ;No resultant string
SETZM EXFATT ;and no attributes
PUSHJ P,FABST2 ;Update FAB STV
;Flag an ambiguous state if we never got conclusive evidence...
CAIE T2,ER$FNF ;File not found?
SETOM UNKXST ;No, can't determine existence
SKIPE RLSFLG ;Release link?
PJRST RLSLNX ;Yes, return +1
PUSHJ P,DRJOFF ;Turn DRJ OFF!
POPJ P,
SEGMENT DATA
LKPFAB: BLOCK 1 ;Address of lookup FAB
RLSFLG: BLOCK 1 ;Non-zero if link to be released
SEGMENT CODE
> ; End %IF20
SUBTTL RETRSA - Store resultant filespec
;++
; FUNCTIONAL DESCRIPTION:
;
; Saves the resultant filespec string from the NAM block after
; a $PARSE/$SEARCH sequence. The string is stored where DESPTR
; points. Attributes, if any, are included. EXFATT will contain
; a byte pointer to the beginning of the attributes portion.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RETRSA
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; DESPTR - Byte pointer to destination
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; Filespec is written to destination.
; EXFATT is updated with a byte pointer to the attributes string,
; which may be zero.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5001] New
%IF20,<
RETRSA: MOVE T1,DESPTR ;Get pointer
MOVEM T1,FNSPNT ;Point FNSCLR at it
PUSHJ P,FNSCLR ;Clear it first
MOVE T1,DESPTR
PUSHJ P,CVTFNS ;Convert string
MOVNI T2,1 ;Back up over the null
IBP T2,T1
MOVEM T2,FNSPNT ;Store
MOVEM T2,EXFATT ;Save attributes pntr, too
PJRST GUSPWA ;Add attributes and return
> ;End %IF20
SUBTTL DRJON - Set DRJ for remote files
;++
; FUNCTIONAL DESCRIPTION:
;
; Sets the DRJ bit for remote files so a $CLOSE will not release
; the network link, or the JFN.
;
; CALLING SEQUENCE:
;
; PUSHJ P,DRJON
; <Return here>
;
; INPUT PARAMETERS:
;
; T4 - Address of FAB
;
; IMPLICIT INPUTS:
;
; NODNAM(D) - Nodename
; FAB(D) - FAB address
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) FOP - FB$DRJ set if remote
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5002] New
%IF20,<
DRJON: $FETCH T1,FOP,<(T4)> ;Get FOP bits
TXO T1,FB$DRJ ;Set DRJ
$STORE T1,FOP,<(T4)> ;Bits back
POPJ P, ;Return
> ;End %IF20
SUBTTL DRJOFF - Turn off DRJ
;++
; FUNCTIONAL DESCRIPTION:
;
; Turn off DRJ in the FAB
;
; CALLING SEQUENCE:
;
; PUSHJ P,DRJOFF
; <Return here>
;
; INPUT PARAMETERS:
;
; T4 - Address of FAB
;
; IMPLICIT INPUTS:
;
; NODNAM(D) - Nodename
; FAB(D) FOP - FB$DRJ
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) FOP - DRJ turned off
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5002] New
%IF20,<
DRJOFF: $FETCH T1,FOP,<(T4)> ;Get FOP bits
TXZ T1,FB$DRJ ;Turn off DRJ
$STORE T1,FOP,<(T4)> ;Reset FOP
POPJ P,
> ;End %IF20
SUBTTL LOCON - Turn on Locate Mode
;++
; FUNCTIONAL DESCRIPTION:
;
; Sets the Locate Mode bit in the RAB
;
; CALLING SEQUENCE:
;
; PUSHJ P,LOCON
; <Return here>
;
; INPUT PARAMETERS:
;
; T4 - Address of RAB
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) ROP - RB$LOC
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5004] New
%IF20,<
LOCON: $FETCH T1,ROP,<(T4)> ;Get ROP bits
TXO T1,RB$LOC ;Turn Locate on
$STORE T1,ROP,<(T4)> ;Reset
POPJ P,
> ;End %IF20
SUBTTL LOCOFF - Turn off Locate Mode
;++
; FUNCTIONAL DESCRIPTION:
;
; Turns off the Locate Mode bit in the FAB
;
; CALLING SEQUENCE:
;
; PUSHJ P,LOCOFF
; <Return here>
;
; INPUT PARAMETERS:
;
; T4 - Address of RAB
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) ROP - RB$LOC off
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5004] New
%IF20,<
LOCOFF: $FETCH T1,ROP,<(T4)> ;Get ROP bits
TXZ T1,RB$LOC ;Turn off Locate
$STORE T1,ROP,<(T4)>
POPJ P,
> ;End %IF20
SUBTTL EOFON - Turn on RB$EOF in RAB(D)
;++
; FUNCTIONAL DESCRIPTION:
;
; Sets EOF option bit in the RAB.
;
; CALLING SEQUENCE:
;
; PUSHJ P,EOFON
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) ROP - RB$EOF
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4.
;
;--
;[5000] New
%IF20,<
EOFON: MOVE T4,RAB(D) ;Get RAB address
$FETCH T1,ROP,<(T4)> ;Get existing ROP bits
TXO T1,RB$EOF ;Turn on EOF
$STORE T1,ROP,<(T4)> ;Set
POPJ P,
> ;End %IF20
SUBTTL EOFOFF - Turn off RB$EOF in RAB(D)
;++
; FUNCTIONAL DESCRIPTION:
;
; Clears EOF bit in ROP of RAB(D).
;
; CALLING SEQUENCE:
;
; PUSHJ P,EOFOFF
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) ROP - RB$EOF cleared
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4.
;
;--
;[5000] New
%IF20,<
EOFOFF: $FETCH T1,ROP,<(T4)> ;Turn off EOF
TXZ T1,RB$EOF
$STORE T1,ROP,<(T4)>
POPJ P,
> ;End %IF20
SUBTTL %RMFNS - Return DDB filespec
;++
; FUNCTIONAL DESCRIPTION:
;
; Returns the DDB filespec as a string in the buffer pointed to by
; T1.
;
; The filestring is of the form:
;
; {node::}dev:<dir>file.typ.gen{;Attributes:}
;
; On return T1 contains the address of the string.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMFNS
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Byte pointer to destination buffer where
; filespec is to be written
;
; IMPLICIT INPUTS:
;
; DDB filespec fields
;
; OUTPUT PARAMETERS:
;
; T1 - Address of destination buffer
;
; IMPLICIT OUTPUTS:
;
; Writes the filespec to the destination buffer
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5000] New
%IF20,<
%RMFNS: MOVEM T1,SAVPTR ;Save destination pointer
MOVEM T1,FNSPNT ; also for FNOJFN
PUSHJ P,FNOJFN ;Output up to generation
MOVE T1,GEN(D) ;Get generation
CAME T1,[ASCIZ/0/] ;Is it zero?
JRST GUSER ;No
MOVE T1,%GNPNT ;Yes, don't output a generation
MOVEM T1,FNSPNT ;Back up pointer
GUSER: PUSHJ P,GUSPWA ;Get USERID, PASSWORD, ACCOUNT,PROT
HRRZ T1,SAVPTR ;Restore original address
POPJ P, ;Return
SEGMENT DATA
SAVPTR: BLOCK 1 ;Pointer storage
DESPTR: BLOCK 1
SEGMENT CODE
> ; End %IF20
SUBTTL GUSPWA - Assemble file attributes
;++
; FUNCTIONAL DESCRIPTION:
;
; Writes USERID, PASSWORD, ACCOUNT, and PROTECTION attributes from
; the DDB to the destination string.
;
; CALLING SEQUENCE:
;
; PUSHJ P,GUSPWA
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FNSPNT - Byte pointer to destination where string is
; to be written
; USERID(D) - DDB USERID field
; PASWRD(D) - PASSWORD
; ACCNT(D) - ACCOUNT
; PROT(D) - PROTECTION
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FNSPNT - Pointer is updated
;
; Writes DDB fields to the destination.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
GUSPWA: SKIPN USERID(D) ;Any USERID?
JRST GPASS ;No, check password
MOVEI T1,[ASCIZ/;USER:/] ;Prefix
PUSHJ P,ASCFNS ;Output it
XMOVEI T1,USERID(D) ;Data
PUSHJ P,ASCFNS ;Output it
GPASS: SKIPN PASWRD(D) ;Any PASSWORD?
JRST GACC ;No, check account
MOVEI T1,[ASCIZ/;PASS:/] ;Prefix
PUSHJ P,ASCFNS ;Output it
XMOVEI T1,PASWRD(D) ;Data
PUSHJ P,ASCFNS ;Output it
GACC: SKIPN ACCNT(D) ;Any ACCOUNT?
JRST GPRO ;No, check protection
MOVEI T1,[ASCIZ/;A:/] ;Prefix
PUSHJ P,ASCFNS ;Output it
XMOVEI T1,ACCNT(D) ;Data
PUSHJ P,ASCFNS ;Output it
GPRO: SKIPN PROT(D) ;Any PROTECTION?
JRST RMFNZ ;No, finish up
MOVEI T1,[ASCIZ/;P:/] ;Prefix
PUSHJ P,ASCFNS ;Output it
XMOVEI T1,PROT(D) ;Data
PUSHJ P,ASCFNS
RMFNZ: SETZ T2,
IDPB T2,FNSPNT ;End with null
POPJ P, ;Return
> ; End %IF20
SUBTTL %RMEFN - Return filespec for error messages
;++
; FUNCTIONAL DESCRIPTION:
;
; Called from FOROPN ERFTAB to return a filespec for use in
; error messages.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMEFN
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FNSPNT - Byte pntr to where filespec is to be written
; NODNAM(D) - Node name
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FNSPNT - Byte pntr updated
; SAVPTR - Original FNSPNT saved
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T3.
;
;--
;[5000] New
%IF20,<
%RMEFN: MOVE T1,FNSPNT ;Get and save destination
MOVEM T1,SAVPTR
PUSHJ P,FNOJFN ;Output up to generation
SKIPE NODNAM(D) ;Remote file?
POPJ P, ;Yes, now have full expanded spec
MOVE T2,SAVPTR ;Local file, treat like non-RMS disk
MOVX T1,GJ%SHT+GJ%OFG+GJ%FLG ;Get parse-only JFN
GTJFN%
ERJMP FNOJFN ;Couldn't, at least output DDB fields
MOVE T2,T1 ;Copy JFN
MOVE T1,SAVPTR ;Restore pointer
SETZ T3, ;No defaults
JFNS% ;Get disk-like spec
JSHALT
MOVEM T1,FNSPNT ;Update pointer
MOVE T1,T2 ;Now release the JFN
RLJFN%
JSHALT ;Shouldn't fail
POPJ P, ;Return
> ; End %IF20
SUBTTL %RMGXF - Return expanded filestring
;++
; FUNCTIONAL DESCRIPTION:
;
; Returns an expanded TOPS20-style filestring in the buffer
; pointed to by global FNSPNT. Called from FOROPN %GTFNS
; with destination buffer cleared and pointer in FNSPNT.
;
; The destination buffer must not be either the RSA or ESA
; buffers pointed to by the NAM block.
;
; The filespec is obtained in one of two ways, depending on the
; setting of IJFN(D) and the status (open/not open) of the file:
;
; IJFN(D) is -1: If the file is not open, but a previous call
; to %RMLKP has returned a resultant string, use
; that. If the file is open already, just return
; the DDB filespec.
;
; IJFN(D) is 0: A deferred-open file. Just return the DDB filespec.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMGXF
; <Return here>
;
; INPUT PARAMETERS:
;
; FNSPNT - Byte pointer to buffer where expanded filespec
; is to be written
;
; IMPLICIT INPUTS:
;
; IJFN(D) - -1 if the file is currently open or a successful
; %RMLKP lookup call has established that it exists.
; FLAGS(D) - Flags
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; DESPTR - Saved destination pointer
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
IF10,<
%RMGXF: $SNH ;Should NOT get here on TOPS-10
> ;End IF10
%IF20,<
%RMGXF: MOVE T1,FNSPNT ;Get destination pointer
SKIPN T2,IJFN(D) ;Any JFN status?
JRST %RMFNS ;No, just get DDB string
CAME T2,[-1] ;If not 0, must be -1!
$SNH ;Bad
MOVE T2,FLAGS(D) ;Get flags
TXNE T2,D%IN+D%OUT ;Is file actually open?
JRST %RMFNS ;Yes, just return DDB string
;Here when the file is not open, or IJFN says we don't know whether the
;file exists or not. If a previous call to %RMLKP has succeeded, IJFN
;will be -1 and EXFBUF will contain the resultant expanded filespec. If
;EXFBUF for some reason hasn't been updated, we have to do a full lookup!
MOVEM T1,DESPTR ;Save destination pointer
SETZM CVFLAG ;Don't ^V anything
SKIPE EXFBUF ;Do we have a resultant spec?
PJRST RETRSA ;Yes, return it
PUSHJ P,%RMLKP ;No. Must do a lookup/expansion
$SNH ;?File not found
PJRST RETRSA ;OK, return string
> ; End %IF20
SUBTTL %RMRFS - Return filespec to DDB variables
;++
; FUNCTIONAL DESCRIPTION:
;
; Returns filespec fields to the DDB. Obtains a parse-only JFN
; on the filespec string pointed to by RSA of the NAMBLK, then
; calls %DOJFNS to update the DDB. The parse-only JFN is discarded
; on return.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMRFS
; <Return here>
;
; INPUT PARAMETERS:
;
; NAMBLK - NAM filespec pointers
; N$RSA - Pointer to expanded filespec
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; NODNAM(D) - Nodename
; DEV(D) - Device
; DIR(D) - Directory
; FILNAM(D) - Name
; EXT(D) - Extension
; GEN(D) - Generation
; PASWRD(D) - Password
; ACCNT(D) - Account
; USERID(D) - Userid
; IJFN(D) - Set, then set to -1 on return to
; indicate DDB contains expanded RMS filespec.
;
; FNSPNT - Destination byte pointer
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
%RMRFS: MOVE T1,[POINT 7,%TXTBF] ;Setup destination pntr
MOVEM T1,DESPTR ;Save
SETOM CVFLAG ;Turn on ^V'ing
PUSHJ P,RETRSA ;Copy string
MOVE T2,DESPTR ;Get string pointer
MOVX T1,GJ%SHT+GJ%OFG+GJ%FLG ;Get parse-only JFN
GTJFN%
JSHALT ;Should not fail
MOVEM T1,IJFN(D) ;Setup for JFNS call
PUSHJ P,%DOJFNS ;Update DDB
PUSHJ P,RELJFN ;Release JFN
SETOM IJFN(D) ;Flag file exists
POPJ P, ;Return
> ; End %IF20
SUBTTL %RMISW/%RSISW - Switch an RMS/RSF file from output to input
;++
; FUNCTIONAL DESCRIPTION:
;
; Called only for sequential RMS and RSF files. Switches to input
; by setting ICNT(D) to zero, so subsequent READ will return EOF.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMISW ;Called only from FOROPN ISWTAB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; ICNT(D) - Current free byte count, cleared.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; For RSF files, writes the current window.
; Uses T1.
;
;--
;[5003] New
%IF20,<
%RSISW: PUSHJ P,%OCLR ;Clear unused bytes in last word
PUSHJ P,RSFOCP ;Output current output window
%RMISW: SETZM ICNT(D) ;Tell IN. we're at EOF!
POPJ P,
> ; End %IF20
SUBTTL %RMOSW - Switch an RMS file to output
;++
; FUNCTIONAL DESCRIPTION:
;
; Switch an RMS file from input to output, truncating
; if necessary. The routine determines whether we are already at
; EOF (thus allowing a bypass of the truncate operation) by performing
; a preliminary $FIND on the next record. If this gets an EOF, and
; the file is already open for write access, we can leave. If we
; don't have write access, or are not at EOF, close the file, reopen
; it for exclusive access, position to the RFA from the $FIND, and
; truncate.
;
; A switch to output is not cheap for a remote file!
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMOSW ;Called from FOROPN OSWTCH
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORGAN(D) - ORGANIZATION
; RAB(D) - RAB address
; FAB(D) - FAB address
; RFA - RFA from last read/write
; FLAGS(D) - DDB flags
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) RAC - RB$RFA for $TRUNCATE
; FAB(D) FOP - FB$DRJ
; SHR - FB$NIL
; FAC - FB$GET!FB$PUT!FB$TRN
; FLAGS(D) - D%WRT if not already set
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4.
; May close, reopen, and truncate the file.
;
;--
;[5004] New
%IF20,<
%RMOSW: SETZM EOFFLG ;Clear "at EOF" flag
SETZM IDXREL ;Clear "IDX/relative file" flag
SETZM ICNT(D) ;Clear input pointers, we need
SETZM IPTR(D) ; an output buffer
LOAD T1,ORGAN(D) ;See if the filetype allows truncating
CAIE T1,OR.REL ;If relative,
CAIN T1,OR.IDX ;or indexed
SETOM IDXREL ;Flag it
SKIPN IDXREL ;Indexed or Relative file?
JRST OSWSEQ ;No, go truncate, maybe
MOVE T1,FLAGS(D) ;IDX/REL. Get DDB flags
TXNE T1,D%WRT ;Already have WRITE access?
POPJ P, ;Yes, nothing to do
JRST OSWCLS ;No, have to close/open
OSWSEQ: MOVE T4,RAB(D) ;Get RAB address
MOVX T1,RB$SEQ ;Set for sequential access
$STORE T1,RAC,<(T4)>
PUSHJ P,FIND$ ;Do $FIND
JFCL ;Ignore error for a moment
PUSHJ P,RABSTV
$FETCH T1,RFA,<(T4)> ;Get the RFA
MOVEM T1,OSWRFA ;Save
CAIGE T2,ER$MIN ;Error?
JRST OSWCLS ;No, go close file
CAIE T2,ER$EOF ;Yes. Was it EOF?
JRST OSWERR ;No, something bad
;We were already at EOF. If we already have WRITE access to the file, there's
; nothing left to do.
SETOM EOFFLG ;Flag "at EOF".
MOVE T1,RAB(D)
PUSHJ P,RETSUC ;Clear error
MOVE T1,FLAGS(D) ;Get DDB flags
TXNE T1,D%WRT ;WRITE access?
POPJ P, ;Yes, all done
OSWCLS: MOVX T1,D%WRT ;We have WRITE access now
IORM T1,FLAGS(D)
MOVE T4,RAB(D)
PUSHJ P,DRJON ;Keep link
PUSHJ P,CLOS$ ;Do $CLOSE
JRST OSWERR ;Error
PUSHJ P,DRJOFF ;Turn DRJ off!
MOVX T1,FB$NIL ;Get exclusive access to file
SKIPE IDXREL ;unless IDX/relative file
$FETCH T1,SHR,<(T4)> ;Don't change share access
$STORE T1,SHR,<(T4)>
MOVX T1,FB$ALL ;Get write access
$STORE T1,FAC,<(T4)>
SETZ T1,
$STORE T1,FOP,<(T4)> ;Clear FOP bits
MOVE T4,FAB(D) ;Get FAB address again
MOVE T1,[POINT 7,%TXTBF] ;Setup to get DDB filespec
PUSHJ P,%RMFNS ;Get it
$STORE T1,FNA,<(T4)> ;Set filespec in FNA
PUSHJ P,OPEN$ ;Do $OPEN
JRST OSWERR ;Error
MOVE T4,RAB(D) ;Get RAB address
SKIPN IDXREL ;If indexed or relative
SKIPN EOFFLG ;or we were not at EOF, normal connect
JRST RMOSCN
PUSHJ P,EOFON ;Turn on EOF
RMOSCN: SETZ T1, ;Clear RAC
$STORE T1,RAC,<(T4)>
$STORE T1,KBF,<(T4)> ;Any key buffer
$STORE T1,KSZ,<(T4)> ;and size
PUSHJ P,CONN$ ;Do $CONNECT
JRST OSWERR ;Error
PUSHJ P,EOFOFF ;Turn off EOF
;Here for the full $TRUNCATE, unless already at EOF.
MOVX T1,RB$RFA ;Get RFA access
$STORE T1,RAC,<(T4)>
SKIPN IDXREL ;Relative?
SKIPE EOFFLG ;At EOF?
JRST RMOSRT ;Yes, don't truncate
MOVE T1,OSWRFA ;Get our RFA
$STORE T1,RFA,<(T4)>
PUSHJ P,FIND$ ;Do $FIND
JRST OSWERR ;Error
PUSHJ P,TRUN$ ;Do $TRUNCATE
JRST OSWERR ;Error
MOVX T1,D%MOD ;Set file-is-modified
IORM T1,FLAGS(D)
RMOSRT: SKIPN IDXREL ;IDX/REL?
POPJ P, ;No, all done
SKIPN T1,RFA(D) ;Any last record to reposition to?
POPJ P, ;No, done
$STORE T1,RFA,<(T4)> ;Yes, set RFA
PUSHJ P,FIND$ ;Re-position to it
TRNA
POPJ P,
;Here for fatal %RMOSW errors.
OSWERR: PUSHJ P,EOFOFF ;Turn off EOF
PUSHJ P,DRJOFF ;and DRJ
$ACALL IOE ;Bad error
SEGMENT DATA
OSWRFA: BLOCK 1 ;RFA for $TRUNCATE
IDXREL: BLOCK 1 ;Indexed/Relative file flag
SEGMENT CODE
> ; End %IF20
SUBTTL %RSOSW - Switch an RSF file to output
;++
; FUNCTIONAL DESCRIPTION:
;
; Called from OSWTCH via DSKOSW via CLSOUT. Switches an RSF file from
; input to output. EOFN(D) has been setup previously to point at
; the highest file byte number so far read from the file. File
; truncation occurs at EOFN.
;
; A switch to output is not cheap for remote files!
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RSOSW ;Called from FOROPN CLSOUT
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; EOFN(D) - New highest file byte #
; BPW(D) - Bytes/word
; FLAGS(D) - DDB flags
; FAB(D) - FAB address
; RAB(D) - RAB address
; IPTR(D) - Input pointer
; WSIZ(D) - Window size
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) FAC - Reset to write access
; SHR - To NIL for truncation
; RAB(D) BKT - To desired page number
; BYTN(D) - To next-window-byte
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5004] New
IF10,<
%RSOSW: $SNH ;Should NOT get here on TOPS-10
> ;End IF10
%IF20,<
%RSOSW: MOVE T3,EOFN(D) ;Get highest file byte
MOVE T1,BPW(D) ;Get bytes/word
LSH T1,LWSIZ ;Get bytes/page
ADDI T3,-1(T1) ;and pages written
IDIVI T3,(T1) ;rounded
;T3 has file page # of EOF byte.
;Try to read the next file page to see if we are already at EOF
ADDI T3,1 ;Bump page #
MOVEM T3,SAVPAG ;Save
MOVEM T3,T1 ;Copy
SETZM EOFFLG ;Clear "At EOF" flag
PUSHJ P,LOCBKT ;Locate page
TRNA ;Error, investigate
JRST ROSCLS ;No error, go close file
CAIE T2,ER$EOF ;Was it EOF?
CAIN T2,ER$RNF ;or page not found?
TRNA ;Yes, OK
JRST ROSWER ;No, something bad
;Already at EOF. If we already have WRITE access to the file, there's
;nothing left to do!
SETOM EOFFLG ;Flag we are at EOF
MOVE T1,RAB(D)
PUSHJ P,RETSUC ;EOF! Clear error
MOVE T1,FLAGS(D) ;Get DDB flags
TXNE T1,D%WRT ;WRITE access?
PJRST %SOCNT ;All done! Set output count
;Here when not at EOF, or need write access. A full OPEN/CLOSE/TRUNCATE
; is required.
ROSCLS: MOVX T1,D%WRT ;We have WRITE access now
IORM T1,FLAGS(D)
MOVE T4,FAB(D) ;Get FAB address
PUSHJ P,DRJON ;Set DRJ, keep net link
PUSHJ P,CLOS$ ;Do $CLOSE
JRST ROSWER ;Error
PUSHJ P,DRJOFF ;Turn DRJ OFF!
MOVX T1,FB$ALL ;Get full write access
$STORE T1,FAC,<(T4)>
MOVX T1,FB$NIL ;Exclusive
$STORE T1,SHR,<(T4)>
MOVE T1,[POINT 7,%TXTBF] ;Setup to get DDB filespec
PUSHJ P,%RMFNS ;Get it
$STORE T1,FNA,<(T4)> ;Set filespec in FNA
PUSHJ P,OPEN$ ;Do $OPEN
JRST ROSWER ;Error
PUSHJ P,CONN$ ;Do $CONNECT
JRST ROSWER ;Error
;Here for $TRUNCATE. The BKT we just read is the page after our EOF byte.
; Truncate from that page to the end...unless we were already at EOF.
SKIPE EOFFLG ;At EOF?
PJRST %SOCNT ;Yes, no need for $TRUNCATE
MOVE T1,SAVPAG ;Get page # back
$STORE T1,BKT,<(T4)> ;Set it
PUSHJ P,TRUN$ ;Do $TRUNCATE
JRST ROSWER ;Error
MOVX T1,D%MOD ;Set file-is-modified
IORM T1,FLAGS(D)
;File is shorter, b'gad. Remap our file window
HRRZ T1,IPTR(D) ;Get address of data
JUMPE T1,%POPJ ;If no data, leave
MOVN T1,WSIZ(D) ;Set to map new window
ADDM T1,BYTN(D)
PUSHJ P,RMAPW ;Map the pages
MOVE T1,WSIZ(D) ;Set next window byte number
ADDM T1,BYTN(D)
PJRST %SOCNT ;Go update count, return
;Here on fatal errors
ROSWER: PUSHJ P,DRJOFF ;Turn DRJ OFF!
$ACALL IOE
SEGMENT DATA
SAVPAG: BLOCK 1 ;Save file page #
EOFFLG: BLOCK 1 ;"At EOF" flag
SEGMENT CODE
> ;End %IF20
SUBTTL GETBKT - $READ a remote page
;++
; FUNCTIONAL DESCRIPTION:
;
; $READs a bucket (page) whose page number is in T1 to the buffer
; whose address is in T2. Updates RAB STS/STV.
;
; CALLING SEQUENCE:
;
; PUSHJ P,GETBKT
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; T1 - File page number to read
; T2 - Destination address for page
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; Returns STS value in T2.
; Returns address of RAB in T4.
;
; IMPLICIT OUTPUTS:
;
; RAB(D) BKT - Set to page #
; UBF - Set to destination address
; USZ - Set to page size (words)
; RAC - Set to BLK
; RFA - Cleared
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4
;
;--
;[5004] New
%IF20,<
GETBKT: MOVE T4,RAB(D) ;Get RAB address
$STORE T1,BKT,<(T4)> ;Set page number to read
$STORE T2,UBF,<(T4)> ;Set destination
MOVEI T1,PSIZ ;Set size to one page
$STORE T1,USZ,<(T4)>
$FETCH T1,RAC,<(T4)> ;Turn on BLK mode
TXO T1,RB$BLK
$STORE T1,RAC,<(T4)>
SETZ T1, ;Clear RFA
$STORE T1,RFA,<(T4)>
PUSHJ P,READ$ ;Do $READ
PJRST LOCOFF ;Turn off Locate Mode if on, error ret
PUSHJ P,LOCOFF ;Turn off Locate Mode
JRST %POPJ1
> ;End %IF20
SUBTTL LOCBKT - GETBKT in Locate mode
;++
; FUNCTIONAL DESCRIPTION:
;
; Calls GETBKT with Locate Mode set. A temporary destination
; buffer (required by RMS, but unused!) is allocated and
; deallocated.
;
; CALLING SEQUENCE:
;
; PUSHJ P,LOCBKT
; <Error return; buffer deallocated>
; <Success return; buffer deallocated>
;
; INPUT PARAMETERS:
;
; T1 - BKT (page) to locate
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; Returns STS value in T2.
; Returns address of RAB in T4.
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5004] New
%IF20,<
LOCBKT: MOVEM T1,SAVBKT ;Save target bucket #
MOVEI T1,PSIZ ;Get temp buffer
PUSHJ P,%GTBLK
$ACALL MFU ;Can't
MOVEM T1,T2 ;Copy for GETBKT
MOVE T4,RAB(D) ;Get RAB address
PUSHJ P,LOCON ;Turn on Locate Mode
MOVE T1,SAVBKT ;Get BKT #, T2 has destination adr
PUSHJ P,GETBKT ;$READ it
JFCL ;Ignore error for a moment
PUSH P,T2 ;Save STS code
PUSHJ P,FTMPPG ;Deallocate temp buffer
POP P,T2 ;Retrieve T2
CAIL T2,ER$MIN ;Error?
POPJ P, ;Yes, take error return
PJRST %POPJ1 ;Take success return
SEGMENT DATA
SAVBKT: BLOCK 1 ;Save BKT #
SEGMENT CODE
> ;End %IF20
SUBTTL PUTBKT - $WRITE a file page
;++
; FUNCTIONAL DESCRIPTION:
;
; $WRITEs the bucket (page) whose number is in T1, and whose core
; address is in T2. Updates RAB STS/STV.
;
; CALLING SEQUENCE:
;
; PUSHJ P,PUTBKT
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; T1 - File page # to write
; T2 - Core buffer address
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) BKT - Page #
; RBF - Buffer address
; RSZ - Buffer size in bytes
; RFA - Cleared
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5004] New
%IF20,<
PUTBKT: MOVE T4,RAB(D) ;Get RAB address
$STORE T1,BKT,<(T4)> ;Set BKT #
$STORE T2,RBF,<(T4)> ;Set buffer address
MOVEI T1,PSIZ ;Get page size in words
IMUL T1,BPW(D) ;Convert to bytes
$STORE T1,RSZ,<(T4)> ;Store in RAB
SETZ T1,
$STORE T1,RFA,<(T4)> ;No RFA
$FETCH T1,RAC,<(T4)> ;Get current access bits
TXO T1,RB$BLK ;Turn on block mode
$STORE T1,RAC,<(T4)>
PUSHJ P,WRIT$ ;Do $WRITE
POPJ P, ;Error
JRST %POPJ1 ;Success
> ;End %IF20
SUBTTL %RMCSY - Maybe OPEN on a CLOSE/EXIT
;++
; FUNCTIONAL DESCRIPTION:
;
; Called from FOROPN CLSITY processing for deferred-open files
; which have not yet been opened. This routine performs a lookup
; on the file. If it exists, it returns +2; if not, +1 for a full
; OPEN. %RMCSY is called instead of %RMLKP so we can avoid
; requesting and relinquishing a network link.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMCSY
; <Return here if file does not exist>
; <Return here if the file exists>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) - Address of allocated FAB
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; May invoke RMS.
; May initialize a FAB
; Uses T1,T4.
;
;--
;[5002] New
%IF20,<
%RMCSY: SKIPN T1,FAB(D) ;Already have a FAB?
PUSHJ P,RMFAB ;No, allocate one
MOVEM T1,FAB(D) ;Save its address
MOVEM T1,T4 ;Copy it
PUSHJ P,RMLKD ;Lookup the file, keep net link
PJRST FETOST ;Not there, return for full OPEN
PUSHJ P,DRJOFF
PUSHJ P,RLSLNK ;There, release link
JRST %POPJ1 ;Return +2
> ;End %IF20
SUBTTL FETOST - Fetch the OS type into OSTYPE(D)
;++
; FUNCTIONAL DESCRIPTION:
;
; Called after a $PARSE has updated the CONFIG XAB with the remote
; OS type. Stores the OS code in OSTYPE(D)
;
; CALLING SEQUENCE:
;
; PUSHJ P,FETOST
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; XA$OST from the CONFIG XAB
;
; OUTPUT PARAMETERS:
;
; T2 - OS type code
;
; IMPLICIT OUTPUTS:
;
; OSTYPE(D)
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; T2,T4.
;
;--
;[5000] New
%IF20,<
FETOST: MOVE T4,FAB(D) ;Get FAB
$FETCH T2,XAB,<(T4)> ;Get XAB link
JUMPE T2,%POPJ ;None, return
$FETCH T2,OST,<(T2)> ;Get OS type
STORE T2,OSTYPE(D) ;Save
POPJ P,
> ;End %IF20
SUBTTL %RMCLS - Close an RMS-opened file
;++
; FUNCTIONAL DESCRIPTION:
;
; Closes RMS and RSF files. For RSF files, writes modified pages
; before closing the file.
;
; CALLING SEQUENCE:
;
; Called only from FOROPN CLSITA via CLSTAB
; Returns +1 on a successful CLOSE, otherwise enters dialog mode.
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; INDX(D) - Device type
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; OJFN/IJFN - Cleared on success
; I/O flags - D%IN+D%OUT+D%WRT+D%MOD cleared on success
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
; On $CLOSE errors, deallocates any XAB chain.
;
;--
;[5002] New
IF10,<
%RMCLS: $SNH ;Should NOT get here on TOPS-10
> ;End IF10
%IF20,<
%RMCLS: MOVE T4,FAB(D) ;Get FAB address
PUSHJ P,DRJOFF ;Make sure DRJ is OFF!
$FETCH T1,IFI,<(T4)> ;Is file open now?
JUMPE T1,%POPJ ;No, don't close it
LOAD T1,INDX(D) ;Get file type
CAIN T1,DI.RSF ;RSF?
PUSHJ P,RMCPG ;Yes, write modified buffers
MOVE T1,[POINT 7,%TXTBF]
PUSHJ P,%RMFNS ;Get address of filespec
MOVE T4,FAB(D)
$STORE T1,FNA,<(T4)> ;Set in FAB
PUSHJ P,CLOS$ ;Do $CLOSE
JRST RMCLER ;Error
SETZM IJFN(D) ;Clear the JFN
SETZM OJFN(D)
MOVX T1,D%IN+D%OUT+D%WRT+D%MOD ;Turn off the I/O bits
ANDCAM T1,FLAGS(D)
POPJ P, ;Return
;Here on $CLOSE errors.
RMCLER: PUSHJ P,RMDUXB ;Deallocate any XAB chain
LOAD T2,STS(D) ;Get error status
CAIE T2,ER$DCF
CAIN T2,ER$DPE ;Ignore protocol errors, the file
POPJ P, ; is really closed
$ACALL CLS ;?Close failed
> ; End %IF20
SUBTTL RMCPG - Write modified RSF pages
;++
; FUNCTIONAL DESCRIPTION:
;
; Called when closing RSF files to write modified pages for
; random-access files, or the last buffer for sequential file,
; free the buffer for sequential files, and deallocate the page
; table and the page flag table. Deallocation is accomplished
; through calls to %FREPGS and %FREBLK.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMCPG
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; WPTR(D) - Address of file pages
; WTAB(D) - Address of in-core page table
; WADR(D) - Offset into WTAB for random-access files
; BUFCT(D) - Number of pages
; PFTAB(D) - Page flag table
; FLAGS(D) - DDB flags
; CC(U) - CARRIAGECONTROL
; BSIZ(D) - Bytesize
; EOFN(D) - EOF byte #
; BPW(D) - Bytes/word
; DMODE(D) - Data mode
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; WPTR,WADR - Cleared
; FDB file page - FB%FOR set if file is CC=FORTRAN
; FB%BSZ set to BSIZ(D)
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4,P1.
;
;--
;[5002] New
%IF20,<
RMCPG: SKIPN WPTR(D) ;Anything to write?
POPJ P, ;No
SKIPN WTAB(D) ;Sequential-access?
JRST CLSSEQ ;Yes, free buffer
SETZM WADR(D) ;Random, point to table start
LOAD P1,BUFCT(D) ;Get # pages
RMPLP: PUSHJ P,RMWPG ;Write if modified
AOS WADR(D) ;Point to next page
SOJG P1,RMPLP ;Do all pages
JRST FREBFS ;Deallocate tables, etc.
;Here for a sequential close to write last buffers.
CLSSEQ: MOVE T1,FLAGS(D) ;Sequential. Get flags
TXNN T1,D%OUT ;Last I/O output?
JRST FREBFS ;No, go free up memory
PUSHJ P,%OCLR ;Yes, clear unused chars of last word
PUSHJ P,RSFOCP ;Output last buffer
;Here for both sequential and random close to deallocate pages, tables, etc.,
; and to update the FDB if necessary.
FREBFS: MOVE T1,WPTR(D) ;Get page pointer
LOAD T2,BUFCT(D) ; and number of pages
PUSHJ P,%FREPGS ;Free them
SETZM WPTR(D) ;Clear window addresses
SETZM WADR(D)
SKIPE T1,WTAB(D) ;If there is a page table
PUSHJ P,%FREBLK ;Free that
SKIPE T1,PFTAB(D) ;And any flag table
PUSHJ P,%FREBLK
MOVE T1,FLAGS(D) ;Get flags
TXNN T1,D%MOD ;Was file modified?
POPJ P, ;No, we're done
;File was modified, so get the FDB page and update it.
PUSHJ P,RSRFDB ;Get FDB page for file
$ACALL CLS ;?Can't: Close failed
MOVEM T1,FDBADR ;Save address
MOVEM T1,T4
LOAD T1,CC(U) ;Get CARRIAGECONTROL
CAIE T1,CC.FOR ;CC=FORTRAN?
JRST FBBSZ ;No, don't set bit
;T4 has the base address of the FDB block in dynamic memory
MOVE T1,.FBCTL(T4) ;Get .FBCTL word of FDB
TXO T1,FB%FOR ;Set Fortran bit
MOVEM T1,.FBCTL(T4) ;Restore to FDB
FBBSZ: MOVE T1,.FBBYV(T4) ;Get .FBBYV word of FDB
MOVX T2,FB%BSZ ;Get field mask
TDZ T1,T2 ;Clear byte size field
LOAD T2,BSIZ(D) ;Get byte size we've been using
LSH T2,^D24 ;Shift into position
TDO T1,T2 ;Set size
MOVX T2,FB%MOD ;Get field mask
TDZ T1,T2 ;Clear data mode field
LOAD T2,DMODE(D) ;Get data mode
MOVSI T2,(T2) ;Shift into position
TDO T1,T2 ;Set it
MOVEM T1,.FBBYV(T4) ;Return to FDB
MOVE T1,EOFN(D) ;Get file size in bytes
LOAD T2,BSIZ(D) ;Get bytesize
CAIE T2,^D36 ;36 bits?
JRST FBSIZ ;No, use EOFN as is
ADD T1,BPW(D) ;Yes, round up
SUBI T1,1
IDIV T1,BPW(D) ;Get words
FBSIZ: MOVE T2,.FBSIZ(T4) ;Get file size word
SETZ T2, ;Clear it
TDO T2,T1
MOVEM T2,.FBSIZ(T4)
MOVE T1,FDBADR ;Get FDB address
PUSHJ P,RSWFDB ;Write the FDB page
$ACALL CLS ;?Can't: Close failed
PJRST FTMPPG ;Free the page, and return
SEGMENT DATA
FDBADR: BLOCK 1 ;Address of page containing FDB
SEGMENT CODE
> ; End %IF20
SUBTTL RMWPG - Write modified random-access pages
;++
; FUNCTIONAL DESCRIPTION:
;
; Writes one page from the page table if modified.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMWPG
; <Return here>
;
; INPUT PARAMETERS:
;
; P1 - File page number to check/write
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
; WADR(D) - Offset into WTAB of least used page
; WPTR(D) - Core page address of file pages
; WTAB(D) - Address of in-core page table
; PFTAB(D) - Address of page flag table (-1=modified)
; BPW(D) - Bytes/word
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) BKT - Set to file page # +1
; UBF - Set to address of in-core page
; RSZ - Set to bytes/in-core page
; RAC - Set to RB$BLK for block-mode
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5003] New
%IF20,<
RMWPG: MOVE T1,WADR(D) ;Get page table offset
ADD T1,PFTAB(D) ;Point to the page flag table
SKIPL (T1) ;Modified?
POPJ P, ;No, just return
SETZM (T1) ;Flag unmodified
MOVE T1,WADR(D) ;Get page table offset to this page
ADD T1,WTAB(D) ;Point into table
MOVE T1,(T1) ;Get page number
ADDI T1,1 ;+1 for bucket
MOVE T2,WADR(D) ;Get offset again for process page
ADD T2,WPTR(D) ;Get process page number
LSH T2,LWSIZ ;Make into address
PUSHJ P,PUTBKT ;$WRITE it
$ACALL IOE ;Can't
POPJ P, ;OK, return
> ; End %IF20
SUBTTL %RMREN - Rename a remote file via RMS
;++
; FUNCTIONAL DESCRIPTION:
;
; Renames a file via RMS and returns the expanded filespec
; from the rename DDB to the old DDB. $RENAME requires 2 FABs,
; which are allocated and deallocated.
;
; If the file is local, this routine transfers control to FOROPN's
; DSKREN for a standard rename operation, bypassing RMS. This is
; necessary (not simply more efficient) because RMS-accessed files
; never perform a GTJFN% and thus locally will never properly interpret
; logical names in the filespec.
;
; If a local filespec is being renamed to a remote spec, produce
; an ER$RTN (Two different nodes) error. The reverse (remote to
; local spec) is permitted, since the rename JFNBLK defaults node
; and access data to those specified in the original filespec.
;
; CALLING SEQUENCE:
;
; Called only from FOROPN CHKREN via RENTAB.
; Returns +2 on success, else $DCALLs to DIALOG.
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; NODNAM(D) - Node name
; GEN(D) - Generation number. If zero, a -1 is used
; in the rename spec to produce the next
; higher generation
; %RNAMD - Rename DDB
; %OLDDB - Old DDB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; Old DDBs filespec fields are updated with the expanded rename
; filespec.
;
; FAB1/FAB2 - Address of rename FABs
; STS(D) - Set to ER$RTN if a local spec is being
; renamed to a remote spec.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
; Allocates 2 temporary FABs, which are deallocated.
;
;--
;[5002] New
%IF20,<
%RMREN: MOVE T1,%OLDDB ;See if either DDB had a node
MOVE T2,%RNAMD
SKIPE NODNAM(T1) ;Is file remote?
JRST RMRENR ;Yes
SKIPN NODNAM(T2) ;This one, too?
JRST DSKREN ;No, do it the simple way
MOVEI T3,ER$RTN ;?Two different remote nodes
STORE T3,STS(T1) ;Put error where FORERR will find it
STORE T3,STS(T2)
$DCALL RNM
RMRENR: PUSHJ P,RMFAB ;Get a FAB for old filespec
MOVEM T1,FAB1 ;Save
MOVE T1,[POINT 7,%TXTBF] ;Get filespec string
PUSHJ P,%RMFNS
MOVE T4,FAB1
$STORE T1,FNA,<(T4)> ;Store filespec address
MOVE D,%RNAMD ;Point at %RNAMD
PUSHJ P,RMFAB ;Get FAB for rename filespec
MOVEM T1,FAB2 ;Save
MOVEM T1,T4 ;Copy
PUSHJ P,ABINI ;Initialize some arg blocks
XMOVEI T1,NAMBLK ;Point at NAMBLK
$STORE T1,NAM,<(T4)>
MOVE T1,GEN(D) ;Get generation
MOVEM T1,SAVGEN ;Save it
SKIPE T1 ;0?
CAMN T1,[ASCIZ/0/] ;or 0?
MOVE T1,[ASCIZ/-1/] ;Yes, set to -1
MOVEM T1,GEN(D)
MOVE T1,[POINT 7,TXTBF2] ;Get new filespec address
PUSHJ P,%RMFNS
MOVE T4,FAB2
$STORE T1,FNA,<(T4)> ;Store filespec address
MOVE T1,SAVGEN ;Restore generation
MOVEM T1,GEN(D)
$RENAME @FAB1,ERCRET,@FAB2
;If success, return the expanded RENAME filespec to the old DDB and return.
;If failure, report error. In any case deallocate the temp FABs and update
;STS/STV
MOVE T1,FAB1 ;Get FAB with status codes
MOVE D,%RNAMD ;Put them in rename DDB
PUSHJ P,FABST2 ;Update STS/STV
MOVE D,%OLDDB ;And also in the %OLDDB
PUSHJ P,FABST2
PUSHJ P,DEAFAB ;Deallocate temporary FABs
LOAD T2,STS(D) ;Get status
CAIL T2,ER$MIN ;Error?
$DCALL RNM ;Yes, report, take error return
PUSHJ P,%RMRFS ;No. Return filespec to DDB
JRST %POPJ1 ;Return +2 for success
DEAFAB: SKIPE T1,FAB1 ;Deallocate temp FABs
PUSHJ P,%FREBLK
SKIPE T1,FAB2
PUSHJ P,%FREBLK
SETZM FAB1 ;Say they're gone
SETZM FAB2
POPJ P,
SEGMENT DATA
FAB1: BLOCK 1 ;Address of original FAB
FAB2: BLOCK 1 ;Address of rename FAB
SAVGEN: BLOCK 1 ;Saved GEN(D)
SEGMENT CODE
> ; End %IF20
SUBTTL %RMDSP - Dispose of a file via RMS
;++
; FUNCTIONAL DESCRIPTION:
;
; Disposes of an RMS-opened file during CLOSE processing. For
; non-queued functions, SAVE and KEEP are no-ops; EXPUNGE is
; the equivalent of DELETE. Queued functions PUNCH and PLOT
; are errors; PRINT/LIST and SUBMIT for RMS files are legal
; only for VAX systems.
;
; CALLING SEQUENCE:
;
; Called only from FOROPN CLSITA via DPTAB. Returns +2 on
; success, +1 to enter DIALOG.
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; CLSDDB - DDB to use during DISPOSE
; ODISP(D) - Orthogonal DISPOSE value
; OSTAT(D) - Orthogonal STATUS value
; INDX(D) - Device index
; STS(D) - RMS status code
; OSTYPE(D) - Operating system type
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; DISP(D) - Zeroed on error to force a recalculation
; of the dispose index after DIALOG.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4,D.
; May allocate and deallocate a FAB.
;
;--
;[5002] New
%IF20,<
%RMDSP: MOVE T2,CLSDDB ;Get CLOSE DDB
LOAD T1,ODISP(T2) ;Get orthogonal DISPOSE vale
JUMPN T1,RMQUE ;Non-zero means queued
;Here when the DISPOSE request is not a queued function (DELETE,
; EXPUNGE,SAVE)
LOAD T1,OSTAT(T2) ;Get orthogonal STATUS value
PUSHJ P,RMNSTA(T1) ;Go do it
POPJ P, ;Can't, error return
JRST %POPJ1 ;Did it
RMNSTA: JRST %POPJ1 ;UNKNOWN (same as SAVE)
JRST %POPJ1 ;SAVE
JRST RMERA ;DELETE
JRST RMEXP ;EXPUNGE (same as DELETE)
RMEXP:
RMERA: PUSHJ P,RMFAB ;Get a new FAB
MOVEM T1,FAB1 ;Save its address
MOVE T1,[POINT 7,%TXTBF]
PUSHJ P,%RMFNS ;Get filespec string (fom old D)
MOVE T4,FAB1 ;Get FAB address
$STORE T1,FNA,<(T4)> ;Store string address
$ERASE <(T4)>,ERCRET
MOVE T1,T4 ;Point at this FAB
PUSHJ P,FABST2 ;Update STS/STV in FAB(old D)
PUSHJ P,DEAFAB ;Deallocate temp FAB
LOAD T2,STS(D) ;Get status
CAIL T2,ER$MIN ;Error?
$DCALL DEL ;Yes, report error
JRST %POPJ1 ;No. Success return
;Here for queue function requests. T1 contains the DISPOSE value from ODISP
RMQUE: MOVEM T1,SODISP ;Save T1
MOVE T2,CLSDDB ;Get DDB
LOAD T1,INDX(T2) ;Get device type
CAIE T1,DI.RMS ;RMS file
JRST RMQUED ;No. Go do what we can
;PRINT or SUBMIT for remote RMS files is meaningful only if the remote
; system is a VAX (which can handle queued RMS files).
MOVE T2,%OLDDB ;Get old DDB
MOVE T2,OSTYPE(T2) ;Get OS type
CAIE T2,XA$VMS ;VMS system?
JRST UDOERR ;No, can't print/submit
RMQUED: MOVE T1,SODISP ;Get saved dispose value
PUSHJ P,RMQTB(T1) ;Go do it
POPJ P, ;Can't, error return
JRST %POPJ1 ;Did it
RMQTB: JRST %POPJ1 ;NOTHING
JRST RMPRIN ;PRINT
JRST UDOERR ;PUNCH:?Unsupported dispose option
JRST RMSUB ;SUBMIT
JRST UDOERR ;PLOT:?Unsupported dispose option
RMSUB: MOVX T1,FB$SCF ;Get SUBMIT bit
MOVEM T1,SODISP ;Save
JRST RMQDEL ;Go do it
RMPRIN: MOVX T1,FB$SPL ;Get PRINT bit
MOVEM T1,SODISP
RMQDEL: MOVE T2,SODISP ;Get whichever
LOAD T1,OSTAT(D) ;Get orthogonal STATUS value
CAIE T1,OS.DEL ;If DELETE
CAIN T1,OS.EXP ;or EXPUNGE
TXO T2,FB$DLT ;turn on DELETE bit
MOVEM T2,SODISP
PUSHJ P,RMFAB ;Get a FAB
MOVEM T1,FAB1 ;Save its address
MOVE T1,[POINT 7,%TXTBF]
PUSHJ P,%RMFNS ;Get filespec string
MOVE T4,FAB1 ;Get FAB address
$STORE T1,FNA,<(T4)>
MOVE T1,SODISP ;Get correct bits
$STORE T1,FOP,<(T4)> ;Set
$OPEN <(T4)> ;OPEN the file again, ignoring errors,
; since a $CLOSE will clean up the
; network link, if any.
$CLOSE <(T4)>,ERCRET ;CLOSE with DISPOSE option
MOVE T1,T4 ;Point at status FAB
PUSHJ P,FABST2 ;Update STS/STV in FAB(old D)
PUSHJ P,DEAFAB ;Deallocate temp FAB
LOAD T2,STS(D) ;Get status
CAIL T2,ER$MIN ;Was there an error
POPJ P, ;Yes
JRST %POPJ1 ;Did it
UDOERR: MOVE T1,SODISP ;Get DISPOSE value
MOVE T1,DSPNAM(T1) ;Get string address
$DCALL UDO
DSPNAM: 0 ;NOTHING
[ASCIZ \PRINT/LIST\]
[ASCIZ \PUNCH\]
[ASCIZ \SUBMIT\]
[ASCIZ \PLOT\]
SEGMENT DATA
SODISP: BLOCK 1 ;Save DISPOSE value
SEGMENT CODE
> ; End %IF20
SUBTTL %IRMS - Read next RMS record
;***************************************************************************
;* *
;* ENTRIES CALLED FROM FORIO *
;* *
;***************************************************************************
;++
; FUNCTIONAL DESCRIPTION:
;
; Reads an RMS record and sets up I/O pointers to it. Called for
; all RMS files (RSF files call %RMSIN/%RMRDW).
;
; CALLING SEQUENCE:
;
; PUSHJ P,%IRMS
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORGAN(D) - File organization code
; RAB(D) - RAB address
; IRBUF(D) - Input record buffer pntr
; IRBLN(D) - Buffer length (bytes)
; RECTP(D) - RECORDTYPE=
; FORM(D) - FORM=
; BPW(D) - Bytes/word
; WTAB(D) - Random-access
; A.KVL - Keyed read value
; A.KRL - Keyed read relational value
; A.KID - Keyed read index id
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RFA(D) - Current record's RFA
; RAB(D) UBF - Buffer address
; USZ - Buffer size (words)
; RAC - Record access mode (SEQ, KEY)
; KBF - Set to REC=
; KSZ - Set to key size for indexed
; FLAGS(D) - Set if EOF
; BUFADR(D) - Reset if buffer expanded
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T0,T1,T3,T4.
;
;--
;[5003] New
%IF20,<
%IRMS: PUSHJ P,GETINB ;Get input buffer if needed
LOAD T1,ORGAN(D) ;Get ORGANIZATION
MOVE T4,RAB(D) ;Setup RAB address
PUSHJ P,ISORGT(T1) ;Do setup by organization
PUSHJ P,IRGET ;Do record input
SKIPE T1,KBFADR ;Temp KBF buffer?
PUSHJ P,%FREBLK ;Yes, toss it
SETZM KBFADR
PJRST RMSWPT ;Setup for I/O from window
;Setup RAB's UBF with buffer address and USZ with buffer size in words
IRGET: PUSHJ P,GET$ ;Do $GET
JRST IRMERR ;Error
$FETCH T1,RSZ,<(T4)>
MOVEM T1,IRLEN(D) ;Save # bytes actually read
MOVEM T1,IRCNT(D)
ADD T1,BPW(D) ;Round up to words
SUBI T1,1
IDIV T1,BPW(D)
MOVEM T1,RECLEN ;Store as local record length
$FETCH T1,RFA,<(T4)> ;Get returned RFA
STORE T1,RFA(D) ;Save
MOVE T1,CREC(D) ;Get record number for CACHIT
PJRST CACHIT ;Go cache, maybe, and return
;Here on $GET errors. If the error is ER$EOF, flag D%END and zero IRCNT.
; If the error is ER$RNF (record not found), we have tried to read a deleted
; record or a record not yet written. If ORG=REL and access is random, return
; RNR ("?record not written") error.
;
; If the error is ER$RTB (record too big), expand the
; record buffer, set access to RFA, re-$GET the record and return.
; All other errors abort.
IRMERR: CAIN T2,ER$EOF ;EOF?
JRST IRMEOF ;Yes, handle it
CAIN T2,ER$RNF ;Record not found?
JRST IRMRNF ;Yes, check it out
CAIN T2,ER$RTB ;Record too big?
JRST IRMRTB ;Yes.
;Here on fatal $GET errors.
PUSHJ P,IRMSTS ;Go update STS/STV
$ACALL IOE
IRMEOF: MOVX T0,D%END
IORM T0,FLAGS(D) ;Set EOF seen
SETZM IRCNT(D) ;We read zero characters
PUSHJ P,RABSTV
POPJ P,
IRMRNF: LOAD T1,ORGAN(D) ;Get ORG=
CAIN T1,OR.REL ;Relative?
SKIPGE WTAB(D) ;or random-access?
JRST RETRNR ;Yes, "Record not written"
MOVE T1,RAB(D)
PUSHJ P,RETSUC ;Clear "error"
SETZM IRLEN(D) ;No, return a null record
SETZM IRCNT(D)
POPJ P,
RETRNR: PUSHJ P,IRMSTS ;Go update STS/STV
LOAD T1,ORGAN(D) ;Get ORGANIZATION
CAIN T1,OR.IDX ;INDEXED?
$ACALL IOE ;Yes, "?Record not found"
$ACALL RNR ;Issue error
;?Record too big for buffer. STV contains the actual size of the
;record, so use that as minimum expansion size.
IRMRTB: $FETCH T3,STV,<(T1)>
PUSHJ P,EXPIRB ;Expand the buffer
PUSHJ P,IRBWIN ;Disguise it as a window
PUSHJ P,UBFUSZ ;Setup UBF,USZ
MOVX T1,RB$RFA
$STORE T1,RAC,<(T4)> ;Set RFA access
MOVE T1,RAB(D)
PUSHJ P,RETSUC
JRST IRGET ;And go try again
;Here for fatal errors. Update STS/STV, deallocate KBF if present
IRMSTS: PUSHJ P,RABSTV
SKIPE T1,KBFADR
PUSHJ P,%FREBLK
SETZM KBFADR
POPJ P,
;Here for ORGANIZATION=SEQUENTIAL
ISSEQ: MOVEI T1,[ASCIZ /SEQUENTIAL/]
SKIPE A.KVL ;Trying keyed read for OR.SEQ?
$ACALL KRI ;?Keyed read illegal
MOVX T1,RB$SEQ ;No. Assume sequential access
;NOTE: the following 2 lines can be uncommented whenever RMS decides
; to fix random $GETs to fixed-length sequential files...
; SKIPE WTAB(D) ;Random?
; MOVX T1,RB$KEY ;Yes, set it
$STORE T1,RAC,<(T4)> ;Set it in RAB
XMOVEI T1,@A.REC ;Get REC= (or 0 for seq-access)
$STORE T1,KBF,<(T4)>
POPJ P,
;Here for ORGANIZATION=RELATIVE. For random-access set RAC=KEY, where KBF
; points to the record number from a REC=. For sequential access set RAC=SEQ;
; the VAX-compatible RMS behavior now will be to silently skip sequential
; requests to read a deleted or empty record and return the next existing
; record (or EOF). This also means that RELATIVE files cannot be BACKSPACEd,
; since the actual file current record # is unavailable to FOROTS.
ISREL: MOVEI T1,[ASCIZ /RELATIVE/]
SKIPE A.KVL ;Trying keyed read for OR.REL?
$ACALL KRI ;?Keyed read illegal
MOVX T1,RB$KEY ;No. Assume random-access
SKIPN WTAB(D) ;Random?
MOVX T1,RB$SEQ ;No, sequential
$STORE T1,RAC,<(T4)> ;Set it in RAB
XMOVEI T1,@A.REC ;Get REC= (or 0 for seq-access)
$STORE T1,KBF,<(T4)>
JUMPE T1,%POPJ ;If seq access, done
MOVE T1,(T1) ;For random, update current rec
MOVEM T1,CREC(D)
POPJ P,
;Here for ORGANIZATION=INDEXED.
; If user's KEYxx keyed read data exists in A.KVL, we setup for a keyed
; read: RAC=KEY; KBF=A.KVL; KRF=keyid (index number); KSZ=A.KVL size in
; bytes for CHARACTER, else zero; ROP=Key relational data. If A.KVL is zero,
; this is a sequential read: RAC=SEQ, KBF/KSZ/ROP=0.
ISIDX: SKIPE A.KVL ;Keyed read?
JRST ISKIDX ;Yes
MOVX T1,RB$SEQ ;No, sequential
$STORE T1,RAC,<(T4)> ;RAC=SEQ
SETZ T1, ;Clear any KSZ/KBF pntrs
$STORE T1,KBF,<(T4)>
$STORE T1,KSZ,<(T4)>
POPJ P,
;Here for keyed read
ISKIDX: MOVX T1,RB$KEY ;RAC=KEY
$STORE T1,RAC,<(T4)>
SKIPN T1,A.KID ;KEYID specified?
JRST ISKKVL ;No, use last READ's, or primary
MOVE T1,@T1 ;Yes, get key-of-reference
$STORE T1,KRF,<(T4)> ;Store
ISKKVL: MOVE T1,A.KVL ;Get key data pntr
XMOVEI T1,@T1 ;Get address of KVL data
LDB T2,[POINTR (A.KVL,ARGTYP)] ;Get type data type
MOVEI T3,4 ;Assume 4 for INTEGER length
CAIE T2,TP%CHR ;CHARACTER?
JRST ISKSTO ;Integer, got the address
DMOVE T0,@A.KVL ;Yes, get descriptor and length
ADD T1,BPW(D) ;In words, plus spare byte(s)
IDIV T1,BPW(D)
PUSHJ P,%GTBLK ;Get tmp key buffer
$ACALL MFU ;Can't
MOVEM T1,KBFADR ;Save address
SUBI T1,1 ;Correct it
HXL T1,BYTPT(D) ;Make byte pntr to buffer
DMOVE T2,@A.KVL ;Get pntr/count back
PUSHJ P,MOVSTR ;Move data to destination
MOVE T4,RAB(D) ;Get RAB address
MOVE T1,KBFADR ;Get KBF address
DMOVE T2,@A.KVL ;Get length back
ISKSTO: $STORE T1,KBF,<(T4)> ;Set KBF
$STORE T3,KSZ,<(T4)> ;Set length
;Here to set key relational (KGE/KGT) value. A.KVL is cleared here,
;so a subsequent %IRMS call in the same READ statement will get the
;next sequential record in the current index.
ISKROP: $FETCH T1,ROP,<(T4)> ;First turn off existing relationals
TXZ T1,RB$KGE!RB$KGT
MOVE T2,@A.KRL ;Get user's new value
TDO T1,KRLTAB(T2) ;Set RMS bits
$STORE T1,ROP,<(T4)>
SETZM A.KVL
POPJ P,
SEGMENT DATA
KBFADR: BLOCK 1 ;Address of KBF data
SEGMENT CODE
KRLTAB: 0 ;(0) KEY=
0 ;(1) KEYEQ=
RB$KGE ;(2) KEYGE=
RB$KGT ;(3) KEYGT=
ISORGT: JRST ISSEQ ;NONE
JRST ISSEQ ;SEQUENTIAL
JRST ISREL ;RELATIVE
JRST ISIDX ;INDEXED
> ; End %IF20
SUBTTL GETINB - Get input buffer, setup RAB
;++
; FUNCTIONAL DESCRIPTION:
;
; Gets an input buffer if not already allocated, sets up window
; pointers to it, and sets up RAB UBF and USZ.
;
; CALLING SEQUENCE:
;
; PUSHJ P,GETINB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
; BUFADR(D) - Address of buffer
; IRBLN(D) - Buffer length (bytes)
; IRBUF(D) - Non-zero if already a buffer
; BPW(D) - Bytes/word
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) UBF - Buffer address
; USZ - Length in words
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4
;
;--
;[5003] New
%IF20,<
GETINB: SKIPN IRBUF(D) ;Have buffer already?
PUSHJ P,GETIRB ;No, get one
PUSHJ P,IRBWIN ;Make it look like a wondow
UBFUSZ: MOVE T4,RAB(D) ;Get RAB address
MOVE T1,BUFADR(D) ;Get buffer address
$STORE T1,UBF,<(T4)> ;Store
MOVE T1,IRBLN(D) ;Get buffer size in bytes
ADD T1,BPW(D) ;Round up to words
SUBI T1,1
IDIV T1,BPW(D) ;Get it in words
$STORE T1,USZ,<(T4)> ;Store
POPJ P,
> ;End %IF20
SUBTTL IRBWIN - Make a buffer look like a window
;++
; FUNCTIONAL DESCRIPTION:
;
; Sets up pointers to a record buffer returned by GETIRB so it
; looks like a window.
;
; CALLING SEQUENCE:
;
; None
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; IRBUF(D) - Buffer pointer
; IRBLN(D) - Buffer size
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; WADR(D) - Updated with IRBUF-1
; BUFADR(D) - " " "
; WPTR(D) - Buffer page number
; WSIZ(D) - Size in bytes
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5003] New
%IF20,<
IRBWIN: MOVE T1,IRBUF(D) ;Get pntr-1 to it
MOVEI T1,1(1) ;Correct it
HRRZM T1,WADR(D) ;Save address
HRRZM T1,BUFADR(D) ;Here too
LSH T1,-LWSIZ ;Make it a page number
MOVEM T1,WPTR(D) ;Save
MOVE T1,IRBLN(D) ;Get buffer size
MOVEM T1,WSIZ(D) ;Save as window size in bytes
POPJ P,
> ; End %IF20
SUBTTL %UORMS - Setup output buffer for unformatted WRITE
;++
; FUNCTIONAL DESCRIPTION:
;
; Called for unformatted RMS writes to setup an output record
; buffer and make it look like a "window." If the buffer already
; exists, checks whether it should be expanded for variable-length
; output.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%UORMS
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORBUF(D) - Address of record buffer, if any.
; RECTP(D) - RECORDTYPE=
; FORM(D) - FORM=
; BPW(D) - Bytes/word
; BYTPT(D) - Byte pointer
; BUFADR(D) - Buffer address
; RSIZE(D) - User-specified RECL
; ORBLN(D) - Buffer size in bytes
; ORBUF(D) - Buffer pointer
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; PAGNUM - Cleared
; BYTUSD - Bytes used in expanded buffer
; EOFN(D) - Infinity
; ORBUF(D) - BP to beginning of record buffer
; ORBEG(D) - " " " " " "
; ORBLN(D) - Buffer length, bytes
; WADR(D) - Set to buffer address
; BUFADR(D) - Set to buffer address
; WPTR(D) - Page number of buffer
; WSIZ(D) - Window size in bytes
; ICNT(D) - Record byte count
; IPTR(D) - Current record pntr
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5004] New
%IF20,<
%UORMS: SKIPE ORBUF(D) ;Any buffer yet?
JRST CHKEXP ;Yes, maybe expand it
PUSHJ P,GETORB ;No. Get a buffer
SETZB T1,T2
DMOVEM T1,PAGNUM ;No used byte count for new buffer
GOTORB: PUSHJ P,ORBWIN ;Make it look like a "window"
;Clear new buffer
MOVE T3,ORBLN(D) ;Get length
ADD T3,BPW(D) ;Round up to words
SUBI T3,1
IDIV T3,BPW(D) ;Get # words
MOVE T1,BUFADR(D) ;Get start address to clear
SETZM (T1)
CAIN T3,1 ;One-word buffer?
JRST UORRET ;Yes
MOVSI T2,(T1)
HRRI T2,1(T1) ;start,,start+1
ADDI T1,(T3) ;Make the BLT limit+1
BLT T2,-1(T1)
UORRET: HRLOI T1,377777 ;Reset RMS's EOFN to infinite
MOVEM T1,EOFN(D)
POPJ P,
CHKEXP: SKIPE ORLEN(D) ;Any record length yet?
SKIPE RSIZE(D) ;Yes. Fixed recordsize specified?
JRST GOTORB ;Yes, no need to expand,or new buffer
HRRZ T1,IPTR(D) ;Any data?
JUMPE T1,GOTORB ;No, don't expand
MOVE T1,ICNT(D) ;Get words in window
IDIV T1,BPW(D)
JUMPG T1,GOTORB ;Room left
;Here to expand the "window"
HRRZ T1,ORBUF(D) ;Get old buffer address
ADDI T1,1 ;Corrected
MOVE T2,ORBLN(D) ;Get old length in bytes
MOVEM T2,BYTUSD ;Save as bytes used
MOVEM T3,ORLEN(D) ;Set current length
IDIV T2,BPW(D) ;in words
MOVEM T2,T3 ;Copy
LSH T3,1 ;Double it for new length
PUSHJ P,%MVBLK ;Move to bigger buffer
$ACALL RTL ;Can't
SUBI T1,1 ;Point to previous word
HXL T1,BYTPT(D) ;Make byte pntr to beg of new
MOVEM T1,ORBUF(D) ;Store new address
MOVEM T1,ORBEG(D)
IMUL T3,BPW(D) ;Get new length in bytes
MOVEM T3,ORBLN(D) ;Store
PUSHJ P,ORBWIN
JRST UORRET
ORBWIN: MOVE T1,ORBUF(D) ;Get pntr-1 to it
MOVEI T1,1(1) ;Correct it
HRRZM T1,WADR(D) ;Save address
HRRZM T1,BUFADR(D) ;Here too
LSH T1,-LWSIZ ;Make it a page number
MOVEM T1,WPTR(D) ;Save
MOVE T2,ORBLN(D) ;Get buffer size
MOVEM T2,WSIZ(D) ;Save as window size in bytes
SUB T2,BYTUSD ;Get bytes available
MOVEM T2,ORLEN(D) ;Set record length
MOVE T3,ORBUF(D) ;Get pntr again
MOVE T1,BYTUSD ;Get bytes used within "page"
ADJBP T1,T3 ;Update pntr
DMOVEM T1,IPTR(D) ;Save pntr/count
POPJ P,
> ; End %IF20
SUBTTL %ORMS - Write a record with RMS
;++
; FUNCTIONAL DESCRIPTION:
;
; Writes an RMS record.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%ORMS
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; ORG - ORGANIZATION
; RAB(D) - Address of RAB
; ORGAN(D) - ORGANIZATION
; ORBEG(D) - BP to beginning of record buffer
; ORLEN(D) - Formatted actual record length
; ORSIZ(D) - Unformatted buffer length
; RECTP(D) - RECORDTYPE
; ORBLN(D) - Record buffer length, bytes
; A.REC - Address of record number
; CREC(D) - Current record #
; FLAGS(D) - DDB flags
; RFA(D) - RFA
; WTAB(D) - Non-zero if random-access
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) RAC - Record access (FB$SEQ, FB$KEY)
; RBF - Record buffer address
; RSZ - Record size, bytes
; KBF - Address of key data
; RFA(D) - RFA from successful output
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T0-T2,T4.
;
;--
;[5004] New
%IF20,<
%ORMS: MOVE T4,RAB(D) ;Get RAB address
MOVE T1,ORBEG(D) ;Get buffer address
MOVEI T1,1(T1) ;Adjust it
$STORE T1,RBF,<(T4)> ;Store
;If records are fixed-length, set RSZ to the buffer size, else set to
; the actual record-length in bytes (formatted), or the unformatted buffer
; size in bytes. Indexed files always set to MRSIZE.
SKIPN T1,ORLEN(D) ;Assume not fixed, use formt'ed len
MOVE T1,ORSIZ(D) ;or unformatted buffer length
LOAD T2,RECTP(D) ;Get RECORDTYPE
CAIN T2,RT.FIX ;FIXED?
MOVE T1,ORBLN(D) ;Yes, use fixed buffer length
LOAD T2,ORGAN(D) ;Get ORGANIZATION
CAIN T2,OR.IDX ;INDEXED?
MOVE T1,MRSIZE(D) ;Yes, use MRS
$STORE T1,RSZ,<(T4)> ;Store as RSZ
XMOVEI T1,@A.REC ;Get address of recnum (or 0)
SKIPN T1 ;If none, use CREC
XMOVEI T1,CREC(D)
$STORE T1,KBF,<(T4)>
LOAD T1,ORGAN(D) ;Get organization
MOVE T2,OSORGT(T1) ;Set RAC by org
$STORE T2,RAC,<(T4)>
MOVE T0,FLAGS(D) ;Get flags
TXNE T0,D%RWI ;Is this a REWRITE?
JRST DOUPD ;Yes, do an $UPDATE instead
;Ugly workaround for relative files. Do a pre-$PUT $FIND on the
;record to see if we will get ER$REX on the $PUT, which must be
;avoided for remote files since it may hang the CONTINUE(abort)
;sequence.
CAIN T1,OR.REL ;ORG=REL?
JRST REXFND ;Yes, do pre-$FIND
DOPUT: PUSHJ P,PUT$ ;Do $PUT
$ACALL IOE
ORMOK: $FETCH T1,RFA,<(T4)> ;Get the RFA
MOVEM T1,RFA(D) ;Save it
MOVE T1,CREC(D) ;Get record number for CACHIT
PUSHJ P,CACHIT ;Cache if necessary
PUSHJ P,ORINI ;Re-init the buffer
SKIPN WTAB(D) ;Random access?
POPJ P, ;No, all done
LOAD T1,ORGAN(D) ;Get ORGANIZATION
CAIN T1,OR.REL ;RELATIVE?
SKIPN A.FMT ;Yes. Formatted output?
POPJ P, ;No, we're done
;Special case for formatted random relative output. Since slash format
;or indefinte repeat may cause more than one record to be written per
;IOLST. call, we must forget about the user-specified record # in A.REC
;and instead use CREC the next time around (ugh), since otherwise
;the same record will get written again with the new data.
SKIPN T1,A.REC ;Get address of recnum
XMOVEI T1,CREC(D) ;or CREC if none
MOVE T1,@T1 ;Get the number
MOVEM T1,CREC(D) ;Set it as current
SETZM A.REC ;Clear A.REC pntr
POPJ P,
;Here for REWRITE (update an indexed/relative file record), or for
;random-access relative files that tried to $PUT a record to an
;already-existing record cell. Indexed records, and fixed-length
;relative records, cannot change record size on an $UPDATE
;(fixed-length records will have been truncated/padded by FOROTS).
;Variable records for which an MRS RECL has been specified
;will get an error if their updated length exceeds MRS.
;
;Indexed $UPDATEs may get errors if the primary key changes or a key
;value is duplicated where these are not allowed in the XAB chain.
DOUPD: MOVX T0,D%RWI ;Turn off REWRITE flag
ANDCAM T0,FLAGS(D)
PUSHJ P,UPDA$ ;Do $UPDATE
$ACALL IOE
JRST ORMOK ;Update RFA/STV, return
;Here to check if the $PUT will ER$REX for relative files.
;Sequential-access relative files fail with ER$REX;
;random-access relative files do an $UPDATE.
REXMM==50133 ;[5023] MICcode for REX STV
REXFND: PUSHJ P,FIND$ ;[5023] Find the target record
JRST DOPUT ;[5023] Presumably not there (good)
SKIPE WTAB(D) ;[5023] Random access?
JRST RELUPD ;[5023] Yes, do an $UPDATE
MOVX T2,ER$REX ;[5023] No. Make ER$REX error
SKIPE NODNAM(D) ;[5023] If remote
MOVEI T3,REXMM ;[5023] also return STV
PUSHJ P,MAKSTS ;[5023] Fake REX
$ACALL IOE
RELUPD: MOVE T1,ORBEG(D) ;[5023] Get buffer address
MOVEI T1,1(T1) ;[5023] Adjust it
$STORE T1,RBF,<(T4)> ;[5023] Store
JRST DOUPD ;go do $UPDATE
OSORGT: RB$SEQ ;NONE
RB$SEQ ;SEQUENTIAL
RB$KEY ;RELATIVE
RB$KEY ;INDEXED
> ;End %IF20
SUBTTL %RMFND - FIND a direct-access relative record
;++
; FUNCTIONAL DESCRIPTION:
;
; Called from FIND processing in FORIO for files with INDX(D) DI.RMS.
; This routine checks that the file is an RMS relative file opened
; for direct access. If not, it aborts. If so, it establishes
; the current record as specified in the user's REC=. No data is
; transferred. An attempt to find a non-existent or deleted
; record will (VAX compatibly) produce an error.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMFND
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORGAN(D) - ORGANIZATION
; WTAB(D) - -1 if random-access
; RAB(D) - RAB address
; A.REC - User's REC=
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RFA(D) - Set to new current record
; RAB(D) RAC - RB$KEY
; RAB(D) RBF - Address of record number
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4.
;
;--
;[5004]
IF10,<
%RMFND: $SNH ;Should NOT get here from TOPS-10
> ;End IF10
%IF20,<
%RMFND: LOAD T1,ORGAN(D) ;Get ORGANIZATION
SKIPE WTAB(D) ;Access must be direct
CAIE T1,OR.REL ;ORG must be RELATIVE
$ACALL CDR ;Can't do direct I/O to seq file
MOVE T4,RAB(D) ;Get RAB address
XMOVEI T1,@A.REC ;Get REC=
$STORE T1,KBF,<(T4)>
MOVX T1,RB$KEY ;Setup for keyed access
$STORE T1,RAC,<(T4)>
PUSHJ P,FIND$ ;Do $FIND
$ACALL IOE ;Error
$FETCH T1,RFA,<(T4)> ;Get RFA
MOVEM T1,RFA(D) ;Update
PJRST %SETAV ;Return
> ;End %IF20
SUBTTL %RMCRW - Check if a REWRITE is legal
;++
; FUNCTIONAL DESCRIPTION:
;
; Checks that the execution of a REWRITE statement is legal for
; the specified unit/file. The file must be an RMS indexed or
; relative file not opened READONLY.
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMCRW
; <Return here; errors to %ABORT>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; INDX(D) - File type
; ORGAN(D) - ORGANIZATION
; RO(D) - READONLY
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; If the requested REWRITE is illegal, enters error handler.
; Uses T1.
;
;--
;[5004] New
%IF20,<
%RMCRW: LOAD T1,ORGAN(D) ;Screen by ORGANIZATION
SKIPE T1 ;If none (non-RMS),
CAIN T1,OR.SEQ ;or SEQUENTIAL,
$ACALL SIF ;then illegal statement
SKIPE A.REC ;Illegal if record number given
$ACALL CDR ;Report random I/O to seq file
LOAD T1,RO(D) ;Get READONLY-ness
JUMPN T1,ILLOUT ;READONLY, complain
POPJ P, ;No, ok
> ;End %IF20
SUBTTL %RMREW - Rewind an RMS file
;++
; FUNCTIONAL DESCRIPTION:
;
; Rewinds a sequentially-accessed RMS file. An error is issued
; if the file is open for direct access.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMREW
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORGAN(D) - ORGANIZATION
; WTAB(D) - Non-zero if access direct
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5004] New
%IF20,<
%RMREW: LOAD T2,ORGAN(D) ;Get ORGANIZATION
CAIE T2,OR.IDX ;Complain if INDEXED, or
SKIPE WTAB(D) ;random-access
$ACALL SIF
MOVX T1,D%END ;Get Flags
ANDCAB T1,FLAGS(D) ;Set no EOF
PUSHJ P,%SETIN ;Get file open for input
PUSHJ P,REWI$ ;Rewind file
$ACALL IOE ;Error
SETZM CREC(D) ;Clear RECORD NUMBER
SETZM IPTR(D) ;Pretend no I/O done
SETZM ICNT(D) ;No bytes in buffer
SETZM BYTN(D) ;Set current byte number to 0
POPJ P, ;Return
> ; End %IF20
SUBTTL %RMBSR - BACKSPACE RMS sequential file
;++
; FUNCTIONAL DESCRIPTION:
;
; Backspace an RMS sequential file. If RFA cacheing is enabled,
; the cache is searched for the target RFA which matches the target
; record number. If not found, or cacheing has been disabled
; (FORPRM parameter CASHSZ is zero), the file rewound and n-1
; records are read ($FIND) to position to the target record.
;
; BACKSPACE is legal only for RMS sequential files not opened
; ACCESS='APPEND'
;.
; CALLING SEQUENCE:
;
; PUSHJ P,%RMBSR
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORGAN(D) - ORGANIZATION
; RAB(D) - Address of RAB
; ROP - RB$EOF
; CREC(D) - Current record #
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; CREC(D) - Decremented
; RAB(D) RAC - RB$KEY
; RFA(D) - Updated during REWIND
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4.
; May rewind file and read n-1 records.
;
;--
;[5013] New
%IF20,<
%RMBSR: LOAD T1,ORGAN(D) ;Get ORGANIZATION
JRST BAKTAB(T1) ;Screen by organization
;Ensure that only ORG=SEQ RMS files can be BACKSPACEd.
BAKTAB: $SNH ;UNKNOWN (should not get here!)
JRST BAKSEQ ;SEQUENTIAL
$ACALL SIF ;RELATIVE (illegal)
$ACALL SIF ;INDEXED (illegal)
BAKSEQ: MOVE T4,RAB(D) ;Get RAB address
$FETCH T1,ROP,<(T4)> ;Get ROP bits
TXNE T1,RB$EOF ;/APPEND?
$ACALL SIF ;Yes, can't backspace
PUSHJ P,%SETIN ;Switch to input
SKIPG CREC(D) ;At beginning of file?
POPJ P, ;Yes, can't backspace more
SOS T1,CREC(D) ;Decrement CREC
MOVE T0,FLAGS(D) ;Get DDB flags
TXNE T0,D%END ;At EOF?
JRST %BAKEF ;Yes, just clear D%END
;Here for a cache search to see if the requested record number's RFA
; is cached. If so, $FIND it and return. If not, rewind and read n-1.
JUMPG T1,BSRGET ;If not at rec#1, must backspace
;Here if at first record. Must REWIND so next read gets same record.
PUSHJ P,REWI$ ;Do rewind
$ACALL IOE ;Error
POPJ P, ;Done
BSRGET: MOVEM T1,TRGREC ;Save target rec#
;Get an input buffer if needed
PUSHJ P,GETINB
;Search the cache for the RFA corresponding to our target record #. If
; cacheing has been disabled, must rewind and read n-1.
PUSHJ P,CSHFND ;Search the cache
JRST GOTRFA ;Found it
;Here when not cached, or no cache. Do a rewind.
PUSHJ P,REWI$ ;Rewind file
$ACALL IOE
SETZM LOCREC ;Clear local counter
MOVX T1,RB$SEQ ;Set sequential access
$STORE T1,RAC,<(T4)>
;Read n-1 records to position the file to the target record.
BSRLP: PUSHJ P,FIND$ ;$FIND a record
$ACALL IOE
$FETCH T1,RFA,<(T4)> ;Get RFA
STORE T1,RFA(D) ;Save for CACHIT
AOS T1,LOCREC ;Bump counter
PUSHJ P,CACHIT ;Update cache
SOSLE TRGREC ;Reached target # yet?
JRST BSRLP ;No, keep going
JRST BSRCRP ;Yes, establish as current record
;Here when we have the target RFA from the cache
GOTRFA: $STORE T1,RFA,<(T4)> ;Store target RFA
BSRCRP: MOVX T1,RB$RFA ;Set RFA access
$STORE T1,RAC,<(T4)>
PUSHJ P,GET$ ;Establish as current
$ACALL IOE
MOVX T1,RB$SEQ ;Reset to SEQ
$STORE T1,RAC,<(T4)>
POPJ P,
SEGMENT DATA
TRGREC: BLOCK 1 ;Target record number
LOCREC: BLOCK 1 ;Local record counter
SEGMENT CODE
> ;End %IF20
SUBTTL CSHFND - Search the cache for a record number
;++
; FUNCTIONAL DESCRIPTION:
;
; Searches the record/RFA cache for the requested record number and
; returns the matching RFA if found.
;
; CALLING SEQUENCE:
;
; PUSHJ P,CSHFND
; <Return here if rec# found>
; <Return here if not found>
;
; INPUT PARAMETERS:
;
; TRGREC - Target record number
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; T1 - RFA if found
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5013] New
%IF20,<
CSHFND: SKIPN T2,CACHE(D) ;Cacheing enabled?
JRST %POPJ1 ;No, return +2
MOVEI T3,CACHSZ
ADD T3,T2 ;Get cache_end+1
CSHLP: CAML T2,T3 ;Beyond limit?
JRST %POPJ1 ;Yes, not found
MOVE T0,(T2) ;Get a record# from cache
JUMPE T0,%POPJ1 ;If entry is null, entry not found
CAMN T0,TRGREC ;Our target #?
JRST CSHGOT ;Yes
ADDI T2,2 ;No, bump pointer to next entry
JRST CSHLP ;Keep going
CSHGOT: MOVE T1,1(T2) ;Get associated RFA
POPJ P, ;Return
> ;End %IF20
SUBTTL %RMASV - Handle RMS ASSOCIATEVARIABLE
;++
; FUNCTIONAL DESCRIPTION:
;
; Updates the ASSOCIATEVARIABLE for RMS files. It is ignored for
; RMS files unless ORGANIZATION='RELATIVE' or ACCESS='DIRECT'.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMASV
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORGAN(D) - ORGANIZATION
; ACC(D) - ACCESS
; CREC(D) - Current record
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; AVAR(D) - ASSOCIATEVARIABLE
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; T1,T2.
;
;--
;[5003] New
IF10,< ;No-op on TOPS10
%RMASV: POPJ P,
> ;End IF10
%IF20,<
%RMASV: LOAD T1,ORGAN(D) ;Get ORGANIZATION=
CAIE T1,OR.REL ;RELATIVE?
POPJ P, ;No, ignore assocvar
LOAD T1,ACC(D) ;Get ACCESS=
CAIE T1,AC.RIO ;ACCESS='DIRECT'?
CAIN T1,AC.RIN
TRNA ;Yes, set the AV
POPJ P, ;No, ignore AV
MOVE T2,AVAR(D) ;Get ASSOCVAR
MOVE T1,CREC(D) ;Get CREC
ADDI T1,1 ;Increment
MOVEM T1,(T2) ;Store
POPJ P,
> ; End %IF20
SUBTTL %RMCDL - Check if DELETE is legal
;++
; FUNCTIONAL DESCRIPTION:
;
; Checks whether a DELETE statement is legal for the requested
; file type. The file must be an RMS relative or indexed file
; for which a DDB has been established.
;
; If a DELETE statement is the first I/O statement for a deferred-
; open unit, a new file will be created for output, and the DELETE
; will fail with a "?No current record" error.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMCDL
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; %CUNIT - Current unit #
; DDBAD(U) - DDB address
; %DDBTAB(U) - UDBs
; RO(D) - READONLY
; ORGAN(D) - ORGANIZATION
; A.REC - Record number
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; %UDBAD - Flagged as I/O in progress
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
; $ACALLs if DELETE is illegal for file.
;
;--
;[5013] New
%IF20,<
%RMCDL: MOVE T1,%CUNIT ;Get unit number
SKIPN U,%DDBTA(T1) ;Get UDB addr
$ACALL SIF ;None. No implicit OPEN/DELETE
MOVEM U,%UDBAD ;We have started an I/O statement
MOVE D,DDBAD(U) ;Get DDB addr
LOAD T1,RO(D) ;Get READONLY-ness
JUMPN T1,ILLOUT ;Can't if readonly
LOAD T1,ORGAN(D) ;Get ORGANIZATION
JRST DELTAB(T1) ;Screen by organization
DELTAB: $ACALL SIF ;UNKNOWN (non-RMS)
$ACALL SIF ;SEQUENTIAL (illegal)
JRST RELDEL ;RELATIVE
JRST IDXDEL ;INDEXED
;Here for RELATIVE deletes. If direct-access, a REC= is required. If
;seq access, a REC= is forbidden.
RELDEL: SKIPN WTAB(D) ;Random I/O?
JRST RELDSQ ;No, must not have REC=.
SKIPN A.REC ;Yes. Must have REC=
$ACALL CDS
POPJ P,
RELDSQ: SKIPE A.REC ;Must not have REC=
$ACALL CDR
POPJ P,
;Here for INDEXED deletes. REC= forbidden.
IDXDEL: SKIPE A.REC ;Make sure there's no record #
$ACALL IRN
POPJ P,
> ;End %IF20
SUBTTL %RMDEL - DELETE an RMS record
;++
; FUNCTIONAL DESCRIPTION:
;
; DELETEs a record from an RMS relative or indexed file. If no REC=
; has been specified, this is a current-record delete: the last record
; successfully located by a READ or FIND is deleted (relative and indexed
; files). If a REC= is supplied (relative files only), the specified
; record is deleted.
;
; After a direct access delete, the ASSOCIATEVARIABLE is set to the
; next record.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMDEL
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
; A.REC - Record number
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) RAC - RB$KEY for direct delete
; KBF - Record number
; CREC(D) - Record number
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T4.
;
;--
;[5013] New
%IF20,<
%RMDEL: MOVE T4,RAB(D) ;Get RAB address
SETZ T1, ;Clear RAC
$STORE T1,RAC,<(T4)>
XMOVEI T1,@A.REC ;Get REC= (or 0)
$STORE T1,KBF,<(T4)>
JUMPE T1,DELREC ;If no REC, delete current rec
SKIPG T1,@T1 ;Direct delete. Legal record number?
$ACALL IRN ;No
MOVEM T1,CREC(D) ;Store as current record
MOVX T1,RB$KEY ;Set keyed access for REC= delete
$STORE T1,RAC,<(T4)>
PUSHJ P,FIND$ ;Do $FIND to establish current rec
$ACALL IOE ;Error
DELREC: PUSHJ P,DELE$ ;Do the delete
$ACALL IOE ;Error
PJRST %SETAV ;Done
> ;End %IF20
SUBTTL %RMCUL - Check if UNLOCK is legal
;++
; FUNCTIONAL DESCRIPTION:
;
; Checks whether an UNLOCK statement is legal for the requested
; file type. The file must be an RMS relative or indexed file
; for which a DDB has been established.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMCUL
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; %CUNIT - Current unit #
; DDBAD(U) - DDB address
; %DDBTAB(U) - UDBs
; ORGAN(D) - ORGANIZATION
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; %UDBAD - Flagged as I/O in progress
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
; $ACALLs if UNLOCK is illegal for file.
;
;--
;[5014] New
%IF20,<
%RMCUL: MOVE T1,%CUNIT ;Get unit number
SKIPN U,%DDBTA(T1) ;Get UDB addr
$ACALL SIF ;None. No implicit OPEN/DELETE
MOVEM U,%UDBAD ;We have started an I/O statement
MOVE D,DDBAD(U) ;Get DDB addr
LOAD T1,ORGAN(D) ;Get ORGANIZATION
JRST UNLTAB(T1)
UNLTAB: $ACALL SIF ;UNKNOWN (illegal)
$ACALL SIF ;SEQUENTIAL (illegal)
JRST %POPJ ;RELATIVE
JRST %POPJ ;INDEXED
> ; End %IF20
SUBTTL %RMUNL - UNLOCK an RMS record
;++
; FUNCTIONAL DESCRIPTION:
;
; UNLOCKS a record in an RMS file. The unlock statement uses
; the $FREE RMS service call. If a "no record is locked" error
; occurs it is ignored.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMUNL
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; %ERIOS - 2nd error number
; A.IOS - IOSTAT variable address
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2
;
;--
;[5014] New
%IF20,<
%RMUNL: PUSHJ P,FREE$ ;Call the $Free service to unlock rec
CAIN T2,ER$RNL ;Ignore "Record not locked" errors
SKIPA ;Good return
$ACALL IOE ;Error
MOVE T1,%ERIOS ;GET 2ND ERROR NUMBER OR ZERO
SKIPE T2,A.IOS ;IOSTAT VARIABLE TO DEFINE?
MOVEM T1,@T2 ;YES. DEFINE IT
SETZM %UDBAD ;NOW NO I/O IN PROGRESS
POPJ P, ;Return
> ;End %IF20
SUBTTL %RMEND - ENDFILE for RMS files
;++
; FUNCTIONAL DESCRIPTION:
;
; Perform ENDFILE processing for RMS sequential files: get the file
; open for output (thus truncating it), then get it open for input
; positioned at EOF. This statement is trapped as illegal for
; RMS relative and indexed files.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMEND
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; ORGAN(D) - ORGANIZATION
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FLAGS(D) - D%END
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
; $ACALLs if ORGANIZATION=RELATIVE or INDEXED.
;
;--
;[5013] New
IF10,<
%RMEND: $SNH ;Should not get here on TOPS-10
> ;End IF10
%IF20,<
%RMEND: LOAD T2,ORGAN(D) ;Get file type
CAIE T2,OR.SEQ ;Must be sequential
$ACALL SIF
PUSHJ P,%SETOUT ;Set to output
PUSHJ P,%SETIN ;Then to input
MOVX T1,D%END ;at EOF
IORM T1,FLAGS(D)
POPJ P,
> ; End %IF20
SUBTTL %RMSIN - Read a sequential RSF page
;++
; FUNCTIONAL DESCRIPTION:
;
; Reads a page from a remote stream file accessed sequentially,
; and updates window pointers via FORIO routine SETPTR.
;
; Entry RMSMPW is called from %RMOPN to map in the last
; page of an RSF file opened ACCESS='APPEND'.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMSIN
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; BYTN(D) - Desired file byte #
; EOFN(D) - EOF byte #
; RAB(D) - Address of RAB
; BPW(D) - Bytes/word as a function of BYTESIZE and/or
; returned file bytesize
; WADR(D) - Address of process page to map to
; BUFCT(D) - Window page count
; WPTR(D) - Page number
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) BKT - Set to page # +1 of file to map
; RAC - Set to RB$BLK for block-mode I/O
; USZ - Set to PSIZ (^D512)
; UBF - Set to WADR(D)
; ICNT(D) - Set to count of free bytes in buffer
; FLAGS(D) - D%END set if EOF
; PAGNUM - Double word containing the page #, bytes used
; in page
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5003] New
%IF20,<
%RMSIN: MOVE T2,BYTN(D) ;Get target byte number
CAMGE T2,EOFN(D) ;At or past EOF?
JRST RMSMPW ;No
MOVX T1,D%END ;Yes. Get EOF
IORM T1,FLAGS(D) ;Set it
POPJ P, ;Return
RMSMPW: PUSHJ P,RMAPW ;Map some pages in
PUSHJ P,SETPTR ;Setup pointer/count
MOVE T2,BYTN(D) ;Get byte # of next window
CAMG T2,EOFN(D) ;Past EOF?
POPJ P, ;No, all done
SUB T2,EOFN(D) ;Get the difference
MOVNI T2,(T2) ;Make negative
ADDM T2,ICNT(D) ;Decrement count
POPJ P,
;Here to read an n-page window.
RMAPW: MOVE T4,RAB(D) ;Get RAB address
MOVE T2,BYTN(D) ;Get target byte #
MOVE T1,BPW(D) ;Calculate page #, get bytes/word
LSH T1,LWSIZ ;# bytes/page
IDIV T2,T1 ;Get file page #
DMOVEM T2,PAGNUM ;Save for SETPTR
ADDI T2,1 ;Bump page # for RMS
MOVEM T2,T1 ;Copy
;Loop to read in n pages
LOAD T3,BUFCT(D) ;Get buffer count
MOVNI T3,(T3) ;Negative
MOVSI T3,(T3) ;In left half
HRR T3,WPTR(D) ;Get page # of bottom page
RMSINL: MOVEI T2,(T3) ;Get core addr
LSH T2,LWSIZ
PUSHJ P,GETBKT ;$READ it
JRST SINERR ;Error
$FETCH T1,BKT,<(T4)> ;Increment file page to get
ADDI T1,1
AOBJN T3,RMSINL ;Back for more
POPJ P, ;Done
SINERR: MOVE T1,RAB(D) ;Get RAB address in T1
CAIE T2,ER$EOF ;EOF error?
CAIN T2,ER$RNF ;or non-existent page?
PJRST RETSUC ;Yes, not really an error, return
$ACALL IOE ;No, something bad
> ; End %IF20
SUBTTL %RMRDW - Read a random RSF page
;++
; FUNCTIONAL DESCRIPTION:
;
; Maps in a page from a randomly-accessed RSF file, writing any
; modified pages first.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMRDW
; <Return here>
;
; INPUT PARAMETERS:
;
; P1 - File page # to map
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
; WADR(D) - Offset into WTAB of least used page
; WPTR(D) - Core page address of file pages
; WTAB(D) - Page table
;
; OUTPUT PARAMETERS:
;
; T1 - Page table pointer
;
; IMPLICIT OUTPUTS:
;
; RAB(D) UBF - Set to destination page address
; BKT - Set to file page # +1
; USZ - Set to page length
; RAC - Set to RB$BLK for block-mode I/O
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5003] New
%IF20,<
%RMRDW: PUSHJ P,RMWPG ;Write any pages which are modified
MOVE T4,RAB(D) ;Get RAB address
MOVE T2,WADR(D) ;Get page table offset
ADD T2,WPTR(D) ;Get core page number
LSH T2,LWSIZ ;Convert to address
SETZM (T2) ;Clear destination page
MOVSI T1,(T2)
HRRI T1,1(T2) ;start,,start+1
BLT T1,PSIZ-1(T2) ;Clear page
MOVEI T1,1(P1) ;Get file page # +1
PUSHJ P,GETBKT ;$READ it
JRST RDWERR ;Some error, investigate
RDWRET: MOVE T1,WADR(D) ;OK. Get page table offset again
ADD T1,WTAB(D) ;Point into page table
MOVEM P1,(T1) ;Store new file page number
POPJ P,
RDWERR: CAIE T2,ER$EOF ;Non-existent page?
CAIN T2,ER$RNF
TRNA ;Yes, not really an error
$ACALL IOE ;No, some other error
MOVE T1,RAB(D)
PUSHJ P,RETSUC ;Clear the "error"
JRST RDWRET
> ; End %IF20
SUBTTL RMSWPT - Setup pointers to a file window
;++
; FUNCTIONAL DESCRIPTION:
;
; Calls SETPTR to update pointers to the window/buffer we
; just read.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMSWPT
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; IRBEG(D) - Record buffer pointer
; BYTN(D) - Current byte number in file
; EOFN(D) - Number of bytes in file
; FLAGS(D) - DDB flags
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; IRPTR(D) - Receives IRBEG
; IPTR(D) - Receives IRBEG
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T2.
;
;--
;[5003] New
%IF20,<
RMSWPT: PUSHJ P,SETPTR ;Setup pointers to window
MOVE T1,IRBEG(D) ;Get record buffer ptr
MOVEM T1,IRPTR(D) ;Initialize it
MOVEM T1,IPTR(D)
SKIPE IRCNT(D) ;Any characters in record?
POPJ P, ;Yes, we're done
MOVE T0,FLAGS(D) ;Get flags
TXNE T0,D%END ;Zero chars; EOF also?
$ACALL EOF ;Yes
POPJ P,
> ; End %IF20
SUBTTL CACHIT - Cache record number and RFA
;++
; FUNCTIONAL DESCRIPTION:
;
; If CACHSZ is non-zero, a cache has been setup at OPEN time for
; sequential and sequentially-accessed RMS relative files. CACHE(D)
; points to the start the cache, CACHPT(D) to the next free cache
; entry.
;
; The cache is a block of CACHSZ words (CACHSR records * 2) of the
; form:
;
; !=====================================!
; CACHE(D) => ! Record number from CREC(D) !
; !-------------------------------------!
; ! RFA from $GET or $PUT !
; !-------------------------------------!
; ! !
;
; When CACHPT(D) points off the end of the cache, it is reset to
; the beginning.
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,CACHIT
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Record number to cache
;
; IMPLICIT INPUTS:
;
; RFA(D) - RFA from last $GET or $PUT
; CREC(D) - Current record number
; CACHE(D) - Address of cache
; CACHPT(D) - Free entry pointer
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; CACHPT(D) - Updated to point to next free
; cache location
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T3.
;
;--
;[5003] New
%IF20,<
CACHIT: SKIPN CACHE(D) ;Are we cacheing?
POPJ P, ;No
MOVE T2,CACHPT(D) ;Get address of free cache location
MOVEM T1,(T2) ;Save record # in cache
ADDI T2,1 ;Bump pointer
MOVE T1,RFA(D) ;Get RFA of record
MOVEM T1,(T2) ;Save in cache
ADDI T2,1 ;Bump pointer
MOVE T1,CACHE(D) ;Get cache start address
MOVEI T3,CACHSZ ;Get cache size
ADD T3,T1 ;Get last word+1
CAIL T2,(T3) ;At or beyond the end?
MOVE T2,T1 ;Yes, reset pntr to start
MOVEM T2,CACHPT(D) ;Save pointer
POPJ P, ;Return
> ; End %IF20
SUBTTL %RMSOU - Map or write an RSF buffer
;++
; FUNCTIONAL DESCRIPTION:
;
; Called from FORIO OSTAB for RSF files when ICNT(D) is zero
; to write out the current output window.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMSOU
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; BYTN(D) - Requested file byte number
; BPW(D) - Bytes/word
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; PAGNUM - Double word containing the page #, bytes used
; in page
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T3.
;
;--
;[5004] New
%IF20,<
%RMSOU: PUSHJ P,RSFOCP ;Output current window
SETZB T2,T3 ;Say we have a new window
DMOVEM T2,PAGNUM
PJRST SETPTR ;Setup new pointers
> ;End %IF20
SUBTTL RSFOCP - Output current RSF output window
;++
; FUNCTIONAL DESCRIPTION:
;
; Writes out the current window to the file, up to and including
; the window page containing the highest byte written so far to
; the file.
;
; Assuming a default 4 page window:
;
; WADR=Core address of IPTR=Byte pntr to last
; 1st window page byte written +1
; \/ \/
; =============================================================
; |/////////////:://////////////::/// :: |
; |/////////////:://////////////::/// :: |
; |/////////////:://////////////:://///// :: |
; =============================================================
; /\ /\
; WPTR=1st window page # EOFN=Highest file byte # written
;
;
; The calculation of how many window pages to write is as follows:
;
; 1) Using EOFN, calculate the highest file page number to write
;
; EOFN + ((bytes/page) - 1)
; LSTFPG = -------------------------
; (bytes/page)
;
; 2) Calculate the number of pages used in the window:
;
; (IPTR<rh> - WADR +1) + (PSIZ-1)
; WINPGS = ------------------------------
; PSIZ
;
; 3) The first file "bucket" to write is thus LSTFG-WINPGS+1.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RSFOCP
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; IPTR(D) - Byte pntr to last written byte in
; window
; WADR(D) - Core address of base window page
; WPTR(D) - Page number of base window page
; EOFN(D) - Highest byte written to file
; BPW(D) - Byes/word
; RAB(D) - Address of RAB
;
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RAB(D) BKT - Set to file page(s) to write
; RAC - RB$BLK for block mode I/O
; USZ - PSIZ
; RBF - Set to core page(s) to write
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5004] New
%IF20,<
RSFOCP: HRRZ T1,IPTR(D) ;Get address of data
JUMPE T1,%POPJ ;Leave if none
SUB T1,WADR(D) ;Get # words to write -1
AOJE T1,%POPJ ;If none to write, leave
;Determine how many pages we have written to the file
MOVE T3,EOFN(D) ;Get highest file byte
MOVE T1,BPW(D) ;Get bytes/word
LSH T1,LWSIZ ;Get bytes/page
ADDI T3,-1(T1) ;and pages written
IDIVI T3,(T1) ;rounded
;and the number of pages we have to write
HRRZ T1,IPTR(D) ;Get current point
SUB T1,WADR(D) ;Get total window words used-1
ADDI T1,1
ADDI T1,PSIZ-1 ;Convert to pages
IDIVI T1,PSIZ
MOVNM T1,WINPGS ;Save negative page count
;Now get the first file page "bucket" to set
SUBI T3,-1(T1) ;Bucket# = page#+1
MOVEM T3,T1 ;Copy
;Setup AOBJN pointer for -# pages to write,,first window page
HRLE T3,WINPGS ;Get neg count in left
HRR T3,WPTR(D) ;page # of bottom page in right
MOVE T4,RAB(D) ;Get RAB address
;Top of loop
RMSOUL: MOVEI T2,(T3) ;Get core addr
LSH T2,LWSIZ
$STORE T2,RBF,<(T4)> ;Store as buffer address
PUSHJ P,PUTBKT ;$WRITE it
$ACALL IOE ;Can't
;Bump bucket number
$FETCH T1,BKT,<(T4)> ;Increment file page to get
ADDI T1,1
AOBJN T3,RMSOUL ;Back for more
POPJ P,
SEGMENT DATA
WINPGS: BLOCK 1 ;Number of window pages to write
SEGMENT CODE
> ; End %IF20
SUBTTL %RMERR - Handle RMS service errors
;***************************************************************************
;* *
;* ENTRIES CALLED FROM FORERR *
;* *
;***************************************************************************
;++
; FUNCTIONAL DESCRIPTION:
;
; Called for RMS errors with $J in the error. Translates the STS
; status code into a string by searching a subset table of all
; RMS STS error codes/strings. If a match is found, the error
; message is constructed and pointed to by global %RMEPT. If
; no match is found, a string consisting of the STS and STV values
; alone is constructed. If the STS code indicates a $SNH (should
; not happen) internal FOROTS error, this routine never returns
; but converts the $DCALL/$ACALL error which called it into an
; OTS error ending at %HALT.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMERR
; <Return here>
;
; INPUT PARAMETERS:
;
; P2 - Error argument block pointer
;
; IMPLICIT INPUTS:
;
; STS(D) - RMS status code
; STV(D) - RMS status value
; STSTAB - Table of matchable error strings in the following
; format:
;
; [Address of error string],,<STS-ER$MIN>
;
; If the error is a $SNH, flag FL%SNH is set in the
; table entry, RH.
;
; %RMPDP - Address+1 of ERCAL call after the RMS $xxxx error
; (used for $SNHs only)
; %FSECT - FOROTS' section number
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; ERRPTR - Error message pointer.
; DESPTR - Saved original pointer
; SAVPTR - Local save for STS string address
; %ERNM2 - Second error number (STS)
; %ERNM3 - Third error number (STV)
; INICHR - 1st error character (to @ for $SNH)
; %RMEPT - Pntr to RMS error message text
;
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2,T4.
;
;--
;[5007] New
%IF20,<
FL%SNH==400000 ;Table $SNH flag
%RMERR: LOAD T1,STV(D) ;Get and save 3rd error number:STV
MOVEM T1,%ERNM3
LOAD T1,STS(D) ;Get and save 2nd error number:STS
MOVEM T1,%ERNM2
SUBI T1,ER$MIN ;Strip error offset
MOVEM T1,T3 ;STS to match in AC3
MOVE T1,[POINT 7,TXTBF2] ;Destination for error string
EXCH T1,ERRPTR
MOVEM T1,DESPTR ;Save original error pntr
MOVEI T1,5*LERRBF-1 ;Set count
MOVEM T1,ERRCNT
SETZ T2,
RMERSL: SETZ T4, ;Clear local $SNH flag
MOVE T1,STSTAB(T2) ;Get table entry
JUMPE T1,NOSTS ;End of table with no match
HRRZ T1,T1 ;Get STS code alone
TXZE T1,FL%SNH ;$SNH error?
SETOM T4 ;Yes, flag it
CAIE T1,(T3) ;Same as our target STS?
AOJA T2,RMERSL ;No, keep looking
;Here with an STS-matched string from the table. If not a $SNH error
; also, return this string.
HLRZ T1,STSTAB(T2) ;Yes, get string address
MOVEM T1,SAVPTR ;Save
JUMPE T4,RTSTR ;If not also a $SNH, go return it
;Here with a $SNH-flagged error. If caused by a USEROPEN routine, it's not
; really a $SNH.
MOVE T1,%FLGS(P2) ;Get error flags
TXNE T1,I%UOF ;USEROPEN error?
JRST RTSTR ;Yes, not *our* $SNH
;Here with a $SNH. Modify the error string we will return.
MOVEI T1,[ASCIZ /Internal FOROTS error at /] ;source
PUSHJ P,ASCTYP ;Move string to buffer
MOVE T1,%RMPDP ;Get PDP of error.
SUBI T1,1 ;Get addr of call
SKIPN %FSECT ;Non-zero section?
MOVEI T1,(T1) ;No. Exclude flags
PUSHJ P,OCTTYP ;Type it in octal
SETZM %RMPDP ;Clear $SNH PDP
MOVEI T1,[ASCIZ /, /]
PUSHJ P,ASCTYP
RTSTR: MOVE T1,SAVPTR ;Get STS string address
PUSHJ P,ASCTYP ;Ouput it
MOVEI T1,[ASCIZ /, /]
PUSHJ P,ASCTYP
NOSTS: MOVEI T1,[ASCIZ /STS:/] ;Output STS code
PUSHJ P,ASCTYP
LOAD T1,STS(D)
PUSHJ P,OCTTYP
MOVEI T1,[ASCIZ /, STV:/] ;And STV
PUSHJ P,ASCTYP
LOAD T1,STV(D)
PUSHJ P,OCTTYP
SETZ T1,
IDPB T1,ERRPTR
MOVE T1,DESPTR ;Restore original error pntr
MOVEM T1,ERRPTR
MOVEI T1,TXTBF2 ;Save pntr to message for $J code
MOVEM T1,%RMEPT ;Save error address
SKIPE %RMPDP ;$SNH?
POPJ P, ;No, done
;Here for $SNH errors, which never return to DIALOG or take an ERR=.
MOVE P2,%ERPTR ;Point to error block
PUSHJ P,EMSGT0 ;Get error message text
MOVEI T1,"@" ;Convert 1st character to SNH
MOVEM T1,INICHR
PJRST FOREC2 ;Go output and die
> ; End %IF20
SUBTTL %RMECL - Cleanup after an RMS error
;++
; FUNCTIONAL DESCRIPTION:
;
; If the error was ER$RTN (RENAME to two different nodes), the user
; tried to:
;
; a) Rename a local OPEN filespec to a remote CLOSE filespec.
; b) Rename a remote file to another node.
;
; In these cases the "remoteness" of the file [NODNAM(D), USERID(D)
; PASWRD(D)] is zeroed, since in re-entering DIALOG after such an
; error there is no way for the user to remove a file's "nodeness".
; This is done now, rather than at the point of error, since FORERR
; must have the node information available to output as part of the
; error text.
;
; In all cases of an RMS error, STS(D) and STV(D) are zeroed here,
; so that a subsequent DIALOG entry which itself gets an error
; (quite possibly unrelated to any RMS file) does not re-call the
; RMS error handler.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMECL
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; STS(D) - RMS completion status code
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; STS(D) - Zeroed
; STV(D) - Zeroed
;
; The following are cleared on ER$RTN
;
; NODNAM(D) - Node name
; PASWRD(D) - Password
; USERID(D) - User ID
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5007] New
%IF20,<
%RMECL: LOAD T1,STS(D) ;Get STS
CAIE T1,ER$RTN ;Two different nodes error?
JRST ZERSV ;No
SETZM NODNAM(D) ;Yes, forget about file's remoteness
SETZM JFNBLK+.GJNOD
SETZM PASWRD(D)
SETZM USERID(D)
SETZM JFNBLK+.GJATR
ZERSV: SETZ T1,
STORE T1,STS(D)
STORE T1,STV(D)
POPJ P,
> ;End %IF20
SUBTTL STS Error Table
%IF20,<
DEFINE USER (STS,STRING) < ;;For RMS errors
.COD.==<STS-ER$MIN>
XWD [ASCIZ @STRING@],.COD.
PURGE .COD.,STS
> ;End USER
DEFINE SNH (STS,STRING) < ;;RMS which $SNH
.COD.==<STS-ER$MIN>+FL%SNH
XWD [ASCIZ @STRING@],.COD.
PURGE .COD.,STS
> ;End SNH
DEFINE IGNORE (STS,STRING) < ;;For ignored RMS error strings
REPEAT 0,<
USER (STS,STRING)
> ;End REPEAT 0
> ;End IGNORE
STSTAB:
IGNORE ER$AID,<Bad AID value>
IGNORE ER$ALQ,<Allocation quantity incorrect>
IGNORE ER$ANI,<Not ANSI 'D' format>
IGNORE ER$BKS,<Bad bucket size>
IGNORE ER$BKZ,<'BKZ' field invalid in XAB>
SNH ER$BLN,<Bad block length>
SNH ER$BSZ,<Bad byte size>
USER ER$BUG,<Internal bug found in RMS-20>
USER ER$CCF,<Cannot $CLOSE file>
USER ER$CCR,<Cannot $CONNECT RAB>
USER ER$CDR,<Cannot $DISCONNECT RAB>
USER ER$CEF,<Cannot $ERASE file>
USER ER$CGJ,<Cannot get JFN for file>
USER ER$CHG,<Key value cannot change>
SNH ER$COD,<Bad COD value in XAB>
USER ER$COF,<Cannot open file>
USER ER$CUR,<No current record>
IGNORE ER$DAN,<Bad data-area number>
USER ER$DEL,<Record has been deleted>
USER ER$DEV,<Illegal device>
IGNORE ER$DFL,<Bad data-fill percentage value>
USER ER$DLK,<Deadlock condition detected>
USER ER$DME,<Dynamic memory exhausted>
SNH ER$DTP,<Bad data-type in XAB>
USER ER$DUP,<Duplicate key exists>
IGNORE ER$EDQ,<Unexpected ENQUE/DEQUE error>
USER ER$EOF,<End of file>
SNH ER$FAB,<Block is not a valid FAB>
SNH ER$FAC,<Bad file access value>
USER ER$FEX,<File already exists>
SNH ER$FLG,<Bad XAB flag combination>
USER ER$FLK,<File already locked by someone else>
SNH ER$FNA,<Bad FNA value>
IGNORE ER$FNC,<File not closed>
USER ER$FNF,<File not found>
SNH ER$FOP,<Bad file options>
IGNORE ER$FSZ,<Invalid header size for VFC-file>
IGNORE ER$FUL,<File full>
IGNORE ER$IAL,<Invalid argument list>
IGNORE ER$IAN,<Bad index-area number>
SNH ER$IBC,<Illegal block mode connection>
SNH ER$IBO,<Illegal block mode operation>
SNH ER$IBS,<Illegal block mode sharing>
SNH ER$IFI,<Bad IFI value>
IGNORE ER$IFL,<Bad index fill percentage>
IGNORE ER$IMX,<Illegal multiple XABs>
SNH ER$IOP,<Invalid operation attempted>
IGNORE ER$IRC,<Illegal record encountered>
SNH ER$ISI,<Bad ISI value>
SNH ER$JFN,<Bad JFN value>
USER ER$KBF,<Bad KBF value>
USER ER$KEY,<Bad record key>
USER ER$KRF,<Bad key of reference value>
USER ER$KSZ,<Bad key size>
IGNORE ER$LSN,<Bad line-sequence number>
USER ER$MRN,<Bad MRN value>
USER ER$MRS,<Bad MRS value>
USER ER$NEF,<Not positioned at EOF>
IGNORE ER$NLG,<Log file not active>
USER ER$NPK,<Indexed file - no primary key defined>
SNH ER$NXT,<Invalid 'NXT' field in a XAB>
SNH ER$ORD,<XABs are not in correct order>
SNH ER$ORG,<Bad file organization value>
USER ER$PEF,<Cannot position to end-of-file>
IGNORE ER$PLG,<Error detected in file's prologue>
SNH ER$POS,<Bad key position value>
USER ER$PRV,<Privilege violation>
IGNORE ER$QPE,<Quiet point enabled>
SNH ER$RAB,<Block is not a valid RAB>
SNH ER$RAC,<Bad record access value>
SNH ER$RAT,<Bad record attributes>
SNH ER$RBF,<Invalid record buffer address>
USER ER$REF,<Bad key reference (REF) value>
IGNORE ER$RER,<File processor read error>
USER ER$REX,<Record already exists>
SNH ER$RFA,<Bad RFA value>
IGNORE ER$RFM,<Bad record format>
USER ER$RLK,<Record already locked by someone else>
USER ER$RNF,<Record not found>
IGNORE ER$RNL,<Record not locked>
SNH ER$ROP,<Bad record options>
IGNORE ER$RRV,<Invalid RRV record found>
IGNORE ER$RSA,<Record stream active>
IGNORE ER$RSD,<Record size discrepancy>
USER ER$RSZ,<Bad record size value>
SNH ER$RTB,<Record too big>
IGNORE ER$SEQ,<Key value not in sequential order>
USER ER$SIZ,<'SIZ' field in XAB invalid>
IGNORE ER$TRE,<Index tree error detected>
USER ER$TRU,<Cannot truncate this file>
SNH ER$UBF,<Bad buffer address>
IGNORE ER$UDF,<File is in undefined state>
IGNORE ER$VER,<Error in version number>
IGNORE ER$WER,<File processor write error>
SNH ER$XAB,<Not a valid XAB>
USER ER$XCL,<File must be open in exclusive access>
USER ER$FSI,<File spec has invalid format>
USER ER$DPE,<DAP protocol error>
USER ER$SUP,<Unsupported operation>
USER ER$DCF,<DAP connection failure>
USER ER$EXT,<File extend error>
SNH ER$NAM,<Invalid NAM block>
IGNORE ER$NMF,<No more files>
USER ER$RTD,<RENAME -- two different devices>
USER ER$RTN,<RENAME -- two different nodes>
USER ER$DCB,<DECNET connection broken>
USER ER$IAC,<Invalid access information>
SNH ER$TYP,<Invalid TYP block>
IGNORE ER$CLA,<Invalid file data class>
Z ;END OF TABLE
PURGE FL%SNH
> ; End %IF20
SUBTTL FNDRMS - See if RMS is around
;***************************************************************************
;* *
;* MISCELLANEOUS ROUTINES *
;* *
;***************************************************************************
;++
; FUNCTIONAL DESCRIPTION:
;
; Does a GTJFN% on SYS:RTL.EXE and XRMS.EXE to see if they are around
; for dynamic-library invocation. If so, just return (or if we
; have already been called). If not, go to DIALOG.
;
; Called from FOROPN DFDEV1 after the device index is established
; as either DI.RMS or DI.RSF.
;
; CALLING SEQUENCE:
;
; PUSHJ P,FNDRMS
; <Error return; enter DIALOG>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RMSJFN - If non-zero on entry, we've already been called
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; RMSJFN - Holds a released JFN
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5000] New
IF20,<
FNDRMS: SKIPE RMSJFN ;Already done this before?
JRST %POPJ1 ;Yes, just return
MOVX T1,GJ%SHT+GJ%OLD+GJ%PHY ;No, check for the RTL
HRROI T2,[ASCIZ /SYS:RTL.EXE/]
GTJFN%
ERJMP NORMS
RLJFN% ;Release JFN
ERJMP .+1
MOVX T1,GJ%SHT+GJ%OLD+GJ%PHY ;Check for XRMS.EXE
HRROI T2,[ASCIZ /SYS:XRMS.EXE/]
GTJFN%
ERJMP NORMS
MOVEM T1,RMSJFN ;Save JFN as flag
RLJFN%
ERJMP .+1
MOVEI T1,FTEXT ;Get global compilation switch
JUMPN T1,%POPJ1
;RMS is on SYS: but FOROTS was compiled on a non-extended machine.
HRROI T1,[ASCIZ/
?RMS can only be called on a processor which supports extended addressing.
This build of FOROTS was compiled on a non-extended machine./]
PSOUT%
SETZM RMSJFN
HALTF%
JRST .-1
;Here when XRMS.EXE/RTL.EXE are not on SYS:. Issue error, enter DIALOG.
NORMS: $DCALL RNA
SEGMENT DATA
RMSJFN: BLOCK 1
SEGMENT CODE
> ;End IF20
SUBTTL RMFAB - Allocate FAB/CONFIG blocks
;++
; FUNCTIONAL DESCRIPTION:
;
; Allocates and initializes a FAB block and returns its address
; in T1. If the file is remote (i.e. a nodename was included in
; the filespec), allocate a CONFIG XAB as well and point FAB FB$XAB
; at it. Allocates via a call to global routine %GTBLK.
;
; FAB format:
;
; !=====================================!
; ! BID ! BLN !
; !-------------------------------------!
; ! STS ! STV !
; !-------------------------------------!
; ! CTX !
; !-------------------------------------!
; ! IFI ! JFN !
; !-------------------------------------!
; ! FAC ! SHR !
; !-------------------------------------!
; ! FOP !ORG! BSZ ! BLS !
; !-------------------------------------!
; ! FNA !
; !-------------------------------------!
; ! RAT ! MRS !
; !-------------------------------------!
; ! MRN !
; !-------------------------------------!
; ! <UNUSED> ! BKS ! RFM !
; !-------------------------------------!
; ! LOG ! XAB !
; !-------------------------------------!
; ! DEV ! SDC !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !=====================================!
;
; Local non-indexed RMS files will be allocated a FAB only,
; whose XAB field will be zero. Local indexed RMS files will have
; a FAB whose XAB field points to the first key XAB of any chain.
;
; Remote non-indexed files (including RSF) will be chained as
; follows to a CONFIG XAB:
;
; --------------------
; FAB: | |
; -------.....---------
; F$XAB:|address of CONFIG |
; --------------------
;
; --------------------
; CONFIG: | |
; -------.....--------
; X$NXT:| 0 |
; --------------------
;
; Remote indexed files' X$NXT in their CONFIG XABs will point
; to the start of the key XAB chain, if any.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMFAB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; NODNAM(D) - Nodename string from OPEN
;
; OUTPUT PARAMETERS:
;
; T1 - Address of allocated FAB
;
; IMPLICIT OUTPUTS:
;
; FABLNK - Link address
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
RMFAB: SKIPN T2,NODNAM(D) ;Nodename specified?
JRST ALFAB ;No, allocate FAB only
MOVX T1,XA$SXC ;Yes. Get length of CONFIG XAB
PUSHJ P,%GTBLK ;Get a block
$ACALL MFU ;Can't
MOVE T2,T1 ;T1 off'd by XAB$B
XAB$B CFG,<(T2)> ;Declare it
XAB$E ;End declaration
ALFAB: MOVEM T2,FABLNK ;Save link address (or zero)
MOVX T1,FA$LNG ;Get FAB length block
PUSHJ P,%GTBLK
$ACALL MFU ;Can't
MOVE T2,T1 ;T1 off'd by FAB$B
FAB$B <(T2)> ;Declare it
FAB$E ;End declaration
MOVE T1,FABLNK ;Restore link address
$STORE T1,XAB,<(T2)>
MOVE T1,T2 ;Return address of FAB
POPJ P, ;Return
> ; End %IF20
SUBTTL RMRAB - Allocate a RAB
;++
; FUNCTIONAL DESCRIPTION:
;
; Allocates a RAB and returns its address in T1. Allocates via a call
; to global routine %GTBLK.
;
; RAB format:
;
; !-------------------------------------!
; ! BID ! BLN !
; !-------------------------------------!
; ! STS ! STV !
; !-------------------------------------!
; ! CTX !
; !-------------------------------------!
; ! ISI ! FAB !
; !-------------------------------------!
; ! RAC ! MBF ! ROP !
; !-------------------------------------!
; ! UBF !
; !-------------------------------------!
; ! RBF !
; !-------------------------------------!
; ! RSZ ! USZ !
; !-------------------------------------!
; ! RFA !
; !-------------------------------------!
; ! KRF ! KSZ ! LSN !
; !-------------------------------------!
; ! KBF !
; !-------------------------------------!
; ! BKT !
; !-------------------------------------!
; ! PAD ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMRAB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; T1 - Address of allocated RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
RMRAB: MOVX T1,RA$LNG ;Get RAB length
PUSHJ P,%GTBLK ;Get it
$ACALL MFU ;Can't
MOVE T2,T1 ;T1 off'd by RAB$B
RAB$B <(T2)> ;Declare it
RAB$E ;End declaration
MOVE T1,T2 ;Return address in T1
POPJ P, ;Return
> ; End %IF20
SUBTTL RMXAB - Allocate a KEY XAB
;++
; FUNCTIONAL DESCRIPTION:
;
; Allocates a key XAB and returns its address in T1. Allocates via
; a call to global routine %GTBLK.
;
; Key XAB format:
;
; !=====================================!
; ! BID ! BLN !
; !-------------------------------------!
; ! <UNUSED> ! COD ! NXT !
; !-------------------------------------!
; ! <UNUSED> ! DTP ! FLG !
; !-------------------------------------!
; ! IAN ! DAN ! LAN ! REF !
; !-------------------------------------!
; ! IFL ! DFL !
; !-------------------------------------!
; ! KNM !
; !-------------------------------------!
; ! <RESERVED> !
; !-------------------------------------!
; ! <RESERVED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! <UNUSED> !
; !-------------------------------------!
; ! POS0 ! SIZ0 !
; !-------------------------------------!
; ! POS1 ! SIZ1 !
; !-------------------------------------!
; ! POS2 ! SIZ2 !
; !-------------------------------------!
; ! POS3 ! SIZ3 !
; !-------------------------------------!
; ! POS4 ! SIZ4 !
; !-------------------------------------!
; ! POS5 ! SIZ5 !
; !-------------------------------------!
; ! POS6 ! SIZ6 !
; !-------------------------------------!
; ! POS7 ! SIZ7 !
; !=====================================!
;
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMXAB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; T1 - Address of allocated XAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
RMXAB: MOVX T1,XA$SXK ;Length of key XAB
PUSHJ P,%GTBLK ;Ask for it
$ACALL MFU ;Can't get it
MOVE T2,T1 ;T1 off'd by XAB$B
XAB$B KEY,<(T2)>
XAB$E
MOVE T1,T2 ;Return address in T1
POPJ P, ;Return
> ;End %IF20
SUBTTL %RMDAB - Deallocate FAB, RAB, XAB(s), cache
;++
; FUNCTIONAL DESCRIPTION:
;
; Deallocates FAB(D), RAB(D) and any XAB(D) chain. Deallocates via
; calls to global routine %FREBLK. If CACHE(D) is non-zero,
; deallocates the cache.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMDAB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; RAB(D) - Address of RAB
; XAB(D) - Address of start of XAB chain
; CACHE(D) - Address of cache
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; Zeros FAB, RAB and XAB(D); CACHE(D), CACHPT(D)
; FABLNK - Link address
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
IF10,< ;No-op on TOPS10
%RMDAB: POPJ P,
> ;End IF10
%IF20,<
%RMDAB: SKIPE %ABFLG ;Are we aborting?
POPJ P, ;Yes, don't deallocate anything
SETZM FABLNK ;Clear any link
SKIPN FAB(D) ;Any FAB?
JRST DXAB ;No, check XAB
MOVE T1,XAB(D) ;Get Key XAB start
MOVEM T1,FABLNK ;Save
MOVE T1,FAB(D) ;Get FAB address
$FETCH T2,XAB,<(T1)> ;Get XAB link from FAB
MOVEM T2,FABLNK ;Save it
PUSHJ P,%FREBLK ;Deallocate the FAB
SETZM FAB(D) ;Clear DDB
DXAB: SKIPN T1,FABLNK ;Was there a XAB link?
JRST DRAB ;No, go check RAB
PUSHJ P,RMDXB ;Deallocate the chain
SETZM XAB(D) ;Clear DDB
DRAB: SKIPN T1,RAB(D) ;Any RAB?
JRST DCACH ;No, check cache
PUSHJ P,%FREBLK ;Yes. Get rid of it
SETZM RAB(D) ;Clear DDB
DCACH: SKIPN T1,CACHE(D) ;Any cache setup?
JRST DABEND ;No, clear buffer pointer
PUSHJ P,%FREBLK ;Yes, it's gone
SETZM CACHE(D)
SETZM CACHPT(D)
DABEND: SETZM BUFADR(D) ;Clear any buffer pointer
POPJ P,
> ; End %IF20
SUBTTL %RMDKB - Deallocate DIALOG /KEY arglist
;++
; FUNCTIONAL DESCRIPTION:
;
; Deallocates a secondary arglist created by parsing /KEY in DIALOG.
; Deallocates via a call to global routine %FREBLK.
;
; CALLING SEQUENCE:
;
; PUSHJ P,%RMDKB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; D.KEY - Address of secondary arglist. Its count word is in
; address-1
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; D.KEY - Address of secondary arglist is zeroed
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5000] New
IF10,<
%RMDKB: POPJ P, ;No-op on TOPS10
> ;End IF10
%IF20,<
%RMDKB: SKIPN T1,D.KEY ;Anything to deallocate?
POPJ P, ;No, just return
SUBI T1,1 ;Get count word address
PUSHJ P,%FREBLK ;Deallocate the arglist
SETZM D.KEY ;It's gone
POPJ P, ;Return
> ; End %IF20
SUBTTL RMDXB - Deallocate a XAB chain
;++
; FUNCTIONAL DESCRIPTION:
;
; Deallocates a XAB chain the first link of which is pointed to by
; T1. Deallocates via calls to global routine %FREBLK.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMDXB
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Address of first XAB to deallocate
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
RMDXB: JUMPE T1,%POPJ ;Zero NXT terminates loop
$FETCH T2,NXT,<(T1)> ;Get this XAB's NXT field
PUSH P,T2 ;Save
PUSHJ P,%FREBLK ;Deallocate this XAB
POP P,T1 ;Make next XAB the current one
JRST RMDXB ; and continue
SEGMENT DATA
PXBADR: BLOCK 1 ;Address of previous XAB
FABLNK: BLOCK 1 ;FAB XAB link
SEGMENT CODE
> ; End %IF20
SUBTTL RMDUXB - Deallocate and unlink a XAB chain
;++
; FUNCTIONAL DESCRIPTION:
;
; Deallocates the XAB chain the first link of which is pointed
; to by XAB(D). Then clears the link from FAB(D) F$XAB if there is
; no CONFIG XAB, or from CONFIG F$NXT if there is one. Clears
; XAB(D) on return. Calls RMDXB to deallocate, ULKXAB to unlink.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RMDUXB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; XAB(D) - Address of key XAB chain start
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; XAB(D) - Zeroed
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1.
;
;--
;[5000] New
%IF20,<
RMDUXB: SKIPN T1,XAB(D) ;Any chain to worry about?
POPJ P, ;No, just return
PUSHJ P,RMDXB ;Yes, deallocate it
PJRST ULKXAB ;Unlink and return
> ; End %IF20
SUBTTL ULKXAB - Unlink FAB or CONFIG from XAB chain
;++
; FUNCTIONAL DESCRIPTION:
;
; Unlinks a key XAB chain from either F$XAB of FAB(D) or F$NXT
; of the CONFIG XAB, if there is one.
;
; CALLING SEQUENCE:
;
; PUSHJ P,ULKXAB
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
; XAB(D) - Address of 1st key XAB
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; FAB(D) F$XAB - Zeroed if no CONFIG XAB
; CONFIG F$NXT - Zeroed if a CONFIG exists
; XAB(D) - Zeroed
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
ULKXAB: SKIPN XAB(D) ;Any XAB chain
POPJ P, ;No, nothing to do
MOVE T1,FAB(D) ;Get FAB address
$FETCH T2,XAB,<(T1)> ;Get its link address
JUMPE T2,%POPJ ;None, just return
CAME T2,XAB(D) ;FAB point to key chain start?
JRST ULKCFG ;No, there's a CONFIG XAB
SETZ T2, ;Yes, clear FAB F$XAB
$STORE T2,XAB,<(T1)>
JRST ZERXAB
ULKCFG: SETZ T1, ;Clear CONFIG's F$NXT
$STORE T1,NXT,<(T2)>
ZERXAB: SETZM XAB(D)
POPJ P,
> ; End %IF20
SUBTTL FABSTV - Update STV(D) and STS(D) from FAB/RAB
;++
; FUNCTIONAL DESCRIPTION:
;
; Called after every RMS service call to update the status return
; values from FAB(D). RMS service calls which update the RAB's
; STV should call RABSTV.
;
; Entry FABST2 is used when the caller passes the address of a
; different FAB in T1 (e.g. a scratch FAB).
;
; CALLING SEQUENCE:
;
; PUSHJ P,FABSTV
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Address of FAB (entry FABST2 only)
;
; IMPLICIT INPUTS:
;
; FAB(D) STV - STV value returned to FAB/RAB
; FAB(D) STS - STS value returned to FAB/RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS value
;
; IMPLICIT OUTPUTS:
;
; STV(D) - STV from FAB/RAB
; STS(D) - STS from FAB/RAB
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
FABSTV: SKIPA T1,FAB(D) ;Get FAB address
RABSTV: MOVE T1,RAB(D) ;or RAB
FABST2: $FETCH T2,STV,<(T1)> ;Get STV value
STORE T2,STV(D) ;Save
$FETCH T2,STS,<(T1)> ;Get STS value
STORE T2,STS(D) ;Save
CAIGE T2,SU$SUC ;Real error or real success?
$SNH ;No, real bad
POPJ P, ;Yes, return STS
> ; End %IF20
SUBTTL RLSLNK - Release a logical link
;++
; FUNCTIONAL DESCRIPTION:
;
; Does a $CLOSE to release any logical link allocated to the FAB.
; $CLOSE errors are ignored. Called only for fatal OPEN errors.
;
; Entry RLSLNX $CLOSEs the SCRFAB.
;
; CALLING SEQUENCE:
;
; PUSHJ P,RLSLNK
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
; Closes the file if open on the FAB.
;
;--
;[5000] New
%IF20,<
RLSLNX: SKIPA T1,[SCRFAB] ;Get scratch FAB address
RLSLNK: MOVE T1,FAB(D) ;Get FAB address
$CLOSE <(T1)> ;Yes. Release link, ignore errors.
POPJ P,
> ; End %IF20
SUBTTL CVTFNS - Convert NAMBLK filespec to TOPS20
;++
; FUNCTIONAL DESCRIPTION:
;
; Using the expanded filespec string pointed to by RSA of the
; NAMBLK, copies and converts the string to the destination pointed
; to by T1. Conversion affects only the nodename field, which is
; translated from:
;
; node"userid password account"::
;
; to:
;
; node::
;
; If CVFLAG is non-zero, each byte in the directory field (except
; for open/close delimiters) is ^V-quoted in the copy.
;
; The opening delimiter of the generation field is always returned
; as a "."
;
; CALLING SEQUENCE:
;
; PUSHJ P,CVTFNS
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Byte pointer to destination where converted string
; is to be written
;
; IMPLICIT INPUTS:
;
; NAMBLK - NAM block pointers
; CVFLAG - Non-zero if ^V'ing is to be performed on the
; directory field.
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; CVFLAG - Cleared
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
%IF20,<
CVTFNS: PUSHJ P,MOVNOD ;Copy/convert node
$FETCH T2,DVA,NAMBLK ;Get Device pntr
$FETCH T3,DVL,NAMBLK ;and length
PUSHJ P,MOVSTR
$FETCH T2,DRA,NAMBLK ;Directory
$FETCH T3,DRL,NAMBLK
MOVEI T4,MOVSTR ;Assume no ^V'ing
SKIPE CVFLAG ;^V this field?
MOVEI T4,CTVDIR ;Yes, use different routine
PUSHJ P,(T4)
$FETCH T2,NMA,NAMBLK ;Name
$FETCH T3,NML,NAMBLK
PUSHJ P,MOVSTR
$FETCH T2,TPA,NAMBLK ;Extention
$FETCH T3,TPL,NAMBLK
PUSHJ P,MOVSTR
$FETCH T2,VRA,NAMBLK ;Generation
$FETCH T3,VRL,NAMBLK
ILDB T4,T2 ;Make sure delimiter is TOPS20
SUBI T3,1 ;Correct the count
MOVEI T4,"."
IDPB T4,T1
PUSHJ P,MOVSTR
SETZ T4,
IDPB T4,T1 ;End with null
SETZM CVFLAG ;Clear ^V flag
POPJ P, ;Return
SEGMENT DATA
CVFLAG: BLOCK 1 ;-1 if ^V'ing is being done
SEGMENT CODE
> ; End %IF20
SUBTTL MOVNOD - Move a node name from the NAM block
;++
; FUNCTIONAL DESCRIPTION:
;
; Moves a nodename of NAM block form (node"userid password account"::)
; to the destination in the form "node::".
;
; CALLING SEQUENCE:
;
; PUSHJ P,MOVNOD
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Destination byte pointer
;
; IMPLICIT INPUTS:
;
; NAMBLK - NAM block field pointers
; NDA/NDL - Nodename character descriptor
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
%IF20,<
MOVNOD: $FETCH T2,NDA,NAMBLK ;Get pointer to node string
$FETCH T3,NDL,NAMBLK ;Get total length
NODLP: JUMPE T3,%POPJ ;Count exhausted
ILDB T4,T2 ;Get a byte
CAIE T4,"""" ;Look for quotes
CAIN T4,":" ; or colon delimiter
JRST GOTNOD ;Got it
IDPB T4,T1 ;Store character
SOJA T3,NODLP ;Keep going
GOTNOD: MOVEI T3,":" ;"node::"
IDPB T3,T1
IDPB T3,T1
POPJ P, ;Return
> ; End %IF20
SUBTTL CTVDIR - Control-V a directory field
;++
; FUNCTIONAL DESCRIPTION:
;
; Copies the NAM block directory field to the destination, preceding
; each directory field character with a ^V.
;
; CALLING SEQUENCE:
;
; PUSHJ P,CTVDIR
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Destination byte pointer
; T2 - Source pointer
; T3 - Field length in bytes
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T0-T4.
;
;--
;[5000] New
%IF20,<
CTVDIR: JUMPE T3,%POPJ ;No length
SUBI T3,2 ;Subtract open/close widgets
JUMPLE T3,%POPJ ;Bad length! Just ignore
ILDB T4,T2 ;Get opening delimiter
IDPB T4,T1 ;Store without ^V
MOVEI T0,"" ;Get a Control-V
CDIRLP: ILDB T4,T2 ;Get source byte
IDPB T0,T1 ;^V this byte
IDPB T4,T1 ;Write the byte
SOJG T3,CDIRLP ;Loop for count
ILDB T4,T2 ;Get closing delimiter
IDPB T4,T1 ;Store without ^V
POPJ P, ;Return
> ; End %IF20
SUBTTL ABINI - Initialize some srgument blocks
;++
; FUNCTIONAL DESCRIPTION:
;
; Initializes the NAM block, a scratch FAB, and a TYP block.
; All are cleared before initialization.
;
; CALLING SEQUENCE:
;
; PUSHJ P,ABINI
; <Return here>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; NAMBLK RSA - Set to address of RSA buffer
; NAMBLK RSS - Set to length of RSA buffer
; NAMBLK ESA - Set to address of ESA buffer
; NAMBLK ESS - Set to length of ESA buffer
;
; TYPBLK CLA - Set to type IMAGE.
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
ABINI: NAM$Z NAMBLK ;Clear NAM block
NAM$B NAMBLK ;Reinit
NAM$E
XMOVEI T1,NAMBLK
MOVE T2,[POINT 7,RSABUF] ;Setup RSA pointer in NAM
$STORE T2,RSA,<(T1)>
MOVEI T2,RSALC ;Byte-length
$STORE T2,RSS,<(T1)>
MOVE T2,[POINT 7,ESABUF] ;Setup ESA pointer
$STORE T2,ESA,<(T1)>
MOVEI T2,ESALC
$STORE T2,ESS,<(T1)>
FAB$Z SCRFAB ;Re-init the SCRFAB
FAB$B SCRFAB
FAB$E
TYP$Z TYPBLK ;Re-init the TYP block
TYP$B TYPBLK
T$CLA TY$IMA ;Class is image, image is class
TYP$E
POPJ P,
> ; End %IF20
SUBTTL MOVSTR - Move string
;++
; FUNCTIONAL DESCRIPTION:
;
; Moves an ASCII string from source to destination. Returns on
; a null byte or when the count is exhausted, whichever occurs
; first.
;
; CALLING SEQUENCE:
;
; PUSHJ P,MOVSTR
; <Return here>
;
; INPUT PARAMETERS:
;
; T1 - Destination byte pointer
; T2 - Source byte pointer
; T3 - Number of bytes to transfer
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1-T4.
;
;--
;[5000] New
%IF20,<
MOVSTR: JUMPLE T3,%POPJ ;Return on count exhausted
ILDB T4,T2 ;Get a source byte
JUMPE T4,%POPJ ;Quit on null
IDPB T4,T1 ;Write to destination
SOJA T3,MOVSTR ;loop
> ; End %IF20
SUBTTL OPEN$ Do $OPEN
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $OPEN and updates FAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,OPEN$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $OPEN
; T4 - Address of FAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T0-T2,T4.
;
;--
;[5000] New
%IF20,<
OPEN$: $OPEN @FAB(D)
RMSFRT: PUSHJ P,FABSTV ;Update STS/STV
MOVE T0,(P) ;Get return address off stack
MOVEM T0,%RMPDP ;Save
MOVE T4,FAB(D) ;Return FAB address
CAIL T2,ER$MIN ;Error?
POPJ P, ;Yes, return +1
JRST %POPJ1
ERCRET: MOVE T0,(P) ;Get return address off stack
MOVEM T0,%RMPDP ;Save error return
$RETURN ;Return to after $call
RETSUC: MOVX T2,SU$SUC ;Clear the error
SETZ T3,
MAKSTS: $STORE T2,STS,<(T1)>
$STORE T3,STV,<(T1)>
PJRST FABST2
> ;End %IF20
SUBTTL CREA$ - Do $CREATE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $CREATE and updates FAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,CREA$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $CREATE
; T4 - Address of FAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
CREA$: $CREATE @FAB(D)
JRST RMSFRT
> ;End %IF20
SUBTTL CLOS$ - Do $CLOSE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $CLOSE and updates FAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,CLOS$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $CLOSE
; T4 - Address of FAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
CLOS$: $CLOSE @FAB(D)
JRST RMSFRT
> ;End %IF20
SUBTTL PARS$ - Do $PARSE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $PARSE and updates FAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,PARS$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; FAB(D) - Address of FAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $PARSE
; T4 - Address of FAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
PARS$: $PARSE @FAB(D)
JRST RMSFRT
> ;End %IF20
SUBTTL GET$ - Do $GET
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $GET and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,GET$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $GET
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T0-T2,T4.
;
;--
;[5000] New
%IF20,<
GET$: $GET @RAB(D)
RMSRRT: MOVE T0,(P) ;Get return address off stack
MOVEM T0,%RMPDP
PUSHJ P,RABSTV
MOVE T4,RAB(D) ;Return RAB address
CAIL T2,ER$MIN ;Error?
POPJ P, ;Yes
JRST %POPJ1
> ;End %IF20
SUBTTL CONN$ - Do $CONNECT
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $CONNECT and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,CONN$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $CONNECT
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
CONN$: $CONNECT @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL DISC$ - Do $DISCONNECT
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $DISCONNECT and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,DISC$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D)
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $DISCONNECT
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5004] New
%IF20,<
DISC$: $DISCONNECT @RAB(D)
PJRST RMSRRT
> ;End %IF20
SUBTTL REWI$ - Do $DISCONNECT/$CONNECT
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $DISCONNECT/$CONNECT sequence to rewind a file to its
; starting position.
;
; CALLING SEQUENCE:
;
; PUSHJ P,REWI$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; None
;
; OUTPUT PARAMETERS:
;
; None
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; None
;
;--
;[5013] New
%IF20,<
REWI$: PUSHJ P,DISC$
POPJ P, ;Error
PUSHJ P,CONN$
POPJ P, ;Error
JRST %POPJ1 ;Success
> ;End %IF20
SUBTTL READ$ - Do $READ
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $READ and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,READ$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $READ
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
READ$: $READ @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL PUT$ - Do $PUT
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $PUT and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,PUT$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $PUT
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
PUT$: $PUT @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL WRIT$ - Do $WRITE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $WRITE and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,WRIT$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $WRITE
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
WRIT$: $WRITE @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL TRUN$ - Do $TRUNCATE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $TRUNCATE and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,TRUN$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $TRUNCATE
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
TRUN$: $TRUNCATE @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL FIND$ - Do $FIND
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $FIND and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,FIND$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $FIND
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
FIND$: $FIND @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL UPDA$ - Do $UPDATE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $UPDATE and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,UPDA$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $UPDATE
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2.
;
;--
;[5000] New
%IF20,<
UPDA$: $UPDATE @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL DELE$ - Do $DELETE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $DELETE and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,DELE$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $DELETE
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2
;
;--
;[5013] New
%IF20,<
DELE$: $DELETE @RAB(D)
JRST RMSRRT
> ;End %IF20
SUBTTL FREE$ - Do $FREE
;++
; FUNCTIONAL DESCRIPTION:
;
; Does $FREE and updates RAB's STS/STV
;
; CALLING SEQUENCE:
;
; PUSHJ P,FREE$
; <Error return>
; <Success return>
;
; INPUT PARAMETERS:
;
; None
;
; IMPLICIT INPUTS:
;
; RAB(D) - Address of RAB
;
; OUTPUT PARAMETERS:
;
; T2 - STS code from $FREE
; T4 - Address of RAB
;
; IMPLICIT OUTPUTS:
;
; None
;
; FUNCTION VALUE:
;
; None
;
; SIDE EFFECTS:
;
; Uses T1,T2
;
;--
;[5014] New
%IF20,<
FREE$: $FREE @RAB(D)
JRST RMSRRT
> ;End %IF20
;***************************************************************************
;* *
;* STATIC RMS ARGUMENT BLOCKS *
;* *
;***************************************************************************
;Scratch FAB for LOOKUPs:
IF20,<
IFNRMS,<ER$MIN==300000>
%ERMIN: ER$MIN ;RMS error base
> ;End IF20
%IF20,<
SEGMENT DATA
SCRFAB: BLOCK FA$LNG
NAMBLK: BLOCK NA$LNG
TYPBLK: BLOCK TY$LNG
RSALW==LTEXTW ;RSA length is %TXTBF's length
RSALC==LTEXTC ;and in characters
ESALC==RSALC ;ESA ditto
RSABUF: BLOCK LTEXTW ;RSA buffer
ESABUF: BLOCK LTEXTW ;ESA buffer
EXFATT: BLOCK 1 ;Pointer to attributes portion
EXFBUF: BLOCK LTEXTW ;Resultant string saved here
SEGMENT CODE
;PURGE as many RMS-generated symbols as we can
DEFINE RMSPRG (PFX,FLDS) <
IF2,<
IRP PFX,<
IRP FLDS,< IFDEF PFX'$$'FLDS,<PURGE PFX'$$'FLDS>
IFDEF $$'PFX'FLDS,<PURGE $$'PFX'FLDS>
IFDEF C$$'FLDS,<PURGE C$$'FLDS>
> ;End IRP FLDS
> ;;End IRP PFX
PURGE FAB$B,FAB$E,RAB$B,RAB$E,XAB$B,XAB$E,NAM$B,NAM$E,TYP$B,TYP$E
PURGE T$$OF,T$$PS,T$$SZ,$$ADDR,$$NEWVAL,$$SET,$$CURR,$$MAPADD
PURGE SF$$CT,SF$$RT,SN$$CT,SN$$RT,SR$$RT,ST$$CT,STO$$C,SX$$CT
PURGE SX$$RT
> ;End IF2
> ;End RMSPRG
RMSPRG (<F,R,X,N,T>,<AID,ALQ,BID,BKS,BKT,BKZ,BLN,BLS,BSZ,CDT,
CHA,COD,CTX,DAN,DEV,DFL,DRA,DTP,DVA,DVL,EDT,EDT,ELS,
ESA,ESL,ESS,FAB,FAC,FLG,FNA,FNB,FOP,FSZ,IAN,IFI,IFL,
ISI,JFN,JNL,KBF,KNM,KRF,KSZ,LAN,LSN,MBF,MRN,MRS,NAM,
NDA,NDL,NMA,NML,NOA,NOK,NOP,NXT,ORG,PAD,PS0,PS1,PS2,
PS3,PS4,PS5,PS6,PS7,RAC,RAT,RBF,RDT,REF,RFA,RFM,RLF,
ROP,RS1,RS2,RS6,RS7,RS8,RS9,RSA,RSL,RSS,RSZ,RX0,RX1,
RX2,RX3,RX4,RX5,SDC,SHR,STS,STV,SZ0,SZ1,SZ2,SZ3,SZ4,
SZ5,SZ6,SZ7,TPA,TPL,TYP,UBF,USZ,VRA,VRL,WCC,XAB>)
> ;End %IF20
END