Trailing-Edge
-
PDP-10 Archives
-
BB-H506D-SM_1983
-
cobol/source/iotmp.mac
There are 6 other files named iotmp.mac in the archive. Click here to see a list.
; UPD ID= 3564 on 6/3/81 at 3:08 PM by WRIGHT
TITLE IOTMP - TEMP FILE I/O PACKAGE
SUBTTL D. WRIGHT Latest update Jan, 1981
;Routines to be used by performance-conscious programs
; to deal with sequential files. The interface for
; TOPS10 and TOPS20 programs is identical in all common cases.
;COPYRIGHT (C) 1981 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;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.
; These routines are native mode on TOPS20.
;On both TOPS10 and TOPS20, these routines
;optimize performance on the latest model cpu.
; This package will also work if run in
;a non-zero section.
SEARCH IOTMPU ;Search IOTMP's universal file
; This picks up TOPS20 definition
SEARCH MMANGU ;Memory manager universal file
IFNDEF DEBUG,<DEBUG==0> ;NO DEBUGGER IF NOT DEFINED
IFN TOPS20,<
SEARCH MONSYM,MACSYM
>
IFE TOPS20,<
SEARCH UUOSYM,MACTEN
>
SALL ;SUPPRESS MACRO EXPANSIONS
;Entry points in IOTMP:
ENTRY $ITINI ;Initialize
ENTRY $ITOPO ;LOGICAL OPEN OUTPUT
ENTRY $ITOPI ;LOGICAL OPEN INPUT
ENTRY $ITINB ;GET A BYTE FROM INPUT FILE
ENTRY $ITOUB ;PUT A BYTE INTO OUTPUT FILE
ENTRY $ITISB ;Input a string of bytes
ENTRY $ITOSB ;Output a string of bytes
ENTRY $ITPSF ;Position file
ENTRY $ITCLS ;Logical close of file
ENTRY $ITRNF ;Rename file
ENTRY $ITRMU ;RETURN MEMORY USAGE *NYI*
ENTRY $ITCBM ;CUT BACK ON MEMORY USAGE *NYI*
ENTRY $ITDEB ;ENTER DEBUGGER *NYI*
IFE TOPS20,<
TWOSEG 400K ;Two segment program, start at 400K
>;END IFE TOPS20
;AC definitions
T1=1 ;5 TEMPS STARTING AT AC 1
T2=2
T3=3
T4=4
T5=5
P1=6 ;3 PERMS STARTING AT AC6
P2=7
P3=10
P=17 ;PUSHDOWN STACK PTR
;Random parameters
.TMTMX==5 ;Number of tries before we decide that the
;"Simultaneous update error" on open is not
;just a race condition, but something that's
; taking too long to go away and we'll stop
; trying again.
IFN TOPS20,<
.NTTYB==^D200 ;Number of bytes available to store a TTY: input line
>;END IFN TOPS20
IFE TOPS20,<
.MXRBC==.RBACT+10 ;Max. number of args in extended LOOKUP/RENAME blocks
>;END IFE TOPS20
SUBTTL MACROS
DEFINE TYPE (ADDR),<
IFN TOPS20,<
HRROI 1,ADDR
PSOUT%
>;END DEFINE TYPE
>;END IFN TOPS20
IFE TOPS20,<
DEFINE TYPE (ADDR),<
OUTSTR ADDR
>;END DEFINE TYPE
>;END IFE TOPS20
DEFINE $TEXT(STRING),<
XLIST
ASCIZ |STRING|
LIST
>;END DEFINE $TEXT
DEFINE $FERR (ABBR,TEXT),<
MOVE T1,[''ABBR'',,[ASCIZ |TEXT|]]
PUSHJ P,ITFERR
>
DEFINE $WERR (ABBR,TEXT),<
MOVE T1,[''ABBR'',,[ASCIZ |TEXT|]]
PUSHJ P,ITWERR
>
OPDEF PJRST [JRST] ;Nobody else defines it!
SUBTTL Interface to memory management module
;These routines only work if there is also a memory management
; module present with the following entry points.
EXTERN INITMU ;Initialize mem manager for a user
EXTERN FINFRE ;Routine to find a clump of free pages
EXTERN RETRN ;Return pages to memory manager
;See MMANGU.MAC for more details
SUBTTL $ITINI--Initialize
;Call:
; 1/ Flags (IT%UES)
; 2/ Default buffer size,,max IFN value
; 3/ (RH) = 3-letter sixbit program abbreviation
;Returns:
; 1/ Status 0=ok, 1=problem
$ITINI: PUSH P,T1 ;SAVE AC
SETZM STTLC ;Clear data area..
MOVE T1,[STTLC,,STTLC+1]
BLT T1,ENDLC ;. .
POP P,T1 ;Restore ac1
HLRZM T2,DEFBFS ;SAVE DEFAULT BUFFER SIZE
HRRZM T2,MXIFNR ;SAVE MAX IFN USER REQUESTED
HRLZM T3,PRGABR ;Save 3-letter program abbreviation
IFN TOPS20,<
TXNE T1,IT%UES ;USE EXTENDED SECTIONS?
JRST [XMOVEI T2,. ;Yes, is this a non-zero section?
TLNE T2,-1
SETOM USEXEX ;Yes, set flag
JRST .+1] ;Else don't set flag
>;END IFN TOPS20
MOVE T1,DEFBFS ;GET DEFAULT BUFFER SIZE
CAILE T1,^D512 ;BIGGER THAN 1 SECTION?
JRST ITINI0 ;YES, COMPLAIN
MOVE T1,MXIFNR ;GET MAX IFN USER REQUESTED
CAILE T1,MAXIFN ;TOO BIG?
JRST ITINI1 ;YES, COMPLAIN
;Call memory manager initialize routine
DMOVEM T3,USR34 ;SAVE USER'S 3 AND 4
MOVX T1,MM%CRM ;We can cut back memory if necessary
IFN TOPS20,<
SKIPN USEXEX ;SHOULD WE USE EXTENDED ADDRESSING?
TXO T1,MM%UXS ;YES, USE EXTENDED SECTIONS
XMOVEI T3,$ITRMU ;Addr of routine to "return mem usage"
XMOVEI T4,$ITCBM ;Addr of routine to "cut back memory"
>;END IFN TOPS20
IFE TOPS20,<
MOVEI T3,$ITRMU ;Addr of routine to "return mem usage"
MOVEI T4,$ITCBM ;Addr of routine to "cut back memory"
>;end IFE TOPS20
MOVE T2,[SIXBIT/IOTMP/] ;This module's name
PUSHJ P,INITMU ;CALL ROUTINE
JUMPN T1,RT1R34 ;RETURN STATUS 1 IF MEM MANAGER DID
JRST RT0R34 ;ALL OK, RETURN STATUS 0
;$ITINI errors
;These are calling errors and so types "?IOTMP.."
ITINI0: TYPE INIEH ;TYPE ERROR HEADER
TYPE [ASCIZ/ Default buffer size requested larger than 512. pages
/]
JRST RETST1 ;RETURN STATUS 1
ITINI1: TYPE INIEH ;TYPE HEADER
TYPE [ASCIZ/ Max IFN requested larger than MAXIFN
/]
JRST RETST1 ;RETURN STATUS 1
;HEADER FOR ITINI ERRORS
INIEH: $TEXT <?IOTMP routine $ITINI cannot proceed:
>
SUBTTL $ITOPO--Open output
;CALL:
; 1/ PTR TO ARG BLOCK
;ARG BLOCK:
; +0/ FLAGS,,IFN ;Flags: IT%OEF
; +1/ BYTE SIZE,,NUMBER PAGES TO KEEP IN CORE
; +2/ IF IT%OEF SET, TOPS20= JFN, TOPS10= PTR TO FILOP. BLOCK
; +3/ (18-bit) Address of ASCIZ generic name of file
;RETURNS:
; .+1
; 1/ STATUS 0=OK, 1= PROBLEM
$ITOPO: DMOVEM T1,USR12 ;SAVE SOME ACS
DMOVEM T3,USR34 ;. .
HRRZ T4,0(T1) ;GET IFN
IMULI T4,IT.SIZ ;GET PTR TO ENTRY
HLLZ T2,0(T1) ;Get user's input flags
TXNN T2,IT%OEF ;Open external file?
JRST [SETZM OPFEXT ;No, clear flag
JRST .+2]
SETOM OPFEXT ;"OPENING AN EXTERNAL FILE" FLAG
PUSHJ P,GETGNN ;Get generic name of file
;Make a couple error checks
MOVE T3,IFNSTR+IT.FLG(T4)
TXNE T3,IT%OPI!IT%OPO ;File already open?
JRST FILALO ;Yes, complain
HLRZ T2,1(T1) ;Get byte size
CAIL T2,1 ;Must be between 1 and ^D36
CAILE T2,^D36
JRST BYTSZB ;Not, complain
MOVEM T2,SVBYTS ;SAVE BYTE SIZE FOR LATER
DPB T2,[POINT 6,IFNSTR+IT.FLG(T4),11]
SETZM IFNSTR+IT.NPD(T4) ;Clear # pages written
SETZM IFNSTR+IT.FSZ(T4) ;Set file size to 0
SKIPN OPFEXT ;Is this an external file?
JRST ITOPO2 ;No, skip some code
IFN TOPS20,<
HRRZ T2,2(T1) ;JFN must be supplied
JUMPE T2,JFN0O ;JFN supplied is 0
MOVEM T2,IFNSTR+IT.JFN(T4)
>
IFE TOPS20,<
MOVE T2,2(T1) ;FILOP. address must be supplied
MOVEM T2,IFNSTR+IT.FBA(T4)
>
HLLZ T2,0(T1) ;Get user's flags again
MOVX T3,IT%EXF ;"External file" flag
IFE TOPS20,<
PUSHJ P,DVCHRR ;Always get dev. char on TOPS-10
JRST RT1R34 ;Problem, return status 1
; JRST ITOPO0 ;Return with bits set in T3
>;END IFE TOPS20
IFN TOPS20,<
TXNN T2,IT%DSK!IT%TTY!IT%NUL ;Did user say whether this is a
; disk or tty file?
JRST [PUSHJ P,DVCHRR ;No, find out
JRST RT1R34 ;Problem, return status 1
JRST ITOPO0] ;Return with bits set in T3
TXNE T2,IT%DSK ;File a disk file?
TXO T3,IT%FDS ;Yes
TXNE T2,IT%TTY ;File a TTY file?
TXO T3,IT%FTY ;Yes
TXNE T2,IT%NUL ;File on NUL:?
TXO T3,IT%FNL ;Yes
>;END IFN TOPS20
ITOPO0: IORM T3,IFNSTR+IT.FLG(T4) ;Set flags
TXNE T3,IT%FDS ;Skip if not DISK file
JRST ITOPO2 ;Go get memory for it
SETZM IFNSTR+IT.CCT(T4) ;Set char count to 0
TXNE T3,IT%FNL ;If NUL:
JRST ITOPO9 ;Finish
PUSHJ P,ITOEXO ;Open file for output
JRST RT1R34 ;Error, return status 1
JRST ITOPO9 ;Finish
;Temp file or external file that requires memory
;Try to get some memory for it
ITOPO2: HRRZ T2,1(T1) ;Get # pages requested
CAIN T2,0 ;0 (use default?)
MOVE T2,DEFBFS ;Yes, get default #
DPB T2,[POINT 6,IFNSTR+IT.FLG(T4),5] ;Remember in file block
DPB T2,[POINT 6,IFNSTR+IT.FLG(T4),35] ;# pages "in use"
SETZ T1, ;No flags
SKIPN USEXEX ;Should we use extended addressing?
TXO T1,MM%GSS ;No, tell memory manager to use same section
PUSHJ P,FINFRE ;Try to get the memory
JUMPN T1,NMEMO ;Not enough memory to open file
MOVEM T2,SVMADR ;Save memory address we got
;Setup byte pointers to the memory
IFN TOPS20,<
SKIPN USEXEX ;Use extended addressing?
JRST ITOPO3 ;No, non-extended
SETZB T1,T2 ;Create starting bp in T1, t2
HRLI T1,440040 ;Start of global byte ptr
MOVE T3,SVBYTS ;Saved byte size
DPB T3,[POINT 6,T1,11] ; in first word
MOVE T2,SVMADR ;Saved global address in 2nd word
DMOVEM T1,IFNSTR+IT.CBP(T4) ;Store Current bp.
DMOVEM T1,IFNSTR+IT.SBP(T4) ;Save starting B.P.
JRST ITOPO4 ;SKIP single-word BP calc
>;END IFN TOPS20
;Setup local byte pointers
ITOPO3: SETZB T1,T2 ;Create bp's in t1, t2
HRLI T1,440000 ;byte ptr stuff
MOVE T3,SVBYTS ;GET SAVED BYTE SIZE
DPB T3,[POINT 6,T1,11]
HRR T1,SVMADR ;GET MEMORY ADDRESS
MOVEM T1,IFNSTR+IT.CBP(T4) ;Current BP at start
MOVEM T1,IFNSTR+IT.SBP(T4) ;Starting B.P.
ITOPO4: PUSHJ P,SETTCT ;Setup IT.TCT
MOVEM T1,IFNSTR+IT.CCT(T4) ;Store current character count
SKIPN OPFEXT ;Skip if opening an external file
JRST ITOPO9 ;No, skip this
PUSHJ P,ITOEXO ;Do the OPEN..
JRST RT1R34 ;Failed.. return status 1
;Logical OPEN OUTPUT is successful
ITOPO9: MOVX T3,IT%OPO ;Set "File is open for output" bit
IORM T3,IFNSTR+IT.FLG(T4)
JRST RT0R34 ;Restore user's 3&4, return status 0
;Errors
FILALO: $FERR (FAO,<Can't open ^8 because:
File is already open>)
JRST RT1R34 ;Return status 1
BYTSZB: $FERR (BSE,<Can't open ^8 because:
Byte size not between 1 and 36>)
JRST RT1R34 ;Return status 1
;Memory manager returned a non-zero status
;Status is in T1
NMEMO: CAIN T1,2 ;User error?
JRST RT1R34 ;Restore 3&4 and return status 1
$FERR (NEM,<Not enough memory for buffers;
can't open ^8 for output>)
JRST RT1R34 ;Return status 1
IFN TOPS20,<
JFN0O: $FERR (JS0,<Can't open ^8 because:
JFN supplied is 0>)
JRST RT1R34 ;Return status 1
>
;DVCHRR - Routine to find out device characteristics
;Call:
; T4/ ptr to file block
; IT.JFN/ JFN
;-or- IT.FBA/ FILOP. block address
;Call:
; PUSHJ P,DVCHRR
; <return here if can't get device characteristics, or unsupported device>
; <return here if OK>
;If routine skips, it returns:
; T3/ OR'd bits IT%FTY or IT%FDS
;Preserves T1
;Uses T2
DVCHRR: PUSH P,T1 ;Preserve T1
IFN TOPS20,<
MOVE T1,IFNSTR+IT.JFN(T4) ;Get JFN
PUSH P,T3 ;Save T3
DVCHR% ;Get characteristics of device
ERJMP DVCHRF ;Problem with DVCHR
POP P,T3 ;Restore T3
LDB T2,[POINTR T2,DV%TYP] ;Get device type
CAIN T2,.DVDSK ;Is it a disk?
JRST [IORX T3,IT%FDS ;Yes, set flag
JRST DVCHR1]
CAIN T2,.DVTTY ;Terminal?
JRST [IORX T3,IT%FTY ;Yes, set flag
JRST DVCHR1]
CAIN T2,.DVNUL ;NUL:?
JRST [IORX T3,IT%FNL ;Yes, set flag
JRST DVCHR1]
JRST UNSDEV ;?Unsupported device
;DVCHR JSYS failed
DVCHRF: POP P,T3 ;restore T3
$FERR (JSE,<Can't open ^8 because:
DVCHR% JSYS failed: ^1>)
JRST DVCHRB
>;END IFN TOPS20
IFE TOPS20,<
MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. addr
MOVE T1,.FODEV(T1) ;Get device name
MOVEM T1,SIXBW1 ;Save incase errors
DEVCHR T1, ;Get characteristics
JUMPE T1,DVCHRF ;Failed
MOVEM T1,IFNSTR+IT.DVC(T4) ;Save device characteristics
TXC T1,DV.DSK!DV.MTA ;Is device NUL:?
TXCN T1,DV.DSK!DV.MTA
JRST [IORX T3,IT%FNL ;Yes, set flag
JRST DVCHR1] ;Return
TXNE T1,DV.DSK ;Is device a disk?
JRST [IORX T3,IT%FDS ;Yes, set flag
JRST DVCHR1] ;Return
TXNE T1,DV.TTY ;Is device a TTY:?
JRST [IORX T3,IT%FTY ;Yes, set flag
JRST DVCHR1] ;Return
JRST UNSDEV ;?Unsupported device
DVCHRF: $FERR (NSD,<No such device: ^6>)
JRST DVCHRB ;"Bad return"
>;end IFE TOPS20
;Unsupported device
UNSDEV: $FERR (DNS,<Can't open ^8:
Specified device is not supported>)
JRST DVCHRB ;. .
;Good return from DVCHRR
DVCHR1: POP P,T1 ;Restore T1
AOS (P) ;Skip return
POPJ P, ;. .
;Bad return from DVCHRR
DVCHRB: POP P,T1 ;RESTORE T1
POPJ P, ;"Bad" return
;ITOEXO: Routine to OPEN external file for output
;Call:
; T4 points to file block
; PUSHJ P,ITOEXO
; <here if errors, message typed>
; <here if ok>
;Uses T1, t2
IFN TOPS20,<
ITOEXO: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FDS ;Is device a disk?
JRST [MOVX T2,<OF%WR> ;Just set write bit
JRST ITOEO2]
TXNE T1,IT%FTY ;Device a tty:
JRST [MOVX T2,<<7B5>+OF%WR> ;Write, 7-bit bytes
JRST ITOEO2]
; ** code here if more devices are supported **
ITOEO2: MOVE T1,IFNSTR+IT.JFN(T4) ;Get JFN
OPENF% ;** OPEN the device **
ERJMP ITOEE3 ;? Problem, go see
JRST CPOPJ1 ;Good return
;Errors opening external file for output
;OPENF error code is in T1
ITOEE3: CAIE T1,OPNX10 ;Entire file structure full?
CAIN T1,OPNX23 ;Disk quota exceeded?
JRST ITOEOQ ;Yes
$FERR (COF,<Can't open ^8 because:
OPENF% JSYS failed: ^1>)
POPJ P, ;Single return
;Disk quota problems, allow him to fix it and continue
ITOEOQ: $FERR (QEX,<^1
(Type "CONTINUE" when the problem has been fixed)>)
HALTF%
JRST ITOEO2 ;Go do OPENF again, T2 is still OK
>;END IFN TOPS20
;And now, repeating for TOPS10:
;Call:
; T4 points to file block
; PUSHJ P,ITOEXO
; <here if errors, message typed>
; <here if OK>
;Uses t1, t2
IFE TOPS20,<
ITOEXO: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FDS ;Is device a disk?
MOVEI T2,.IODMP ;Yes, use dump mode
TXNE T1,IT%FTY ;Is device a TTY:?
MOVEI T2,.IOASC ;Yes, use ASCIZ mode
HRRZ T1,IFNSTR+IT.FBA(T4) ;Get addr of FILOP. block
MOVEM T2,.FOIOS(T1) ;Store open mode
MOVEI T2,.FOWRT ;Function code (Write the file)
HRRM T2,.FOFNC(T1) ;Store function code
HRLI T1,.FOPAT+1 ;Length of arg list
FILOP. T1, ;** OPEN the file for create **
JRST ITOXE1 ;?Error return
JRST CPOPJ1 ;OK return
;FILOP. failed
ITOXE1: MOVEM T1,FLPERR ;Store FILOP. error
$FERR (CEF,<Can't enter ^8 because:
FILOP. UUO failed: (^A) -- ^B>)
POPJ P, ;Single (error) return
>;END IFE TOPS20
;SETTCT - Routine to setup IT.TCT
;Also returns the number in T1
;Uses t1,t2,T3
;Inputs:
; t4/ pointer to file block
; IT%NPB byte/ # pages in buffer
; SVBYTS/ byte size (bits)
;Call:
; PUSHJ P,SETTCT
; <return here always>
SETTCT: LDB T1,[POINT 6,IFNSTR+IT.FLG(T4),5] ;Get # pages used
LSH T1,^D9 ;Get # words used
MOVEI T2,^D36 ;BITS/WORD
IDIV T2,SVBYTS ; BITS/WORD / BITS/BYTE = BYTES/WORD
IMUL T1,T2 ;GET bytes/buffer
MOVEM T1,IFNSTR+IT.TCT(T4) ;Store total character count
POPJ P, ;Return with count in T1
SUBTTL $ITOPI - Open input
;Call:
; 1/ ptr to arg block
;Arg block:
; +0/ Flags,,IFN
; +1/ Byte size,,number pages to keep in core
; +2/ If IT%OEF set, TOPS20 = JFN, TOPS10= Ptr to FILOP. block
; +3/ 18-bit address of generic name of file
;Returns:
; .+1
; 1/ Status 0=OK, 1= problem (message typed)
$ITOPI: DMOVEM T1,USR12 ;SAVE SOME ACS
DMOVEM T3,USR34 ;. .
HRRZ T4,0(T1) ;GET IFN
IMULI T4,IT.SIZ ;GET PTR TO ENTRY
HLLZ T2,0(T1) ;Get user flags
TXNN T2,IT%OEF ;Opening external file?
JRST [SETZM OPFEXT ;No, clear flag
JRST .+2]
SETOM OPFEXT ;Yes, set flag
PUSHJ P,GETGNN ;Go get generic name of file
;Make a couple error checks
MOVE T3,IFNSTR+IT.FLG(T4)
TXNE T3,IT%OPI!IT%OPO ;File already open?
JRST FILALI ;Yes, complain
HLRZ T2,1(T1) ;Get byte size
CAIL T2,1 ;Check limits
CAILE T2,^D36
JRST BYTSZI ;No good, complain
MOVEM T2,SVBYTS ;Save byte size for later
SKIPE OPFEXT ;Opening an external file?
JRST ITOPIE ;Yes, go open it
TXNN T3,IT%WRT ;Is file logically written?
JRST FILNWR ;No, complain
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),11] ;GET BYTE SIZE
CAME T2,SVBYTS ;MUST BE SAME AS OLD BYTE SIZE
JRST NOTSMB ;?No, complain
SKIPE IFNSTR+IT.NPD(T4) ;Any pages written to disk?
JRST ITOPI2 ;Yes, same actions as an external file
MOVE T1,IFNSTR+IT.FSZ(T4) ;File size is limit
MOVEM T1,IFNSTR+IT.CCT(T4) ;= char count in this buffer
DMOVE T1,IFNSTR+IT.SBP(T4) ;Set current byte ptr
DMOVEM T1,IFNSTR+IT.CBP(T4) ; To starting byte ptr
JRST ITPI2A ;Skip some code for disk case
;Some pages had been written to disk
;That means that the whole file is written to disk
ITOPI2: DMOVE T1,IFNSTR+IT.SBP(T4) ;Set current byte ptr
DMOVEM T1,IFNSTR+IT.CBP(T4) ; To starting byte ptr
HLLZS IFNSTR+IT.NPD(T4) ;Set #pages read so far= 0
SETZM IFNSTR+IT.CCT(T4) ;Set char count to 0, so first input
; will read the pages in
IFE TOPS20,<
PUSHJ P,USTTI1 ;USETI file to block 1
JRST RT1R34 ;?Error, return status 1
>;END IFE TOPS20
ITPI2A: PUSHJ P,SETTCT ;Setup total char count
;Finished setting up file block
ITOPI3: MOVX T1,IT%OPI ;Set "File is open for input"
IORM T1,IFNSTR+IT.FLG(T4)
JRST RT0R34 ;Restore acs, return status 0
IFE TOPS20,<
;USTTI1 - USETI file to block 1
;Called when a temp file has been written to disk and
; now we want to read it back in.
;Call:
; PUSHJ P,USTTI1
; <here if errors, message typed>
; <here if OK>
;Uses T1-T3
USTTI1: MOVEI T1,1 ;Get block number to position to
MOVEM T1,FLP1AG+1 ;Store in FILOP. arg block
HRRZ T1,IFNSTR+IT.FBA(T4) ;Get ptr to FILOP. block
LDB T1,[POINT 9,.FOFNC(T1),17] ;Get channel number
HRLZM T1,FLP1AG ;Store channel number
MOVEI T1,.FOUSI ;Perform "USETI" call
HRRM T1,FLP1AG
MOVE T1,[2,,FLP1AG]
FILOP. T1, ;** Position file **
JRST USTT1E ;?Error
JRST CPOPJ1 ;OK return
;FILOP. failed
USTT1E: MOVEM T1,FLPERR ;Store error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get filename to type
MOVEM T1,EFNPTR ;Store for error message printer
$FERR (EPF,<Error positioning ^8:
FILOP. UUO (USETI) failed, error (^A) -- ^B>)
POPJ P, ;Error return
>;END IFE TOPS20
;Here to open external file for input
;T4 points to file block
;T1 points to user input block
ITOPIE:
IFN TOPS20,<
HRRZ T2,2(T1) ;JFN must be supplied
JUMPE T2,JFN0I ;JFN supplied is 0
MOVEM T2,IFNSTR+IT.JFN(T4)
>
IFE TOPS20,<
MOVE T2,2(T1) ;FILOP. address must be supplied
MOVEM T2,IFNSTR+IT.FBA(T4)
>
HLLZ T2,0(T1) ;Reget input flags
MOVX T3,IT%EXF ;"External file" flag
IFE TOPS20,<
PUSHJ P,DVCHRR ;Always get dev. char on TOPS-10
JRST RT1R34 ;Problems, return status 1
; JRST ITOPI4 ;Return with bits set in T3
>;END IFE TOPS20
IFN TOPS20,<
TXNN T2,IT%DSK!IT%TTY!IT%NUL ;Did user say whether this is a
; disk or tty file?
JRST [PUSHJ P,DVCHRR ;No, find out
JRST RT1R34 ;Problem, return status 1
JRST ITOPI4] ;Return with bits set in T3
TXNE T2,IT%DSK ;File a disk file?
TXO T3,IT%FDS ;Yes
TXNE T2,IT%TTY ;File a TTY file?
TXO T3,IT%FTY ;Yes
TXNE T2,IT%NUL ;File on NUL:?
TXO T3,IT%FNL ;Yes
>;END IFN TOPS20
ITOPI4: IORM T3,IFNSTR+IT.FLG(T4) ;Set flags
MOVE T2,SVBYTS ;Get saved byte size
DPB T2,[POINT 6,IFNSTR+IT.FLG(T4),11] ;Save in entry
TXNE T3,IT%FDS ;Is file a DSK: file?
JRST GMEXTI ;Yes, go get memory for it
SETZM IFNSTR+IT.CCT(T4) ;Set char count to 0
TXNE T3,IT%FNL ;Is file on NUL:?
JRST ITOPI3 ;Yes, return now
SKIPE ITTFOP ;Make sure another TTY: file is not opened
JRST ANOTFO ;Can't do it
PUSHJ P,ITOEXI ;** OPEN file**
JRST RT1R34 ;Error, return status 1
SETOM ITTFOP ;Set flag saying TTY: file is open for input
JRST ITOPI3 ;Set bit saying file is open, return
;Get memory for it
GMEXTI: HRRZ T2,1(T1) ;Get # pages requested
CAIN T2,0 ;0 (Use default) ?
MOVE T2,DEFBFS ;Yes, get default #
DPB T2,[POINT 6,IFNSTR+IT.FLG(T4),5] ;Remember in file block
SETZ T1, ;No flags
SKIPN USEXEX ;Extended addressing?
TXO T1,MM%GSS ;No, tell memory manager to use same section
PUSHJ P,FINFRE ;Try to get the memory
JUMPN T1,NMEMI ;Not enough memory to open file
MOVEM T2,SVMADR ;Save memory address we got
PUSHJ P,ITOEXI ;** Physical open file for input**
JRST [PUSHJ P,RMEMSV ;?Failed, release the memory
JRST RT1R34] ; and go return status 1
PUSHJ P,SETTCT ;Setup total char count (per buffer)
;Setup starting byte pointer
IFN TOPS20,<
SKIPN USEXEX ;Extended addressing?
JRST ITOPI5 ;No
SETZB T1,T2 ;Create starting bp in T1, t2
HRLI T1,440040 ;Start of global byte ptr
MOVE T3,SVBYTS ;Saved byte size
DPB T3,[POINT 6,T1,11] ; in first word
MOVE T2,SVMADR ;Saved global address in 2nd word
DMOVEM T1,IFNSTR+IT.SBP(T4) ;Save starting byte ptr
JRST ITOPI6 ;Skip single-word BP calc.
>;END IFN TOPS20
;Setup starting byte pointer (a local pointer)
ITOPI5: HRLZI T1,440000 ;Create bp in T1
MOVE T3,SVBYTS ;Get saved byte size
DPB T3,[POINT 6,T1,11]
HRR T1,SVMADR ;Get memory address
MOVEM T1,IFNSTR+IT.SBP(T4) ;Save starting byte ptr
;Read in first buffer, set character count
ITOPI6: SETOM IFNSTR+IT.NPD(T4) ;Set # pages written to -1
HLLZS IFNSTR+IT.NPD(T4) ;Set # pages read so far to 0
PUSHJ P,RDNBUF ;Read next buffer..
JRST [CAIN T1,2 ;EOF?
JRST ITOPI3 ;Yes, return OK
JRST RT1R34] ;Can't
JRST ITOPI3 ;OK, Set bit saying file is open, return
;Error routines for $ITOPI
FILALI: $FERR (FAO,<Can't open ^8 because:
File is already open>)
JRST RT1R34 ;Return status 1, restore user's acs
BYTSZI: $FERR (BSE,<Can't open ^8 because:
Byte size not between 1 and 36>)
JRST RT1R34 ;Return status 1
FILNWR: $FERR (RBW,<Can't open ^8 because:
Attempt to read temp file before writing it>)
JRST RT1R34 ;Return status 1
NOTSMB: $FERR (BSD,<Can't open ^8 because:
Input byte size differs from output byte size>)
JRST RT1R34 ;Return status 1
ANOTFO: $FERR (TFO,<Can't open ^8 because:
Can't open more than one TTY: file for input at the same time>)
JRST RT1R34 ;Return status 1
IFN TOPS20,<
JFN0I: $FERR (JS0,<Can't open ^8 because:
JFN supplied is 0>)
JRST RT1R34 ;Return status 1
>;END IFN TOPS20
;FINFRE returned a non-zero status
NMEMI: CAIN T1,2 ;User error?
JRST RT1R34 ;Message already typed
$FERR (NEM,<Can't open ^8 because:
Not enough memory for buffers>)
JRST RT1R34
;Release memory because file open failed.
;Address is in SVMADR, # pages is in file block.
;Uses T1, T2
RMEMSV: PUSH P,T3 ;Save T3
SETZ T1, ;No flags
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),5] ;Get # pages
MOVE T3,SVMADR ;Get address
PUSHJ P,RETRN ;** Return the memory **
POP P,T3 ;Restore T3
POPJ P, ;Return
;ITOEXI: Routine to OPEN external file for input
;Call:
; T4 points to file block
; PUSHJ P,ITOEXI
; <here if errors, message typed>
; <here if ok, IT.FSZ word setup>
;Uses T1, t2
IFN TOPS20,<
ITOEXI: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FDS ;Is device a disk?
JRST [MOVX T2,<OF%RD> ;Just set read bit
JRST ITOEI2]
TXNE T1,IT%FTY ;Device a tty:
JRST [MOVX T2,<<7B5>+OF%RD> ;Read, 7-bit bytes
JRST ITOEI2]
; ** code here if more devices are supported **
ITOEI2: MOVE T1,IFNSTR+IT.JFN(T4) ;Get JFN
OPENF% ;** OPEN the device **
ERJMP ITIEE3 ;? Problem, go see
MOVE T1,IFNSTR+IT.FLG(T4) ;GET FLAGS
TXNE T1,IT%FTY ;Is device a TTY:?
JRST CPOPJ1 ;Yes, just take good return
;Setup the IT.FSZ word
MOVE T1,IFNSTR+IT.JFN(T4) ;Find file's size
SIZEF% ;Get # of bytes written
ERJMP ITIEE4 ;?Problem
MOVEM T2,ITOSSZ ;Save file's size
PUSH P,T3 ;Save T3
MOVE T1,IFNSTR+IT.JFN(T4) ;Find byte size
MOVE T2,[1,,.FBBYV]
MOVEI T3,BYVWRD ;Store word here
GTFDB% ;Get bits/byte
ERJMP ITIEE5 ;?problem
POP P,T3 ;Restore T3
LDB T2,[POINT 6,BYVWRD,11] ;Get bits/byte written
CAMN T2,SVBYTS ;Just what we want to read?
JRST [MOVE T1,ITOSSZ ;Yes, just use size given
MOVEM T1,IFNSTR+IT.FSZ(T4)
JRST CPOPJ1] ;Go give good return
;Find # 36-bit words in the file
;T2= Bits/byte written
MOVEI T1,^D36 ;Bits/word
IDIV T1,T2 ;Get bytes/word
MOVE T2,ITOSSZ ;# bytes written
EXCH T1,T2
IDIV T1,T2 ;Get # words
SKIPE T2
ADDI T1,1 ;Round up to nearest word
MOVEM T1,ITOSSZ ;Save # words
;Find # bytes of new size that will be used
MOVEI T1,^D36 ;Bits/word
IDIV T1,SVBYTS ;Bytes/word
IMUL T1,ITOSSZ ; * # words = # BYTES
MOVEM T1,IFNSTR+IT.FSZ(T4) ;Save file size
JRST CPOPJ1 ;Good return
;TOPS20 Errors trying to open external file for input
ITIEE3: $FERR (JSE,<Can't open ^8 because:
OPENF% JSYS failed: ^1>)
POPJ P, ;Single return
ITIEE4: $FERR (JSE,<Can't open ^8 because:
SIZEF% JSYS failed: ^1>)
POPJ P, ;Single return
ITIEE5: POP P,T3 ;Restore T3
$FERR (JSE,<Can't open ^8 because:
GTFDB% JSYS failed: ^1>)
POPJ P, ;Single return
>;END IFN TOPS20
;Repeating the documentation for TOPS10:
;Call:
; T4 points to file block
; PUSHJ P,ITOEXI
; <here if errors, message typed>
; <here if OK, IT.FSZ word setup>
;Uses T1, T2
IFE TOPS20,<
;If supplied LOOKUP block is an extended block, he has to
; give TOPS-10 room to store .RBSIZ word.
ITOEXI: MOVE T1,IFNSTR+IT.FBA(T4) ;Get addr of FILOP. block
HRRZ T1,.FOLEB(T1) ;Get addr of LOOKUP block
MOVE T1,(T1) ;Get first word
TLNE T1,-1 ;Extended block?
JRST ITOEX0 ;No, ok
ANDI T1,77777 ;Get size of block
CAIGE T1,.RBSIZ+1 ;Big enough?
JRST ITIXE0 ;?no, complain
ITOEX0: MOVE T1,IFNSTR+IT.FLG(T4) ;get flags
TXNE T1,IT%FDS ;Is device a disk?
MOVEI T2,.IODMP ;Yes, use dump mode
TXNE T1,IT%FTY ;Is device TTY:?
MOVEI T2,.IOASC ;yes, use Ascii mode
HRRZ T1,IFNSTR+IT.FBA(T4) ;Get addr of FILOP. block
MOVEM T2,.FOIOS(T1) ;Save open mode
MOVEI T2,.FORED ;Function code (Read the file)
HRRM T2,.FOFNC(T1) ;Store function code
HRLI T1,.FOPAT+1 ;Length of arg list
FILOP. T1, ;** OPEN FILE FOR INPUT **
JRST ITIXE1 ;Error return
MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FTY ;TTY: file?
JRST CPOPJ1 ;Yes, just take good return
;setup IT.FSZ word
MOVE T1,IFNSTR+IT.FBA(T4) ;Get addr of FILOP. block
HRRZ T1,.FOLEB(T1) ;Get addr of LOOKUP block
MOVE T2,0(T1) ;Get first word
TLNN T2,-1 ;Extended block?
JRST [MOVE T1,.RBSIZ(T1) ;Yes, get # words
JRST SZFNWD]
HLRE T1,3(T1) ;No, get size returned
JUMPL T1,[MOVN T1,T1 ;Get # words
JRST SZFNWD] ;Go store 'em
IMULI T1,^D128 ;Get # words
SZFNWD: MOVEM T1,ITOSSZ ;Save size of file
MOVEI T2,^D36 ;# bits/byte written
CAMN T2,SVBYTS ;Just what we want to read?
JRST [MOVEM T1,IFNSTR+IT.FSZ(T4) ;Yes, save size
JRST CPOPJ1] ;Give good return
;Find # bytes of new size that will be used
MOVEI T1,^D36 ;Bits/word
IDIV T1,SVBYTS ;Bytes/word
IMUL T1,ITOSSZ ; * # words = # bytes
MOVEM T1,IFNSTR+IT.FSZ(T4) ;Save file size
JRST CPOPJ1 ;Good return
;Extended LOOKUP block is too small
ITIXE0: $FERR (CRF,<Can't read from ^8 because:
Supplied extended LOOKUP block is too small - must have room for .RBSIZ word>)
POPJ P, ;Error return
;FILOP. error
ITIXE1: MOVEM T1,FLPERR ;Save FILOP. error code
$FERR (CRF,<Can't read from ^8 because:
FILOP. UUO failed: (^A) -- ^B>)
POPJ P,
>;END IFE TOPS20
SUBTTL GETGNN - Get generic filename and store byte ptr to it
;Call:
; T1/ pointer to arg list for $ITOPI or $ITOPO
; 3(T1) / address of ASCIZ generic name of file
; T4/ pointer to file block
; OPFEXT flag has been set to -1 if file is an external file
; PUSHJ P,GETGNN
; <return here always>
;Uses T2,T3 only
GETGNN: SKIPN T2,3(T1) ;Get address of ASCIZ name
JRST GETGN1 ;None supplied
IFN TOPS20,<
TLNE T2,-1 ;Is this an extended address?
JRST GETGN2 ;Yes, go make it a 2-word byte ptr
;It's a local address in the section of the caller
HLRZ T3,T1 ;Get section number of the arg list
XMOVEI T2,. ;Get my section number
HLRZ T2,T2 ;Put in RH(t2)
CAME T2,T3 ;Same section?
JRST [MOVE T2,3(T1) ;No, get address again
HLL T2,T1 ;Make a global address
JRST GETGN2] ;Go make a 2-word byte ptr
MOVE T2,3(T1) ;get address again
>;END IFN TOPS20
;Create a 1-word byte ptr to the address
GETGN3: HRLI T2,(POINT 7,)
MOVEM T2,IFNSTR+IT.GNP(T4) ;Store byte ptr in generic name pointer
MOVEM T2,EFNPTR ;Store here incase errors on OPEN, too
POPJ P, ;And return
;Here if no name supplied
GETGN1: MOVEI T2,[ASCIZ/file/] ;Get a generic name
SKIPN OPFEXT ;Is this a temp file?
MOVEI T2,[ASCIZ/temp file/] ;Yes, will say that
JRST GETGN3 ;Go store it with a 1-word bp
IFN TOPS20,<
;Here to create a 2-word byte ptr to the item and store it
GETGN2: MOVE T3,T2 ;Get address in 2nd word of byte ptr
MOVX T2,<^D36B5>+<7B11>+1B12 ;First word of 2-word bp.
DMOVEM T2,IFNSTR+IT.GNP(T4) ;Store byte ptr to generic file name
DMOVEM T2,EFNPTR ;Store incase errors on OPEN, too
POPJ P, ;Done, return
>;END IFN TOPS20
SUBTTL $ITOUB - Output 1 byte
;Call:
; 1/ IFN
; 2/ character
;Returns:
; 1/ Status 0= ok, 1= problem
$ITOUB: IMULI T1,IT.SIZ ;Get ptr to entry
ITOUB0: SOSGE IFNSTR+IT.CCT(T1) ;Still room in buffer?
JRST ITOUB1 ;No--see what to do
IDPB T2,IFNSTR+IT.CBP(T1) ;Store char
SETZ T1, ;Return status 0
POPJ P, ;. .
;# chars in buffer ran out
ITOUB1: SETZM IFNSTR+IT.CCT(T1) ;Clear char count
MOVEM T2,SVOUTB ;Save byte to output
MOVE T2,IFNSTR+IT.FLG(T1) ;Get flags
TXNE T2,IT%FTY!IT%FNL ;TTY or NUL: file?
JRST ITOUBT ;Yes
;Buffer ran out for disk file
PUSH P,T3 ;Save acs
PUSH P,T4
MOVE T4,T1 ;Set t4=ptr to file block
PUSHJ P,WRTBUF ;** Write out buffer **
SKIPA T2,[1] ;?Problems, set status to 1
SETZ T2, ;OK, set status to 0
MOVE T1,T4 ;Get t1=pointer to block
POP P,T4 ;Restore saved acs
POP P,T3
JUMPN T2,RETST1 ;If no good, return status 1
MOVE T2,SVOUTB ;Get saved output byte
JRST ITOUB0 ;Go output it (finally)
;File is TTY: or NUL:
ITOUBT: TXNE T2,IT%FNL ;NUL:?
JRST RETST0 ;Yes, return status 0 (OK)
;Here to write character to TTY: file
IFN TOPS20,<
PUSH P,T4 ;Save t4
MOVE T4,T1 ;Copy File block ptr
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
MOVE T2,SVOUTB ;Get byte
BOUT% ;Output the byte
ERJMP ITNBTE ;BOUT failed!
POP P,T4 ;Ok, restore T4
>
IFE TOPS20,<
OUTCHR SVOUTB ;Output the byte
>
JRST RETST0 ;Return status 0
IFN TOPS20,<
;Here if "BOUT" fails
ITNBTE: PUSH P,T3 ;Save T3
DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Error writing ^8:
BOUT% JSYS failed: ^1>)
POP P,T3 ;Restore T3
POP P,T4 ;Restore T4
JRST RETST1 ;Return status 1
>;END IFN TOPS20
;WRTBUF - Write out buffer for disk file
;Called when the buffer has filled up or you want to write out
; whatever is in buffer.
;If the file is currently not open, it is opened
;Inputs:
; t4/ ptr to file block
; IT.CCT/ # chars that can be still put in buffer
; IT.TCT/ total # chars that can be stored in full buffer
;Call:
; PUSHJ P,WRTBUF
; <return here if problem, message typed>
; <Return here if OK>
;Outputs:
; IT.CBP set to IT.SBP
; IT.CCT set to IT.TCT
;Uses:
;T1-T3
WRTBUF: DMOVE T1,IFNSTR+IT.CBP(T4) ;Save current BP
DMOVEM T1,SVBPWB ; Incase needed to store nulls
DMOVE T1,IFNSTR+IT.SBP(T4) ;Make BP be starting BP
DMOVEM T1,IFNSTR+IT.CBP(T4) ;. .
MOVE T1,IFNSTR+IT.TCT(T4) ;Get total # bytes that fit
MOVE T2,T1 ;Copy to T2
SUB T1,IFNSTR+IT.CCT(T4) ;Get # bytes written into buffer
JUMPE T1,CPOPJ1 ;Skip return if nothing to do
MOVEM T1,WTBUFC ;Save # chars written to buffer
ADDM T1,IFNSTR+IT.FSZ(T4) ;Update file size
MOVEM T2,IFNSTR+IT.CCT(T4) ;Restore char count remaining to max.
HLRZ T1,IFNSTR+IT.NPD(T4) ;Get #pages written so far
JUMPE T1,WRTBF1 ;Zero, might have to open file first
WRTBF0: CAMN T2,WTBUFC ;Writing max # chars?
JRST WRTBF2 ;Yes, use simple page IO
MOVEI T1,^D36 ;Bits/word
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),11] ;Bits/byte
IDIV T1,T2 ;Bytes/word
MOVE T2,WTBUFC ;Get # bytes to write
IDIV T2,T1 ;# words to write
JUMPE T3,LSTWOK ;Round up to nearest word
; Jump if we used the whole last word
ADDI T2,1 ;T2= # words to write
;T1= # bytes per word, T3= # bytes used in this word.
;We must make sure the rest of the word is zero (since we weren't
; being careful about making sure it started out null, for performance).
PUSH P,T2 ;Save T2
SUB T1,T3 ;T1= # bytes left to write
SETZ T2, ;Get a zero byte
IDPB T2,SVBPWB ;Put in this word
SOJG T1,.-1 ; Make rest of word null
POP P,T2 ;Restore T2
;Get here when last word of buffer is ok to write out
; i.e. the unused parts are null.
LSTWOK:
IFN TOPS20,<
;PMAP all the pages that contain something
TRZE T2,777 ;Round up to # pages
ADDI T2,1000
LSH T2,-^D9 ;T2= # pages to write
;Here to PMAP (T2) pages
WT2BF1: MOVE T3,T2 ;Get # pages
SKIPN T1,IFNSTR+IT.SBP+1(T4) ;Get starting process page #
HRRZ T1,IFNSTR+IT.SBP(T4) ; . .
LSH T1,-^D9 ; . .
HRLI T1,.FHSLF ;This process
HRLZ T2,IFNSTR+IT.JFN(T4) ;JFN of file in LH
HLR T2,IFNSTR+IT.NPD(T4) ;Page # in file in RH
TXO T3,PM%CNT!PM%RD!PM%WR ;Give page read and write access
;Acs T1-T3 set for PMAP now
WT2PMP: PMAP% ;** Write the file pages **
ERJMP WT2PMF ;?PMAP failed
HRRZ T3,T3 ;Get # pages written just then
HLRZ T2,IFNSTR+IT.NPD(T4) ;Update # pages written
ADD T2,T3
HRLM T2,IFNSTR+IT.NPD(T4) ; . .
JRST CPOPJ1 ;Give good return
;Output PMAP failed, possibly quota exceeded
WT2PMF: PUSH P,T1 ;Save acs
PUSH P,T2
PUSH P,T3
MOVEI T1,.FHSLF ;Get error code
GETER%
CAME T2,[.FHSLF,,PMAPX6] ;Disk quota exceeded?
CAMN T2,[.FHSLF,,IOX11] ;Quota exceeded or disk full?
JRST WT2PFQ ;Yes, allow him to fix the problem
DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Error writing ^8:
PMAP% JSYS failed: ^1>)
POP P,T3 ;Restore saved acs
POP P,T2
POP P,T1
POPJ P, ;Give popj return
WT2PFQ: $FERR (QEX,<^1
(Type "CONTINUE" when the problem has been fixed)>)
HALTF%
POP P,T3 ;Restore acs for PMAP
POP P,T2
POP P,T1
JRST WT2PMP ;Go try again
>;END IFN TOPS20
IFE TOPS20,<
;WRITE exactly (T2) words
WT1BF1: MOVN T2,T2 ;Get -n
HRLE T2,T2 ;GET -n,,-1
HRR T2,IFNSTR+IT.SBP(T4) ;Get -n,,addr
SUBI T2,1 ;Get IOWD n,addr
MOVEM T2,FLPDL ;Store 1st word of dump list
SETZM FLPDL+1 ;Clear 2nd word of dump list
MOVEI T1,FLPDL ;Point to FILOP. dump list
MOVEM T1,FLP1AG+1
HRRZ T1,IFNSTR+IT.FBA(T4) ;Get ptr to FILOP. list
LDB T1,[POINT 9,.FOFNC(T1),17] ;Get channel number
HRLZM T1,FLP1AG ;Store channel number
HRRI T1,.FOOUT ;Perform "OUT"
HRRM T1,FLP1AG ;Store function code
MOVE T1,[2,,FLP1AG] ;Point to arg list
FILOP. T1, ;Do FILOP.
JRST WTFLPE ;Error
;Update # pages written
HLRE T1,FLPDL ;Get word from dump list
MOVN T1,T1 ;T1= # words written
TRNE T1,777 ;Round up to nearest page
ADDI T1,1000
LSH T1,-^D9 ;# pages written
HLRZ T2,IFNSTR+IT.NPD(T4) ;# written up till now
ADD T2,T1
HRLM T2,IFNSTR+IT.NPD(T4) ;Update it
JRST CPOPJ1 ;Give good return
;FILOP. error on write
WTFLPE: MOVEM T1,FLPERR ;Store error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (EWF,<Error writing ^8:
FILOP. UUO error (^A) -- ^B>)
POPJ P, ;Give bad return
>;END IFE TOPS20
;Here if we are writing the max # pages
WRTBF2:
IFN TOPS20,<
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),5] ;# pages in buffer
JRST WT2BF1 ;Go PMAP that # of pages
>;END IFN TOPS20
IFE TOPS20,<
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),5] ;# pages in buffer
LSH T2,^D9 ;# words in buffer
JRST WT1BF1 ;Go write that many words
>;END IFE TOPS20
;Here if # pages written so far is 0
WRTBF1: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%EXF ;Is file an external file?
JRST WRTBF0 ;Yes, it's already open anyway.
PUSHJ P,OPNTMO ;Go open temp file for output
POPJ P, ;?Error, return .+1
MOVE T2,IFNSTR+IT.TCT(T4) ;Get total # bytes that fit
JRST WRTBF0 ;Go rejoin code
SUBTTL OPNTMO - OPEN temp file for output
;This is only necessary if we run out of space in the buffer
; we allocated to it. This routine is called from "WRTBUF" only.
;Inputs:
; t4/ points to file block
;Call:
; PUSHJ P,OPNTMO
; <return here if error, message typed>
; <return here if OK, file open>
;Uses T1-T3
IFN TOPS20,< ;TOPS20 "OPNTMO" routine
;A temp file is given the name "XXX.TMP.-1;T" and made invisible
OPNTMO: MOVE T2,[POINT 7,[ASCIZ/XXX.TMP.-1;T/]]
SETZM TMOTRY ;Number of tries so far = 0
OPNTX0: MOVX T1,GJ%SHT!GJ%FOU ;Next generation number, please
GTJFN% ;Get handle on a temp file
ERJMP OTME01 ;Can't
MOVEM T1,OTMJFN ;Save it
;Open file for I/O so it can remain open until we are done with it.
; This is necessary because we are going to set the deleted bit and
; don't want someone to "EXPUNGE" when it is closed but we are not done.
OPNTXX: MOVE T2,[<^D36>B5+OF%RD!OF%WR] ;OPEN for I-O
OPENF% ;So file can stay open
ERJMP OTME02 ;Can't
;Set the "deleted" bit in the FDB. This is done so if the user types
; CTRL/C, "RESET", the file will not be left around in the directory. The
; pages will still be allocated, but there isn't anything practical
; that we can do about that.
MOVX T1,<<.FBCTL>B17> ;Change this word in the FDB
HRR T1,OTMJFN ;For this file
MOVX T2,FB%DEL ;"File is deleted" bit
MOVX T3,FB%DEL ;Turn it on
CHFDB% ;Change the FDB word..
ERJMP OTME03 ;Can't
;Do an "Update file pages" JSYS so the file will exist. This must
; be done in order to avoid the "simultaneous access" error if more
; than one of these temp files is open at once.
UFPGXX: HRLZ T1,OTMJFN ;Update file pages to make the file appear
SETZ T2,
UFPGS%
ERJMP OTME04 ;Can't
;All ok!
MOVE T1,OTMJFN ;Copy JFN to block
MOVEM T1,IFNSTR+IT.JFN(T4) ; . .
JRST CPOPJ1 ;Give good return
;Errors for TOPS20 OPNTMO routine
OTME01: $FERR (JSE,<Can't open ^8 because:
GTJFN% JSYS failed: ^1>)
POPJ P,
OTME02: CAIE T1,OPNX10 ;Entire file structure full?
CAIN T1,OPNX23 ;Disk quota exceeded?
JRST OTME2Q ;Yes, go let him fix it and continue
CAIN T1,OPNX9 ;Invalid simultaneous access?
JRST OTME2S ;Yes, got into the race condition,
; go try another filename
OTME2E: $FERR (JSE,<Can't open ^8 because:
OPENF% JSYS failed: ^1>)
POPJ P,
;OPENF% failed because of quota exceeded
OTME2Q: $FERR (QEX,<Can't open ^8 - ^1
(Type "CONTINUE" when the problem has been fixed)>)
HALTF%
MOVE T1,OTMJFN ;Get back JFN
JRST OPNTXX ;Go try OPENF again
;OPENF% failed because of invalid simultaneous access
;Note that this should only happen if there are two users on the system
; and one has opened a file with the same name as this user but has not
; done an "UPFGS" JSYS yet. We will simply pick another name, try that,
; and if it continues to fail the same way we'll just give the error.
OTME2S: AOS T1,TMOTRY ;Increment number of tries
CAILE T1,.TMTMX ;Tried too many times?
JRST OTME2E ;Yes, go give an error (don't get caught
; in infinite loop!)
MOVE T1,OTMJFN ;Release JFN we got before
RLJFN%
ERJMP .+1 ;This should not happen
MOVEI T1,^D100 ;Sleep for a fraction of a second
DISMS%
GTAD% ;Return current date and time
ANDI T1,3 ;Get random number 0 to 3
MOVE T2,OTMFNS(T1) ;Get a random filename
JRST OPNTX0 ;Go try again
OTMFNS: POINT 7,[ASCIZ/YXX.TMP.-1;T/]
POINT 7,[ASCIZ/ZXX.TMP.-1;T/]
POINT 7,[ASCIZ/WXX.TMP.-1;T/]
POINT 7,[ASCIZ/UXX.TMP.-1;T/]
OTME03: $FERR (JSE,<Can't open ^8 because:
CHFDB% JSYS failed: ^1>)
POPJ P,
OTME04: CAIN T1,IOX11 ;Quota exceeded?
JRST OTME4Q ;Yes, give him a chance to fix it
$FERR (JSE,<Can't open ^8 because:
UFPGS% failed: ^1>)
POPJ P,
OTME4Q: $FERR (QEX,<Can't open ^8: ^1
(Type "CONTINUE" when the problem has been fixed)>)
HALTF%
JRST UFPGXX ;Go do the JSYS again
>;END IFN TOPS20
IFE TOPS20,< ;TOPS10 "OPNTMO" routine
;This is only necessary if we run out of space in the buffer
; we allocated to it. This routine is called from "WRTBUF" only.
;Inputs:
; t4/ points to file block
;Call:
; PUSHJ P,OPNTMO
; <return here if error, message typed>
; <return here if OK, file open>
;Uses T1-T3
OPNTMO: SETZM TMOTRY ;# tries so far = 0
OPNT00: PUSHJ P,SETFLB ;Setup temp FILOP. block
PUSHJ P,GTMPNM ;Get temp name and put in FILOP. block
OPNTM0: MOVEI T1,.FOSAU ;"Update file, single-access mode"
HRRM T1,IFNSTR+IT.SFB+.FOFNC(T4)
MOVEI T1,.IODMP ;Dump-mode IO
MOVEM T1,IFNSTR+IT.SFB+.FOIOS(T4)
HRLI T1,.FOPAT+1 ;Length of arg block
HRRI T1,IFNSTR+IT.SFB(T4) ;Addr of arg block
FILOP. T1, ;** OPEN FILE FOR UPDATE **
JRST OTM0FE ;Error
JRST CPOPJ1 ;Return OK
;FILOP. UUO failed
OTM0FE: CAIN T1,ERAEF% ;Tried to supersede?
JRST OTMNSE ;Yes, oh dear
;Dreadful error.
OTMDRD: MOVEM T1,FLPERR
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (UER,<Can't open ^8 because:
FILOP. UUO to open file for single-access update failed:
(^A) -- ^B>)
POPJ P,
;FILOP. UUO failed because of non-superseding error
;Get another filename and try again. If we already tried
; too many times with the same error, there must be something
; dreadfully wrong, so quit.
OTMNSE: AOS T2,TMOTRY ;Count # tries
CAIN T2,.TMTMX ;Too many?
JRST OTMDRD ;yes, just give FILOP. error
JRST OPNT00 ;Go try again
;Setup temp FILOP. block
;Inputs:
; T4/ file block address
;Call:
; PUSHJ P,SETFLB
; <return here always>
;USES T1-T3
SETFLB: MOVEI T1,IFNSTR+IT.SFB(T4) ;Get address of start of FILOP. block
MOVEM T1,IFNSTR+IT.FBA(T4) ;Store it
SETZM (T1) ;Clear it out
HRL T2,T1
HRRI T2,1(T1)
BLT T2,IFNSTR+IT.FBA+IT.FSZ-1(T4) ;Clear out whole FILOP. block
MOVSI T2,'DSK' ;Device name
MOVEM T2,IFNSTR+IT.SFB+.FODEV(T4) ;Store in FILOP. block
HRLI T2,IFNSTR+IT.SRB(T4) ;Start of rename block
HRRI T2,IFNSTR+IT.SLB(T4) ;,,Start of LOOKUP block
MOVEM T2,.FOLEB(T1) ;Store in FILOP. block
MOVEI T2,IFNSTR+IT.SPB(T4) ;Addr of returned PATH. block
MOVEM T2,.FOPAT(T1) ;Store in FILOP. block
HRLI T2,IFNSTR+IT.OBH(T4) ;Addr of output buffer header
HRRI T2,IFNSTR+IT.IBH(T4) ;,,addr of input buffer header
MOVEM T2,.FOBRH(T1) ;Store in FILOP. block
MOVX T2,FO.ASC+FO.PRV ;"Get extended channel"
;Also set FO.PRV to be consistant with
; TOPS20 when a user "ENABLE's".
MOVEM T2,.FOFNC(T1) ;Store in FILOP. block
MOVEI T2,IFNSTR+IT.SLP(T4) ;Start of LOOKUP path block
MOVEM T2,IFNSTR+IT.SLB+.RBPPN(T4) ;Store in LOOKUP block
MOVEI T2,.RBPRV+1 ;Size of LOOKUP/ENTER blocks needed
MOVEM T2,IFNSTR+IT.SRB+.RBCNT(T4) ;Store in RENAME block count word
TXO T2,RB.NSE ;Set "Non-supersede" ENTER
MOVEM T2,IFNSTR+IT.SLB+.RBCNT(T4) ;Store count word and flags
POPJ P, ;Done, return
;Get temp name and put in FILOP. block
;Inputs:
; T4/ file block address
;Uses t1-t3
;Call:
; PUSHJ P,GTMPNM
; <return here always>
GTMPNM: SKIPE SEED ;Already have a random seed?
JRST GTMPN1 ;Yes
MSTIME T1, ;Get time of day in milliseconds
HRRM T1,SEED ;Save RN seed
HRLM T1,SEED ; . .
GTMPN1: PUSHJ P,GTMWRD ;Get sixbit word in T1
MOVEM T1,IFNSTR+IT.SLB+.RBNAM(T4)
MOVSI T1,'TMP' ;.TMP
HLLZM T1,IFNSTR+IT.SLB+.RBEXT(T4)
POPJ P, ;Return
;Routine to get random sixbit word in T1
GTMWRD: SETZ T1, ;Start with nothing
PUSH P,T4 ;Save T4
MOVEI T4,6 ;# chars
GTMWR1: PUSHJ P,GTMCHR ;Get random char
LSH T1,6 ;Shift left six
ADDI T1,(T2) ;Add in char
SOJG T4,GTMWR1 ;Loop
POP P,T4 ;Restore T4
POPJ P, ;And return
;Routine to get random char in T2
;Uses T3
GTMCHR: MOVE T3,SEED ;Get current seed
ANDI T3,17 ;Just save last 4 bits
MOVEI T2,'A'(T3) ;Get letter
MOVE T3,SEED ;Get current seed
ROT T3,7 ;Rotate
ADD T3,T2 ;Add in value of letter
MOVEM T3,SEED ;Store new seed
POPJ P, ;Return
>;END IFE TOPS20
SUBTTL $ITINB - Input 1 byte
;Call:
; 1/ IFN
;Returns:
; 1/ Status 0= ok, 1= problem, 2=EOF
; 2/ character
$ITINB: IMULI T1,IT.SIZ ;Get ptr to entry
ITINB0: SOSGE IFNSTR+IT.CCT(T1) ;Still bytes in buffer?
JRST ITINB1 ;No--see what to do
ILDB T2,IFNSTR+IT.CBP(T1) ;Fetch byte
SETZ T1, ;Return status 0
POPJ P, ;. .
ITINB1: MOVE T2,IFNSTR+IT.FLG(T1) ;Get flags
TXNE T2,IT%FTY!IT%FNL ;Is file a TTY: or NUL: file?
JRST ITINBT ;Yes
;Buffer ran out for disk file
SKIPN IFNSTR+IT.NPD(T1) ;Any pages on disk?
JRST RETEOF ;No, return "EOF"
PUSH P,T3 ;Save T3
PUSH P,T4 ;Save T4
;Read another buffer from disk
PUSH P,T1 ;Save T1
MOVE T4,T1 ;Ptr to file block in T4
PUSHJ P,RDNBUF ; . .
JRST INBRE1 ;Failed..go see if EOF or other error
POP P,T1 ;restore T1
POP P,T4 ;Restore acs
POP P,T3
JRST ITINB0 ;Go read the byte now
;RDNBUF failed - EOF or fatal error
INBRE1: POP P,(P) ;Throw away AC1
POP P,T4 ;Restore acs
POP P,T3
;Status in T1 is exactly what I want to return now.
; i.e. 1= problem, 2= EOF
POPJ P, ;** Return, status is in T1 **
;Here to read character from NUL: or TTY: file
;Note: No acs saved so far
ITINBT: SETZM IFNSTR+IT.CCT(T1) ;Set # bytes in buffer again
TXNE T2,IT%FNL ;Is file NUL:?
JRST RETEOF ;Yes, return EOF
;TTY: file
IFN TOPS20,<
ITINT2: SOSGE TTYLCT ;Any more chars in line?
JRST TTYFGL ;No, read in a line
ILDB T2,TTYLBP ;Read a character
JRST ITINGT ;Got TTY: character
;Read in another line from TTY:
; (let him use CTRL/U and RUBOUT to edit the line)
TTYFGL: PUSH P,T4 ;SAVE T4
PUSH P,T3 ;Save T3
MOVE T4,T1 ;Save T1 incase errors
MOVE T2,[POINT 7,TLINE] ;Buffer pointer
MOVEM T2,TTYLBP ;Save BP to start of line
MOVE T1,[TXTILT,,TXTIBL] ;Copy virgin TEXTI block
BLT T1,TXTIBE ;Copy it
MOVEI T1,TXTIBL ;Use TEXTI% to read line
TEXTI% ;Do TEXTI%
ERJMP ITNBER ;? Error reading from TTY:
MOVE T2,TXTIBL+.RDDBC ;Get number of bytes in string (returned)
MOVEM T2,TTYLCT ;Save count
MOVE T1,T4 ;Get back file ptr
POP P,T3 ;Restore T3
POP P,T4 ;Restore T4
JRST ITINT2 ;Go back to get character
ITINGT:
>;END IFN TOPS20
IFE TOPS20,<
INCHWL T2 ;Read character to T2
>;END IFE TOPS20
CAIN T2,32 ;If character was Control-Z
JRST RETEOF ; Return EOF status
JRST RETST0 ;Character in T2, Return status 0
IFN TOPS20,<
ITNBER: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Error reading ^8:
TEXTI% JSYS failed: ^1>)
POP P,T3 ;Restore T3
POP P,T4 ;Restore T4
JRST RETST1 ;Return status 1
>;END IFN TOPS20
;RDNBUF - Read next buffer
;Inputs:
; T4/ points to file block
; RH(IT.NPD)/ number of pages read so far
; IT.FSZ/ File size
;Call:
; PUSHJ P,RDNBUF
; <return here if problems, message typed, or EOF (T1=2)>
; <return here if OK>
;Outputs:
; T1= status on POPJ return (1=problem, 2=EOF (no chars read))
; IT.CCT - character count
; IT.CBP - set to IT.SBP
; IT.NPD - updated
;Uses acs: T1, T2, T3
RDNBUF: DMOVE T1,IFNSTR+IT.SBP(T4)
DMOVEM T1,IFNSTR+IT.CBP(T4) ;setup current input byte ptr
MOVEI T1,^D36 ;Bits/word
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),11] ;bits/byte
IDIV T1,T2 ;Bytes/word
LSH T1,^D9 ;Bytes/page
MOVE T3,T1 ;Save this number
HRRZ T2,IFNSTR+IT.NPD(T4) ;# pages read so far
IMUL T1,T2 ;Bytes read so far
CAML T1,IFNSTR+IT.FSZ(T4) ;Greater or equal to total size of file?
JRST RDNBEF ;Yes, return "EOF"
;Setup IT.CCT
MOVE T2,IFNSTR+IT.FSZ(T4) ;Get total file size (bytes)
SUB T2,T1 ;Get # bytes left to read
CAMLE T2,IFNSTR+IT.TCT(T4) ;More than total # chars in buffer?
MOVE T2,IFNSTR+IT.TCT(T4) ;Yes, set byte count to this
MOVEM T2,IFNSTR+IT.CCT(T4) ;. .
;Read 'em in
;T2= # bytes to read in
;T3= # bytes/page
IFN TOPS20,<
IDIV T2,T3 ;Get total # pages to read in
SKIPE T3
ADDI T2,1 ;Round up
MOVE T3,T2 ;Save in T3
;Do PMAP% to read in pages
HRLZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
HRR T1,IFNSTR+IT.NPD(T4) ;# pages read so far = file page to read
SKIPN T2,IFNSTR+IT.SBP+1(T4) ;Get starting address of buffer
HRRZ T2,IFNSTR+IT.SBP(T4) ;(Non-extended byte ptr)
LSH T2,-^D9 ;Get page number in process
HRLI T2,.FHSLF ;Process handle in LH
TXO T3,PM%CNT+PM%RD ;Set bits
PMAP% ;Map the pages..
ERJMP RDBPER ;?Error
HRRZ T3,T3 ; Get # pages we read in
DPB T3,[POINT 6,IFNSTR+IT.FLG(T4),35] ;Set # pages "in use"
ADDM T3,IFNSTR+IT.NPD(T4) ;Update # pages read in
JRST CPOPJ1 ;Good return
RDBPER: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Error reading ^8:
PMAP% JSYS failed: ^1>)
MOVEI T1,1 ;Status 1
POPJ P, ;Return
>
IFE TOPS20,<
;T2= # bytes to read in
;T3= bytes/page
DMOVEM T2,RDNINF ;Save for a sec..
LSH T3,-^D9 ;Bytes/word
IDIV T2,T3 ;Get # words to read in
; (Should not have to round up)
MOVN T2,T2 ;Get -# words
HRLE T2,T2 ;Get -n,,-1
HRR T2,IFNSTR+IT.SBP(T4) ;Get -n,,addr
SUBI T2,1 ;Get IOWD N,addr
MOVEM T2,FLPDL ;Store 1st word in dump list
SETZM FLPDL+1 ;Clear 2nd word in dump list
MOVEI T1,FLPDL ;Point to FILOP. dump list
MOVEM T1,FLP1AG+1
HRRZ T1,IFNSTR+IT.FBA(T4) ;Get ptr to FILOP. list
LDB T1,[POINT 9,.FOFNC(T1),17] ;Get channel number
HRLZM T1,FLP1AG ;Store channel number
HRRI T1,.FOINP ;Perform "IN"
HRRM T1,FLP1AG ;Store function code
MOVE T1,[2,,FLP1AG] ;# args,,addr of arg list
FILOP. T1, ;Do FILOP.
JRST RDFLPE ;Error
;Update # pages read
DMOVE T2,RDNINF ;Get saved info
;T2= # bytes we read in
;T3= bytes/page
IDIV T2,T3 ;Total # pages
SKIPE T3 ;Round up
ADDI T2,1
DPB T2,[POINT 6,IFNSTR+IT.FLG(T4),35] ;# pages "in use"
ADDM T2,IFNSTR+IT.NPD(T4) ;Add to total read so far
JRST CPOPJ1 ;Good return
RDFLPE: MOVEM T1,FLPERR ;Store error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (ERF,<Error reading ^8:
FILOP. UUO error (^A) -- ^B>)
MOVEI T1,1 ;Set status to "bad error"
POPJ P, ;Error return
>;END IFE TOPS20
;Return "EOF"
RDNBEF: SETZM IFNSTR+IT.CCT(T4) ;Set char count to 0
MOVEI T1,2 ;EOF status
POPJ P, ;Single return
SUBTTL $ITOSB - Output string of bytes
;Call:
; 1/ IFN
; 2/ Number of bytes, or -1 to terminate at 0 byte
; 3/ byte ptr to bytes
; 4/ 2nd word of 2-word BP (if needed)
;Returns:
; 1/ status 0=ok, 1=problem
; 3 & 4/ preserved
$ITOSB: DMOVEM T3,USR34 ;Preserve ACs.
DMOVEM T3,STRNBP ;Save string byte-ptr
IMULI T1,IT.SIZ ;Get offset to file block info
MOVEM T1,ITOSFP ;Save ptr offset
JUMPL T2,ITOSB1 ;Jump if he wants to terminate at 0 byte
;Output a certain number of bytes
MOVEM T2,ITNBYT ;Save # of bytes
ITOSB0: SOSGE ITNBYT ;Bytes left to do?
JRST RT0R34 ;No, return status 0
MOVE T1,ITOSFP ;Call "output a char" routine
ILDB T2,STRNBP ; . .
PUSHJ P,ITOUB0 ; . .
JUMPE T1,ITOSB0 ;Loop if good status
JRST RT1R34 ;Else return status 1
;Output bytes until 0 byte
ITOSB1: ILDB T2,STRNBP ;Get another byte
JUMPE T2,RT0R34 ;Return status 0 when 0 byte gotten
MOVE T1,ITOSFP ;Call "output a char" routine
PUSHJ P,ITOUB0
JUMPE T1,ITOSB1 ;Loop if good status
JRST RT1R34 ;Else return status 1
SUBTTL $ITISB - Input string of bytes
;Call:
; 1/ IFN
; 2/ Number of bytes
; 3/ byte ptr to bytes
; 4/ 2nd word of byte pointer if needed
;Returns:
; 1/ status 0=ok, 1=problem, 2=EOF
; 2/ number of bytes requested that were not input
; 3 & 4/ preserved
$ITISB: DMOVEM T3,USR34 ;Save acs
DMOVEM T3,STRNBP ;Save string byte ptr
IMULI T1,IT.SIZ ;Get offset to file block
MOVEM T1,ITOSFP ;Save ptr offset
;Input (T2) bytes
MOVEM T2,ITNBYT ;Save # of bytes
ITISB0: SOSGE ITNBYT ;Bytes left to read?
JRST RT0R34 ;No, return status 0
MOVE T1,ITOSFP ;Call "Get a character" routine
PUSHJ P,ITINB0 ;. .
JUMPN T1,ITISB1 ;Non-zero status, go see why
IDPB T2,STRNBP ;Store the byte
JRST ITISB0 ;Loop for them all
;Non-zero status on input
ITISB1: MOVE T2,ITNBYT ;# bytes we didn't read
ADDI T2,1 ;. .
DMOVE T3,USR34 ;Restore acs 3,4
POPJ P, ;Return with same status
SUBTTL $ITPSF - Position file
;Call:
; 1/ IFN
; 2/ byte # to start at (0 = start of file)
;Returns:
; 1/ Status 0=ok, 1=problem, 2=file not that big
; 2/ smashed
$ITPSF: MOVEM T2,PSFBNM ;Save byte number
IMULI T1,IT.SIZ ;Point to block
MOVE T2,IFNSTR+IT.FLG(T1) ;Get flags
TXNN T2,IT%OPI ;Is file opened for input?
JRST ITPFE1 ;No, give error
TXNE T2,IT%FTY ;Is file a TTY: file?
JRST ITPFE2 ;Yes, complain
TXNE T2,IT%FNL ;Is file NUL:?
JRST [SKIPN PSFBNM ;Yes, do we want byte 0?
JRST RETST0 ;Yes, return status 0
JRST RETST2] ;No, return "Not within bounds"
;Position disk file opened for input
MOVE T2,IFNSTR+IT.FSZ(T1) ;Within bounds?
CAMGE T2,PSFBNM ; . .
JRST RETST2 ;No, return status 2
;Figure out which page contains this byte #.
; If it is in core, we don't have to do any physical I/O.
DMOVEM T3,USR34 ;Save acs 3, 4
MOVE T4,T1 ;T4= ptr to file block
;Get bytes/page
MOVEI T1,^D36 ;Bits/word
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),11] ;Get bits/byte
IDIV T1,T2 ;Bytes/word
MOVEM T1,PSFBPW ;Save bytes/word
LSH T1,^D9 ;Bytes/page
MOVEM T1,PSFBPP ;Save bytes/page
;What page number is this byte on?
MOVE T2,PSFBNM ;Get byte number
IDIV T2,T1 ;Get page number
MOVEM T2,PSFPNM ;Save page number
MOVEM T3,PSFBOF ;Save byte offset on page
;Is page in core?
HRRZ T1,IFNSTR+IT.NPD(T4) ;Get # pages read in so far
PUSH P,T1 ;Save this a sec.
LDB T3,[POINT 6,IFNSTR+IT.FLG(T4),35] ;Total # pages in core
SUB T1,T3 ;Get T1=First page # in core
SKIPGE T1
MOVEI T1,0 ;Min. is 0
POP P,T3 ;Get last page +1
SUBI T3,1 ;T3=Last page in core
CAML T2,T1 ;In core?
CAMLE T2,T3 ;. .
JRST ITPFNI ;No, have to do physical I/O
;Just position buffer
PUSHJ P,PSFBUF ;Position buffer pointers
JRST RT0R34 ;Return status 0, restore acs
;Must physically position file
ITPFNI: PUSHJ P,PSFPAG ;Position to proper page, read it in
JRST RT1R34 ;?Can't, return status 1
PUSHJ P,PSFBUF ;Position buffer pointers
JRST RT0R34 ;Return status 0, restore acs
;ITPSF errors
ITPFE1: DMOVEM T3,USR34 ;Save acs
DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (FNO,<Can't position ^8: File not opened for input>)
JRST RT1R34 ;Return status 1
ITPFE2: DMOVEM T3,USR34 ;Save acs
DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (FMD,<Can't position ^8: File must be a disk file>)
JRST RT1R34 ;Return status 1
;PSFBUF - Position buffer for $ITPSF
;Inputs:
; T4/ pointer to file block
; PSFPNM/ Page number (must be in core)
; PSFBOF/ Byte offset in page
; PSFBPP/ Bytes per page
; PSFBPW/ Bytes per word
;Call:
; PUSHJ P,PSFBUF
; <return here always>
;Outputs:
; IT.CCT
; IT.CBP
;Uses t1-t3
PSFBUF: HRRZ T1,IFNSTR+IT.NPD(T4) ;Get # pages read so far
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),35] ;# pages in buffer
SUB T1,T2 ;Get starting page number
SKIPGE T1 ;If less than 0,
MOVEI T1,0 ;Make starting page #0
MOVE T2,PSFPNM ;Get page number desired
SUB T2,T1 ;Get # pages to skip
LSH T2,^D9 ;# words to skip
MOVE T1,T2 ;Put in T1
MOVE T2,PSFBOF ;Get # bytes to skip in page
IDIV T2,PSFBPW ;# WORDS, t3 is remaining # bytes
ADD T1,T2 ;t1= total # words to skip
PUSH P,T3 ;Save # of extra bytes to skip
DMOVE T2,IFNSTR+IT.SBP(T4) ;Get starting byte ptr
IFN TOPS20,<
SKIPN T3 ;Extended byte ptr?
JRST PSFBF1 ;No
ADD T3,T1 ;Add words to address part
JRST PSFBF2
PSFBF1:
>;END IFN TOPS20
ADD T2,T1 ;Add words to address part
PSFBF2: SOSGE 0(P) ;Any more extra bytes?
JRST PSFBF3 ;No
IBP T2 ;Increment byte ptr
JRST PSFBF2 ;Loop
PSFBF3: DMOVEM T2,IFNSTR+IT.CBP(T4) ;Store new current byte ptr
POP P,(P) ;Fix stack
;PSFBUF - Cont'd
;Compute new IT.CCT = IT.TCT - byte offset in buffer
HRRZ T1,IFNSTR+IT.NPD(T4) ;Get # pages read so far
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),5] ;# pages allocated for buffer
SUB T1,T2 ;Get starting page number
SKIPGE T1 ;If less than 0,
MOVEI T1,0 ;Make starting page #0
MOVE T2,PSFPNM ;Get page number desired
SUB T2,T1 ;Get # pages to skip
IMUL T2,PSFBPP ;Get byte offset
ADD T2,PSFBOF ; . .
MOVE T1,IFNSTR+IT.TCT(T4) ;Compute new IT.CCT
SUB T1,T2 ; . .
MOVEM T1,IFNSTR+IT.CCT(T4) ;Store new one
POPJ P, ;Return
;ITPSF routines
;PSFPAG - Position file to desired page
;Inputs:
; T4/ pointer to file block
; PSFPNM/ page number
; PSFBPW/ bytes per word
; IT.FSZ/ file size
;Call:
; PUSHJ P,PSFPAG
; <return here if error, message typed>
; <return here if OK>
;Outputs:
; IT.NPD set to next page # to read
;Uses t1-t3
PSFPAG:
IFN TOPS20,<
PUSHJ P,UNMAPP ;Unmap pages there now
POPJ P, ;Error, single return
;Read in pages starting at desired one with PMAP
MOVE T2,IFNSTR+IT.FSZ(T4) ;Total file size (bytes)
IDIV T2,PSFBPP ;Total # pages in the file
SKIPE T3
ADDI T2,1 ;Round up
HRRZ T1,IFNSTR+IT.NPD(T4) ;How many more pages in file?
SUB T2,T1 ;# pages to PMAP (in order to get total #)
LDB T1,[POINT 6,IFNSTR+IT.FLG(T4),5] ;# pages in buffer
CAMGE T1,T2 ;Get smaller
MOVE T2,T1 ;In T2
;PMAP (T2) pages
MOVE T3,T2 ;# pages in T3
HRLZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
HRR T1,PSFPNM ;Starting at this page number
SKIPN T2,IFNSTR+IT.SBP+1(T4) ;Get starting address of buffer
HRRZ T2,IFNSTR+IT.SBP(T4) ;(Non-extended byte ptr)
LSH T2,-^D9 ;Get page number in process
HRLI T2,.FHSLF ;Process handle in LH
TXO T3,PM%CNT+PM%RD ;Set bits
PMAP% ;Map the pages..
ERJMP PSFPME ;?Can't
HRRZ T3,T3 ;Update IT.NPD
DPB T3,[POINT 6,IFNSTR+IT.FLG(T4),35] ;# pages "in use"
ADD T3,PSFPNM
HRRM T3,IFNSTR+IT.NPD(T4) ; . .
JRST CPOPJ1 ;Skip return
; Still in TOPS20
; Still in TOPS20
;PMAP% failed trying to read pages
PSFPME: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't position file because:
PMAP% JSYS failed: ^1>)
POPJ P, ;Error return
>;END IFN TOPS20
;PSFPAG routine--TOPS10
;Uses t1-t3
IFE TOPS20,<
MOVE T1,PSFPNM ;Get page number to position to
LSH T1,2 ;Get block number
ADDI T1,1 ; . .
MOVEM T1,FLP1AG+1 ;Store in FILOP. arg block
HRRZ T1,IFNSTR+IT.FBA(T4) ;Get ptr to FILOP. block
LDB T1,[POINT 9,.FOFNC(T1),17] ;Get channel number
HRLZM T1,FLP1AG ;Store channel number
MOVEI T1,.FOUSI ;Perform "USETI" call
HRRM T1,FLP1AG
MOVE T1,[2,,FLP1AG]
FILOP. T1, ;** Position file **
JRST USFLPE ;?Error
;Try to read to end of file, if end is too far, read exactly
; that number of pages.
MOVE T2,IFNSTR+IT.FSZ(T4) ;Total file size (bytes)
IDIV T2,PSFBPW ;T2:= # words in file (total)
LDB T1,[POINT 6,IFNSTR+IT.FLG(T4),5] ;# pages in buffer
LSH T1,^D9 ;# words in buffer
MOVE T3,PSFPNM ;Get page number
LSH T3,^D9 ;First word to get read in
SUB T2,T3 ;t2=# words left to read in
CAMLE T1,T2 ;If less than a buffer size
MOVE T1,T2 ;Only read in that many
;Read in (t1) words.
MOVN T1,T1 ;For IOWD ptr
HRLE T2,T1
HRR T2,IFNSTR+IT.SBP(T4) ;Get -n,,addr
SUBI T2,1 ;Make IOWD
MOVEM T2,FLPDL
SETZM FLPDL+1 ;Set end of dump list
MOVEI T1,FLPDL ;Store ptr in FILOP. block
MOVEM T1,FLP1AG+1
MOVEI T1,.FOINP ;Perform "IN"
HRRM T1,FLP1AG ;Store function code
MOVE T1,[2,,FLP1AG]
FILOP. T1, ;** Read in words **
JRST PSFFF2 ;?Can't read in words
;Update IT.NPD
HLRE T1,FLPDL ;Get -n words read in
MOVN T1,T1 ;Get n
IDIVI T1,1000 ;# pages
SKIPE T2
ADDI T1,1 ;Round up
DPB T1,[POINT 6,IFNSTR+IT.FLG(T4),35] ;# pages "in use"
ADD T1,PSFPNM ;+ # we started at
HRRM T1,IFNSTR+IT.NPD(T4) ;Save next page number to read
JRST CPOPJ1 ;Success return
;FILOP. failed trying to position file
USFLPE: MOVEM T1,FLPERR ;Store error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get filename to type
MOVEM T1,EFNPTR ;Store for error message printer
$FERR (EPF,<Error positioning ^8:
FILOP. UUO (USETI) failed, error (^A) -- ^B>)
POPJ P, ;Error return
PSFFF2: MOVEM T1,FLPERR ;Store error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get filename to type
MOVEM T1,EFNPTR ;Store for error mess printer
$FERR (EPF,<Error positioning ^8:
FILOP. UUO (IN) failed, error (^A) -- ^B>)
POPJ P, ;Error return
>;END IFE TOPS20
SUBTTL $ITCLS - Close file
;Call:
; 1/ IFN
; 2/ flags (IT%NRF, IT%NRJ)
;Returns:
; 1/ Status 0=ok, 1=problem
;Note:
; If the file is an external file, the JFN is released unless
; the flag IT%NRJ is set.
$ITCLS: IMULI T1,IT.SIZ ;Point to the file block
DMOVEM T1,USR12 ;Save acs
DMOVEM T3,USR34 ;Save acs
MOVE T4,T1 ;T4:= offset
MOVE T3,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T3,IT%OPI ;Closing a file open for input?
JRST ITCLS1 ;Yes
TXNN T3,IT%OPO ;No, how about open for output?
JRST CLSNTO ;? File was not open
;Close file open for output
;T3= file block flags, t2= user flags
ITCLS0: TXNE T3,IT%EXF ;External file?
JRST CLSOEX ;Yes, go close external file
;Close temp file that had been opened for output
TXNE T2,IT%NRF ;Don't retain file?
JRST ITCLO5 ;Yes, get rid of it
HLRZ T1,IFNSTR+IT.NPD(T4) ;Get # pages written
JUMPE T1,CLSTD1 ;None written, file was not open
PUSHJ P,WRTBUF ;Write out remainder of current buffer
JRST RT1R34 ;Error, return status 1
JRST ITCLS3 ;End-code, then exit
;Here if temp file was not physically open.
;Compute total file size
CLSTD1: MOVE T1,IFNSTR+IT.TCT(T4) ;Get total char count
SUB T1,IFNSTR+IT.CCT(T4) ;- Current count
ADDM T1,IFNSTR+IT.FSZ(T4) ;Add to file size word
;Here when everything is set but the flags.
; Set flags so file can be opened for input and read.
ITCLS3: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXZ T1,IT%OPO ;Clear flags that says file is open for output
TXO T1,IT%WRT ;Set flag: File has been written
MOVEM T1,IFNSTR+IT.FLG(T4) ;Store updated flags
JRST RT0R34 ;return status 0
;Close temp file opened for output and get rid of it.
ITCLO5: PUSHJ P,RDTFLO ;Call system-specific routine
JRST RT1R34 ;?Failed, return status 1
PUSHJ P,CLSRMM ;Release memory
JUMPN T1,RT1R34 ;If error, return status 1
SETZM IFNSTR+IT.FLG(T4) ;Clear all flags
JRST RT0R34 ;Return status 0
;Here to close external file open for output
;T2 contains users input flags
CLSOEX: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FTY ;Is file a tty: file?
JRST CLSOXT ;Yes
TXNE T1,IT%FNL ;NUL:?
JRST CLSOXY ;Yes
;Close external disk file opened for output
TXNE T2,IT%NRF ;Don't retain file?
JRST CLSOXK ;Yes
PUSHJ P,WRTBUF ;Write out current buffer
JRST RT1R34 ;Error, return status 1
PUSHJ P,PYCLSO ;Physically close file
JRST RT1R34 ;Error, return status 1
CLSOXX: PUSHJ P,CLSRMM ;Return memory used to memory manager
JUMPN T1,RT1R34 ;If problems, return status 1
CLSOXY: SETZM IFNSTR+IT.FLG(T4) ;Clear all flags
; (includes: File is open for output)
JRST RT0R34 ;Return status 0
;Close external disk file, and get rid of it
CLSOXK: PUSHJ P,RDTFLO ;Call system-specific routine
JRST RT1R34 ;?Can't do it
JRST CLSOXX ;Go rejoin code above
;Close external TTY: file opened for output
CLSOXT: PUSHJ P,PYCLSO ;Physically close file
JRST RT1R34 ;Errors, return status 1
SETZM IFNSTR+IT.FLG(T4) ;Clear all flags
JRST RT0R34 ;Return status 0
;$ITCLS - continued
;Close file open for input
;T3= file block flags, t2= user flags
ITCLS1: TXNE T3,IT%EXF ;Is file an External file?
JRST CLSEXI ;Yes, go close external file for input
;Close temp disk file opened for input
HLRZ T1,IFNSTR+IT.NPD(T4) ;Were any pages written?
JUMPE T1,CLSTIN ;No, no physical file
IFN TOPS20,<
PUSHJ P,UNMAPP ;Unmap any pages in core
JRST RT1R34 ;?errors, return status 1
>;END IFN TOPS20
PUSHJ P,RDTMOI ;Rid ourselves of the file
JRST RT1R34 ;Errors, return status 1
CLSTIN: PUSHJ P,CLSRMM ;Return memory used
JUMPN T1,RT1R34 ;?Error
SETZM IFNSTR+IT.FLG(T4) ;Clear all flags
JRST RT0R34 ;Return status 0
;Close external file open for input
CLSEXI: TXNE T3,IT%FTY ;Is file a TTY: file?
JRST CLSETI ;Yes
TXNE T3,IT%FNL ;NUL:?
JRST CLSETN ;Yes
;Close external disk file open for input
IFN TOPS20,<
PUSHJ P,UNMAPP ;Unmapped pages still mapped
JRST RT1R34 ;Errors, return status 1
>;END IFN TOPS20
PUSHJ P,PYCLSI ;Physically close file
JRST RT1R34 ;Errors, return status 1
PUSHJ P,CLSRMM ;Return memory used
JUMPN T1,RT1R34 ;Error, return status 1
SETZM IFNSTR+IT.FLG(T4) ;Clear all flags
JRST RT0R34 ;return status 0
;Close external TTY: file open for input
CLSETI: PUSHJ P,PYCLSI ;Physically close file
JRST RT1R34 ;Errors, return status 1
SETZM ITTFOP ;Clear "TTY file open for input" flag
CLSETN: SETZM IFNSTR+IT.FLG(T4) ;Clear all flags
JRST RT0R34 ;Return status 0
;Routine to physically close a file open for output
; This routine is called to close the following types of files:
;External TTY:
;External DSK:
; This routine only handles files which are not aborted.
;i.e. they will exist after the "CLOSE" is done.
;Inputs:
; T4/ pointer to file block
; IT.SIZ - size of file in bytes
; USR12+1/ user input flags (for CLOSE)
;Call:
; PUSHJ P,PYCLSO
; <return here if errors, message typed>
; <return here if OK>
;Uses t1,t2,t3
IFN TOPS20,<
PYCLSO: MOVE T1,IFNSTR+IT.FLG(T4) ;GET FLAGS
TXNE T1,IT%FNL ;NUL:?
JRST PYCLS9 ;Go release JFN (maybe)
TXNE T1,IT%FTY ;A TTY: file?
JRST PYCLS1 ;Yes
;Set end pointer on file
MOVE T2,IFNSTR+IT.FSZ(T4) ;Get byte count to set
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
SFPTR% ;Set the end pointer
ERJMP PYCLSF ;?Failed
HRLI T1,.FBSIZ ;Set EOF ptr in file (CLOSF does not when
MOVE T3,T2 ;no sequential output has been done)
SETO T2,
CHFDB%
ERJMP PYCLCF ;?Failed
;Set byte size of file
; (CLOSF does not set it when no seq output has been done)
HRLI T1,.FBBYV
SETZ T3,
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),11] ;Get byte size to set
DPB T2,[POINTR T3,FB%BSZ] ;Set in TOPS20 word
HRLZI T2,<77B11>B53
CHFDB% ;Change the FDB word
ERJMP PYCLCF ;?Failed
;Fall thru if disk file
;Come here directly if TTY: file
;Actually close the file
PYCLS1: HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
MOVE T3,USR12+1 ;Get user input flags
TXNE T3,IT%NRJ ;Don't release JFN?
TXO T1,CO%NRJ ;Yes, set flag
;Here when AC1 is set for CLOSF%
CLZFXX: PUSH P,T1 ;Save AC1
CLOSF% ;. .
ERJMP PYCLZF ;?failed
POP P,T1 ;Fix stack
JRST CPOPJ1 ;Give good return
;Here for NUL:
PYCLS9: MOVE T3,USR12+1 ;Get user input flags
TXNE T3,IT%NRJ ;Don't release JFN?
JRST CPOPJ1 ;Right, just return now
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
RLJFN% ;Release it
ERJMP PYCRJF ;?Can't release JFN
JRST CPOPJ1 ;Did it, skip return
;Some TOPS20 errors
;SFPTR failed
PYCLSF: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't close ^8 because:
SFPTR% JSYS failed: ^1>)
POPJ P,
;CHFDB failed
PYCLCF: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't close ^8 because:
CHFDB% JSYS failed: ^1>)
POPJ P,
;CLOSF failed
PYCLZF: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
CAIN T1,IOX11 ;Quota exceeded?
JRST PYCZFQ ;Yes
POP P,T1 ;Fix stack
$FERR (JSE,<Can't close ^8 because:
CLOSF% JSYS failed: ^1>)
POPJ P,
;CLOSF failed because quota was exceeded
PYCZFQ: $FERR (QEX,<Can't close ^8: ^1
(Type "CONTINUE" when the problem has been fixed)>)
HALTF%
POP P,T1 ;Get T1 back for CLOSF%
JRST CLZFXX ;Go try CLOSF again
;RLJFN failed
PYCRJF: $FERR (JSE,<Can't close ^8 because:
RLJFN% JSYS failed: ^1>)
POPJ P,
>;END IFN TOPS20
IFE TOPS20,<
;Inputs:
; T4/ pointer to file block
; IT.SIZ - size of file in bytes
; USR12+1/ user input flags (for CLOSE)
;Call:
; PUSHJ P,PYCLSO
; <return here if errors, message typed>
; <return here if OK>
;Uses t1,t2,t3
PYCLSO: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FNL ;Null?
JRST CPOPJ1 ;Yes, just return ok
MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. address
MOVEI T2,.FOCLS ;Perform CLOSE
HRRM T2,.FOFNC(T1) ; Stick function in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ; ** DO CLOSE **
JRST PYCFE1 ;Error
MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. address again
MOVEI T2,.FOREL ;Perform RELEASE
HRRM T2,.FOFNC(T1) ; Stick function in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ; ** DO RELEASE **
JRST PYCFE2 ;Error
JRST CPOPJ1 ;Return OK
;CLOSE FILOP. failed
PYCFE1: MOVEM T1,FLPERR ;Save error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (UOE,<Can't close ^8 because:
CLOSE function of FILOP. UUO failed: (^A) -- ^B>)
POPJ P, ;Error return
PYCFE2: MOVEM T1,FLPERR ;Save error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (UOE,<Can't close ^8 because:
RELEAS function of FILOP. UUO failed: (^A)--^B>)
POPJ P, ;Error return
>;END IFE TOPS20
;Routine to physically close file open for input
;Inputs:
; T4/ pointer to file block
; USR12+1 / Users input flags
;Call:
; PUSHJ P,PYCLSI
; <return here if errors, message typed>
; <return here if OK>
;Uses t1,t2,t3
IFN TOPS20,<
PYCLSI: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FNL ;Is this the NUL: file?
JRST PYCLI1 ;Yes
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
MOVE T3,USR12+1 ;Get user's flags
TXNE T3,IT%NRJ ;Don't release JFN
TXO T1,CO%NRJ ;Yes
CLOSF% ;** CLOSE FILE **
ERJMP PYCZYE ;?Can't, complain
JRST CPOPJ1 ;Ok return
;Here for NUL:
PYCLI1: MOVE T3,USR12+1 ;Get user's flags
TXNE T3,IT%NRJ ;Don't release JFN?
JRST CPOPJ1 ;Right, just return
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
RLJFN% ;Release JFN
ERJMP PYCRJE ;Error
JRST CPOPJ1 ;Ok return
PYCZYE: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't close ^8 because:
CLOSF% JSYS failed: ^1>)
POPJ P,
PYCRJE: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't close ^8 because:
RLJFN% JSYS failed: ^1>)
POPJ P,
>;END IFN TOPS20
IFE TOPS20,<
;Inputs:
; T4/ pointer to file block
; USR12+1 / Users input flags
;Call:
; PUSHJ P,PYCLSI
; <return here if errors, message typed>
; <return here if OK>
;Uses t1,t2,t3
PYCLSI: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%FNL ;Is this the NUL: file?
JRST CPOPJ1 ;Yes, just return ok
MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. address
MOVEI T2,.FOCLS ;Perform CLOSE
HRRM T2,.FOFNC(T1) ; Stick function in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ; ** DO CLOSE **
JRST PYCFE1 ;Error
MOVE T3,USR12+1 ;Get user's flags
TXNE T3,IT%NRJ ;Don't release channel?
JRST CPOPJ1 ;Right, just return
MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. address again
MOVEI T2,.FOREL ;Perform RELEASE
HRRM T2,.FOFNC(T1) ; Stick function in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ; ** DO RELEASE **
JRST PYCFE2 ;Error
JRST CPOPJ1 ;Return OK
>;END IFE TOPS20
;Routine to return memory to the memory manager when file is closed.
;;Call:
;t4/ pointer to file block
;Return:
; t1/ status (0=ok, 1=problem, message has been typed out)
;Uses t1 thru t4
CLSRMM: SETZ T1, ;No flags
LDB T2,[POINT 6,IFNSTR+IT.FLG(T4),5] ;# pages in buffer
IFN TOPS20,<
SKIPN T3,IFNSTR+IT.SBP+1(T4) ;Possibly address in 2nd word of B.P.
>
HRRZ T3,IFNSTR+IT.SBP(T4) ;Address from RH of B.P. word
PUSHJ P,RETRN ;Return memory
POPJ P, ;Return
CLSNTO: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (CCF,<Can't close ^8: File was not open>)
JRST RT1R34 ;Return status 1, restore acs
;Routine to get rid of a file open for output
;Inputs:
; T4/ ptr to file block
; USR12+1/ User's input flags (IT%NRJ)
;Call:
; For temp file or external file,
; PUSHJ P,RDTFLO
; <return here if errors, message typed>
; <return here if OK>
RDTFLO: MOVE T1,IFNSTR+IT.FLG(T4) ;Get flags
TXNE T1,IT%EXF ;Is file an external file?
JRST RDTFLE ;Yes
;Temp file, maybe it was not actually physically opened at all.
HLRZ T1,IFNSTR+IT.NPD(T4) ;Get # pages written
JUMPE T1,CPOPJ1 ;None written, file was not physically open
;Temp file was actually opened for output
IFN TOPS20,<
;On TOPS20 we have to do a CLOSF% with the ABORT flag,
; then a DELF% to actually get the file expunged. (CLOSF%
; with abort flag set does not actually expunge the file,
; so we are left with deleted pages on disk).
RDTFL1: HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
TXO T1,CZ%ABT!CO%NRJ ;Abort file- will close and expunge
CLOSF%
ERJMP RDTCFF ;?Failed
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN again
TXO T1,DF%EXP ;Expunge contents of file
DELF%
ERJMP RDTDFF ;?Failed
JRST CPOPJ1 ;Success, return
RDTCFF: $FERR (JSE,<Can't close ^8 because:
CLOSF% JSYS failed: ^1>)
POPJ P, ;Failure return
RDTDFF: $FERR (JSE,<Can't close ^8 because:
DELF% JSYS failed: ^1>)
POPJ P, ;Failure return
>;END IFN TOPS20
IFE TOPS20,<
;Temp file was actually opened.
; Close it then delete it
JRST RDTFLE ;Same as TOPS10 "get rid of external file"
>;END IFE TOPS20
;External file was opened for output
RDTFLE:
IFN TOPS20,<
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
TXO T1,CZ%ABT ;Abort file- will close and expunge
MOVE T2,USR12+1 ;Get user's input flags
TXNE T2,IT%NRJ ; Does he want to retain JFN?
TXO T1,CO%NRJ ;Yes, keep it even tho file is aborted
CLOSF% ;** Close the file **
ERJMP RDTCFF ;?Failed
JRST CPOPJ1 ;Success
>;END IFN TOPS20
IFE TOPS20,<
;Get rid of external file opened for output
; (or temp disk file opened for output).
;Close it and delete it.
MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. address
MOVEI T2,.FOCLS ;Perform CLOSE
HRRM T2,.FOFNC(T1) ; Stick function in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ;Do close
JRST RDTCCF ;?Can't close
;Delete.
MOVE T1,IFNSTR+IT.FBA(T4) ;Reget FILOP. address
MOVEI T2,.FODLT ;Perform "DELETE"
HRRM T2,.FOFNC(T1) ;Put function in FILOP. block
HRLI T1,.FOPAT+1 ;Length
FILOP. T1, ;** Do DELETE **
JRST RDTCDF ;?Can't delete
;Release channel unless user said not to.
MOVE T1,IFNSTR+IT.FLG(T4) ;Get file flags
TXNN T1,IT%EXF ;Is file an external file?
JRST RDTDRC ;No, definitely release the channel
; (No matter what the input flags say.)
MOVE T1,USR12+1 ;Get user's input flags
TXNE T1,IT%NRJ ;Don't release channel?
JRST CPOPJ1 ;Right, just return "success"
;Release the channel
RDTDRC: MOVE T1,IFNSTR+IT.FBA(T4) ;FILOP. address
LDB T2,[POINT 9,.FOFNC(T1),17] ;Get channel number
HRLZ T2,T2 ;Chann #,,0
HRRI T2,.FOREL ;Chann,, function code
MOVE T1,[1,,T2] ;1-word arg block in T2
FILOP. T1, ;** RELEASE channel **
JRST RDTCRC ;?Can't release
JRST CPOPJ1 ;Success
;Can't CLOSE
RDTCCF: MOVEM T1,FLPERR
MOVE T1,IFNSTR+IT.GNP(T4)
MOVEM T1,EFNPTR
$FERR (UOE,<Can't get rid of ^8:
FILOP. CLOSE UUO failed: (^A) -- ^B>)
POPJ P, ;Error return
;Can't delete
RDTCDF: MOVEM T1,FLPERR
MOVE T1,IFNSTR+IT.GNP(T4)
MOVEM T1,EFNPTR
$FERR (UOE,<Can't get rid of ^8:
FILOP. DELETE UUO failed: (^A) -- ^B>)
POPJ P, ;Error return
;Can't release
RDTCRC: MOVEM T1,FLPERR
MOVE T1,IFNSTR+IT.GNP(T4)
MOVEM T1,EFNPTR
$FERR (UOE,<Can't get rid of ^8:
FILOP. RELEASE UUO failed: (^A) -- ^B>)
POPJ P, ;Error return
>;END IFE TOPS20
;TOPS20 routine to unmap pages of input file still mapped
;Called before a CLOSF is done for a disk file
; either external disk file or temp file that had been written
;Input:
; T4/ pointer to file block
;Call:
; PUSHJ P,UNMAPP
; <here if errors>
; <here if OK>
;Uses t1-t3
IFN TOPS20,<
UNMAPP: SKIPN T2,IFNSTR+IT.SBP+1(T4) ;Get starting page #
HRRZ T2,IFNSTR+IT.SBP(T4) ;In process
LSH T2,-^D9 ;In RH(t2)
HRLI T2,.FHSLF ;My process
LDB T3,[POINT 6,IFNSTR+IT.FLG(T4),5] ;Get # pages used
TXO T3,PM%CNT ;Set repeat count
SETO T1, ;Tell PMAP we are unmapping pages
PMAP% ;Do it
ERJMP UNMPE1 ;?ERROR
JRST CPOPJ1 ;Give good return
UNMPE1: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<PMAP% JSYS failed: ^1,
couldn't unmap pages of ^8>)
POPJ P, ;Give bad return
>;END IFN TOPS20
;Routine to get of temp disk file opened for input
; When it got written to disk
;Inputs:
; T4/ ptr to file block
;Call:
; PUSHJ P,RDTMOI
; <return here if errors, message typed>
; <return here if OK>
;USES T1-T3
;The file is still open when this routine is called.
IFN TOPS20,<
RDTMOI: HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
TXO T1,CO%NRJ ;Don't release JFN
CLOSF% ;CLOSE the file
ERJMP RDTME1 ;?Error
HRRZ T1,IFNSTR+IT.JFN(T4) ;Get JFN
TXO T1,DF%EXP ;Expunge contents of file
DELF% ;This also releases the JFN
ERJMP RDTME2 ;?Error
AOS (P) ;Skip return
POPJ P, ;. .
RDTME1: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't close ^8 because:
CLOSF% JSYS failed: ^1>)
POPJ P, ;Error return
RDTME2: DMOVE T2,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T2,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't close ^8 because:
DELF% JSYS failed: ^1>)
POPJ P, ;Error return
>;END IFN TOPS20
IFE TOPS20,<
;Repeating for TOPS-10:
;Routine to get of temp disk file opened for input
; When it got written to disk
;Inputs:
; T4/ ptr to file block
;Call:
; PUSHJ P,RDTMOI
; <return here if errors, message typed>
; <return here if OK>
;USES T1-T3
;The file is still open when this routine is called.
RDTMOI: MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. address
MOVEI T2,.FOCLS ;Perform "Close"
HRRM T2,.FOFNC(T1) ;Put function in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ; ** DO CLOSE **
JRST RDTME1 ;?Can't
;Delete the file
MOVE T1,IFNSTR+IT.FBA(T4) ;Re-get FILOP. address
MOVEI T2,.FODLT ;Perform "DELETE"
HRRM T2,.FOFNC(T1) ;Put function in FILOP. block
HRLI T1,.FOPAT+1 ;Length
FILOP. T1, ; ** Do DELETE **
JRST RDTME2 ;?Can't
;Release channel
MOVE T1,IFNSTR+IT.FBA(T4) ;Get ptr to FILOP. block
LDB T2,[POINT 9,.FOFNC(T1),17] ;Get channel number
HRLZ T2,T2 ;Chann #,,0
HRRI T2,.FOREL ;Chann #,,function code
MOVE T1,[1,,T2] ;1-word arg block in T2
FILOP. T1, ;** RELEASE channel **
JRST RDTME3 ;?Can't
JRST CPOPJ1 ;OK, return
;CLOSE failed
RDTME1: MOVEM T1,FLPERR ;Save FILOP. error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get ptr to generic filename
MOVEM T1,EFNPTR ;Store for error message printer
$FERR (UOE,<Can't get rid of ^8:
FILOP. CLOSE UUO failed (^A) -- ^B>)
POPJ P, ;Error return
;DELETE failed
RDTME2: MOVEM T1,FLPERR
MOVE T1,IFNSTR+IT.GNP(T4)
MOVEM T1,EFNPTR
$FERR (UOE,<Can't get rid of ^8:
FILOP. DELETE UUO failed (^A) -- ^B>)
POPJ P,
;RELEASE failed
RDTME3: MOVEM T1,FLPERR
MOVE T1,IFNSTR+IT.GNP(T4)
MOVEM T1,EFNPTR
$FERR (UOE,<Can't get rid of ^8:
FILOP. RELEASE UUO failed (^A) -- ^B>)
POPJ P,
>;END IFE TOPS20
SUBTTL $ITRNF - Rename file
; This routine should be called after $ITCLS is called for a file,
;$ITCLS must have been called with the IT%NRJ bit set.
;Inputs:
; T1/ IFN
; T2/ Flags [+ JFN (T20 only)]
;Call:
; PUSHJ P,$ITRNF
; <return here always>
;Outputs:
; T1/ status (0=OK, 1=error)
;Uses T1,T2
$ITRNF: IMULI T1,IT.SIZ ;Get ptr to entry
PUSH P,T4 ;Save T4
PUSH P,T2 ;Save T2
MOVE T4,T1 ;Copy ptr
IFN TOPS20,<
MOVE T1,IFNSTR+IT.JFN(T4) ;Get JFN of old file
HRRZ T2,T2 ;Just save JFN
RNAMF% ;Rename file
ERJMP ITRNFE ;?Error
POP P,T2 ;Restore flags
TXNN T2,IT%RLS ;Release file?
JRST ITRNFR ;No, return
MOVE T1,T2 ;Get JFN to release
RLJFN% ;Release it
ERJMP ITRNRE ;?Error
ITRNFR: POP P,T4 ;Restore T4
JRST RETST0 ;Return status 0
;RNANF% failed
ITRNFE: DMOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T1,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't RENAME ^8, reason:
RNAMF% JSYS failed: ^1>)
POP P,T2 ;Restore T2
POP P,T4 ;Restore T4
JRST RETST1 ;Return status 1
;RLJFN failed
ITRNRE: DMOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
DMOVEM T1,EFNPTR ;And store for error message printer
$FERR (JSE,<Can't RENAME ^8, reason:
RLJFN% JSYS failed: ^1>)
POP P,T4 ;Restore T4
JRST RETST1 ;return status 1
>;END IFN TOPS20
IFE TOPS20,<
;T2, T4 on stack
SETZM RTRYNM ;Didn't try RENAME FILOP. yet
ITRNF0: MOVE T1,IFNSTR+IT.FBA(T4) ;Get FILOP. address
;Save away RENAME block stuff incase the FILOP. fails
MOVEI T2,4 ;Assume short RENAME block
MOVEM T2,SVRNLN ;Save length away
SETZM EXRNBL ;Clear flag "Extended RENAME block"
HLRZ T2,.FOLEB(T1) ;Get addr of rename block
MOVE T2,0(T2) ;Get first word
JUMPE T2,ITRNSB ;Short block if zero
TLNE T2,-1 ;Stuff in LH?
JRST ITRNSB ;Yes, short block
ANDI T2,77777 ;Just save size
CAILE T2,.MXRBC ;Too high?
JRST ITFMXE ;Yes, complain
SETOM EXRNBL ;Set "Extended RENAME block"
MOVEM T2,SVRNLN ;Save length of block
;Copy extended RENAME block
HLLZ T2,.FOLEB(T1) ;Get addr of RENAME block
HRRI T2,SVRNBL
PUSH P,T3 ;Save T3 a sec.
MOVE T3,SVRNLN ;Get length
BLT T2,SVRNBL-1(T3) ;Copy whole block
POP P,T3 ;Restore T3
SKIPN T2,SVRNBL+.RBPPN ;Any PPN or PATH?
JRST ITRND1 ;No, done copying
JRST CKITRP ;Check path
;Copy short RENAME block
ITRNSB: HLLZ T2,.FOLEB(T1) ;Get addr of RENAME block
HRRI T2,SVRNBL ;Save here
BLT T2,SVRNBL+3
SKIPN T2,SVRNBL+3 ;Any PPN or PATH?
JRST ITRNF1 ;No
;Here with T2= PPN or PATH pointer from RENAME block.
;If PATH pointer, copy the PATH block also.
CKITRP: TLNE T2,-1 ;PPN?
JRST ITRNF1 ;Yes, no PATH block to copy
HRLZ T2,T2 ;From
HRRI T2,SVRNPB ;To
BLT T2,SVRNPB+.PTMAX ; Copy whole block
;Here with T1 pointing to users FILOP. block
ITRNF1: MOVEI T2,.FORNM ;RENAME function
HRRM T2,.FOFNC(T1) ;Store in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ;** RENAME file **
JRST ITRNFE ;FILOP. failed to rename file
POP P,T2 ;Restore user's flags
TXNN T2,IT%RLS ;Release file?
JRST ITRNFR ;No, return
MOVE T1,IFNSTR+IT.FBA(T4) ;Reget FILOP. address
MOVEI T2,.FOREL ;RELEASE function
HRRM T2,.FOFNC(T1) ;Store in FILOP. block
HRLI T1,.FOPAT+1 ;Length of arg block
FILOP. T1, ;* RELEASE the file *
JRST ITRNRE ;?Failed
ITRNFR: POP P,T4 ;Restore T4
JRST RETST0 ;Return status 0
;RENAME FILOP. failed
ITRNFE: CAIN T1,ERAEF% ;File already exists?
JRST ITRNFD ;Yes, delete old one first.
MOVEM T1,FLPERR ;Save FILOP. error for message
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (CRF,<Can't RENAME ^8:
FILOP. UUO failed (^A) -- ^B>)
POP P,T2 ;Restore acs
POP P,T4
JRST RETST1 ;Return status 1
;Specified file already exists. Delete the old copy and
; go back to try again.
ITRNFD: SKIPE RTRYNM ;Have we been here before?
JRST ITRDE1 ;Yes, bomb out
SETOM RTRYNM ;Set to -1
;The FILOP. that failed has now totally screwed up the RENAME block,
; so first we'll copy it all back.
MOVE T1,IFNSTR+IT.FBA(T4) ;Get addr of FILOP. block
SKIPN EXRNBL ;Extended RENAME block?
JRST ITRND0 ;No
;Copy extended RENAME block back
HLRZ T2,.FOLEB(T1) ;T2= addr of RENAME block
PUSH P,T3 ;Save T3 a sec.
MOVE T3,SVRNLN ;Get saved length of RENAME block
ADDI T3,-1(T2) ;Get last loc to BLT to
HRLI T2,SVRNBL ;Copy from here
BLT T2,(T3) ;Copy whole block back
POP P,T3 ;Restore T3
SKIPN T2,SVRNBL+.RBPPN ;PPN or PATH pointer?
JRST ITRND1 ;No
JRST CBPPNP ;Copy back PATH if necessary
;Copy short RENAME block back
ITRND0: HLRZ T2,.FOLEB(T1) ;Write to RENAME block
MOVEI T1,3(T2) ;Last location to BLT to
HRLI T2,SVRNBL ; From saved RENAME block
BLT T2,(T1) ;Copy it
SKIPN T2,SVRNBL+3 ;PPN or PATH pointer?
JRST ITRND1 ;No
;Here with T2= PPN or ptr to PATH block from original RENAME block
CBPPNP: TLNE T2,-1 ;PPN?
JRST ITRND1 ;Yes, don't copy path block too
MOVEI T1,.PTMAX(T2) ;Last location to BLT to
HRLI T2,SVRNPB ;From saved path block
BLT T2,(T1) ;Copy it
ITRND1: MOVE T1,IFNSTR+IT.FBA(T4) ;reget FILOP. address
MOVE T2,.FOLEB(T1) ;Get RENAME,,LOOKUP block ptrs
MOVEM T2,SVLKRP ;Save 'em
HLRM T2,.FOLEB(T1) ;Make LOOKUP ptr be RENAME ptr
MOVEI T2,.FODLT ;Delete function
HRRM T2,.FOFNC(T1) ;Store in FILOP. block
HRLI T1,.FOPAT+1 ;Length of block
FILOP. T1, ;** DELETE old file **
JRST ITFDE2 ;?Failed
REPEAT 0,<
;Again, restore saved RENAME and PATH block
MOVE T1,IFNSTR+IT.FBA(T4) ;Get addr of FILOP. block
MOVE T2,SVLKRP ;Restore ptrs
MOVEM T2,.FOLEB(T1)
HLRZ T2,T2 ;Write to RENAME block
MOVEI T1,3(T2) ;Last location to BLT to
HRLI T2,SVRNBL ; From saved RENAME block
BLT T2,(T1) ;Copy it
SKIPN T2,SVRNBL+3 ;PPN or PATH pointer?
JRST ITRND2 ;No
TLNE T2,-1 ;PPN?
JRST ITRND2 ;Yes, don't copy path block too
MOVEI T1,.PTMAX(T2) ;Last location to BLT to
HRLI T2,SVRNPB ;From saved path block
BLT T2,(T1) ;Copy it
>;END REPEAT 0
ITRND2: MOVE T1,IFNSTR+IT.FBA(T4) ;Reget t1= addr of FILOP. block
JRST ITRNF1 ;Go back and try again
ITFMXE: MOVE T1,IFNSTR+IT.GNP(T4) ;Get filename to print
MOVEM T1,EFNPTR
$FERR (MXE,<Can't RENAME ^8:
Size of EXTENDED ENTER block supplied is too large>)
POP P,T2
POP P,T4
JRST RETST1 ;Return status 1
ITRDE1: MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (CRF,<Can't RENAME ^8:
FILOP. UUO seems to be broken at ITRNFD in IOTMP module>)
POP P,T2
POP P,T4
JRST RETST1
ITFDE2: MOVEM T1,FLPERR ;Store error code for message print
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (CDF,<Can't RENAME ^8:
FILOP. UUO failed trying to delete old file:
(^A) -- ^B>)
POP P,T2
POP P,T4
JRST RETST1
;RELEASE FILOP. failed
ITRNRE: MOVEM T1,FLPERR ;Save FILOP. error code
MOVE T1,IFNSTR+IT.GNP(T4) ;Get byte ptr to generic filename
MOVEM T1,EFNPTR ;And store for error message printer
$FERR (CRF,<Can't RELEASE ^8:
FILOP. UUO failed (^A) -- ^B>)
POP P,T4 ;Restore T4
JRST RETST1 ;Return status 1
>;END IFE TOPS20
IFN TOPS20,<
;ROUTINE TO TYPE OUT LAST ERROR IN THIS FORK
;CALL:
; PUSHJ P,LSTLEF
; <Return here always>
;No acs destroyed
LSTLEF: PUSH P,T1 ;SAVE ACS
PUSH P,T2
PUSH P,T3
MOVEI T1,.PRIOU ;OUTPUT TO TERMINAL
HRLOI T2,.FHSLF ;LAST ERROR IN THIS FORK
SETZ T3, ;ALL OF THE TEXT
ERSTR%
JFCL
JFCL
POP P,T3 ;restore acs
POP P,T2
POP P,T1
POPJ P, ;Return
>;END IFN TOPS20
SUBTTL $ITRMU - Return memory usage
;Call:
; 1/ IFN (-1 for all files plus overhead)
;Returns:
; 1/ number of pages used (TOTAL)
; 2/ number of pages that can be released
$ITRMU:
POPJ P, ;RETURN
SUBTTL $ITCBM - Cut back on memory
;Call:
; 1/ IFN (-1 to get rid of memory everywhere possible)
; 2/ number of pages to release
;Returns:
; 1/ Status 0= ok, 1= problem
$ITCBM:
POPJ P, ;RETURN
SUBTTL $ITDEB - Enter debugger
;Call:
; -no acs used-
;Returns:
; -no acs used-
$ITDEB:
POPJ P, ;RETURN
SUBTTL Error message printer
;Called by $FERR and $WERR macros
;T1/ (lh) = 3-letter sixbit abbrev for error message
;t1/ (rh) = local address of error message
; The error message can contain the following symbols:
;^^ - Insert one up-arrow
;^1 - Insert last JSYS error message
;^2 - Insert ASCIZ string whose address is in ASCS1
;^3 - Insert ASCIZ string whose address is in ASCS2
;^4 - Insert octal number from ENUMBR
;^5 - Insert decimal number from ENUMBR
;^6 - Insert SIXBIT word from SIXBW1
;^7 - If column is greater than 72, skip to a new line
;^8 - Insert generic file name string (BP in EFNPTR)
;^9 - Stop message here and don't append a CRLF
;^A - (TOPS-10) Type octal number from FLPERR
;^B - (TOPS-10) Type ASCII FILOP. error code text using FLPERR
;Only AC1 is used
ITWERR: HLLZM T1,LOCABR ;Save abbrev for error
HRLI T1,(POINT 7,) ;Get byte ptr to message
MOVEM T1,LOCMSP ;Save message ptr
MOVEI T1,"%" ;Warnings start with "%"
JRST ITER1 ;Go join common code
ITFERR: HLLZM T1,LOCABR ;Save abbrev for error
HRLI T1,(POINT 7,) ;Get byte ptr to message
MOVEM T1,LOCMSP ;Save message ptr
MOVEI T1,"?" ;Fatal error starts with "?"
ITER1: PUSH P,T2 ;Save ac T2
PUSH P,T3 ;Save T3
MOVE T2,[POINT 7,ERTXTB] ;Byte ptr to error text buffer
MOVEM T2,ERTXTP ;Save it
MOVEI T2,1 ;Start at column 1
MOVEM T2,NCOLM ;. .
PUSHJ P,ITECHR ;Store first character of message
MOVE T1,PRGABR ;3-letter program abbrev
PUSHJ P,ITERSB ;Store sixbit word
MOVE T1,LOCABR ;3-letter abbrev for specific message
PUSHJ P,ITERSB ;Store sixbit word
MOVEI T1," " ;Space
PUSHJ P,ITECHR ;Store it
;Put characters in the output buffer
ITER2: ILDB T1,LOCMSP ;Get next character of message
JUMPE T1,ITEEND ;Null means end of string
CAIN T1,"^" ;Up-arrow could be a "MACRO"
JRST ITER3
ITER2A: CAIN T1,.CHCRT ;Carriage-return
SETZM NCOLM ; sends column back to 0
PUSHJ P,ITECHR ;Just a regular character, store
JRST ITER2 ;Continue
;Up-arrow seen, possibly a MACRO
ITER3: ILDB T1,LOCMSP ;Get next character of message
CAIN T1,"^" ;Another uparrow, means go insert an uparrow
JRST ITER2A
CAIN T1,"2" ;^2
JRST ITER32 ;Insert ASCIZ string
CAIN T1,"3" ;^3
JRST ITER33 ;Insert ASCIZ string
CAIN T1,"4"
JRST ITER34 ;Insert OCTAL number
CAIN T1,"5"
JRST ITER35 ;Insert DECIMAL number
CAIN T1,"6"
JRST ITER36 ;Insert SIXBIT word
CAIN T1,"7"
JRST ITER37 ;Skip to new line if column > 72
CAIN T1,"8" ;^8
JRST ITER38 ;Insert generic filename
IFN TOPS20,<
CAIN T1,"1" ;^1
JRST ITER31 ;Insert last JSYS error
>
IFE TOPS20,<
CAIN T1,"A" ;^A
JRST ITER3A ;Insert octal number from FLPERR
CAIN T1,"B" ;^B
JRST ITER3B ;insert FILOP. error code
>;END IFE TOPS20
CAIN T1,"9" ;^9
JRST ITENNC ;Stop message here and don't insert a CRLF
;Nothing special, insert up-arrow and the character
MOVEI T2,"^" ;Up-arrow
IDPB T2,ERTXTP ;Store it
JRST ITER2A ;Go store character and continue
; Here are routines to do the special actions
;for specific characters following up-arrow
;
; When the action is completed, the code will usually branch
;back to "ITER2" to continue copying characters from the input
;string to the output string.
IFN TOPS20,<
;^1 - Insert last JSYS error message
ITER31: MOVE T1,ERTXTP ;Get error text pointer
HRLOI T2,.FHSLF ;LAST ERROR IN THIS FORK
SETZ T3, ;ALL OF THE TEXT
ERSTR%
JFCL
JFCL
EXCH T1,ERTXTP ;Store updated error pointer
SETZ T2, ;T2= # of columns used
ITERUC: CAMN T1,ERTXTP ;Did we update column all the way yet?
JRST ITEUC1 ;Yes
IBP T1 ;Account for each byte
AOJA T2,ITERUC ;Back to loop
ITEUC1: ADDM T2,NCOLM ;Update column number
JRST ITER2 ;Go back for more characters
>;END IFN TOPS20
;^2 - Insert ASCIZ string whose (18-bit) address is in ASCS1
ITER32: SKIPA T2,ASCS1 ;Get address and skip
;^3 - Insert ASCIZ string whose (18-bit) address is in ASCS2
ITER33: HRRZ T2,ASCS2 ;Get address
HRLI T2,(POINT 7,)
ITEASC: ILDB T1,T2 ;Get character
JUMPE T1,ITER2 ;When done, go back for another character
CAIN T1,.CHCRT ;Carriage-return
SETZM NCOLM ; sends column back to 0
PUSHJ P,ITECHR ;Insert character
JRST ITEASC ;Loop
IFE TOPS20,<
;^A - Insert octal number from FLPERR
ITER3A: SKIPA T2,FLPERR ;Get number
>;END IFE TOPS20
;^4 - Insert octal number from ENUMBR
ITER34: MOVE T2,ENUMBR ;Get number
MOVEI T3,^D8 ;Get base
PUSHJ P,ITENBR ;Insert number into error text
JRST ITER2 ;Go back for more characters
;^5 - Insert decimal number from ENUMBR
ITER35: MOVE T2,ENUMBR ;Get number
MOVEI T3,^D10 ;Base in T3
PUSHJ P,ITENBR ;Insert number into error text
JRST ITER2 ;Go back for more characters
;^6 - Insert SIXBIT word from SIXBW1
ITER36: MOVE T1,SIXBW1 ;Get sixbit word
PUSHJ P,ITERSB ;Call routine to insert it
JRST ITER2 ;Go back for more message text
;^7 - If column is greater than 72, skip to a new line
ITER37: MOVE T1,NCOLM ;Get column
CAIGE T1,^D72 ;More than 72?
JRST ITER2 ;No, do nothing
MOVEI T1,.CHCRT ;Insert CR
PUSHJ P,ITECHR
SETZM NCOLM ;After LF, column will be 1
MOVEI T1,.CHLFD ;Insert LF
PUSHJ P,ITECHR
JRST ITER2 ;Go back for another character
;^8 - Insert generic filename string from EFNPTR
ITER38: DMOVE T1,EFNPTR ;Get ptr
DMOVEM T1,IT8PTR ;Save here
ITE381: ILDB T1,IT8PTR ;Get character
JUMPE T1,ITER2 ;All done, return
PUSHJ P,ITECHR ;Type a character
JRST ITE381 ;Loop
IFE TOPS20,<
;^B - Insert ASCII FILOP. error from number in FLPERR
ITER3B: MOVE T1,FLPERR ;Get error number
CAILE T1,.FESZ ;Too big?
JRST ITE3B1 ;Yes, get default message
HRRZ T2,FLPEMS(T1) ;Get error message
HRLI T2,(POINT 7,) ;BP to it
TRNE T2,-1 ;Any message?
JRST ITEASC ;Yes, Go insert message
HRRI T2,[ASCIZ/** Error pertains to RUN, GETSEG, or MERGE. **/]
JRST ITEASC ;Go tell him that
ITE3B1: MOVE T2,[POINT 7,[ASCIZ/** Unknown FILOP. error **/]]
JRST ITEASC ;Go insert message
;LIST of FILOP. errors
FLPEMS: [ASCIZ/File not found/]
[ASCIZ/UFD does not exist/]
[ASCIZ/Protection failure/]
[ASCIZ/File being modified/]
[ASCIZ/Specified file already exists/]
[ASCIZ/Illegal sequence of UUOs/]
[ASCIZ/Device or data error/]
0 ;Not a save file
0 ;Not enough core
0 ;Device not available
0 ;No such device
[ASCIZ/Illegal monitor call for FILOP./]
[ASCIZ/No room or quota exceeded/]
[ASCIZ/Write-lock error/]
[ASCIZ/Not enough monitor table space available/]
[ASCIZ/Partial allocation only/]
[ASCIZ/Block not free on allocated position/]
[ASCIZ/Cannot supersede a directory/]
[ASCIZ/Cannot delete non-empty directory/]
[ASCIZ/SFD not found/]
[ASCIZ/Search list is empty/]
[ASCIZ/SFD level too deep/]
[ASCIZ/No DSK: available to create a file on/]
0 ;GETSEG error
[ASCIZ/Cannot update file/]
0 ;GETSET/MERGE. error
0 ;User not logged in
[ASCIZ/File still has outstanding locks set/]
0 ;Bad EXE file directory
0 ;Bad extension for EXE file
0 ;EXE directory too big
[ASCIZ/Network capacity exceeded, no space for connect message/]
[ASCIZ/Task was not available/]
[ASCIZ/Unknown network node/]
[ASCIZ/SFD is inuse by another job/] ;RENAME error
[ASCIZ/File has an NDR lock/] ;DELETE
[ASCIZ/Too many readers/]
[ASCIZ/SFD to lower level/] ;RENAME
[ASCIZ/Channel not open/] ;46 - FILOP.
[ASCIZ/Device down and ususeable/] ;47
[ASCIZ/Device is restricted/] ;50
[ASCIZ/Device is controlled by the MDA/]
[ASCIZ/Device belongs to another job/]
[ASCIZ/Illegal data mode/]
[ASCIZ \Undefined/unknown open bits set\]
[ASCIZ/Device in use on MPX channel/]
[ASCIZ \Not enough per process space for extended I/O channel table\]
[ASCIZ/No free channels available/]
[ASCIZ/Unknown FILOP. function/]
[ASCIZ/Channel number too big/] ;61
[ASCIZ/Channel illegal for operation/]
.FESZ==.-FLPEMS-1 ;Last known FILOP. error
>;END IFE TOPS20
;The message has now been built in ERTXTB
;Insert a CRLF to end the message
ITEEND: MOVEI T1,.CHCRT ;CR
IDPB T1,ERTXTP
MOVEI T1,.CHLFD ;LF
IDPB T1,ERTXTP
;Enter here to stop message without appending a CRLF
ITENNC: SETZ T1, ;Null to end message
IDPB T1,ERTXTP
TYPE ERTXTB ;Type the error message
POP P,T3 ;Restore T3
POP P,T2 ;Restore T2
POPJ P, ;Done, return
;Little subroutines for error message printer
;ITERSB - routine to append sixbit word in T1 to error message
;Uses T1, T2
ITERSB: MOVE T2,T1 ;Copy word to T2
ITRSB1: JUMPE T2,CPOPJ ;Return when done
SETZ T1, ;Clear T1
LSHC T1,6 ;Shift another byte
ADDI T1,"0"-'0' ;Make ASCII
PUSHJ P,ITECHR ;Go insert character
JRST ITRSB1 ;Loop for more characters
;ITENBR - Routine to put a number into the error text
;Call:
; T2/ Number
; T3/ Base
; PUSHJ P,ITENBR
; <Returns here always>
;Uses t1-t3
ITENBR: MOVEM T3,NBASE ;Store base
JUMPGE T2,ITENB1 ;Jump if number is not negative
MOVEI T1,"-" ;It is, print "-"
PUSHJ P,ITECHR
MOVM T2,T2 ;And get the ABS
ITENB1: IDIV T2,NBASE ;Divide by base
PUSH P,T3 ;Store remainder
SKIPE T2 ;Number all done?
PUSHJ P,ITENB1 ;No, recurse
POP P,T1 ;Get digit
ADDI T1,"0" ;Make ASCII
PJRST ITECHR ;Print character and unwind
;ITECHR - Routine to insert one character in error text
ITECHR: IDPB T1,ERTXTP ;Append to error text
AOS NCOLM ;Increment column
POPJ P, ;Return
SUBTTL Return status routines
RT1R34: DMOVE T3,USR34 ;Restore user's 3 & 4
JRST RETST1 ;Return status 1
RT0R34: DMOVE T3,USR34 ;Restore user's 3 and 4
JRST RETST0 ;Return status 0
RETST2:
RETEOF: MOVEI T1,2 ;Set status = 2
POPJ P, ;Return
RETST0: TDZA T1,T1 ;STATUS 0
RETST1: MOVEI T1,1 ;STATUS 1
POPJ P, ;RETURN
CPOPJ1: AOS (P) ;Give skip return
CPOPJ: POPJ P, ;. .
;Address of a CRLF
CRLF: ASCIZ/
/
SUBTTL DATA SECTION
IFE TOPS20,<
RELOC 0 ;Relocate to low-seg for impure data
>;END IFE TOPS20
;Literals
IFN TOPS20,< ;TOPS20 literals
TXTILT: .RDRTY ;Last word given
RD%JFN!RD%BEL!RD%BRK ;Flags--Break on end of TTY: line or CTRL/Z
.PRIIN,,.PRIOU ;Input,,output JFNs
POINT 7,TLINE ;Destination ptr
.NTTYB ;Number of bytes available
0 ;Use start of buffer as above
0 ;Control-R text
>;END IFN TOPS20
STTLC==. ;Starting location to clear
PRGABR: BLOCK 1 ;3-letter sixbit abbreviation for main program
; (used for error message typeout).
USR12: BLOCK 2 ;USER'S ACS 1 AND 2
USR34: BLOCK 2 ;USER'S ACS 3 AND 4
DEFBFS: BLOCK 1 ;DEFAULT BUFFER SIZE (PAGES)
MXIFNR: BLOCK 1 ;MAX IFN USER REQUESTED
IFNSTR: BLOCK IT.SIZ * MAXIFN ;SPACE FOR ALL FILE STORAGE
USEXEX: BLOCK 1 ;-1 IF WE SHOULD USE EXTENDED ADDRESSING
USDPGS: BLOCK 1 ;# of used pages (Total)
RBLPGS: BLOCK 1 ;# of returnable pages
OPFEXT: BLOCK 1 ;Opening an external file if -1
SVBYTS: BLOCK 1 ;Saved byte size for a file
SVMADR: BLOCK 1 ;Saved memory address we got back
ITOSSZ: BLOCK 1 ;Size of file (used by ITOEXI)
BYVWRD: BLOCK 1 ;Bits/byte written
SVOUTB: BLOCK 1 ;Saved byte to output (ITOUB)
WTBUFC: BLOCK 1 ;# chars written to buffer (WRTBUF)
OTMJFN: BLOCK 1 ;JFN used by OPNTMP
ITOSFP: BLOCK 1 ;Offset saved by ITOSB
STRNBP: BLOCK 2 ;String byte pointer (used by ITOSB and ITISB)
ITNBYT: BLOCK 1 ;# bytes to read/write
PSFBNM: BLOCK 1 ;Byte number for ITPSF
PSFBPW: BLOCK 1 ;bytes/word
PSFBPP: BLOCK 1 ;Bytes/page for ITPSF
PSFPNM: BLOCK 1 ;Page number desired
PSFBOF: BLOCK 1 ;byte offset on the page
LOCABR: BLOCK 1 ;LH = 3-letter abbrev for error printing
LOCMSP: BLOCK 1 ;Local message ptr
ERTXTB: BLOCK ^D50 ;Block for error text
ERTXTP: BLOCK 1 ;Byte ptr to block
NCOLM: BLOCK 1 ;Column number we are at
NBASE: BLOCK 1 ;For ITENBR
ASCS1: BLOCK 1 ;Address of an ASCIZ string for error routine
ASCS2: BLOCK 1 ;Another address for ASCIZ string (if two are needed)
SIXBW1: BLOCK 1 ;Sixbit string input for error routine
ENUMBR: BLOCK 1 ;Number stored for error printing routine
EFNPTR: BLOCK 2 ;Byte ptr to ASCIZ generic file name string on errors
IT8PTR: BLOCK 2 ;Saved Bp to EFNPTR
TMOTRY: BLOCK 1 ;Number of times we tried to loop back with
;another name after we got the "simultaneous access
; error".
ITTFOP: BLOCK 1 ;-1 if a TTY: file is open for input
SVBPWB: BLOCK 2 ;Saved BP to buffer in WRTBUF
IFN TOPS20,< ;TOPS-20 only data
TXTIBL: BLOCK .RDRTY+1 ;TEXTI block
TXTIBE==.-1 ;End location of TEXTI block
TLINE: BLOCK <.NTTYB/5>+1 ;For holding a TTY: line
TTYLCT: BLOCK 1 ;Number of bytes still in TLINE
TTYLBP: BLOCK 1 ;Current bp to TLINE
>;END IFN TOPS20
IFE TOPS20,< ;TOPS-10 only data
FLPERR: BLOCK 1 ;FILOP. error code
FLP1AG: BLOCK 2 ;For IN and OUT FILOP. calls
FLPDL: BLOCK 2 ;Dump mode list
RDNINF: BLOCK 2 ;Saved info for RDNBUF
RTRYNM: BLOCK 1 ;Flag for ITRNF
SVRNBL: BLOCK .MXRBC ;Saved RENAME block for FILOP.
; Used by $ITRNF
SVRNPB: BLOCK .PTMAX+1 ;Saved PATH block for FILOP. (if needed)
EXRNBL: BLOCK 1 ;Flag- 0= not extended RENAME block, -1= yes
SVRNLN: BLOCK 1 ;Saved RENAME block length copied.
SVLKRP: BLOCK 1 ;Saved .FOLEB during FILOP. delete
SEED: BLOCK 1 ;Random number seed
>;END IFE TOPS20
ENDLC==.-1 ;Ending location to clear
END