Trailing-Edge
-
PDP-10 Archives
-
bb-4157j-bm_fortran20_v11_16mt9
-
fortran-ots-debugger/forerr.mac
There are 27 other files named forerr.mac in the archive. Click here to see a list.
SEARCH MTHPRM,FORPRM
TV FORERR ERROR HANDLER,11(5025)
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1981, 1987
;ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
;TRANSFERRED.
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
COMMENT \
***** Begin Revision History *****
1100 CKS 13-Jun-79
New
1403 DAW 6-Apr-81
Get rid of magic JOBDAT numbers that prevents users
from loading FOROTS at places other than 400K.
1437 DAW 17-Apr-81
Change FILOP error code 12 from "No such device" to "Can't OPEN
device"-- open of LPT could cause this.
1464 DAW 21-May-81
Put all "ERR" and "IOERR" messages in this file.
1473 CKS 21-May-81
Many error message fixes.
1504 BL 1-Jun-81 Q10-06141
Prevent TRACEBACK default call from displaying itself.
1532 DAW 14-Jul-81
OPEN rewrite: Base level 1
1533 DAW 14-Jul-81
Errors that were supposed to print input record didn't.
Also they would mess up the error message text for ERRSNS.
1537 DAW 16-Jul-81
More work on OPEN for TOPS-20.
1560 DAW 28-Jul-81
OPEN rewrite: Base level 2
1573 DAW 31-Jul-81
Eliminate typing random CRLF's when ERR= branch taken.
1603 DAW 12-Aug-81
Don't type statement name more than once if many IOERR's
are done.
1611 DAW 17-Aug-81
"%integer overflow" bombed out pgm instead of continuing..
1624 DAW 21-Aug-81
"?Illegal record number" got record number from wrong ac.
1625 DAW 21-Aug-81
Get rid of "DF".
1630 JLC 24-Aug-81
Illegal magtape OP's now illegal.
1642 JLC 27-Aug-81
Replace %FILOP calls with FILOPs.
1645 DAW 28-Aug-81
Get to column 1 before errors on TOPS-10.
1651 DAW 31-Aug-81
Do TRMOP. function to wait for output done before getting HPOS.
(Fix to 1645).
1652 DAW 1-Sep-81
Make "IOE" a "?" error.
1656 DAW 2-Sep-81
Get rid of magic numbers.
1661 BL 4-Sep-81
Fix incorrect info coming from TRACE; & illegal instruction return.
1662 DAW 4-SEP-81
%CALU; user error handling routine.
1665 DAW 8-Sep-81
D.TTY hack.
1706 DAW 11-Sep-81
Lots of changes to error messages, codes, etc.
1725 DAW 18-Sep-81
Better error reporting in OPEN args & dialog strings.
1737 DAW 23-Sep-81
Fix "RBR" error.
1753 DAW 29-Sep-81
IOERR's and LERR's to type the PC.
1760 JLC 5-Oct-81
Print 2 decimal places for time typouts.
1762 DAW 6-Oct-81 Q10-06581
Don't print format with error in wrong place.
1763 DAW 7-Oct-81
Fatal error "?Can't write to LINED file".
1766 DAW 7-Oct-81
Don't type PC flags as part of the PC.
1773 DAW 8-Oct-81
Change "CMU" to "IEM" - internal error in mem. management.
1774 DAW 8-Oct-81
Change message for FILOP. code 52 to "Device is assigned by
another job".
2003 BL 14-Oct-81 Q10-06574
Change data type "0" from "U" to "I".
2013 DAW 19-Oct-81
Fix TRACE to store "..." at end of string, not into a literal.
2022 DAW 22-Oct-81
Better error message for TOPS-20 when the JFNs run out.
2031 DAW 27-Oct-81
Fix smashing of AC if no symbols loaded.
***** Begin Version 7 *****
3035 JLC 5-Feb-82
Add error messages for new binary code. Combine
error message for ordinary I/O and ENCODE/DECODE.
3037 JLC 11-Feb-82
Add new error msg for dump mode IO list too long.
Removed non-fatal error messages for magtape.
3056 JLC 23-Mar-82
Separated error messages from FORERR into FORMSG.MAC.
Fixed error buffer typeout so it doesn't trash the FOROTS
data area if the record is very long. Make TRACE work
in extended sections.
3122 JLC 28-May-82
Rework of error entry. Moved %IOERR into FORERR. Rework
of calling user program.
3125 JLC 3-May-82
Moved the error character to the beginning of the error macros.
3136 JLC 26-Jun-82
Separated the 2nd error number from the type code in the
trap subroutine block.
3140 JLC 2-Jul-82
Get proper PC for $P in extended sections.
3141 JLC 2-Jul-82
Fix to edit 3140.
3147 AHM 8-Jul-82
Fix GETPC so that it doesn't die trying to evaluate the jump
address of PUSHJs and overlay calls. Merely setting the sign
bit on a word that has bit 1 set (such as the PUSHJ
instruction) resulted in a type 3 indirect word that causes an
ill mem ref. Bit 0 must be set and bit 1 must be cleared.
3151 AHM 13-Jul-82
Add a whole new ADRCHK for Tops-20 that decides whether or not
a PC is believable by checking whether it refers to an
existing section. Also, preserve section numbers in GETPC.
3155 AHM 19-Jul-82
Remove a lot of code that discards section numbers around
ADDPCM, TRACEL and SYMSRH. Also, make ADRCHK punt on section
numbers that are greater than 37.
3161 JLC 16-Aug-82
Added $R, to print out a record number from CREC(D).
3162 AHM 23-Aug-82
Make the Tops-20 ADRCHK light FH%EPR when running in a
non-zero section so that addresses getting checked don't have
section 0 interpreted as "our section".
3165 JLC 28-Aug-82
Fix error record typout by rewriting it.
3166 JLC 31-Aug-82
Eliminate ER2PTR ref, fix SYMSRH so it doesn't need XHLLI,
which isn't defined on the -10.
3172 JLC 2-Sep-82
Fix code at NERR1 to get proper PDP to use for NOSYM. Fix
NOSYM so it wasn't fooled by T2 pointing to MAIN. if no
stuff on stack.
3175 JLC 8-Sep-82
Fix $I to get the error bits from the right place.
3176 JLC 9-Sep-82
Installed disk quota exceeded trap.
3200 JLC 24-Sep-82
Save ACs in 3 separate local areas instead of on the stack,
to avoid problems with global stacks. Fix I/O within I/O,
that is, used A.UNIT instead of UNUM(U) to type the unit
number in the fatal message.
3201 JLC 4-Oct-82
Add kluge to prevent tracing arg lists of MTHCPX routines which
don't have an arglist.
3202 JLC 26-Oct-82
Fix AC save routines so they don't use the stack, so that
non-zero section stacks are TRACEable.
3216 JLC 16-Nov-82
Restore the ERSTKP on ERR= and IOSTAT=.
3217 PLB 17-Nov-82
Change ADRCHK to check %FSECT to get FOROTS section.
3225 JLC 24-Nov-82
Type nulls in records and FORMATs as spaces. Fix TRACE for
calls from APR traps.
3231 JLC 14-Dec-82
Fix GETPC for multiple sections of code, allow indexed PUSHJs
and indexed and indirected XMOVEIs.
3240 JLC 20-Dec-82
Fix TRACE called from a user program - was using last stored
trace stack.
3250 JLC 7-Jan-83
Use SVEACS for TRACE instead of %SAVAC, so user can trace
from ERRSET subroutine on I/O warnings.
3252 JLC 12-Jan-83
Fix RENAME error msg reporting, by making $F get an argument,
supplied in the error msg macro.
3253 JLC 14-Jan-83
Fix TRACE so it saves and restores the GETPC return PC.
3260 JLC 17-Jan-83
Fix library error reporting with no symbols so that positive
PC offsets get out. Fix TRACE not to print PCs on every line
if it is the ERRSET routine.
***** End V7 Development *****
3271 JLC 14-Feb-83
Restore the AC's before jumping out of TRACE or exiting it.
3275 RJD 18-Mar-83
Have TRACE routine print the number of arguments in decimal
rather than in octal.
3352 MRB 27-Sep-83
Insert a check for arithmetic trap errors and change the
second number to the number of the occurances (of the error).
3353 RJD 30-Sep-83
Have XTIME routine handle elapsed times with greater
than 99 hours.
3375 RJD 14-Dec-83 SPR:10-34341
Have XTIME use the DPOS routine to print hours.
3406 TGS 25-Jan-84 SPR:NONE
Fix SYMCNV/SYMSRH to properly handle extended addresses. Values
fetched from the symbol table were not always having a section
number inserted. If the symbol+offset found is an offset from
MAIN. and there is also a PROGRAM name symbol, prefer the latter.
***** Begin Version 10 *****
4000 JLC 22-Feb-83
Save/restore ACs around TRACE calls correctly. Move code
around to prevent GETPC call for library warnings unless
an ERRSET or break address is set.
4013 PLB 1-Jun-83
Fix FOREC to be able to type out library errors when
the error text resides in a different section from FORERR.
4014 JLC 14-Jun-83
Changed names of some DDB variables so they wouldn't conflict
with definitions in MACSYM and MONSYM.
4015 PLB 21-Jun-83
Fix SYMSRH to handle symbol table from another section.
4021 PLB 24-Jun-83
Teach TRACE% not to use AOBJN.
4031 JLC 7-Jul-83
Fix FORER% so it uses the lowseg arg list for the user
subroutine call.
4036 JLC 8-Aug-83
Widen TRACE output for extended addressing.
4037 JLC 11-Aug-83
Fix error messages which have no unit number printed
Also fix TRACE output so it's aligned.
4044 JLC 27-Sep-83
Changed type code for immediate args to "I" for tracebacks.
4046 JLC 3-Oct-83
Repair edit 3352. Return sense of %CHKEL is opposite from
V7.
4047 JLC 5-Oct-83
Fix GETPC for routines in overlays.
4050 JLC 6-Oct-83
Modify TRACE to give special trace line for ERRSET subroutine
calls.
4051 JLC 6-Oct-83
Fix edit 4050. Setup of L was moved to after it was used.
4052 JLC 12-Oct-83
Don't print magtape attributes in error lines. Code changes
necessary for minor performance enhancements for formatted
I/O.
4061 JLC 4-Nov-83
Fix IOSTAT bug, set %ERIOS instead of IOSTAT variable,
set IOSTAT variable in %SETAV at end of I/O.
4064 JLC 14-Nov-83
Fix updated IOSTAT processing, was not recording IOSTAT value
if no DDB.
4065 JLC 6-Dec-83
Remove some unused code.
4066 JLC 11-Jan-84
More preparations for RMS.
4076 TGS 6-Feb-84
Fix SYMSRH so it does not depend on the module count word in
the symble table containing an 18-bit module start address in
the right half. Future LINKs may not supply this in non-zero
sections. Search for the global symbol corresponding to the
module name instead.
4077 JLC 6-Feb-84
Fix tracebacks so they print more information, especially
in the case of I/O errors where ERRSET has been used. This
code depends on the previous development effort which
eliminated IOPDL.
4102 JLC 17-Feb-84
Use the "standard" filename string code to get the
filename for error messages. Eliminate the extraneous
blank in non-filename typeouts. Create a new entry point
for compatibility message output.
4104 JLC 22-Feb-84
More compatibility flagging code.
4105 JLC 28-Feb-84
Change the handling of fatal ("?") error messages to
always go to a fatal error handler (e.g., %ABORT).
Add a new entry for DIALOG error handling: %DERR, called
with a $DCALL, which sets the fatal error handler to
REQDIA.
4106 JLC 2-Mar-84
Fix ADRCHK bug - we were calling it with the address in
the stack entry, then actually peeking at that address-1,
creating pages on the -20 and getting ill mem ref on the -10.
4107 JLC 5-Mar-84
Add $E to TOPS-20 message handler, same as $J.
4111 JLC 16-Mar-84
Add two new entry points (%AERR and %DERR) for fatal error messages.
Ignore the continuation address, and substitute a fatal
error handler address (%ABORT or REQDIA) for $AERR and $DERR.
4114 JLC 28-Mar-84
Remove I%TCH on TOPS-10, as it is almost useless
and didn't work anyhow.
4116 JLC 4-Apr-84
Remove $E, substitute (smarter) $J.
4122 JLC 2-May-84
A whole raft of changes to make the TOPS-10 and TOPS-20
DDB databases the same.
4123 JLC 5-May-84
Fix ADRCHK on TOPS-10 for twoseg programs.
4127 JLC 15-May-84
Partial fix for ERR= and IOSTAT= freeing of UDB and DDB.
Eliminate F%DCU.
4131 JLC 12-Jun-84
Hopefully final fix for ERR= and IOSTAT= freeing of UDB and
DDB. Add $E for memory full diagnostic. For TOPS-20, save the
I/O error (retrieved with GETER%) in saved T1, so that recursive
errors (such as an error on the DIVERT unit) will not lose it.
Fix the TOPS-10 error diagnostic for "wrong direction for device".
4152 JLC 24-Sep-84
Use %SVCNV to convert the contents of .JBSYM into address
and length of symbol table.
4153 JLC 27-Sep-84
Reference the user program start address indirectly, as it is now
the address of a location containing the start address.
4154 JLC 1-Oct-84
Don't call error break subroutine for informational messages
or FOROTS internal errors.
4155 JLC 17-Oct-84
Deallocate the rename DDB and UDB on errors with IOSTAT= or ERR=.
4156 JLC 23-Oct-84
Since we set %UDBAD to -1 in %SAVAC so that it is really a flag
of whether I/O is in progress, we must check for %UDBAD being
negative or zero.
***** End V10 Development *****
***** Begin Version 11 *****
5007 TGS 4-Jan-85
Add RMS error handling. This becomes an extention of the $J
JSYS error handling for local disk files.
5010 MRB 5-Feb-86
Add handeling for long names for in traceback message $S.
reads sixbit string from HELLO macro. symbol table lookup
not done yet.
5017 MRB 19-JUN-86
Fix routine that types out R50 symbol names to type out
the long (SIXBIT) symbol names it they are there.
Routines: R50TYP, FND2ST, SRH2ST
5020 MRB 3-JUL-86
Check to see if the error PC is zero and don't type the
symbolic address for $E calls.
5021 MRB 18-AUG-86
Fix long symbol typeout routine SIXPTR (again).
5025 MRB 10-DEC-86
Change routine SIXPTR to use OWGBP to get chars.
(Only needed when user code and FOROTS are in different
sections.)
***** End Revision History *****
\
ENTRY %TRACX,%IOERR,%OTSER,%TRPER
EXTERN %UDBAD,%DDBTAB,%FSECT,I.BAT,%PC1,%ABORT,%ABFLG,I.XSIR,O.DIAL
EXTERN %SETAV,%FREBL,%EOREC,%HALT,%CIPOS,%CLSCL,%RNAMD,%RNAMU
EXTERN E.NAM,%MSGVX,%MSG77,%MSGB,%FLIDX,%IONAM
EXTERN %SAVE1,%SAVE2,%SAVE3,AU.ACS
EXTERN %ERRCT,%ERRLM,%ERRSB,%ERRSZ,%ERRBK,%NAMLN,%LALAD
EXTERN %POPJ,%POPJ1
EXTERN %STADD
EXTERN %RIPOS,%SIPOS,%IBYTE,%ERFNS,%SVCNV
EXTERN FMT.BP,FMT.BG,FMT.SZ,USR.SZ
EXTERN A.END,A.ERR,A.IOS,%CUNIT
EXTERN %FSECT
EXTERN %MSLVL
EXTERN %RMDAB,O.KEY ;[5000]
IF20,< EXTERN %RMECL,%RMERR,%ERMIN ;[5007]>
INTERN %ERNM1,%ERNM2,%UNFXD,%FIXED,%ERTYP,%ERPDP,%ERRPC,%ERCHR
INTERN %DFERR,%ERNAM,%LERN1,%LERN2,%ERIOS,%EOPTR,%EOCNT,%ERINI
INTERN %DERR,%AERR
INTERN %ERNM3
IF20,< INTERN %RMPDP,ERRPTR,OCTTYP,ASCTYP,INICHR ;[5007]>
IF20,< INTERN %RMEPT,FOREC2,EMSGT0,%ERPTR,ERRCNT ;[5007]>
SEGMENT CODE
IF10,<
%DFERR: $SNH ;NO DISK-FULL HANDLER NEEDED ON TOPS-10
>
IF20,<
;DISK FULL ERROR HANDLER
;GETS HERE VIA THE SOFWARE INTERRUPT SYSTEM IF THE USER HAS NOT
;STOLEN THE CHANNEL FROM FOROTS. TREATED LIKE ANY OTHER I/O ERROR,
;EXCEPT THAT IF THE PROCESS IS INTERACTIVE, IT DOES A HALTF% TO
;LET THE USER EXPUNGE OR OTHERWISE CLEAN UP THE DISK, AND THEN,
;IF CONTINUED, WILL DEBRK% TO CONTINUE THE PROCESS. IF THE PROCESS
;IS BATCH, WE JUST JUMP OFF TO %ABORT TO CLOSE ALL FILES.
;FOR THE ERR= AND IOSTAT= CASE, IT IS COMPLICATED BY THE FACT
;THAT WE MUST DO A DEBRK%, BUT WE DO NOT WANT TO CONTINUE
;THE PROCESS AT THE INTERRUPTED LOCATION, SO WE MUST SUBSTITUTE
;THE ERR= OR (FOR IOSTAT WITH OLDER .REL FILES) THE RETURN ADDRESS
;FROM THE FOROTS CALL FOR THE INTERRUPT ADDRESS.
%DFERR: SKIPE I.BAT ;BATCH JOB?
JRST SETDBK ;YES. DEBREAK AND HANDLE ERR= OR ABORT
SKIPN A.ERR ;ERR= OR IOSTAT= SPECIFIED?
SKIPE A.IOS
JRST SETDBK ;YES. SET DEBREAK ADDRESS TO ERROR HANDLER
$ECALL DQW ;NO. PRINT DISK QUOTA EXCEEDED MESSAGE
HALTF% ;HALT THE PROCESS
DEBRK% ;CONTINUE THE PROCESS IF CONTINUED
SETDBK: PUSH P,T1 ;SAVE T1 VERY TEMPORARILY
XMOVEI T1,DFDBK ;SET DEBREAK ADDRESS HERE
SKIPN I.XSIR ;USING EXTENDED PSI TABLE?
JRST STDBS0 ;NO
MOVEM T1,%PC1+1
POP P,T1 ;RESTORE T1
DEBRK%
STDBS0: HRRM T1,%PC1 ;STORE PC
POP P,T1 ;RESTORE T1
DEBRK% ;AND DEBREAK
DFDBK: $ACALL DQE ;AND PRINT ERROR MESSAGE AND DIE
> ;END IF20
;HERE FROM ERROR MACROS
;
;CALLS:
;
; $DERR (CHR,COD,N1,N2,MSG,ARGS,FLGS) ;ERROR WITH DIALOG REQUEST
; $ERR (CHR,COD,N1,N2,MSG,ARGS,FLGS) ;FOROTS ERROR OR PROMPT LINE
; $IOERR (CHR,COD,N1,N2,MSG,ARGS,FLGS) ;I/O ERROR
; $LERR (CHR,COD,N1,N2,MSG,ARGS,FLGS) ;MATHLIB ERROR
; $FERR (CHR,COD,N1,N2,MSG,ARGS,FLGS) ;FORLIB ERROR
; $TERR (CHR,COD,N1,N2,MSG,ARGS,FLGS) ;APR TRAP CALL
;
;CHR INITIAL CHAR FOR ERROR MESSAGE ([, %, ?)
; IF [, MESSAGE IS TERMINATED WITH ]
; IF ?, TYPEAHEAD CLEARED AFTER MESSAGE
; IF NULL, 3-CHAR PREFIX ISN'T TYPED
; IF $, FIRST ARG IS INITIAL CHAR
;COD 3-CHARACTER PREFIX
;N1 ERROR CLASS NUMBER
;N2 2ND ERROR NUMBER
;MSG TEXT OF ERROR MESSAGE
; $ INDICATES AN ARG TO BE SUBSTITUTED INTO THE MESSAGE
; THE CHAR AFTER THE $ GIVES THE FORMAT OF THE SUBSTITUTION
;ARGS LIST OF ARGUMENT ADDRESSES, ONE-TO-ONE CORRESPONDENCE WITH $S
; IN MESSAGE TEXT
;FLGS ERROR FLAGS
;
;THE ERROR MACROS GENERATE 1 WORD IN LINE, SO CAN BE SKIPPED OVER.
;THEY DO NOT ALTER ANY ACS.
%ERINI: XMOVEI T1,ERRSTK ;SETUP ERROR STACK
MOVEM T1,ERSTKP
POPJ P,
%CMSG: 0 ;NO COMPATIBILITY MESSAGE
%MSGVX ;VAX COMPATIBILITY MESSAGE
%MSG77 ;ANSI-77 COMPATIBILITY MESSAGE
%MSGB ;BOTH VAX AND ANSI-77
%IOERR: POP P,IOERP ;SAVE ARG POINTER
PUSHJ P,SVEACS ;SAVE THE ACS ON THE ERROR STACK
SETZM FERADR ;NO FATAL ERROR ADDRESS
JRST IOER1 ;JOIN COMMON CODE
%DERR: POP P,IOERP ;SAVE ARG POINTER
PUSHJ P,SVEACS ;SAVE THE ACS ON THE ERROR STACK
XMOVEI T1,REQDIA ;GET ADDR OF DIALOG REQUEST
SKIPE %ABFLG ;[4131] BUT IF WE ARE ABORTING
XMOVEI T1,%ABORT ;[4131] ABORT IT AGAIN
MOVEM T1,FERADR ;SAVE AS FATAL ERROR ADDRESS
JRST IOER1 ;JOIN COMMON CODE
%AERR: POP P,IOERP ;SAVE ARG POINTER
PUSHJ P,SVEACS ;SAVE THE ACS ON THE ERROR STACK
XMOVEI T1,%ABORT ;GET ADDR OF ABORT ENTRY
MOVEM T1,FERADR ;SAVE AS FATAL ERROR ADDRESS
IOER1: MOVE P2,IOERP ;GET ARG POINTER
MOVEM P2,%ERPTR ;SAVE FOR COMMON ROUTINES
MOVE T2,%NUM1(P2) ;GET ERROR CLASS NUMBER
MOVEM T2,%ERNM1 ;SAVE ERROR CLASS NUMBER
MOVEM T2,%LERN1 ;ALSO SAVE IT SEMI-PERMANENTLY
MOVE T2,%NUM2(P2) ;GET 2ND ERROR NUMBER
MOVEM T2,%ERNM2 ;SAVE 2ND ERROR NUMBER
MOVEM T2,%LERN2 ;ALSO SAVE IT SEMI-PERMANENTLY
XMOVEI T1,%ARGS-1(P2) ;GET ARGUMENT POINTER
MOVEM T1,ARGPTR ;SAVE IT
MOVE T1,%FLGS(P2) ;[4131] GET ERROR FLAGS
TXNE T1,I%JERR ;[4131] $J IN ERROR MSG?
PUSHJ P,ESAVE ;[4131] YES. GET ERROR CODE INTO SAVED T1
MOVE T1,%CHR(P2) ;GET CHARACTER
CAIN T1,"$" ;CHARACTER IN ARGUMENT?
PUSHJ P,GETARG ;YES. GET IT
MOVEM T1,%ERCHR ;SAVE IT FOR MESSAGE
;If this is a "?" error, do the ERR= or END= stuff
CAIE T1,"?" ;"?" says take ERR= if we can.
JRST NERR1 ;Not fatal, just go type message
;Fatal error. Clear %UDBAD
; This is so all the IOLST. calls that follow an IO call that gets
; a fatal error will not screw up things any more.
SKIPGE %ERNM2 ;EOF?
SKIPN T1,A.END ;Yes, use END= address not ERR=
;But if no END= specified, use ERR=
MOVE T1,A.ERR ;Get ERR= Address
JUMPE T1,NERR ;IF ANY
XMOVEI T1,@T1 ;DO EA CALC
;Take END= or ERR= branch.
;Address of where to go is in T1.
;T2 contains the error number
MOVE P,AU.ACS ;GET ADDR OF USER'S ACS
MOVE P,P(P) ;GET THE OLD STACK
MOVEM T1,(P) ;Store return address
ADJSP P,1 ;WE NEED OUR ACS BACK
PUSHJ P,%EMSGT ;Get error message text for ERRSNS.
MOVE T1,%ERNM2 ;GET 2ND ERROR NUMBER
MOVEM T1,%ERIOS ;SAVE FOR IOSTAT VARIABLE SETTING
PUSHJ P,FXTRET ;FIXUP STUFF TO RETURN
MOVNI T1,20 ;ADJUST ERROR STACK POINTER
ADDM T1,ERSTKP ;TOSS THE SAVED FOROTS ACS
PJRST %SETAV ;RETURN TO USER PROGRAM
;No END= or ERR= specified
NERR: SKIPN A.IOS ;How about IOSTAT=?
JRST NERR1 ;No
;Return to next statement in the program.
;For V7 and beyond, this code should never be
;executed, since IOSTAT= gets a gratutious ERR= to avoid
;character stack unwinding and function call problems.
PUSHJ P,%EMSGT ;Get error message text for ERRSNS.
MOVE T1,%ERNM2 ;GET 2ND ERROR NUMBER
MOVEM T1,%ERIOS ;SAVE FOR IOSTAT VARIABLE SETTING
PUSHJ P,FXTRET ;Fixup stuff to return
MOVE P,AU.ACS ;GET ADDR OF USER'S ACS
MOVE P,P(P) ;RESET STACK
ADJSP P,1 ; Fix so we get our acs back
MOVNI T1,20 ;ADJUST ERROR STACK POINTER
ADDM T1,ERSTKP ;TOSS THE SAVED FOROTS ACS
PJRST %SETAV ;RETURN TO USER'S PROGRAM
;Routine to fixup stuff to return from IO error.
;[4131] NEW CODE
FXTRET: SKIPE T1,%RNAMU ;[4155] ANY UDB FOR RENAME?
PUSHJ P,%FREBL ;[4155] YES. DEALLOCATE IT
SKIPE T1,%RNAMD ;[4155] ANY DDB FOR RENAME?
PUSHJ P,%FREBL ;[4155] YES. DEALLOCATE IT
SETZM %RNAMU ;[4155] NOW CLEAR THEIR POINTERS
SETZM %RNAMD ;[4155]
SETZM O.KEY ;[5007] CLEAR ANY KEY PNTR
SKIPG U,%UDBAD ;[4156] ANY DDB ALLOCATED?
POPJ P, ;No. Don't deallocate
HXRE T1,UNUM(U) ;GET THE UNIT NUMBER
CAIG T1,MAXUNIT ;IS IT A REAL UNIT?
CAMGE T1,[MINUNIT]
POPJ P, ;NO. LEAVE
SKIPE %DDBTA(T1) ;IS DDB ESTABLISHED?
POPJ P, ;YES. DON'T FREE IT
MOVE D,DDBAD(U) ;GET DDB ADDRESS TO TOSS
PJRST %CLSCL ;CLEAN UP AS IF AFTER CLOSE
;Print out the error.
NERR1: MOVE P1,P ;USE CURRENT STACK PNTR
PUSHJ P,GETPC ;GET CALLER, CALLED ADDR
MOVEM P1,%ERPDP ;SAVE NEXT STACK IN CASE NO SYMBOLS
MOVEM T1,%ERRPC ;SAVE PC OF CALL
MOVE T1,-1(T2) ;[4131] GET NAME OF FOROTS ROUTINE
MOVEM T1,%ERNAM ;[4131] SAVE FOR MESSAGE
SETZM MSGPC ;ASSUME NO PC DESIRED IN MESSAGE
PUSHJ P,%CHKEL ;CHECK IF WE SHOULD PRINT MESSAGE
PUSHJ P,IOMSG ;YES. OUTPUT MESSAGE
XMOVEI T1,%EARGL ;GET ADDRESS OF OTS ERROR BLOCK
MOVEM T1,EARGPT ;SAVE IT FOR USER SUBR CALL
SKIPN FERADR ;ANY FATAL ERROR ADDRESS SET?
JRST CALRET ;NO. GO CALL USER, RETURN
PUSHJ P,CALRET ;YES. CALL USER
JRST @FERADR ;AND GO TO FATAL ERROR HANDLER
IOMSG: SKIPE %NAMLN ;NAME LINE ALREADY OUT?
JRST FOREC ;YES. JUST OUTPUT MESSAGE DIRECTLY
MOVE T1,%ERRPC ;GET ERROR PC
MOVEM T1,MSGPC ;SAVE IT FOR MESSAGE
XMOVEI T2,E.NAM+%EOFF ;POINT TO MESSAGE DESIRED
MOVEM T2,%ERPTR ;SAVE POINTER
PUSHJ P,FOREC ;OUTPUT IT
SETZM MSGPC ;NO PC PRINTOUT ON SUBSEQUENT LINES
MOVE T1,IOERP ;GET ORIGINAL POINTER BACK
MOVEM T1,%ERPTR ;SAVE POINTER
SETOM %NAMLN ;SET FLAG SO WE DON'T GET NAME LINE AGAIN
PJRST FOREC ;OUTPUT THE MESSAGE
REQDIA: SKIPGE I.BAT## ;BATCH?
JRST %ABORT ;YES, DON'T TRY TO DIALOG WITH A .CTL FILE
SETOM O.DIAL ;[4131] SET REQUEST FOR DIALOG
POPJ P, ;RETURN FROM ROUTINE CONTAINING ERROR
%TRPER: POP P,%ERPTR ;GET ERROR BLOCK POINTER
PUSHJ P,SVEACS ;SAVE THE ACS ON THE ERROR STACK
MOVE T1,%ERRPC ;GET ERROR PC
MOVEM T1,MSGPC ;SAVE FOR MESSAGE
MOVE T1,%ERPTR ;GET ERROR BLOCK POINTER
MOVE T2,%NUM1(T1) ;GET ERROR CLASS NUMBER
MOVEM T2,%ERNM1 ;SAVE ERROR CLASS NUMBER
MOVE T2,%NUM2(T1) ;GET 2ND ERROR NUMBER
MOVEM T2,%ERNM2 ;SAVE 2ND ERROR NUMBER
PUSHJ P,%CHKEL ;CHECK IF WE WANT MESSAGE
PUSHJ P,FOREC ;YES. OUTPUT THE MESSAGE
XMOVEI T1,%EARGL ;GET ADDRESS OF OTS ERROR BLOCK
MOVEM T1,EARGPT ;SAVE IT FOR USER SUBR CALL
JRST CALRET ;GO CALL USER, RETURN
%OTSER: POP P,%ERPTR ;GET ERROR BLOCK POINTER
MOVEM P,%ERPDP ;SAVE CALLER ADDR FOR MSG
PUSHJ P,SVEACS ;SAVE ACS
MOVE T1,%ERPTR ;GET ERROR BLOCK POINTER
MOVE T2,%NUM1(T1) ;GET ERROR CLASS NUMBER
MOVEM T2,%ERNM1 ;SAVE ERROR CLASS NUMBER
MOVE T2,%NUM2(T1) ;GET 2ND ERROR NUMBER
MOVEM T2,%ERNM2 ;SAVE 2ND ERROR NUMBER
SETZM %ERRPC ;NO PC TO GIVE
SETZM MSGPC ;DON'T PRINT PC IN GENERAL
PUSHJ P,%CHKEL ;CHECK IF WE WANT MESSAGE
PUSHJ P,FOREC ;YES. OUTPUT MESSAGE
XMOVEI T1,%EARGL ;GET ADDRESS OF OTS ERROR BLOCK
MOVEM T1,EARGPT ;SAVE IT FOR USER SUBR CALL
JRST CALRET ;GO CALL USER, RETURN
FENTRY (MTHER,FORER)
POP P,%ERPTR ;SAVE ERROR BLOCK POINTER
MOVEM P,%ERPDP ;SAVE PDP FOR NOSYM
PUSHJ P,SVEACS ;SAVE ACS
MOVE T1,%ERPTR ;GET ERROR BLOCK POINTER
MOVE T2,%NUM1(T1) ;GET ERROR CLASS NUMBER
MOVEM T2,%ERNM1 ;SAVE ERROR CLASS NUMBER
MOVE T2,%NUM2(T1) ;GET 2ND ERROR NUMBER
MOVEM T2,%ERNM2 ;SAVE 2ND ERROR NUMBER
MOVE T1,%LALAD ;GET LOWSEG ARG LIST ADDRESS
MOVEM T1,EARGPT ;SAVE FOR USER SUBR CALL
PUSHJ P,%CHKEL ;CHECK IF WE WANT MESSAGE
JRST FOMSG ;YES. GO GET PC AND OUTPUT MESSAGE
PUSHJ P,ECHKU ;CHECK IF USER SUBR TO CALL
JRST FOCALU ;YES. GO GET PC AND CALL USER
PUSHJ P,ECHKB ;CHECK IF BREAK SPECIFIED
JRST FOCALB ;YES. GO GET PC AND BREAK
JRST ERRET ;RETURN
FOMSG: PUSHJ P,FOGPC ;GET PC
PUSHJ P,FOREC ;OUTPUT MESSAGE
JRST CALRET ;GO CALL USER, RETURN
FOCALU: PUSHJ P,FOGPC ;GET PC
JRST CALRET ;CALL USER, RETURN
FOCALB: PUSHJ P,FOGPC ;GET PC
PUSHJ P,ECALB ;CALL BREAK
JRST ERRET
FOGPC: MOVE P1,%ERPDP ;GET ERROR STACK PNTR AGAIN
PUSHJ P,GETPC ;GET CALLER ADDR
MOVEM T1,%ERRPC ;SAVE IT
MOVEM T1,MSGPC ;SAVE FOR MESSAGE
MOVE T1,-1(T2) ;GET NAME OF LIBRARY ROUTINE
MOVEM T1,%ERNAM ;SAVE FOR MESSAGE
MOVEM P1,%ERPDP ;SAVE USER'S STACK PNTR
POPJ P,
CALRET: PUSHJ P,ECALU ;CALL USER IF SPECIFIED
PUSHJ P,ECALB ;CALL BREAK ROUTINE
ERRET: MOVNI T1,20 ;DROP THE ERROR STACK POINTER
ADDM T1,ERSTKP ;A BLOCK OF ACS
HRLZ 16,ERSTKP ;RESTORE ACS
BLT 16,16
POPJ P,
FOREC: MOVE P2,%ERPTR ;POINT TO ERROR BLOCK
PUSHJ P,EMSGT0 ;Get error message text
SKIPE MSGPC ;PC TO PRINT?
PUSHJ P,ADDPCM ;YES. Add PC to message text.
FOREC2: PUSHJ P,EMSGT1 ;[5007] FINISH ERROR MESSAGE
MOVE T1,[POINT 7,ERRBUF] ;GET POINTER TO ERROR BUFFER
MOVEM T1,%EOPTR ;SAVE IT
MOVEI T1,5*LERRBF-1 ;GET ORIGINAL COUNT
SUB T1,ERRCNT ;GET # CHARS IN MESSAGE
MOVEM T1,%EOCNT ;SAVE IT
PUSHJ P,%EOREC ;TYPE MESSAGE
MOVE T1,%FLGS(P2) ;GET FLAGS
TXNE T1,I%REC ;TYPE RECORD WITH ARROW UNDER IT IF REQUESTED
JRST RECTYP
TXNE T1,I%REC1 ;TYPE RECORD WITH ARROW MOVED back 1
JRST RCTYB1
TXNE T1,I%FMT ;TYPE FORMAT WITH ARROW UNDER IT
JRST FMTTYP
MOVE T1,INICHR ;GET THE INITIAL CHAR AGAIN
CAIN T1,"@" ;WAS IT REALLY BAD?
JRST %HALT ;YES. STOP EVERYTHING
POPJ P,
%CHKEL: MOVE T1,%ERPTR ;GET ERROR BLOCK POINTER
SKIPGE T2,%NUM1(T1) ;GET 1ST ERROR NUMBER
POPJ P, ;IF NEGATIVE, DON'T CHECK LIMITS
CAIL T2,%ERRSZ ;WITHIN ERROR TABLE?
POPJ P, ;NO. DON'T CHECK ANYTHING
AOS T4,%ERRCT(T2) ;INCREMENT LIBRARY ERROR COUNT
MOVE T3,%CHR(T1) ;GET INITIAL CHARACTER
CAIN T3,"?" ;FATAL ERROR?
POPJ P, ;YES. DON'T CHECK LIMITS
MOVE T1,%ERNM1 ;[3352]get first number
CAIGE T1,10 ;[3352]Is it less than 10?
MOVEM T4,%ERNM2 ;[3352]Yes; save new second number!
CAMLE T4,%ERRLM(T2) ;[3352]PAST LIMIT?
AOS (P) ;YES. SKIP RETURN
POPJ P,
ECHKB: SKIPN %ERRBK ;ANY BREAK ADDR?
AOS (P) ;NONE
POPJ P,
ECALB: SKIPE P1,%ERRBK ;[4154] GET BREAK ADDR
SKIPGE %ERNM1 ;[4154] DON'T BREAK ON ERRORS WITH NUM1=-1
POPJ P, ;[4154] NO BREAK ADDR OR NUM1 NEGATIVE
ECALB1: MOVE L,EARGPT ;GET ARG POINTER
MOVE T1,%ERNM1 ;GET ERROR CLASS AGAIN
MOVEM T1,@%OECN(L) ;SAVE IT
MOVE T1,%ERRPC ;GET PC
MOVEM T1,@%OEPC(L) ;SAVE IT
MOVE T1,%ERNM2 ;GET 2ND ERROR NUMBER
MOVEM T1,@%OIEN(L) ;SAVE IT
PJRST @%ERRBK ;** Call user routine **
ECHKU: SKIPGE T1,%ERNM1 ;GET ERROR CLASS, NO SUBR IF NEGATIVE
JRST %POPJ1
CAIGE T1,%ERRSZ ;WITHIN TABLE?
SKIPN P1,%ERRSB(T1) ;YES. ANY USER TRAP ROUTINE SPECIFIED?
AOS (P) ;NO. SKIP RETURN
POPJ P,
ECALU: SKIPGE T1,%ERNM1 ;GET ERROR CLASS, NO SUBR IF NEGATIVE
POPJ P,
CAIGE T1,%ERRSZ ;WITHIN TABLE?
SKIPN P1,%ERRSB(T1) ;YES. ANY USER TRAP ROUTINE SPECIFIED?
POPJ P, ;NO. RETURN
MOVEM P1,USRADR ;SAVE ADDR FOR CALL
MOVE L,EARGPT ;GET ARG POINTER
MOVE T1,%ERNM1 ;GET ERROR CLASS AGAIN
MOVEM T1,@%OECN(L) ;SAVE IT
MOVE T1,%ERRPC ;GET PC
MOVEM T1,@%OEPC(L) ;SAVE IT
MOVE T1,%ERNM2 ;GET 2ND ERROR NUMBER
MOVEM T1,@%OIEN(L) ;SAVE IT
XMOVEI L,@EARGPT ;GET ARG POINTER IN WAY SO TRACE LIKES IT
UTRAPC: PUSHJ P,@USRADR ;CALL USER ROUTINE SO TRACE CAN FIND IT
POPJ P,
-%EAEND+%EARGL,,0
%EARGL: IFIW TP%INT,%EARG1
IFIW TP%INT,%EARG2
IFIW TP%INT,%EARG3
IFIW TP%INT,%ERTYP
IFIW TP%UDF,%UNFXD
IFIW TP%UDF,%FIXED
%EAEND=.
SEGMENT DATA
ERSTKP: BLOCK 1 ;ERROR AC STACK POINTER
AERACS: BLOCK 1 ;LOCAL ADDR OF SAVED ACS
ERRSTK: BLOCK 60 ;ERROR AC STACK
MSGPC: BLOCK 1 ;PC FOR MESSAGE
IOERP: BLOCK 1 ;IOERR PNTR SAVE LOC
EARGPT: BLOCK 1 ;ARG LIST POINTER
USRADR: BLOCK 1 ;USER ROUTINE ADDR
FERADR: BLOCK 1 ;FATAL ERROR HANDLER ADDRESS
;ARGS FOR USER ROUTINE
%EARG1: BLOCK 1 ;ERROR CLASS NUMBER
%EARG2: BLOCK 1 ;PC
%EARG3: BLOCK 1 ;ERROR 2ND NUMBER
%ERTYP: BLOCK 1 ;VARIABLE TYPE
%UNFXD: BLOCK 4 ;UNFIXED RESULT
%FIXED: BLOCK 4 ;FIXED RESULT
%LERN1: BLOCK 1 ;ERROR CLASS NUMBER, NOT CLEARED
%LERN2: BLOCK 1 ;2ND ERROR NUMBER, NOT CLEARED
%ERNM1: BLOCK 1 ;ERROR CLASS NUMBER
%ERNM2: BLOCK 1 ;2ND ERROR NUMBER
%ERNM3: BLOCK 1 ;[5007] 3RD ERROR NUMBER (STV FOR RMS)
%ERIOS: BLOCK 1 ;2ND ERROR NUMBER FOR IOSTAT
%ERNAM: BLOCK 1 ;ROUTINE NAME FOR MESSAGE
%ERRPC: BLOCK 1 ;PC TO TYPE
%RMEPT: BLOCK 1 ;[5007] RMS ERROR MSG POINTER
%ERPTR: BLOCK 1 ;POINTER TO ERROR BLOCK
%RMPDP: BLOCK 1 ;[5007] RMS ERROR STACK POINTER
%ERPDP: BLOCK 1 ;STACK POINTER FOR GETPC, NOSYM
%ERCHR: BLOCK 1 ;ERROR CHAR FOR I/O ERRORS
%EOPTR: BLOCK 1 ;OUTPUT ERROR MESSAGE POINTER
%EOCNT: BLOCK 1 ;OUTPUT ERROR MESSAGE COUNT
SEGMENT CODE
;Routine to save the acs
;Call: PUSHJ P,SVEACS
; <return here>
SVEACS: DMOVEM 0,@ERSTKP ;SAVE 0 AND 1
HRRZ 1,ERSTKP ;GET BASE OF SAVED ACS
MOVEM 1,AERACS ;SAVE LOCAL ADDR OF SAVED ACS
MOVEI 0,(1) ;SETUP FOR BLT
ADD 0,[2,,2] ;SAVE 2-17
BLT 0,17(1)
MOVEI 0,20 ;AND ADJUST THE ERROR STACK
ADDM 0,ERSTKP
POPJ P,
;%EMSGT - Get error message text in ERRBUF.
; This routine just sets it up, it does not type it.
; (In case of taking the ERR= branch you don't want to!).
;Input:
;P2 points to error arg block.
%EMSGT: PUSHJ P,EMSGT0 ;Get message text with no null
;Enter here to finish error string
EMSGT1: MOVE T1,INICHR ;GET INITIAL CHAR AGAIN
CAIE T1,"[" ;OPEN BRACKET?
JRST EMSGNL ;PUT A NULL CHAR AT END OF MESSAGE
MOVEI T1,"]" ;YES, TYPE CLOSING BRACKET
PUSHJ P,EPUTCH
EMSGNL: SETZ T1, ;PUT A NULL AT END OF STRING
IDPB T1,ERRPTR ;BUT DON'T COUNT IT AS A CHARACTER
POPJ P,
EMSGT0: XMOVEI P3,%MSG(P2) ;[4013] GET GLOBAL ADDR OF LOCAL BYTE POINTER
HRR P3,%MSG(P2) ;[4013] STEAL Y FIELD OF BYTE POINTER
$BLDBP P3 ;[4013] MAKE POINTER TO INPUT ERROR STRING
MOVE T1,[POINT 7,ERRBUF] ;SET POINTER TO START OF OUTPUT ERR STRING
MOVEM T1,ERRPTR
MOVEI T1,5*LERRBF-1 ;SET COUNT (LEAVE ROOM FOR NULL)
MOVEM T1,ERRCNT
XMOVEI T1,%ARGS-1(P2) ;GET ARG POINTER
MOVEM T1,ARGPTR
MOVE T1,%CHR(P2) ;GET INITIAL CHAR
CAIN T1,"$" ;INDIRECT CHAR?
PUSHJ P,GETARG ;YES, GET PREFIX CHAR
MOVEM T1,INICHR ;SAVE IT
CAIN T1,"@" ;IS IT REALLY BAD?
MOVEI T1,"?" ;YES. SUBSTITUTE A QUERY
PUSHJ P,TYPEQM ;Type it.
ENXTCH: ILDB T1,P3 ;GET NEXT CHAR FROM MSG
JUMPE T1,%POPJ ;END. WE'RE DONE
CAIE T1,"$" ;SPECIAL CHAR?
JRST ECHR ;NO, JUST NORMAL TEXT CHAR
SETZ T2, ;CLEAR ARG
ERARGL: ILDB T1,P3 ;GET CHAR AFTER $
CAIL T1,"0" ;DIGIT?
CAILE T1,"9"
JRST ERRCMD ;NO, GO EXECUTE COMMAND CHAR
IMULI T2,^D10 ;ADD DIGIT INTO ARGUMENT
ADDI T2,-"0"(T1)
JRST ERARGL ;GO FINISH ARG
ERRCMD: MOVEM T2,ERRARG ;SAVE ARGUMENT TO COMMAND
MOVSI T2,-LERRTB ;GET AOBJN POINTER TO ERR TABLE
ERTBLP: HLRZ T3,ERRTAB(T2) ;GET CHAR
CAIE T1,(T3) ;MATCH?
AOBJN T2,ERTBLP ;NO, KEEP LOOKING
JUMPGE T2,ENXTCH ;NOT FOUND, IGNORE
HRRZ T2,ERRTAB(T2) ;GET ROUTINE ADDRESS
PUSHJ P,(T2) ;CALL ROUTINE
JRST ENXTCH ;LOOP
ECHR: PUSHJ P,EPUTCH ;PUT CHAR IN OUTPUT STRING
JRST ENXTCH ;LOOP
;TABLE OF SPECIAL CHAR ACTIONS IN MESSAGES
ERRTAB: XWD "$",$$ ;TYPE $
XWD "[",$LAB ;TYPE LEFT ANGLE BRACKET
XWD "5",$5 ;RADIX50 WORD
XWD "A",$A ;ASCIZ STRING
XWD "C",$C ;ASCII CHAR, RIGHT-JUSTIFIED
XWD "D",$D ;DECIMAL NUMBER
XWD "E",$E ;ADD A USER PC TO THE LINE [4131]
XWD "F",$F ;FILESPEC FROM DDB [NO ARG, USES (D)]
XWD "I",$I ;INCOMPATIBILITY FLAGGER INDEX
XWD "J",$J ;JSYS (TOPS-20) OR I/O (TOPS-10) ERROR
XWD "L",$L ;TYPE VALUE AS SYMBOL+OFFSET
XWD "N",$N ;NAME OF ROUTINE (SIXBIT) FROM %ERNAM [NO ARG]
XWD "O",$O ;OCTAL NUMBER
XWD "P",$P ;ERROR PC, OCTAL [NO ARG]
XWD "R",$R ;RECORD NUMBER
XWD "S",$S ;SIXBIT WORD
XWD "T",$T ;SPACES TO GET TO COL N
XWD "U",$U ;UNIT NUMBER, DON'T TYPE IF NEGATIVE [NO ARG]
XWD "X",$X ;XWD FORMAT, OCTAL
XWD "Y",$Y ;MS TIME AS HH:MM:SS.SS
LERRTB==.-ERRTAB
$LAB: SKIPA T1,["<"] ;TYPE LEFT ANGLE BRACKET [BALANCING >]
$$: MOVEI T1,"$" ;TYPE $
PJRST EPUTCH
$U: SKIPLE %UDBAD ;[4156] ARE WE IN AN I/O STATEMENT?
SKIPGE %CUNIT ;YES. GET UNIT #
POPJ P, ;NOT I/O OR NEG UNIT, NO UNIT NUMBER
MOVEI T1,[ASCIZ / unit /]
PUSHJ P,ASCTYP
MOVE T1,%CUNIT ;GET THE UNIT NUMBER
MOVEI T3,^D10 ;RADIX 10
PJRST NUMLP ;OUTPUT IT
$R: MOVE T1,CREC(D) ;GET CURRENT RECORD NUMBER
JRST DPOS ;GO PRINT IT
$D: PUSHJ P,GETARG ;GET NUMBER TO TYPE
DNOUT: JUMPGE T1,DPOS ;ALL OK IF IT'S POSITIVE
PUSH P,T1 ;NEGATIVE, TYPE MINUS SIGN
MOVEI T1,"-"
PUSHJ P,EPUTCH
POP P,T1
MOVM T1,T1
DPOS: MOVEI T3,^D10 ;RADIX 10
JRST NUMLP
$C: PUSHJ P,GETARG
CAIL T1," "
PJRST EPUTCH
PUSH P,T1
MOVEI T1,"^"
PUSHJ P,EPUTCH
POP P,T1
ADDI T1,100
PJRST EPUTCH
$I: PUSHJ P,GETARG ;GET OFFENDING COMP INDEX
AND T1,%FLIDX ;CALC COMPOSITE INDEX
MOVE T1,%CMSG(T1) ;GET ADDRESS OF PROPER STRING
PJRST ASCTYP ;OUTPUT MESSAGE
$N: MOVE T2,%ERNAM
NOPLP: JUMPE T2,%POPJ ;DONE IF ONLY SPACES LEFT
SETZ T1, ;CLEAR CHAR
LSHC T1,6 ;GET CHAR
ADDI T1,40 ;CONVERT TO ASCII
CAIE T1,"." ;PRINT IF NOT DOT
PUSHJ P,EPUTCH ;OUTPUT CHAR
JRST NOPLP
$S: PUSHJ P,GETARG ;Get next argument from the list (into T1)
; [5010] Check to see if the argument is a sixbit word or a pointer to
; a (null terminated) sixbit string.
SIXTYP: MOVE T2,[POINT 6,T1] ;[5010] Make a byte pointer to the char
ILDB T2,T2 ;[5010] Grab the first byte
JUMPE T2,SIXPTR ;[5010] If it's null then its a pointer
MOVE T2,T1 ;It's a sixbit word just type it out
SIX1: JUMPE T2,%POPJ
SETZ T1,
LSHC T1,6
ADDI T1,40
PUSHJ P,EPUTCH
JRST SIX1
;+ ;[5010]
; SIXPTR - It's a pointer to a SIXBIT string. Output SIXBIT string.
; Address of string is in T1.
; Trashes T2
;-
SIXPTR: MOVE T2,[POINT 3,T1,5];[5021]Make a byte pointer
LDB T3,T2 ;[5021]Get the word count
SKIPN ,T3 ;[5021]It's zero must be SIXBITZ
MOVEI T3,6 ;[5021]Set it to the max size
IMULI T3,6 ;[5021]Calc. max number of bytes
MOVE T2,T1 ;[5021] Get the address of the string
TLZ T2,770000 ;[5025] Shut any of these bits off!
TLO T2,450000 ;[5025] Make the OWGBP
SIXLOP: ILDB T1,T2 ;[5021] Get a byte
JUMPE T1,%POPJ ;[5021] If it's null then end of string,
ADDI T1,40 ;[5021] Else, convert it to ASCII
PUSHJ P,EPUTCH ;[5021] and type out the character.
SOJG T3,SIXLOP ;[5021] Loop for each char in string.
POPJ P, ;[5021]End of routine SIXPTR
$X: PUSHJ P,GETARG
XWDTYP: PUSH P,T1
HLRZ T1,T1
PUSHJ P,OCTTYP
MOVEI T1,","
PUSHJ P,EPUTCH
POP P,T1
MOVEI T1,(T1)
PJRST OCTTYP
$OFFS: PUSHJ P,GETARG ;GET ARG
OFFTYP: JUMPE T1,%POPJ ;DON'T TYPE 0
PUSH P,T1 ;SAVE IT
CAIGE T1,0 ;POSITIVE?
SKIPA T1,["-"] ;NO
MOVEI T1,"+" ;YES
PUSHJ P,EPUTCH ;TYPE SIGN
POP P,T1
MOVM T1,T1
JRST OCTTYP ;TYPE OCTAL NUMBER
$O: SKIPE ERRARG ;$1O MEANS TYPE SIGN FIRST
JRST $OFFS
PUSHJ P,GETARG ;GET ARG IN T1
OCTTYP: MOVEI T3,^D8
NUMLP: LSHC T1,-^D35
LSH T2,-1
DIVI T1,(T3)
JUMPE T1,.+4
PUSH P,T2
PUSHJ P,NUMLP
POP P,T2
MOVEI T1,"0"(T2)
PJRST EPUTCH
$P: MOVE T1,%ERPDP ;GET PDP OF ERROR.
MOVE T1,(T1) ;GET THE CALLER ADDR+1
SUBI T1,1 ;GET ADDR OF CALL
SKIPN %FSECT ;NON-ZERO SECTION?
MOVEI T1,(T1) ;NO. EXCLUDE FLAGS
PJRST OCTTYP ;TYPE IT IN OCTAL
$Y: PUSHJ P,GETARG ;GET TIME IN MS
ADDI T1,5 ;ROUND TO HUNDREDTHS
IDIVI T1,^D10
IDIVI T1,^D100 ;GET SECONDS AND HUNDREDTHS
PUSH P,T2 ;SAVE HUNDREDTHS
PUSHJ P,XTIME ;TYPE HH:MM:SS
MOVEI T1,"." ;TYPE .S
PUSHJ P,EPUTCH
POP P,T1 ;GET HUNDREDTHS
IDIVI T1,^D10 ;BREAK INTO 2 DIGITS
ADDI T1,"0" ;MAKE ASCII
PUSHJ P,EPUTCH ;OUTPUT IT
MOVEI T1,"0"(T2) ;MAKE 2ND DIGIT ASCII
PJRST EPUTCH ;TYPE IT
XTIME: IDIVI T1,^D60 ;GET SECONDS
JUMPE T1,TIMEX ;ANY MINUTES?
PUSH P,T2 ;YES, SAVE SECONDS
IDIVI T1,^D60 ;[3353] GET MINUTES
JUMPE T1,PRMIN ;[3353] ANY HOURS?
PUSH P,T2 ;[3353] YES, SAVE MINUTES
MOVE T2,T1 ;[3353] GET HOURS
PUSHJ P,DPOS ;[3375] TYPE HOURS
MOVEI T1,":" ;[3353] TYPE COLON
PUSHJ P,EPUTCH ;[3353]
POP P,T2 ;[3353] GET MINUTES
PUSHJ P,TIMEZ ;[3353] TYPE MINUTES
TRNA ;[3353]
PRMIN: PUSHJ P,TIMEX ;[3353] TYPE MINUTES
MOVEI T1,":" ;TYPE COLON
PUSHJ P,EPUTCH ;
POP P,T2 ;GET SECONDS
TIMEZ: IDIVI T2,^D10 ;[3353] GET 2 DECIMAL DIGITS
MOVEI T1,"0"(T2) ;TYPE 2-DIGIT NUMBER
PUSHJ P,EPUTCH
MOVEI T1,"0"(T3)
PJRST EPUTCH
TIMEX: IDIVI T2,^D10 ;GET HIGH-ORDER DIGITS
MOVEI T1,"0"(T2)
CAIE T1,"0"
PUSHJ P,EPUTCH
MOVEI T1,"0"(T3)
PJRST EPUTCH
$L: PUSHJ P,GETARG ;GET PC TO CONVERT
MOVEM T1,ORGADR ;SAVE IT
PUSHJ P,SYMCNV ;CONVERT TO LABEL + OFFSET
SKIPN T1,SYMNAM ;GET SYMBOL NAME
JRST MODCNV ;NONE. PRINT MODULE + OFFSET
PUSHJ P,R50TYP ;TYPE IT
MOVE T1,SYMOFF ;GET OFFSET FROM SYMBOL
PJRST OFFTYP ;TYPE IT
MODCNV: MOVE P1,%ERPDP ;GET USER'S PDP
SETZM EADDR
NSYM0: PUSHJ P,GETPC ;GET A PC FROM STACK
JUMPE P1,NSYM1 ;NONE LEFT, DONE
CAML T2,EADDR ;BETTER THAN PREVIOUS BEST APPROXIMATION?
CAMLE T2,ORGADR ;YES, BUT NOT PAST ARG PC?
JRST NSYM0 ;NO, SKIP IT
MOVEM T2,EADDR ;SAVE ROUTINE ADDRESS
JRST NSYM0 ;LOOK THROUGH WHOLE STACK
NSYM1: SKIPN P1,EADDR ;GET ROUTINE ADDRESS
SKIPA P1,@%STADD ;NONE FOUND, USE MAIN START ADDRESS
SKIPA T1,-1(P1) ;GET ROUTINE NAME
MOVE T1,['MAIN. '] ;OR MAIN PROGRAM NAME
PUSHJ P,SIXTYP ;TYPE IT
MOVE T1,ORGADR ;GET ARG PC
SUB T1,P1 ;SUBTRACT ROUTINE ADDRESS
PJRST OFFTYP ;TYPE OFFSET
;Routine called to append the PC to the error message.
$E:
ADDPCM: MOVEI T1,[ASCIZ/ at /]
PUSHJ P,ASCTYP
SKIPN T1,MSGPC ;[5021]Is the PC = zero?
JRST PCTYP ;[5021]just type the PC not symbol!
MOVEM T1,ORGADR ;SAVE FOR CONVERSION
PUSHJ P,SYMCNV ;CONVERT TO LABEL+OFFSET
SKIPN T1,SYMNAM ;GET SYMBOL NAME
JRST NOSYM ;NONE. TRY SEARCHING MODULE NAMES
PUSHJ P,R50TYP ;TYPE RADIX50 SYMBOL
MOVE T1,SYMOFF ;GET OFFSET FROM SYMBOL
PUSHJ P,OFFTYP ;TYPE IT AS SIGNED OCTAL
MOVEI T1,[ASCIZ / in /] ;TYPE NOISE WORD FOR MODULE NAME
PUSHJ P,ASCTYP
MOVE T1,SYMMOD ;GET MODULE NAME
PUSHJ P,R50TYP ;TYPE IT TOO
PCTYP: MOVEI T1,[ASCIZ / (PC /] ;FINISH UP WITH THE OCTAL ADDRESS
PUSHJ P,ASCTYP
HLRZ T1,MSGPC ;GET SECTION #
JUMPE T1,PCTYP0
PUSHJ P,OCTTYP ;Type section #
MOVEI T1,","
PUSHJ P,EPUTCH
PUSHJ P,EPUTCH ;",,"
PCTYP0: HRRZ T1,MSGPC ;GET LOCAL ADDR
PUSHJ P,OCTTYP
MOVEI T1,")"
PJRST EPUTCH
NOSYM: MOVE P1,%ERPDP ;GET USER'S PDP
PUSHJ P,GETPC ;GET A PC FROM STACK
JUMPE P1,USMAIN ;NONE. USE MAIN.
MOVE P1,T2 ;GET ROUTINE ADDR
MOVE T1,-1(P1) ;GET ROUTINE NAME
JRST NSTYPE ;GO TYPE THEM
USMAIN: MOVE P1,@%STADD ;NONE FOUND, USE MAIN START ADDRESS
MOVE T1,['MAIN. '] ;AND MAIN PROGRAM NAME
NSTYPE: PUSHJ P,SIXTYP ;TYPE IT
MOVE T1,ORGADR ;GET ARG PC
SUB T1,P1 ;SUBTRACT ROUTINE ADDRESS
PUSHJ P,OFFTYP ;TYPE OFFSET
PJRST PCTYP ;GO TYPE PC IN OCTAL
$5: PUSHJ P,GETARG ;GET ARG IN T1
JUMPE T1,%POPJ
PUSH P,T1
MOVEI T1," " ;Output a space?
PUSHJ P,EPUTCH
POP P,T1
;+ ;[5017]
; R50TYP - Output a RADIX50 symbol name {to the output buffer}.
; T1 - Contains either a RADIX50 word or a Pointer
; to a SIXBIT string {for long symbol names}.
;-
R50TYP:
;
; [5017] Check to see if the argument is a RADIX50 word or a pointer to
; a (null terminated) sixbit string {for long symbol names}. Check to see
; if any of the first 4 bits are lit. These bits are used if the address
; is a byte pointer and cleared for symbols.
MOVE T2,[POINT 4,T1] ;[5017] Make a byte pointer to the char
ILDB T2,T2 ;[5017] Grab the R50 flags.
JUMPN T2,SIXPTR ;[5017] If there zero then its a pointer
;[5017] Otherwise, It's R50 format.
R50LP: IDIVI T1,50
JUMPE T1,.+4 ;Any more characters?
PUSH P,T2 ;Yes, put this one on the stack
PUSHJ P,R50LP ; and type it out
POP P,T2 ;No,
JUMPE T2,%POPJ
MOVEI T1,<"0"-R50(0)>(T2)
CAILE T1,"9"
ADDI T1,"A"-R50(A)-"0"+R50(0)
CAILE T1,"Z"
SUBI T1,-<"$"-R50($)-"A"+R50(A)>
CAIN T1,"$"-1
MOVEI T1,"."
JRST EPUTCH
;+
; EPUTCH - Outputs a character to the error message buffer.
; T1/ Contains the ASCII character to be output.
;-
EPUTCH: AOS COLCNT ;KEEP TRACK OF WHAT COL WE'RE ON
SOSL ERRCNT ;DECREMENT COUNT OF CHARS LEFT
IDPB T1,ERRPTR ;SPACE LEFT, STORE CHAR
POPJ P,
;+
; GETARG - Gets the next arg on the argument list.
; DOES NOT SUPPORT INDEXING OR INDIRECTION
;-
GETARG: AOS T1,ARGPTR ;GET CURRENT POINTER
MOVE T1,(T1) ;GET ARG ADDR
CAIG T1,17 ;IS ARG IN AC?
JRST ACARG ;YES. GO GET IT
HLL T1,ARGPTR ;ADD SECTION # OF CALLER
MOVE T1,(T1) ;GET ACTUAL ARG
POPJ P,
ACARG: ADD T1,AERACS ;POINT TO SAVED AC
MOVE T1,(T1) ;GET ACTUAL ARG
POPJ P,
IF10,<
ESAVE: POPJ P, ;[4131] ERROR CODE IS ALREADY IN T1!
$J: MOVE T1,AERACS ;GET ADDRESS OF SAVED ACS
MOVE T1,T1(T1) ;GET SAVED T1
TXNE T1,IO.IMP!IO.DER!IO.DTE!IO.BKT!IO.EOF ;[4131] I/O ERROR?
JRST IEROUT ;YES
CAIL T1,0 ;NEGATIVE?
CAILE T1,LERMAX ;OR TOO BIG?
JRST LERUNK ;YES, TYPE GENERAL-PURPOSE MSG
MOVEI T2,(T1) ;COPY ERROR CODE
ADDI T2,^D250 ;ADD 250, BECAUSE V5A DID IT...
MOVEM T2,%ERNM2 ;Fix error number
JUMPN T1,LERNAM ;[4131] NOT AMBIGUOUS
LOAD T2,INDX(D) ;[4131] GET DEVICE INDEX
CAIE T2,DI.DSK ;[4131] DISK?
JRST WRGDIR ;[4131] NO. GIVE "WRONG DIRECTION" MSG
LERNAM: IDIVI T1,4 ;[4131] GET STRING OFFSET
LDB T1,LERTBL(T2)
CAIN T1,777 ;NO MSG FOR THIS ERROR?
JRST LERUNK ;YES, GO TYPE G.P. MSG
MOVEI T1,LERMSG(T1) ;GET STRING ADDRESS
PJRST ASCTYP ;GO TYPE IT
LERUNK: MOVEI T1,[ASCIZ /Unknown FILOP error, code /]
PUSHJ P,ASCTYP
MOVE T1,AERACS ;GET ADDRESS OF SAVED ACS
MOVE T1,T1(T1) ;GET SAVED T1
PJRST OCTTYP ;TYPE IT
WRGDIR: MOVEI T1,[ASCIZ /Wrong direction for device/] ;[4131]
PJRST ASCTYP ;[4131] TYPE MESSAGE AND LEAVE
LERTBL: POINT 9,LERPTR(T1),8
POINT 9,LERPTR(T1),17
POINT 9,LERPTR(T1),26
POINT 9,LERPTR(T1),35
DEFINE X (STRG) <
XOFFS==[ASCIZ \STRG\]-LERMSG
XXX (XOFFS)
>
DEFINE XX (STRG) <
XXX (-1)
>
DEFINE XXX (OFFS) <
XXXWD==XXXWD + <OFFS&777>_<XXXCT*9>
XXXCT==XXXCT-1
IFL XXXCT,<
EXP XXXWD
XXXWD==0
XXXCT==3
>
>
XXXWD==0
XXXCT==3
LERPTR: X No such file ;0
X No such directory ;1
X Protection failure ;2
X File is being modified ;3
X File already exists ;4
XX Illegal sequence of UUOs ;5
X RIB error ;6
XX Bad format .SAV file ;7
XX Insufficient memory ;10
X Device is not available ;11
X Can't OPEN device ;12
XX Illegal UUO ;13
X Device full ;14
X Device is write locked ;15
X Insufficient monitor table space ;16
XX Can't allocate contiguous space ;17
XX Requested block not free ;20
X Can't write a directory ;21
X Directory is not empty ;22
X No such directory ;23
X Search list empty ;24
X SFDs nested too deep ;25
X All structures have NOCREATE set ;26
XX Segment not in swap space ;27
X Can't update file ;30
XX Page overlap ;31
XX Not logged in ;32
X Locks still set ;33
XX Bad format .EXE file ;34
XX Extension must be .EXE ;35
XX .EXE directory too big ;36
X Network full ;37
X Task not available ;40
X No such node ;41
X SFD in use ;42
X File has an NDR lock ;43
X Monitor use count overflow ;44
X Can't rename SFD downward ;45
XX Channel not open ;46
X Device is down ;47
X Device is restricted ;50
X Device must be mounted ;51
X Device is assigned to another job ;52
X Illegal data mode ;53
XX Unknown OPEN bits ;54
X Device is not available ;55
X Funny space full ;56
X Too many open units ;57
XX Unknown function code ;60
XX Illegal channel number ;61
XX Illegal channel number ;62
LERMAX==62 ;MAX STRING IN TABLE
IFN XXXCT-3,<EXP XXXWD>
LERMSG: ;LIT
XLIST
LIT
LIST
;STILL IF10
;TYPE IO ERROR MESSAGE
IEROUT: PUSHJ P,%SAVE3 ;SAVE P ACS
MOVEI T1,[ASCIZ /IO error /]
PUSHJ P,ASCTYP
MOVE T1,AERACS ;GET ADDRESS OF SAVED ACS
MOVE T1,T1(T1) ;GET SAVED T1
SKIPN %ERNM2 ;IF NO 2ND NUMBER YET
MOVEM T1,%ERNM2 ;STORE I/O ERROR BITS
HRLZ P1,T1 ;SAVE THEM, IN LH
PUSHJ P,OCTTYP ;TYPE THEM IN OCTAL
MOVE D,AERACS ;GET ADDRESS OF SAVED ACS
MOVE D,D(D) ;GET DDB POINTER
TLZ P1,-1-IO.ERR-IO.EOF-IO.EOT ;CLEAR BORING BITS
LOAD T4,DVTYP(D) ;GET DEVTYP
CAIN T4,.TYMTA ;MTA?
TLZ P1,IO.EOT ;NO, EOT ISN'T REALLY EOT, SO IS BORING
LOAD T1,INDX(D) ;GET DEV INDEX
CAIN T1,DI.DSK ;DISK?
MOVEI T4,.TYDSK ;YES, SPOOLED DEV OR REAL DISK
MOVEI P3,IBUF-1 ;POINT TO BUFFER FOR MSGS
JRST IOENXT ;GO DO FIRST BIT
IOELP: ANDCM P1,[EXP 1B0,1B1,1B2,1B3,1B4,1B5,1B6,1B7](P2) ;CLEAR BIT
DPB P2,[POINT 3,T4,29] ;STORE ERROR CODE WITH DEVTYP
MOVEI T3,(T4) ;COPY ERR BIT & DEV TYP
IOELP1: MOVE T2,[-LITAB,,ITAB] ;POINT TO TABLE
IOELP2: LDB T1,[POINT 9,(T2),9] ;GET ERR BIT & DEVTYP
CAIE T1,(T3) ;MATCH?
AOBJN T2,IOELP2 ;NO, KEEP LOOKING
JUMPL T2,IOEEND ;JUMP IF WE FOUND IT
ORI T3,.TYXXX ;USE DEFAULT IF NOT FOUND
JRST IOELP1
IOEEND: MOVE T2,(T2) ;GET MESSAGE POINTER
PUSH P3,T2 ;SAVE MESSAGE FOR THIS BIT
IOENXT: JFFO P1,IOELP ;DO NEXT BIT
PUSH P3,[0] ;FLAG END OF LIST
MOVEI P1,IBUF
SKIPA T1,[[ASCIZ / (/]] ;FIRST MSG GETS PAREN
MSGLP: MOVEI T1,[ASCIZ /, /] ;OTHERS GET COMMAS
SKIPN P2,(P1) ;GET A MSG
JRST MSGEND ;NONE LEFT
PUSHJ P,ASCTYP ;TYPE PAREN OR COMMA
CAIL P2,0 ;ROUTINE TO CALL?
PUSHJ P,(P2) ;YES, CALL IT
SKIPE T1,P2 ;POINT TO STRING
PUSHJ P,ASCTYP ;TYPE IT
AOJA P1,MSGLP ;LOOP OVER ALL MSGS
MSGEND: MOVEI T1,")" ;TYPE CLOSE PAREN
SKIPE IBUF
PUSHJ P,EPUTCH
HLLZ T2,CHAN(D) ;CLEAR ERROR BITS
HRRI T2,.FOSET
MOVE T3,@ARGPTR ;GET BITS BACK
ANDI T3,-1-IO.ERR ;CLEAR ERR BITS, LEAVE EOF AND EOT
MOVE T1,[2,,T2] ;SET LENGTH, ADDRESS
FILOP. T1, ;DO FILOP
JFCL
POPJ P,
;STILL IF10
.TYXXX==77 ;FAKE DEVTYP FOR DEFAULT DEVICE
DEFINE X (DEV,ERR,FATAL<0>,MSG) <
BYTE (1)1(3)^L<IO.'ERR,,0>(6).TY'DEV(1)FATAL(7)0(18)[ASCIZ \MSG\]
>
DEFINE XS (DEV,ERR,FATAL<0>,SUB) <
BYTE (1)0(3)^L<IO.'ERR,,0>(6).TY'DEV(1)FATAL(7)0(18)SUB
>
ITAB: X CDP,BKT,,card too large
X CDR,IMP,,nonbinary card
X CDR,DTE,,checksum error
X MTA,IMP,1,write locked
X MTA,DTE,,parity error
X MTA,BKT,,record exceeds BLOCKSIZE
X MTA,EOT,1,EOT
X PTR,IMP,,block incomplete
X PTR,DTE,,checksum error
X PTY,BKT,,char lost
X TTY,IMP,1,not assigned
X TTY,DER,1,^C typed
X TTY,DTE,,echo check
X TTY,BKT,,char lost
XS DSK,IMP,1,DSKIMP ;write locked or RIB error
X DSK,DTE,,parity error
XS DSK,BKT,1,DSKBKT ;str full or quota exceeded
X DTA,IMP,1,write locked
X DTA,DTE,,parity error
X DTA,BKT,1,tape full
X XXX,IMP,1,improper mode (whatever that means)
XS XXX,DER,,XXXDER ;device error
X XXX,DTE,,data error
X XXX,BKT,,block too large
X XXX,EOF,,end of file
X XXX,EOT,,EOT ;SNH
LITAB==.-ITAB
SEGMENT DATA
IBUF: BLOCK 6 ;ONE MESSAGE EACH FOR 5 POSSIBLE BITS
DCBLK: BLOCK 1+.DCFCT ;ARG BLOCK FOR DSKCHR
SEGMENT CODE
;STILL IF10
DSKBKT: SKIPN T1,PTHB+.PTSTR(D);GET STR FILE IS ON
JRST DSKFUL ;CAN'T, JUST SAY DISK FULL
MOVEM T1,DCBLK ;SAVE FOR DSKCHR
MOVE T1,[1+.DCFCT,,DCBLK] ;SET UP FOR DSKCHR
DSKCHR T1,UU.PHY ;FIND SPACE REMAINING
JRST DSKFUL
MOVE P2,[X (DSK,BKT,1,quota or storage exceeded)]
SKIPG DCBLK+.DCUFT ;CHECK BLOCKS LEFT IN QUOTA
MOVE P2,[X (DSK,BKT,1,quota exceeded)]
SKIPG DCBLK+.DCFCT ;CHECK BLOCKS LEFT ON STR
DSKFUL: MOVE P2,[X (DSK,BKT,1,structure full)]
POPJ P,
DSKIMP: SKIPN T1,PTHB+.PTSTR(D) ;GET STR NAME
JRST DSKWL ;CAN'T
MOVEM T1,DCBLK ;SAVE FOR DSKCHR
MOVE T1,[1,,DCBLK] ;SET FOR DSKCHR
DSKCHR T1,UU.PHY ;FIND WRITE-LOCK STATUS
JRST DSKWL
TXNE T1,DC.HWP+DC.SWP ;CHECK WRITE PROTECTION
JRST DSKWL ; IT'S WRITE-LOCK
MOVE T1,LKPB+.RBSTS(D) ;GET RIB STATUS WORD
MOVE P2,[X (DSK,IMP,1,checksum error)]
TXNN T1,RP.FCE ;CHECKSUM ERROR?
MOVE P2,[X (DSK,IMP,1,RIB error)] ;NO
POPJ P,
DSKWL: MOVE P2,[X (DSK,IMP,1,write locked)]
POPJ P,
XXXDER: SETZ P2, ;CLEAR OUTPUT MSG, WE'LL DO THE TYPING
MOVEI T1,[ASCIZ /device error/]
PUSHJ P,ASCTYP
LDB T1,[POINTR CHAN(D),FO.CHN] ;GET CHANNEL NUMBER
DEVSTS T1, ;GET CONI AT LAST INTERRUPT
POPJ P, ;CAN'T
PUSH P,T1 ;TYPE IT
MOVEI T1,[ASCIZ /, CONI /]
PUSHJ P,ASCTYP
POP P,T1
PJRST OCTTYP
> ;IF10
IF20,<
;[4131] NEW CODE
ESAVE: LOAD T1,STS(D) ;[5007] GET STS CODE
CAMGE T1,%ERMIN ;[5007] RMS ERROR?
TRNA ;[5007] NO
PJRST %RMERR ;[5007] YES, HANDLE STS ($SNH NEVER RETURNS)
MOVEI T1,.FHSLF ;GET JSYS ERROR NUMBER FOR LAST ERROR
GETER%
ERJMP .+1
MOVE T1,AERACS ;GET ADDRESS OF SAVED ACS
MOVEM T2,T1(T1) ;SAVE ERROR CODE IN SAVED AC1
POPJ P,
;[4131] NEW CODE
$J: LOAD T1,STS(D) ;[5007] GET STS CODE
CAMGE T1,%ERMIN ;[5007] RMS ERROR?
TRNA ;[5007] NO
JRST RMSERS ;[5007] YES, GO HANDLE
MOVE T1,AERACS ;GET ADDRESS OF SAVED ACS
MOVE T1,T1(T1) ;GET SAVED T1
MOVEI T2,(T1) ;GET JUST RIGHT HALF
SKIPN %ERNM2 ;IS 2ND ERROR NUMBER 0?
MOVEM T2,%ERNM2 ;YES. STORE JSYS ERROR NUMBER
CAIN T2,GJFX3 ;"No JFNs available"?
JRST NOJFNA ;Yes, doing ERSTR% doesn't help!
MOVE T1,ERRPTR ;GET POINTER TO DESTINATION STRING
HRLI T2,.FHSLF
MOVN T3,ERRCNT ;NEGATIVE OF NUMBER OF CHARS IN BUFFER
MOVSI T3,(T3) ;IN LEFT HALF
ERSTR% ;GET ERROR STRING
JRST ERNSE ;NO SUCH ERROR
TRN ;STRING TOO SHORT, MSG TRUNCATED
EXCH T1,ERRPTR ;SAVE NEW PNTR, GET OLD ONE BACK
MOVEI T2,(T1) ;GET JUST RIGHT HALF
HRRZ T3,ERRPTR ;GET JUST ADDRESS OF NEW PNTR
SUBI T3,(T2) ;GET # WORDS USED
IMULI T3,IBPW ;GET # CHARS USED
MULI T1,IBPW ;GET # BYTES NOT USED BY OLD PNTR
ADDI T3,(T1) ;ADD THEM
MOVE T1,ERRPTR ;GET NEW PNTR AGAIN
MULI T1,IBPW ;GET # BYTES NOT USED BY NEW PNTR
SUBI T3,(T1) ;SUBTRACT THEM
MOVNI T3,(T3) ;GET NEGATIVE
ADDM T3,ERRCNT ;DECREMENT COUNT
POPJ P,
NOJFNA: MOVEI T1,[ASCIZ/no JFNs available/] ;Get error
PJRST ASCTYP
ERNSE: SKIPA T1,[[ASCIZ /(undefined error number)/]]
ERERR: MOVEI T1,[ASCIZ /(error in ERSTR)/]
PJRST ASCTYP
RMSERS: MOVE T1,%RMEPT ;[5007] GET RMS MSG POINTER
PUSHJ P,ASCTYP ;[5007] OUTPUT IT
PJRST %RMECL ;[5007] CLEAN UP AFTER RMS ERROR
>;END IF20
;Type filespec from DDB
$F: PUSHJ P,GETARG ;GET UDB ADDRESS
JUMPLE T1,%POPJ ;[4156] IF ZERO, NOTHING TO PRINT
SKIPN D,DDBAD(T1) ;GET DDB POINTER
POPJ P, ;NONE. DON'T PRINT TRASH
MOVEI T1," " ;OUTPUT SPACE
PUSHJ P,EPUTCH
MOVE T1,[POINT 7,JFNBUF] ;GET FILESPEC
PUSHJ P,%ERFNS
MOVEI T1,JFNBUF ;POINT TO FILESPEC BUFFER
PJRST ASCTYP ;OUTPUT IT
SEGMENT DATA
JFNBUF: BLOCK LTEXTW ;Buffer for JFNS string
SEGMENT CODE
$T: MOVE T2,ERRARG ;GET COL TO TAB TO
SUB T2,COLCNT ;GET NUMBER OF SPACES WE NEED
MOVEI T1," "
PUSHJ P,EPUTCH ;TYPE A SPACE
SOJG T2,.-1 ;LOOP UNTIL AT DESIRED COL
POPJ P, ;DONE
$A: PUSHJ P,GETARG ;GET ADDRESS OF STRING
ASCTYP: HRLI T1,(POINT 7,) ;MAKE INTO BYTE POINTER
MOVE T4,T1 ;PUT IN SAFE PLACE
ASCLP: ILDB T1,T4 ;GET CHAR OF STRING
JUMPE T1,%POPJ ;NULL TERMINATES STRING
PUSHJ P,EPUTCH ;TYPE CHAR
JRST ASCLP ;LOOP
;Routine to get initial PREFIX part of message
;CAll: t1/ prefix char
TYPEQM: JUMPE T1,TYPQM1 ;Don't type anything if no char
PUSHJ P,EPUTCH ;Type char
IF10,<
MOVE T1,%MSLVL ;Get message level
TXNN T1,JW.WPR ;Does user want prefix?
JRST NPR ;No, skip it
HLRZ T1,%COD(P2) ;Get 3-letter error code
HRLI T1,'FRS' ;Put in FOROTS prefix
PUSHJ P,SIXTYP ;Type it
MOVEI T1," " ;Follow with space
PUSHJ P,EPUTCH
NPR:
>;END IF10
TYPQM1: SETZM COLCNT ;Start counting cols for tabs
POPJ P, ;Return
;TYPE INPUT RECORD (PRESUMABLY CONTAINING AN ERROR) AND PUT AN ARROW
;UNDER THE ERRONEOUS CHARACTER. THE ERROR POSITION IS GOTTEN FROM RPOS.
RCTYB1: MOVNI T1,1 ;MOVE POINTER BACK 1 CHAR
PUSHJ P,%CIPOS
RECTYP: SETZM ERRCNT ;CLEAR # CHARS IN ERROR BUFFER
PUSHJ P,%RIPOS ;GET POSITION OF NEXT CHAR
SUBI T1,1 ;GET POSITION OF BAD CHAR
MOVEI T2,(T1) ;COPY IT
CAILE T2,BEFSIZ ;MORE THAN WILL FIT?
MOVEI T2,BEFSIZ ;YES. SUBSTITUTE JUST ENOUGH
MOVEM T2,ERRPOS ;SAVE FOR PRINTING THE ARROW
SUBI T1,(T2) ;CHOP OFF UNNEEDED CHARS
ADDI T1,1 ;POINT TO CORRECT CHAR
PUSHJ P,%SIPOS
MOVE T1,[POINT 7,ER1BUF] ;PREPARE TO COPY RECORD TO ERROR BUFFER
MOVEM T1,ER1PTR ;SAVE PNTR
MOVE T3,ERRPOS ;GET POSITION OF BAD CHAR
SOJLE T3,ILCPEC ;GET # CHARS PRECEDING IT FOR ARROW
ILCLP: PUSHJ P,%IBYTE ;GET CHAR FROM RECORD
PUSHJ P,PUTERC ;PUT IN BUFFER
SOJG T3,ILCLP ;COPY RECORD UP TO BAD CHAR
ILCPEC: PUSHJ P,%IBYTE ;GET BAD CHAR
PUSHJ P,PUTER1 ;STORE IT
MOVEI T3,BEFSIZ+AFTSIZ ;GET TOTAL ALLOWED SANDWICH
SUB T3,ERRPOS ;MINUS CHARS ALREADY OUT
ILCLP2: SKIPG IRCNT(D) ;AND CHARS IN RECORD?
JRST ILCEND ;NO
PUSHJ P,%IBYTE ;GET NEXT CHAR
PUSHJ P,PUTER1 ;STORE IT
SOJG T3,ILCLP2
ILCEND: PUSHJ P,BUFTYP ;TYPE RECORD
PJRST AROUT ;NOW OUTPUT ARROW LINE
PUTERC: CAIN T1,177 ;RUBOUT?
MOVNI T1,1 ;YES. MAKE IT -1
CAIN T1,0 ;NULL?
MOVEI T1," " ;YES. MAKE IT A SPACE
CAIGE T1," " ;OR OTHER NON-PRINTING CHAR?
JRST ERCTL ;YES. GO PRECEDE WITH "^"
IDPB T1,ER1PTR ;NO. JUST DEPOSIT IT
AOS ERRCNT ;INCR # CHARS IN BUFFER
POPJ P,
PUTER1: CAIN T1,177 ;RUBOUT?
MOVNI T1,1 ;YES. MAKE IT -1
CAIN T1,0 ;NULL?
MOVEI T1," " ;YES. MAKE IT A SPACE
CAIGE T1," " ;OTHER NON-PRINTING CHAR?
JRST ER1CTL ;YES. PRECEDE WITH "^"
IDPB T1,ER1PTR ;NO. JUST STORE IT
AOS ERRCNT ;INCR # CHARS IN BUFFER
POPJ P,
ERCTL: AOS ERRPOS ;INCR ARROW SPACE COUNT FOR "^"
ER1CTL: MOVEI T2,"^" ;OUTPUT UP-ARROW
IDPB T2,ER1PTR
ADDI T1,100 ;CTL CHARS TO UPPER CASE, RUBOUT TO "?"
IDPB T1,ER1PTR ;STORE IT
MOVEI T1,2 ;ADD 2 TO COUNT
ADDM T1,ERRCNT
POPJ P,
BUFTYP: SETZ T1, ;DEPOSIT A NULL AT THE END
IDPB T1,ER1PTR
MOVE T1,[POINT 7,ER1BUF] ;ERROR BUFFER
MOVEM T1,%EOPTR ;SAVE IT
MOVE T1,ERRCNT ;GET # CHARS IN IT
MOVEM T1,%EOCNT ;SAVE IT
PJRST %EOREC ;Type it and return
AROUT: MOVE T4,[POINT 7,ER1BUF] ;POINT TO ERROR BUFFER AGAIN
MOVE T3,ERRPOS ;GET SPACE COUNT
SOJLE T3,PUTARO ;IF 1, JUST OUTPUT THE ARROW
SETZB T0,T1 ;NO SOURCE
EXTEND T0,[EXP <MOVSLJ>," "] ;PAD WITH SPACES
$SNH
PUTARO: MOVEI T1,"^" ;PUT IN ARROW
IDPB T1,T4
SETZ T1, ;AND FINALLY A NULL CHAR
IDPB T1,T4
MOVE T1,[POINT 7,ER1BUF] ;POINT TO IT YET AGAIN
MOVEM T1,%EOPTR ;SAVE IT
MOVE T1,ERRPOS ;AND SAVE # CHARS IN ARROW LINE
MOVEM T1,%EOCNT
PJRST %EOREC ;TYPE IT
;TYPE FORMAT (PRESUMABLY CONTAINING AN ERROR) AND PUT AN ARROW UNDER THE
;ERRONEOUS CHARACTER. THE ERROR POSITION IS GOTTEN FROM FMT.BP.
FMTTYP: SETZM ERRCNT ;CLEAR # CHARS IN ERROR BUFFER
MOVE T1,USR.SZ ;GET FORMAT SIZE
SUB T1,FMT.SZ ;GET CURRENT POSITION
MOVEI T2,(T1) ;COPY IT
CAILE T2,BEFSIZ ;TOO BIG?
MOVEI T2,BEFSIZ ;YES. TRUNCATE IT
MOVEM T2,ERRPOS ;SAVE ERROR CHAR POSITION
SUBI T1,(T2) ;GET NUMBER OF CHARS TO SKIP
MOVE T3,USR.SZ ;GET # CHARS IN FORMAT AGAIN
SUBI T3,(T1) ;GET # CHARS IN TRUNCATED FORMAT
CAILE T3,BEFSIZ+AFTSIZ ;BUT NOT MORE THAN A PROPER SANDWICH
MOVEI T3,BEFSIZ+AFTSIZ
MOVEM T3,FMTCNT ;SAVE IT
ADJBP T1,FMT.BG ;GET A POINTER TO THE FORMAT
MOVEM T1,ERRPTR ;SAVE IT
MOVE T1,[POINT 7,ER1BUF] ;POINT TO ERROR BUFFER
MOVEM T1,ER1PTR
MOVE T3,ERRPOS ;GET # CHARS PRECEDING ERROR CHAR
SOJLE T3,FMTPEC ;IF NONE, GO OUTPUT ERROR CHAR
FMTELP: ILDB T1,ERRPTR ;GET A CHAR
PUSHJ P,PUTERC ;STORE IN ERROR BUFFER, SPACE IN ARROW LINE
SOJG T3,FMTELP
FMTPEC: ILDB T1,ERRPTR ;GET ERROR CHAR
PUSHJ P,PUTER1 ;STORE IN ERROR BUFFER
MOVE T3,FMTCNT ;GET TOTAL # CHARS AGAIN
SUB T3,ERRPOS ;GET SIZE OF REST OF FORMAT
FMTEL2: ILDB T1,ERRPTR ;GET ANOTHER FORMAT CHAR
PUSHJ P,PUTER1 ;STORE IN ERROR BUFFER
SOJG T3,FMTEL2
PUSHJ P,BUFTYP ;OUTPUT FORMAT
PJRST AROUT ;OUTPUT ARROW LINE
SEGMENT DATA
BEFSIZ==^D50 ;50 CHARS BEFORE ILCHR PRINTED
AFTSIZ==^D20 ;20 CHARS AFTER ILCHR
RERRBF==30 ;LENGTH OF RECORD AND FORMAT BUFFER
LERRBF==:60 ;[5007] LENGTH OF MESSAGE BUFFER, WORDS
G.ERBF:: ;GLOBAL TAG
ERRBUF: BLOCK LERRBF ;BUFFER FOR THE ERROR MESSAGE
ERRCNT: BLOCK 1 ;COUNT OF CHARS LEFT IN IT
ERRPTR: BLOCK 1 ;POINTER TO NEXT FREE CHAR
ER1PTR: BLOCK 1 ;POINTER TO ERROR LINE BUFFER
ER1BUF: BLOCK RERRBF ;Buffer for the record
FMTCNT: BLOCK 1 ;FORMAT SIZE FOR PRINTING
ERRPOS: BLOCK 1 ;POSITION OF ERROR CHARACTER
INICHR: BLOCK 1 ;PREFIX CHAR OF ERROR MESSAGE
ERRARG: BLOCK 1 ;ARG TO $<N>X COMMAND
COLCNT: BLOCK 1 ;COLUMN NUMBER
ARGPTR: BLOCK 1 ;POINTER TO NEXT ARG
EADDR: BLOCK 1 ;ERROR ADDRESS TEMP
SUBTTL TRACE
SEGMENT CODE
$ERR (,TR0,-1,0)
$ERR (,TR1,-1,0,<$S$1T($O)$31T$[$[--$36T$S$1O$1T($O)$71T$D$75T$A>,<RNAME,RPC,CNAME,OFFS,CPC,TRARGS,RGPTR>) ;[5010]
$ERR (,TR2,-1,0,<$S$1T($O)$31T$[$[--$36TERRSET subroutine call$71T$D$75T$A>,<RNAME,RPC,TRARGS,RGPTR>) ;[5010]
$ERR (,TRC,-1,0,< Name (Loc) $[$[-- Called From (Loc) Args Types>) ;[5010]
FENTRY (TRACE)
MOVEM P,%ERPDP ;AND ERROR STACK FOR MODCNV
%TRACX: PUSHJ P,SVEACS ;SAVE USER'S ACS
SETZM MSGPC ;NO PC ON EACH MESSAGE, PLEASE
MOVE P1,P ;GET TRACE PDP
PUSHJ P,GETPC ;GET TOP CALL ON STACK
JUMPE P1,ERRET ;NONE THERE, RESTORE ACS AND RETURN
MOVEM P1,SAVPC ;SAVE DECREMENTED PC
MOVEM T1,CPC ;[3155] Save caller PC
MOVEM T2,RPC ;[3155] Save routine address
MOVEM T3,TRARGS ;[4021] SAVE ARGLIST FOR LATER
MOVE T3,-1(T2) ;GET SIXBIT SUBROUTINE NAME
MOVEM T3,RNAME ;SAVE IT
XMOVEI T1,E.TR0+%EOFF ;OUTPUT BLANK LINE
MOVEM T1,%ERPTR
PUSHJ P,FOREC
XMOVEI T1,E.TRC+%EOFF ;OUTPUT TRACE HEADER
MOVEM T1,%ERPTR
PUSHJ P,FOREC
TRACEL: MOVE P1,SAVPC ;GET DECREMENTED PC FROM LAST CALL
PUSHJ P,GETPC ;GET NEXT PC ON STACK
MOVEM P1,SAVPC ;AND SAVE DECREMENTED ONE
PUSH P,T1 ;SAVE INFO FOR NEXT LOOP
PUSH P,T2
PUSH P,T3
MOVE T4,CPC ;GET CALLER PC
SUB T4,T2 ;[3155] Subtract start of caller's routine
MOVEM T4,OFFS
CAIN P1,0 ;MAIN PROGRAM?
SKIPA T4,[SIXBIT /MAIN./] ;YES, GET ITS NAME
MOVE T4,-1(T2) ;SUBROUTINE, GET NAME
MOVEM T4,CNAME ;SAVE AS CALLER'S NAME
SETZM STRNG ;INIT TO NULLS
MOVE T1,[STRNG,,STRNG+1] ;SETUP
BLT T1,STRNG+STRWDS-1 ;INIT STRING
MOVE T1,[POINT 7,STRNG] ;PTR TO STRING
MOVEM T1,RGPTR ;STORE FOR ERR MACRO
MOVE T3,TRARGS ;[4021] RETRIEVE ARGLST
HLRE T4,-1(T3) ;[4021] COUNT
MOVNM T4,TRARGS ;STORE FOR ERR MACRO
SKIPN T5,TRARGS ;[4021] ANY ARGS?
JRST TRCSHO ; NOPE, GO DISPLAY
CAIG T5,STRLEN ;[4021] TOO MANY ARGS TO DISPLAY?
JRST TRCPTR ; NOPE, GO FINISH SETTING UP
MOVEI T5,STRLEN ;[4021] SET COUNTR TO MAX
MOVE T4,[ASCIZ/.../] ;UNDISPLAYED ARGS
MOVEM T4,STRNG+STRWDS ;STORE
TRCPTR: MOVE T4,[POINT 7,STRNG] ;DEST PTR
TRCRGL: LDB T1,[POINT 4,(T3),12] ;GET DATA TYPE
IDIVI T1,5 ;IN WHICH WORD IS SYMBOL?
MOVE T0,TYPCOD(T1) ;LOAD THE WORD
IMULI T2,7 ;REMAINDER TO BIT OFFSET
ROT T0,7(T2) ;RIGHT JUSTIFY DATA TYPE SYMBOL
IDPB T0,T4 ;SYMBOL TO STRNG
AOJ T3, ;[4021] BUMP ARG PTR
SOJG T5,TRCRGL ;[4021] LOOP IF MORE ARGS
TRCSHO: XMOVEI T1,E.TR1+%EOFF ;OUTPUT A TRACE LINE
MOVE T2,CPC ;GET CALLER PC
XMOVEI T3,UTRAPC ;GET EXTENDED ADDR OF ERRSET CALL LOC
CAMN T2,T3 ;IS IT AN ERRSET CALL?
XMOVEI T1,E.TR2+%EOFF ;YES. USE AN ALTERNATE TRACE LINE
MOVEM T1,%ERPTR
PUSHJ P,FOREC
POP P,T3 ;RESTORE 'GETPC' DATA FOR LOOP
POP P,T2
POP P,T1
MOVEM T1,CPC ;[3155] Save caller PC
MOVEM T2,RPC ;[3155] Save routine address
MOVEM T3,TRARGS ;[4021] SAVE ARGLST FOR LATER
MOVE T3,-1(T2) ;GET SIXBIT SUBROUTINE NAME
MOVEM T3,RNAME ;SAVE IT
SKIPE SAVPC ;ANY MORE STACK TO TRACE?
JRST TRACEL ;YES. GO DO IT
XMOVEI T1,E.TR0+%EOFF ;NO. OUTPUT BLANK LINE
MOVEM T1,%ERPTR
PUSHJ P,FOREC ;AND LEAVE
JRST ERRET ;GO RESTORE ACS
STRWDS==3 ;WORDS TO ACCOMODATE ARGUMENT SYMBOL STRING
STRLEN==5*STRWDS ;5 ASCII BYTES PER WORD
; 0123456701234567
TYPCOD: ASCII /ILIUFUOSDIOGXCUH/
repeat 0,<
DATA TYPE
0 INTEGER
1 LOGICAL
2 INTEGER
3
4 REAL
5
6 OCTAL
7 STATEMENT LABEL
10 DOUBLE REAL
11 DOUBLE INTEGER
12 DOUBLE OCTAL
13 G-FLOATING
14 COMPLEX
15 CHARACTER
16
17 LITERAL STRING
>
SEGMENT DATA
STRNG: BLOCK STRWDS+1 ;SYMBOL STRING + '...'
SAVPC: BLOCK 1 ;PLACE FOR DECREMENTED PC FROM GETPC
CPC: BLOCK 1 ;CALLER PC
RPC: BLOCK 1 ;ROUTINE PC
CNAME: BLOCK 1 ;CALLER NAME
RNAME: BLOCK 1 ;ROUTINE NAME
OFFS: BLOCK 1 ;OFFSET FROM BEGINNING OF CALLER
TRARGS: BLOCK 1 ;# ARGUMENTS
RGPTR: BLOCK 1 ;STRING POINTER FOR ERROR MACRO
SEGMENT CODE
;ROUTINE TO FIND THE NEXT PC ON THE STACK
;ARG: P1 = POINTER TO STACK
;RETURN: P1 = UPDATED TO PAST RETURNED PC, 0 IF NO PC FOUND
; T1 = PC OF PUSHJ
; T2 = DEST ADDRESS OF PUSHJ
; T3 = ADDRESS OF ARG LIST
GETPC: JUMPE P1,%POPJ ;DON'T PROCEED ON ZERO!
MOVE T1,(P1) ;GET SOMETHING OFF STACK
CAMN T1,['STOP!!'] ;MAGIC END-OF-STACK CONSTANT?
JRST GETPCE ;YES, GO RETURN END-OF-STACK INDICATION
SKIPN %FSECT ;NON-ZERO SECTION?
TLZ T1,-1 ;[3151] No, discard section 0 flag bits
SUBI T1,1 ;LOOK AT THAT ADDR-1
MOVEM T1,PCADR ;SAVE IT
HLLZM T1,PCSECT ;SAVE SECTION #
PUSHJ P,ADRCHK ;CHECK THAT ADDRESS IS REASONABLE
SOJA P1,GETPC ;NOT, NOT A PC
MOVE T1,PCADR ;GET ADDRESS AGAIN
HLRZ T2,(T1) ;GET INSTRUCTION POINTED TO BY STACK
TRZ T2,37 ;TURN OFF INDIRECT AND INDEX
CAIE T2,(PUSHJ P,) ;A SUBROUTINE CALL?
SOJA P1,GETPC ;NO, NOT A PC
HLRZ T2,-1(T1) ;GET INSTRUCTION BEFORE THE PUSHJ
TRZ T2,37 ;TURN OFF INDEIRECT AND INDEX
CAIE T2,(MOVEI L,) ;CORRECT?
CAIN T2,(XMOVEI L,) ; (The other choice)
TRNA ;Yes
SOJA P1,GETPC ;NO
MOVE T3,(T1) ;GET THE PUSHJ INST
TLNE T3,17 ;INDEXED?
JRST UNKDST ;YES. DESTINATION UNKNOWN
HRRZ T2,(T1) ;GET THE PUSHJ INST DEST
HLL T2,PCSECT ;GET SECTION FROM CALLER ADDR
TLNE T3,(@) ;INDIRECT?
XMOVEI T2,@(T2) ;YES. GET DEST ADDR OF PUSHJ
HLRZ T3,(T2) ;GET INSTRUCTION AT THAT ADDRESS
CAIE T3,(JSP 1,) ;POSSIBLE OVRLAY CALL?
JRST GETPC1 ;NO
HRRZ T3,(T2) ;GET RH OF JSP
MOVE T4,-1(T3) ;GET WORD BEFORE JSP TARGET
CAME T4,['.OVRLA'] ;IS IT LINK'S OVERLAY ROUTINE?
JRST GETPC1 ;NO, NOT AN OVERLAY CALL
MOVE T2,1(T2) ;GET THE WORD AFTER THE JSP
MOVE T2,(T2) ;GET THE DEST ADDR OF THE OVERLAY CALL
JRST GETPC1 ;AND PROCESS IT
UNKDST: XMOVEI T2,1+[EXP <SIXBIT /UNKNWN/>,0]
GETPC1: MOVE T3,-1(T2) ;GET ROUTINE NAME
MOVE T4,-1(T1) ;GET XMOVEI OR MOVEI AGAIN
TLNE T4,17 ;INDEXED?
JRST ZERARG ;YES. UNKNOWN ARG LIST
HRRZ T3,-1(T1) ;GET ARG LIST ADDRESS FROM MOVEI INSTRUCTION
HLL T3,PCSECT ;ADD IN SECTION #
TLNE T4,(@) ;INDIRECT XMOVEI?
XMOVEI T3,@(T3) ;YES. RESOLVE IT
JUMPE T3,ZERARG ;Is there a null arg list ptr?
MOVS T4,-1(T3) ;GET ARG COUNT FROM -1 WORD OF LIST
CAIL T4,400000 ;MUST BE NEGATIVE
CAILE T4,777777
JUMPN T4,GETPCN ;OR ZERO
SOJA P1,%POPJ ;DONE
GETPCN: SOJA P1,GETPC ;NOT SO, NOT A POSSIBLE PC
ZERARG: XMOVEI T3,1+[EXP 0,0] ;POINT T3 AT NULL ARG LIST
SOJA P1,%POPJ ;DONE
GETPCE: SETZ P1, ;FLAG THAT PDL IS DONE
SETZ T1, ;Return a zero.
MOVE T2,@%STADD ;GET START ADDRESS
MOVEI T3,1+[0] ;NO ARGS
POPJ P, ;DONE
;ROUTINE TO ADDRESS CHECK A PC
;ARG: T1 = ADDRESS
;SKIP RETURN IF ADDRESS OK, NONSKIP OTHERWISE
;ADDRESS IS OK IF IT'S IN LOW SEGMENT, HIGH SEGMENT, OR FOROTS
ADRCHK: TXNE T1,777B8 ;[3155] Does the page number fit on a KL ?
POPJ P, ;[3155] No, can't be a good address
IF10,<
HLLZ T3,T1 ;GET SECTION NUMBER OF PC
MOVEI T1,(T1) ;AND MAKE PC SECTION-LOCAL
HRRZ T2,.JBREL(T3) ;GET LOWSEG END IN PC SECTION
CAMG T1,T2 ;BELOW LOW SEG END?
JRST %POPJ1 ;YES, FINE
HRRZ T2,.JBHRL(T3) ;GET HIGH SEG HIGHEST ADDRESS
JUMPE T2,%POPJ ;NONE
CAILE T1,(T2) ;COULD ADDRESS BE IN HIGH SEG?
POPJ P, ;NO
HLRZ T3,.JBHRL(T3) ;GET HIGH SEG LENGTH
SUBI T2,-1(T3) ;GET HIGH SEG ORIGIN
TRZ T2,777
CAIL T1,(T2) ;IS ADDRESS IN HIGH SEG?
AOS (P) ;YES, IT'S OK
POPJ P, ;ADDRESS IS ILLEGAL
> ;END IF10
IF20,<
FH%EPN==1B19 ;[3162] Extended page number (Release 5 symbol)
LSH T1,-^D9 ;[3151] Change to page number
HRLI T1,.FHSLF ;[3151] Inquire about our process
SKIPE %FSECT ;[3217] Running in a non-zero section ?
TXO T1,(FH%EPN) ;[3162] Yes, don't let section 0 be defaulted
RPACS% ;[3151] See what the page's attributes are
ERJMP RETURN ;[3151] Definitely not a return PC, punt
TXNE T2,PA%PEX ;[3151] Does the page exist ?
AOS (P) ;[3151] Yes, set up for skip (success return)
RETURN: POPJ P, ;[3151] Return
> ;[3151] End of IF20
;ROUTINE TO CONVERT AN ADDRESS INTO SYMBOL+OFFSET
;ARG: ORGADR = ADDRESS TO CONVERT
;RETURN: SYMNAM = RADIX50 SYMBOL NAME
; SYMVAL = VALUE OF SYMBOL
; SYMOFF = OFFSET FROM SYMBOL
; SYMMOD = RADIX50 MODULE NAME
;THIS ROUTINE FINDS THE LARGEST SYMBOL LESS THAN OR EQUAL TO THE ADDRESS.
;IT IS DESIGNED FOR CONVERTING PCS ... IT ASSUMES THAT THE USEFUL SYMBOLS
;IN ANY ROUTINE HAVE VALUES GREATER THAN THE ROUTINE START ADDRESS.
;ZERO IS RETURNED IN SYMNAM IF THERE IS NO SYMBOL TABLE OR IF THE ADDRESS
;IS NOT IN ANY MODULE (FUNCTION, SUBROUTINE, OR MAIN PROGRAM) IN THE TABLE.
;MODULE NAMES ARE USED AS LAST-DITCH CANDIDATES FOR SYMBOLS.
SYMCNV: SETZM SYMNAM ;CLEAR THE MATCHED SYMBOL & VALUE
SETZM SYMVAL
SETZM SYMMOD ;AND MODULE NAME
SKIPE T1,.JBSYM ;[4152] GET SYMTAB POINTER OR VECTOR ADDRESS
PUSHJ P,%SVCNV ;[4152] CONVERT VECTOR OR IOWD TO ADDRESS/LENGTH
JUMPE T1,CNVDON ;[4152] NONE.
PUSHJ P,SYMSRH ;DO A SEARCH
JRST CNVDON ;NO VALID SYMBOLS
MOVEM T1,SYMNAM ;SAVE THE SYMBOL NAME
MOVEM T2,SYMVAL ;AND ITS VALUE
MOVEM T3,SYMMOD ;AND MODULE NAME
MOVE T1,ORGADR ;GET ORIGINAL ADDR
SUB T1,SYMVAL ;TURN INTO OFFSET FROM SYMBOL FOUND
MOVEM T1,SYMOFF ;AND SAVE IT
CNVDON: POPJ P,
; SYMBOL SEARCH ROUTINE:
; T2/ SYMBOL TABLE LEN
; T3/ SYMBOL TABLE ADDR
;[4076]
; SEARCHS THE SYMBOL TABLE POINTED TO BY T3 FROM BOTTOM TO TOP. THE MODLP
; PASS THROUGH THE TABLE LOOKS FOR THE BEST MODULE CANDIDATE WITHIN WHICH
; THE PC TO BE CONVERTED IS LOCATED. RETRIEVE THE RADIX 50 MODULE NAME
; AND SEARCH BACKWARDS FOR ITS GLOBAL EQUIVALENT R50 NAME WITHIN THE MODULE.
; FETCH ITS GLOBAL VALUE. IF THIS VALUE IS THE CLOSEST VALUE YET FOUND
; LESS THAN/EQUAL THE ORIGINAL PC, STORE IT IN SRHVAL, THE END+1 SYMTAB ADDRESS
; OF THE MODULE IN MODEND, AND THE MODULE NAME IN SRHSYM AND SRHMOD. AFTER
; ONE PASS THROUGH THE SYMBOL TABLE, THE CLOSEST MODULE WILL EITHER HAVE
; BEEN FOUND OR A +1 RETURN WILL INDICATE SEARCH FAILURE.
;
;SYMBOL TABLE FORMAT:
; ~----------------------------~<= Symbol table start
; ~ ~
; |----------------------------|<= Module symbol table start
; / | F ! Radix50 name |<= MODBEG
; symbol pair |----------------------------|
; \ | value |
; |----------------------------|
; / | F ! Radix50 name |
; symbol pair |----------------------------|
; \ | value |
; |----------------------------|
; ~ ~
; ~ ~
; |----------------------------|
; / | F ! Radix50 Module name |<= Flags=0
; end pair |----------------------------|
; \ | -length,,start addr | -length,,0 in non-zero sections
; |----------------------------|<= End module symbols, start next
; | F ! Radix50 name |<= MODEND (END+1)
; |----------------------------|
; | value |
; |----------------------------|
; ~ ~
; ~ ~
; |----------------------------|<= End symbol table
;
; F => bits 0-3 in the Radix50 word, where:
;
; bit 0 (400000) => On if symbol is deleted output
; bit 1 (200000) => On if symbol is deleted input
; bit 2 (100000) => On if symbol is local
; bit 3 (040000) => On if symbol is global
; If 0-3 are off (740000), the symbol is a program name
; ALL FORTRAN MODULES WILL HAVE A GLOBAL R50 MODULE NAME. MACRO MODULES
; MAY NOT, IN WHICH CASE A SYMBOL+OFFSET FROM THE CLOSEST PREVIOUS FORTRAN
; MODULE (OR MACRO MODULE WITH GLOBAL MODULE SYMBOL) WILL BE RETURNED.
; IF THERE ARE NO PREVIOUS FORTRAN OR GLOBAL MACRO MODULES, A +1 RETURN
; DEFAULTS TO "MAIN.+n".
; ONCE A MODULE CANDIDATE IS FOUND, SYMLP SEARCHES THE MODULE FROM TOP DOWN
; FOR THE CLOSEST SYMBOL PLUS OFFSET.
SYMSRH: MOVEM T1,SYMBEG ;[4015] SAVE ADDRESS
ADD T2,T1 ;[4015] GET SYMBOL TABLE END + 1
MOVEM T2,MODBEG ;[4076] INITIALIZE MODULE BEGINNING ADDRESS
SETZM MODEND ;[3406] CLEAR MODULE END ADDRESS
SETZM SRHVAL ;INITIALIZE BEST-SO-FAR MODULE ADDRESS
SETZM SRHSYM ;AND SYMBOL
MODLP: MOVE T1,MODBEG ;[4076] POINT TO START OF MODULE
CAMG T1,SYMBEG ;STILL IN SYMBOL TABLE?
JRST MODLPE ;NO, SEARCH DONE
HLRE T2,-1(T1) ;GET -LENGTH OF MODULE SYMBOLS
CAIGE T2,0 ;[4015] IF POSITIVE, JUNK SYMBOL TABLE FORMAT
TRNE T2,1 ;MUST ALSO BE EVEN
POPJ P, ;[3155] Odd, go die
MOVE T4,-2(T1) ;AND NEXT TO LAST, MODULE NAME
TLNE T4,740000 ;AN ACTUAL MODULE NAME?
POPJ P, ;[3155] No, invalid symbol table format
TLO T4,040000 ;[4076] SET ITS GLOBAL FLAG FOR COMPARISON
ADD T2,T1 ;POINT TO START OF MODULE SYMBOLS
MOVEM T2,MODBEG ;[4076] SAVE
XMOVEI T2,-4(T1) ;[4076] POINT AT LAST PAIR IN MODULE
MODLP2: MOVE T3,(T2) ;[4076] GET ENTRY
CAMN T3,T4 ;[4076] SAME AS MODULE NAME?
JRST MODLPM ;[4076] YES, GET GLOBAL ADDRESS
SUBI T2,2 ;[4076] NO, POINT TO PREVIOUS ENTRY PAIR
CAML T2,MODBEG ;[4076] AT START OF MODULE?
JRST MODLP2 ;[4076] NO, KEEP TRYING
JRST MODLP ;[4076] YES, TRY NEXT MODULE
MODLPM: MOVE T3,1(T2) ;[4076] YES, GET ITS GLOBAL VALUE
TLNN T3,-1 ;[4076] ALREADY A SECTION NUMBER?
HLL T3,T2 ;[4076] NO, INSERT IT
CAMG T3,ORGADR ;DOES MODULE START AFTER ADDRESS TO CONVERT?
CAMGE T3,SRHVAL ;NO, IS MODULE BETTER THAN PREVIOUS BEST?
JRST MODLP ;NO, LOOP UNTIL FIND APPROPRIATE MODULE
MOVEM T1,MODEND ;SAVE END+1 ADDRESS OF MODULE SYMBOLS
MOVEM T3,SRHVAL ;SAVE MODULE ADDRESS
TLZ T4,040000 ;[4076] CLEAR GLOBAL FLAG
MOVEM T4,SRHSYM ;AND MODULE NAME AS SYMBOL NAME
MOVEM T4,SRHMOD ;ALSO SAVE MODULE NAME FOR MESSAGES
JRST MODLP ;SEARCH WHOLE SYMBOL TABLE
MODLPE: SKIPN T1,MODEND ;GET END+1 ADDRESS OF SYMBOLS
POPJ P, ;[3155] No suitable module, can't do conversion
HLRE T2,-1(T1) ;FIND START ADDRESS OF SYMBOLS
ADD T1,T2
;+ ;[5017]
; Search for a long symbol table name in the DDT symbol table.
; If the symbol named .SYMTB is found in this module then there
; is a secondary symbol table that must be searched. Otherwise,
; just search the DDT symbol table.
;-
MOVEM T1,MODBEG ;Save {address of first symbol in module}
FND2ST: DMOVE T2,(T1) ;Get a symbols' name and value
CAMN T2,[RADIX50 10,.SYMTB] ;Is it .SYMTB ????
JRST SRH2ST ;Yes, Go search long symbol table
;Otherwise, continue searching
ADDI T1,2 ;Bump address to next symbol name
CAMGE T1,MODEND ;Reached END OF MODULE?
JRST FND2ST ;No, Continue searching...
MOVE T1,MODBEG ;Restore address of first symbol in module
JRST SYMLP ;Go Search DDT symbol table {.SYMTB not found}
;+ ;[5017]
; SRH2ST - Search the secondary symbol table.
; T3 contains address of the long symbol table
;-
SRH2ST: MOVE T4,(T3) ;Number of symbols in table
AOJ T3, ;Increment to first symbol entry
DMOVE T1,(T3) ;Get module name from table (and addr)
MOVEM T2,SRHVAL ;Save modules address
MOVEM T1,SRHMOD ;Save modules name
MOVEM T1,SRHSYM ;Save module name as symbol name
SETOM SRHLSM ;Set flag "this is a long symbol"
;
; If the count of symbols in the long symbol table is one then, this table
; contains only the module name. The other symbols are in the DDT table.
;
CAIE T4,1 ;Is there more than one symbol in table?
JRST SRH2LP ;Yes, Search entire long symbol table
MOVE T1,MODBEG ;No, Restore address of first symbol in module
JRST SYMLP ;Go Search DDT symbol table {.SYMTB not found}
SRH2LP: DMOVE T1,(T3) ;Get byte pointer and value
CAMG T2,ORGADR ;.GT. Requested symbols' value
CAMG T2,SRHVAL ;.AND. Closer to req syms' value
JRST SRH2LE ;No, continue searching
MOVEM T2,SRHVAL ;Save symbols' value
MOVEM T1,SRHSYM ;Save byt pointer to symbol name string
SRH2LE: ADDI T3,2 ;Adjust pointer to next symbol
SOJG T4,SRH2LP ;Decrement counter and loop
AOS (P) ;Increment return address
MOVE T3,SRHMOD ;Get the module name
POPJ P, ;Return
;NOW HAVE T1 POINTING TO FIRST SYMBOL IN MODULE, AND
;MODEND = END+1 ADDRESS OF SYMBOLS IN MODULE
SYMLP: MOVE T2,1(T1) ;GET A SYMBOL VALUE
XMOVEI T2,(T2) ;[3406] GET SECTION NUMBER
CAMG T2,ORGADR ;BELOW DESIRED ADDRESS?
CAMG T2,SRHVAL ;[3046] YES, BETTER VALUE THAN PREVIOUS BEST?
JRST SYMLPN ;NO, FORGET IT
PUSHJ P,SUPCHK ;IS SYMBOL OF FORM <n>M?
JRST SYMLPN ;YES, FORGET IT EVER HAPPENED
DMOVE T2,(T1) ;GET SYMBOL AND VALUE
MOVEM T2,SRHSYM ;SAVE NEW SYMBOL NAME
XMOVEI T3,(T3) ;[3406] GET SECTION NUMBER
MOVEM T3,SRHVAL ;SAVE NEW BEST VALUE
SETZM SRHLSM ;Clear long symbol flag
SYMLPN: ADDI T1,2 ;BUMP TO NEXT SYMBOL
CAMGE T1,MODEND ;AT END OF MODULE?
JRST SYMLP ;NO, SEARCH WHOLE THING
AOS (P) ;INCREMENT RETURN ADDRESS
MOVE T1,SRHSYM ;GET SYMBOL
SKIPN 0,SRHLSM ;Is this a long symbol?
TLZ T1,740000 ;No, CLEAR HIGH BITS OF SYMBOL
MOVE T2,SRHVAL ;GET ITS VALUE
MOVE T3,SRHMOD ;AND GET THE MODULE NAME
POPJ P,
SEGMENT DATA
PCADR: BLOCK 1 ;ADDRESS FOUND IN STACK ENTRY
PCSECT: BLOCK 1 ;SECTION # FOR GETPC IN LEFT HALF
SRHSYM: BLOCK 1 ;SYMBOL
SRHVAL: BLOCK 1 ;ITS VALUE
SRHMOD: BLOCK 1 ;RADIX50 MODULE NAME FROM SYMBOL SEARCH
SRHLSM: BLOCK 1 ;Symbol in SRHSYM is a byte pointer to a
; long symbol name. {Don't clear flag bits}
ORGADR: BLOCK 1 ;ADDR WE'RE TRYING TO MATCH
SYMBEG: BLOCK 1 ;BEG OF SYMBOL TABLE
MODEND: BLOCK 1 ;MODULE END
MODBEG: BLOCK 1 ;[4076] MODULE START
SYMNAM: BLOCK 1 ;FINAL SYMBOL
SYMVAL: BLOCK 1 ;FINAL VALUE
SYMOFF: BLOCK 1 ;OFFSET OF ADDR FROM SYMBOL
SYMMOD: BLOCK 1 ;FINAL MODULE NAME
SEGMENT CODE
;ROUTINE TO DECIDE IF A SYMBOL SHOULD BE SUPPRESSED FROM TYPEOUT
;ARG: T1 = POINTER TO SYMBOL
;NONSKIP RETURN IF SYMBOL SHOULD BE SUPPRESSED.
;SUPPRESSED SYMBOLS ARE:
; COMPILER-GENERATED TEMP LABELS OF THE FORM <DIGITS>M
; SYMBOLS (CURRENTLY GENERATED ONLY BY MACRO) DEFINED WITH ==
;PRESERVES T1
SUPCHK: MOVE T2,(T1) ;GET RADIX50 SYMBOL NAME
JUMPL T2,%POPJ ;IF SUPPRESS BIT SET, SUPPRESS SYMBOL
TLZ T2,740000 ;CLEAR EXTRA BITS
IDIVI T2,50 ;GET LOW-ORDER CHAR IN T4
JUMPE T2,%POPJ1 ;IF SYMBOL WAS ONLY 1 CHAR, NOT AN M-SYMBOL
CAIE T3,R50(M) ;DOES SYMBOL END WITH M?
JRST %POPJ1 ;NO, NOT AN M-SYMBOL
SCHKLP: IDIVI T2,50 ;GET NEXT CHAR
CAIL T3,R50(0) ;IS IT A DIGIT?
CAILE T3,R50(9)
JRST %POPJ1 ;NONDIGIT, NOT AN M-SYMBOL
JUMPN T2,SCHKLP ;CHECK WHOLE SYMBOL FOR DIGITNESS
POPJ P, ;SYMBOL IS AN M-SYMBOL, SUPPRESS IT
PURGE $SEG$
END