Trailing-Edge
-
PDP-10 Archives
-
BB-J713A-BM
-
language-sources/glxtxt.mac
There are 27 other files named glxtxt.mac in the archive. Click here to see a list.
TITLE GLXTXT -- Formatted Text Handler for GLXLIB
SUBTTL Irwin L. Goverman/ILG/CER/MLB/DC/PJT/WLH Sept 27, 1979
;
;
;
; COPYRIGHT (c) 1975,1976,1977,1978,1979 BY
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MA.
;
; 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.
SEARCH GLXMAC ;GET AT GALAXY LIBRARY SYMBOLS
PROLOG(GLXTXT,TXT) ;PRODUCE PROLOG CODE
TXTEDT==35 ;MODULE EDIT LEVEL
ENTRY T%INIT ;INITIALIZATION
ENTRY T%TEXT ;$TEXT ENTRY POINT
ENTRY T%TTY ;DEFAULT TERMINAL OUTPUT
; This file contains the support code for the $TEXT macro, which
; is responsible for formatting all static string and variable type
; output. For a more detailed explanation of the $TEXT macro, please
; refer to the GLXMAC and GLXLIB modules.
; This module differs from most members of the GLXLIB family in two respects.
; First, it is called via a pseudo instruction, $TEXT, rather than
; via the usual S1/S2 accumulator calls. Secondly, all ACs are preserved
; across calls, which are skippable.
; The user of the $TEXT instruction must provide one or several output routines.
; This routine must conform to the standard GLXLIB conventions.
SUBTTL Table of Contents
; TABLE OF CONTENTS FOR GLXTXT
;
;
; SECTION PAGE
; 1. Table of Contents......................................... 2
; 2. Revision History.......................................... 3
; 3. Local Macros.............................................. 4
; 4. Global storage............................................ 5
; 5. T%INIT - Initialize the TEXT module....................... 6
; 6. T%TEXT - Routine to format text output.................... 7
; 7. T%TTY - Buffered terminal output routine................. 8
; 8. PROBLK - Process an entire T%TEXT argument block.......... 9
; 9. PROARG - Routine to process each T%TEXT argument.......... 10
; 10. PTAB - Dispatch table for argument processors........... 11
; 11. PROx - Processors for each type of formatting........... 12
; 12. PROT - Process a string of ASCIZ text................... 13
; 13. PRO3 - Process a an ASCIZ string created by $TEXT....... 13
; 14. PROQ - Process a byte pointer to an ASCIZ string........ 14
; 15. PROB - Process a GLXLIB object block.................... 15
; 16. PRO1 - Process an object type........................... 16
; 17. PRON - Process a node specification..................... 16
; 18. PROO - Process unsigned octal numbers................... 17
; 19. PROD - Process a signed decimal number.................. 17
; 20. PROF - Process a system dependent file specification... 18
; 21. PRO7 - Process a single 7 bit ASCII character........... 19
; 22. PRO6 - Process a single 6 bit ASCII character........... 19
; 23. PRO5 - Process ASCIZ single word........................ 19
; 24. PROW - Process a SIXBIT word............................ 19
; 25. PROP - Process a directory ID of either PPN or directory NUMBER 20
; 26. PROU - Process a user ID or either PPN or User number... 20
; 27. PROR - Process routine for Job Info Block............... 21
; 28. PROE - Process a GLXLIB error number.................... 23
; 29. PROI - Process an indirect text request................. 24
; 30. PROV - Process a program version number................. 25
; 31. PROM - Process a request for a CONTROL-M (Carriage Ret.) 26
; 32. PROJ - Process a request for a CONTROL-J (Line Feed).... 26
; 33. PROL - Process a request for a CONTROL-L (Form Feed).... 26
; 34. PROK - Process a request for a CONTROL-K (Vertical Tab). 26
; 35. PRO2 - Process a request for up-arrow................... 26
; 36. PROA - Process a request to supress free <CR-LF>........ 26
; 37. PRO0 - Process a request to put null (0) at end of line. 26
; 38. FETCH - Routine to get a word from caller's address space 27
; 39. SPACES - Routine to provide any padding requested......... 28
; 40. CNTDT - Convert UDT to TOPS-10 DATE UUO Time and MSTIME.. 29
; 41. Local output routines..................................... 31
; 42. PUTU
; 42.1 OUTPUT USER NAME OR PPN........................... 35
; 43. SAVLVL-RSTLVL - Save and restore TEXT levels.............. 36
SUBTTL Revision History
COMMENT \
Edit SPR/GCO Explanation
---- ------- ---------------------------------------------
0001 First attempt
0002 Convert to new OTS format
0003 Make multiple levels work
0004 Add PRO2 and PROQ
0005 Add PROB and PRO1
0006 G013 Add PRON/PUTN
0007 G014 FIX BUG IN ^I OF SPACING CAUSING SPACING TO
HAPPEN TWICE.
0010 FIX BUG WHICH DID NOT ALLOW THE
FIRST PARAMETER IN $TEXT MACRO TO USE
INDIRECT AND INDEXED ADDRESSING. THIS MOD NEEDS
ONLY TO JFCL 1 INSTRUCTION IN X.
0011 CHANGE T%INIT TO USE IIB SET UP BE I%INI1
0012 Add ^R for Job Info blocks and isolate PUTU for
Displaying User Info.
0013 Add STOPCODE IJU for Bad User Info in JIB (^R)
0014 Change ^R Display
0015 Convert to use I%JINF Routines
0016 Fix ^R on -10 with 0 second name word
0017 Fix ^N to Handle SIXBIT on the -10
0020 Make IQN $STOP give bad index, addr of error
0021 Make BTA $STOP give a hint of where we went south
0022 Removed usage of PJUMPE opdef
0023 Have ^E on the -20 accept 20 error codes and expand
them. Those are codes greater than 600000
0024 Allow Indexing and Indirect references for ^Q
0025 Generate Stopcode on invalid ^E function value
0026 Generate asciz pointer for ^Q if size and
position weren't set in fetched pointer.
(i.e. allow ^Q/KEYTAB(S1),LHMASK/)
0027 Change ^E to get dynamic buffer area and have -2
represent the last TOPS20 error.
0030 Fix -10 ^B to Check Node name and Number to decide
if at same node
0031 Modify PROB (Object Block Processor) so that if the
object type is .OTMNT then the unit is put out as a
sixbit value.
0032 Output Date/Time internally instead of using ODTIM.
0033 Convert CNTDT to accept and return arguments in S1 and
S2
0034 Change PUTU so that if the DIRST fails (-20 only),
we will put out 'User Unknown' instead of stopcode'ing
0035 Fix a bug. Initialize LINPTR in $TEXT init code.
\ ;End of Revision History
SUBTTL Local Macros
; These macros are pseudo instructions, and as such they
; preserve all registers and are skippable.
; Define a local macro for printing single characters
DEFINE $PUT7(CHAR)<
PUSHJ P,PUT7X ;;CHARACTER OUTPUT ROUTINE
XLIST ;;NO NEED TO LIST
JUMP "CHAR" ;;NO-OP + CHARACTER
LIST
> ;END OF $PUT7 DEFINITION
; DEFINE A LOCAL MACRO FOR PRINTING STRINGS
DEFINE $PUTT(STRING)<
PUSHJ P,PUTTX
XLIST
JUMP [ASCIZ \STRING\]
LIST
> ;END OF $PUTT DEFINITION
SYSPRM TTXBFS,2,^D10 ;TEMPORARY TEXT BUFFER SIZE
ND LINSIZ,^D20 ;SIZE OF DEFAULT OUTPUT LINE
ND EBFSZ,^D20 ;SIZE OF BUFFER AREA
SUBTTL Global storage
EXT IIB ;EXTERNAL INITIALIZATION BLOCK
$DATA DEFERR ;DEFAULT ERROR EXIT ADDRESS FROM IB.
$DATA DEFOUT ;DEFAULT OUTPUT ROUTINE FROM IB
$GDATA TXTLVL ;LEVEL WE ARE AT
$DATA FSAVE,0 ;FIRST LOCATION TO SAVE AT EACH LEVEL
$DATA LINBUF,LINSIZ ;LINE BUFFER
LINMAX==<<LINSIZ>*^D5>-1 ;MAXIMUM CHARACTER COUNT
$DATA ARGADR ;ADDRESS OF CALLER'S ARG LIST
$DATA USRACS,20 ;USER-CONTEXT ACS
$DATA USROUT ;ADDRESS OF CALLER'S OUTPUT ROUTINE
$DATA USRRET ;FIRST WORD AFTER $TEXT ARG BLOCK
TOPS20< $DATA ERRBUF> ;ERROR BUFFER AREA
$DATA CALOC ;CURRENT ARGUMENT EFFECTIVE ADDRESS
$DATA CAFLG ;CURRENT ARGUMENT'S FLAGS + RAW ADDRESS
$DATA CAPTR ;POINTER WORD FOR CURRENT ARG (IF ANY)
$DATA CASPAC ;SPACING WORD FOR CURRENT ARGUMENT (IF ANY)
$DATA CACCTR ;NUMBER OF CHARACTERS IN CURRENT ARGUMENT
$DATA CACMAX ;MAXIMUM CHARACTERS FIELD MAY BE
$DATA ENDFLG ;-1=NOTHING,0=CR-LF,+1=NULL AT END
$DATA NOOUTP ;-1 WHEN ACTUAL OUTPUT IS SUPRESSED
$DATA ERREXT ;A USER EXIT ROUTINE HAS RETURNED FALSE.
$DATA TTXBUF,TTXBFS ;PLACE TO BUILD TEMPORARY STRINGS
$DATA LINCTR ;COUNTER FOR CURRENT LINE
$DATA LINPTR ;POINTER TO CURRENT LINE
$DATA TMFCTR ;TIME ADJUSTMENT FACTOR
$DATA DSTCHG ;TIME FACTOR IS BASED ON
$DATA LSAVE,0 ;LAST LOCATION TO SAVE
IF1,<SSAREA==<LSAVE-FSAVE-1>> ;SIZE OF THE SAVE AREA
$DATA SAREA,SSAREA ;PLACE TO SAVE EACH LEVEL
SUBTTL T%INIT - Initialize the TEXT module
;This routine puts the TEXT module into a known state and
; stores the user specified default output routine
;CALL IS: IIB setup by I%INI1 in GLXINI
;
;TRUE RETURN: Always
T%INIT: SKIPN S1,IIB+IB.OUT ;PICK UP USER DEFAULT OUTPUT ROUTINE
$STOP(DOR,Default output routine required) ;MUST BE THERE
MOVEM S1,DEFOUT ;SAVE IT FOR LATER
MOVE S1,IIB+IB.ERR ;GET USER ERROR EXIT ROUTINE
MOVEM S1,DEFERR ;SAVE IT FOR LATER.
SETOM TXTLVL ;INITIALIZE THE COUNT OF LEVELS
TOPS20 <
PUSHJ P,CLCFCT ;CALCULATE A TIMEZONE CONVERSION FACTOR
>;END TOPS20 CONDITIONAL
$RETT ;AND RETURN
;This routine is called to recompute the local time
; conversion factor. The factor takes into account
; the local time zone as well as the daylight savings
; time adjustment. Note that the routine calculates
; the next local time occurrence of 0200 hours and
; saves it for later comparison.
TOPS20 <
CLCFCT: MOVEI S1,.SFTMZ ;TIME ZONE FUNCTION
TMON ;GET THE ZONE
SETOM TMFCTR ;REVERSE NUMBER LINE VALUE
IMULM S2,TMFCTR ;CALCULATE BASE HOURS
GTAD ;GET DATE/TIME
MOVE S2,S1 ;RELOCATE
HRRI S2,25253*2 ;LOAD RIGHT WITH 0200
MOVEM S2,DSTCHG ;SAVE IT
HRRZ S2,S1
CAIG S2,25253*2 ;AFTER 0200?
JRST TINI.1 ;NO,WE'RE DONE
HRLZI S2,1 ;YUP, MAKE IT TOMORROW
ADDM S2,DSTCHG ;..
TINI.1: MOVE S2,S1 ;RELOCATE TIME
SETZ T2,0 ;..
ODCNV
SETZ S2,0 ;SET FOR NO DST ADJUSTMENT
TXNE T2,IC%ADS ;FACTOR FOR DST?
AOS TMFCTR ;YES, DO SO
HRLZI S1,1 ;SETUP FULL DAY FACTOR [1,,0]
IMUL S1,TMFCTR ;COMPUTE FACTOR HOURS
IDIVI S1,^D24 ;..AND THE BASE OFFSET
MOVEM S1,TMFCTR ;STORE IT AWAY
$RETT
>;END OF TOPS20 CONDITIONAL ASSEMBLY
SUBTTL T%TEXT - Routine to format text output
;Calls to T%TEXT come only through invokation of the $TEXT
; macro, described in GLXMAC.
; Call is: Pushdown list top entry points to start of argument block-1,
; which is a JRST around an argument block, formatted as follows:
;
; PUSHJ P,T%TEXT ;CALL
; JRST %L1 ;JUMP AROUND CALL
; OUTPUT ROUTINE OR B.P. ;ADDR OF CHAR OUTPUT ROUTINE OR -1,,ADDR (BP)
; FLAGS+<QUAL.#>+ADDRESS ;DESCRIPTION AND ADDRESS OF ARG
; BYTE POINTER FOR ARG ;ONLY IF A BYTE POINTER IS NEEDED
; SPACING INFORMATION ;ONLY IF SPACING INFORMATION IS NEEDED
; .... ;MORE ARGUMENT SINGLETS,PAIRS OR TRIPLETS
; %L1:
;Where: Flags tell us whether qualifier takes any argument
; and whether position and spacing words are present.
; The spacing information is: "CHAR"B6+<SIDE>B17+<Number of positions>B35
;
; Return: Return is to the location after the PUSHJ to T%TEXT, which
; is the JRST around the arg block. This makes $TEXT skippable.
T%TEXT: AOSE TXTLVL ;INCREMENT LEVEL COUNT
PUSHJ P,SAVLVL ;SAVE LEVEL IF NOT FIRST
MOVEM 0,USRACS ;STORE FIRST AC
MOVE 0,[XWD 1,USRACS+1] ;TRANSFER USER ACS TO THE
BLT 0,USRACS+17 ;SAVE AREA
SOS USRACS+P ;ADJUST SHADOW VERSION OF "P"
SETZM ENDFLG ;ASSUME WANTS CR-LF AT END
SETZM ERREXT ;NO USER EXIT ERROR.
SETZM NOOUTP ;NOT SUPRESSING OUTPUT
SETOM LINCTR ;FLAG THAT BUFFER IS NOT IN USE
MOVE S1,[POINT 7,LINBUF] ;GET POINTER TO TTY OUTPUT BUFFER
MOVEM S1,LINPTR ;AND SAVE IT
HRRZ S1,0(P) ;GET THE ADDRESS CALLED FROM
MOVE 0,1(S1) ;GET THE USER ROUTINE ADDRESS INSTR.
MOVE S1,USRACS+1 ;RESTORE S1 TO ORIGIONAL VALUE.
XCT 0 ;GET THE USER REUTINE/BYTE PTR ADDR.
HRRZ S1,0(P) ;RE-GET THE ADDRESS CALLED FROM.
HRRZ S2,0(S1) ;GET FIRST WORD PAST ARGUMENT BLOCK
MOVEM S2,USRRET ;REMEMBER WHERE IT IS
SKIPN S2,0 ;FETCH USER OUTPUT ROUTINE ADDRESS
MOVE S2,DEFOUT ;IF NONE SPECIFIED, USE DEFAULT
SKIPN S2 ;HAVE WE GOT ONE SOME WAY?
MOVEI S2,T%TTY ;NO, MUST NOT BE INITED YET
JUMPG S2,TEXT.1 ;HAVE WE GOT A DEFAULT BYTE POINTER?
HRLI S2,(POINT 7,0) ;MAKE IT A BYTE POINTER.
MOVEM S2,LINPTR ;AND STORE POINTER
MOVEI S2,TDPB ;GET ADDR OF ROUTINE TO USE THE POINTER
TEXT.1: MOVEM S2,USROUT ;STORE IT AWAY FOR LATER
ADDI S1,2 ;COMPUTE THE START OF PARAMETER BLOCK
MOVEM S1,ARGADR ;REMEMBER IT
PUSHJ P,PROBLK ;PROCESS THE ARGUMENT BLOCK
PUSHJ P,PEND ;GIVE PROPER ENDING TO STRING
SKIPL LINCTR ;IF WE USED DEFAULT ROUTINE,
PUSHJ P,TDMP ;DUMP BUFFER NOW
MOVE 0,[XWD USRACS+1,1] ;RESTORE USER ACS
BLT 0,16 ;EXCEPT FOR PDL POINTER
MOVE 0,USRACS ;RESTORE AC USED FOR BLT
SOSL TXTLVL ;DECREMENT COUNT, IF NOT
PUSHJ P,RSTLVL ;AT PRIMARY, RESTORE THE LEVEL
SKIPE ERREXT ;DO WE TAKE THE ERROR EXIT ???
SKIPN DEFERR ;IS THE ROUTINE ADDRESS THERE ???
SKIPA ;NO,,JUST RETURN NORMALLY.
JRST @DEFERR ;YES,,DO IT.
POPJ P, ;RETURN WITHOUT AFFECTING TF
SUBTTL T%TTY - Buffered terminal output routine
;If a $TEXT instruction has a blank first argument, then the
; default output routine is used. This routine is identified
; in the Initialization Block.
;T%TTY is a default output routine which buffers output to
; the terminal controlling this job.
; Call is: S1/ contains 1 character, 7 bit, right justified
;
; Return: TRUE always
T%TTY: SOSGE LINCTR ;ROOM IN THE BUFFER?
JRST [ PUSHJ P,TDMP ;NO, DUMP THE BUFFER
JRST T%TTY ] ;AND RETRY
JUMPE S1,.RETT ;IF NULL CHARACTER, RETURN NOW
IDPB S1,LINPTR ;DEPOSIT THE CHARACTER
$RETT ;ALWAYS RETURN TRUE
TDMP: PUSH P,S1 ;SAVE CHARACTER
MOVEI S1,0 ;GET NULL CHARACTER
IDPB S1,LINPTR ;STORE TERMINATING NULL INTO BUFFER
MOVE S1,[POINT 7,LINBUF] ;GET BUFFER POINTER
MOVEM S1,LINPTR ;STORE IT
SKIPE LINBUF ;IF NULL BUFFER, SKIP IT
PUSHJ P,K%SOUT ;ELSE PRINT IT
SETZM LINBUF ;CLEAR FIRST WORD OF BUFFER
MOVEI S1,LINMAX ;RESET THE BUFFER COUNTER
MOVEM S1,LINCTR ;TO ITS MAXIMUM
POP P,S1 ;RESTORE THE CHARACTER
$RETT ;AND RETURN
TDPB: IDPB S1,LINPTR ;STORE WHERE CALLER SPECIFIED
$RETT ;AND RETURN
SUBTTL PROBLK - Process an entire T%TEXT argument block
;PROBLK is used to process a list of T%TEXT arguments. The
; lower level routine, PROARG, is called to process each
; argument and errors are checked for.
; Call: ARGADR/ Address of start of argument block
;
; Return: Always TRUE
PROBLK: MOVE S1,ARGADR ;GET ADDRESS OF CURRENT ARGUMENT WORD
CAME S1,USRRET ;ARE WE PAST THE END?
SKIPN 0(S1) ; OR INTO ZERO WORD (ITEXT BLOCK END)?
$RETT ;YES, SO RETURN NOW TO CALLER
PUSHJ P,PROARG ;PROCESS THE ARGUMENT POINTED TO
SKIPT ;IF OK, DONT'T STOP NOW
$STOP(BTA,<Bad $TEXT argument given at address ^O/ARGADR/>)
LOAD S1,CASPAC,TXT.SP ;GET SPACING POSITIONS
LOAD S2,CASPAC,TXT.SS ;AND SIDE CODE
CAXE S1,0 ;IF NOT SPACING,
CAXN S2,TXT.SR ; OR RIGHT JUSTIFYING,
JRST PROBLK ;JUST LOOP FOR NEXT ARGUMENT
PUSHJ P,SPACES ;GIVE ANY SPACES NEEDED
JRST PROBLK ;THEN LOOP FOR NEXT ARGUMENT
SUBTTL PROARG - Routine to process each T%TEXT argument
;PROARG is responsible for setting up argument specific data
; areas for the processing routines and adjusting ARGADR.
; CALL IS: NO ARGUMENTS
;
; RETURN: TRUE IF NO BAD ARGUMENTS DETECTED
; FALSE IF SOMETHING IS WRONG
;
PROARG: SETZM CACCTR ;CLEAR CHARACTER COUNTER
SETZM CASPAC ;AND THE SPACING WORD
SETZM CAPTR ;AND POINTER WORD
MOVE S1,@ARGADR ;GET CONTENTS OF FIRST ARG WORD
MOVEM S1,CAFLG ;SAVE IT FOR ITS FLAGS
MOVE 0,[XWD USRACS+1,1] ;RESTORE THE ACS
BLT 0,16 ;THAT WE MAY RESEMBLE
MOVE 0,USRACS ;THE USER'S CONTEXT
EXCH P,USRACS+P ;SET UP PUSHDOWN LIST TOO
MOVEI S1,@CAFLG ;CALCULATE EFFECTIVE ADDRESS
MOVEM S1,CALOC ;STORE EFFECTIVE ADDR (0 FOR TXT.NA)
EXCH P,USRACS+P ;RESTORE STACK POINTER
MOVEI T1,@ARGADR ;Get address of this arg, for $STOP
LOAD S1,CAFLG,TXT.P ;IS THIS A TWO WORD TYPE OF ARG?
JUMPE S1,PARG.1 ;NO, SO ADJUST BY ONLY ONE WORD
AOS S1,ARGADR ;ELSE ADJUST FOR THE SECOND WORD NOW
MOVE S1,0(S1) ;GET THE BYTE POINTER WORD
MOVEM S1,CAPTR ;AND STORE FOR LATER
PARG.1: LOAD S1,CAFLG,TXT.S ;IS THERE A SPACING WORD?
JUMPE S1,PARG.2 ;NO, DONT PROCESS IT
AOS S1,ARGADR ;GET THE ADDRESS OF SPACING WORD
MOVE S1,0(S1) ;GET THE SPACING WORD
MOVEM S1,CASPAC ;AND STORE IT
PARG.2: AOS ARGADR ;ADJUST CURRENT ADDRESS
LOAD S1,CAFLG,TXT.M ;GET THE QUALIFIER INDEX ALONE
CAILE S1,0 ;IF OUT OF RANGE,
CAIL S1,PTABL ;
$STOP(IQN,Illegal qualifier number ^O/S1/ at ^O/T1/)
LOAD T1,CASPAC,TXT.SP ;GET SPACING POSITIONS
MOVEM T1,CACMAX ;STORE AS MAXIMUM CHARS IN FIELD
LOAD S2,CASPAC,TXT.SS ;AND GET SIDE CODE
CAXE T1,0 ;IF NO SPACING,
CAXN S2,TXT.SL ;OR LEFT JUSTIFYING ONLY
PJRST @PTAB(S1) ;THEN JUST DO THE OUTPUT
SETOM NOOUTP ;SUPRESS THE OUTPUT,
PUSHJ P,@PTAB(S1) ;THEN, CALL THE PROCESSOR
SETZM NOOUTP ;CLEAR THE SUPRESS FLAG
PUSHJ P,SPACES ;GIVE ANY PADDING NECESSARY,
LOAD S1,CAFLG,TXT.M ;GET QUALIFIER NUMBER AGAIN
PJRST @PTAB(S1) ;THEN FINALLY OUTPUT THE ARGUMENT
SUBTTL PTAB - Dispatch table for argument processors
; Note well: Any changes in the order or contents of the TQUALS
; macro in GLXMAC should be reflected by recompilation and/or
; code changes in GLXTXT.
; Define processor table creation mechanism
DEFINE X(A,ARG)<
Z PRO'A
>
PTAB: PJRST .RETF ;FILL IN THE 0 (UNUSED) ENTRY
TQUALS ;AND THEN THE REST OF THE TABLE
PTABL==.-PTAB
SUBTTL PROx - Processors for each type of formatting
;The following are the separate processors for each type of
; ASCII formatting that we might have to do. Most are system
; independent, a couple are not. for all intents and
; purposes, these are the top level routines, and they have
; access to all AC's etc.
;Several locations are set up for these routines to use:
; CALOC is the effective address of the current argument
; or 0 (which will be unused) for TXT.NA (argument-less) qualifers
; CAFLG is the flag word for this argument
; CAPTR is the optional pointer word, used to get only a byte from the
; word containing the argument.
; CASPAC is the optional spacing information word, used only when the
; argument type-out is to have left justification, right justification, or be
; centered.
; ARGADR points to the word immediately following this argument in the list
; USRACS contain registers 0-17 inclusive of the caller's ACS
; USRRET contains the address of the first word not part of this $TEXT's
; argument block. It is used to calculate the end of the T%TEXT arg block.
;USROUT contains the address of the user routine for
; outputting each byte The supplied routine takes its byte as
; 7 bit ASCII, right justified in AC S1, and returns either
; TRUE or FALSE. A return of FALSE will cause a STOP CODE to
; occur. The output routine supplied may destroy both S1 and
; S2, but must preserve all other registers.
;Each of the following routines is named 'PROx' where x is
; the letter or digit corresponding to the $TEXT qualifier
; that follows the '^' (up-arrow) to indicate that this type
; of output is wanted.
SUBTTL PROT - Process a string of ASCIZ text
;Since a user created string could be in the ACs or be a field or
; something odd like that, we process it one word at at a time if we
; have to. If we do not, then we go to PRO3 which is faster.
PROT: MOVE P1,CALOC ;GET LOCATION OF STRING
MOVEI P2,0 ;FAKE EXHAUSTED COUNT
SKIPN CAPTR ;IS THIS A FIELD ONLY?
CAIGE P1,20 ;OR IN THE ACS?
SOSA P1 ;YES, BACK ADDR OF ONE FOR LOOP, USE WORD BY WORD
JRST PRO3 ;ELSE DO AS PURE ASCIZ STRING
PROT.1: SOJGE P2,PROT.2 ;ANY MORE BYTES IN WORD?
AOS S1,P1 ;NO, NEED NEXT WORD
PUSHJ P,FETCH ;SO GET IT
MOVE P3,S1 ;AND MOVE INTO PERMANENT PLACE
MOVE P4,[POINT 7,P3] ;MAKE UP A BYTE POINTER
MOVEI P2,4 ;GET NEW COUNT
PROT.2: ILDB S1,P4 ;GET A BYTE
JUMPE S1,.RETT ;RETURN NOW IF WE GET A NULL
PUSHJ P,PUT7 ;PUT OUT THE BYTE
JRST PROT.1 ;LOOP FOR NEXT BYTE
SUBTTL PRO3 - Process a an ASCIZ string created by $TEXT
;PRO3 is used to process strings created by the $TEXT instruction itself.
; These strings do not have to be processed word by word since
; they are created in a literal.
PRO3: MOVE S1,CALOC ;GET LOCATION STRING STARTS AT
PJRST PUTT ;AND PROCESS IT
SUBTTL PROQ - Process a byte pointer to an ASCIZ string
;PROQ is used to process an ASCIZ string which does not start on a word
; boundary. The address fed to the ^Q qualifer is that of a byte
; pointer to the string to be output.
PROQ: PUSHJ P,.SAVE1 ;PRESERVE AN AC
MOVE S1,CALOC ;GET LOCATION OF BYTE POINTER
PUSHJ P,FETCH ;FETCH IT NOW
TLNN S1,777700 ;WAS POINTER SPECIFIED?
TLO S1,(POINT 7,0) ;NO..MAKE STANDARD POINTER
TLC S1,-1
TLCN S1,-1 ;WAS POINTER -1,,X
HRLI S1,(POINT 7,0) ;YES..CREATE BYTE POINTER
PROQ.1: TXNN S1,<@(17)> ;INDIRECT OR INDEXED?
JRST PROQ.3 ;NO..PROCESS IT
LDB S2,[POINT 4,S1,17] ;GET THE INDEX FIELD
JUMPE S2,PROQ.2 ;JUMP IF NO INDEXING
HRRZ S2,USRACS(S2) ;GET THE INDEX VALUE
ADDI S2,(S1) ;DO INDEX CALCULATION
HRR S1,S2 ;STORE NEW EFFECTIVE ADDRESS
TLZ S1,17 ;CLEAR INDEXING
PROQ.2: TXNN S1,<@> ;INDIRECT?
JRST PROQ.3 ;NO..FINISH UP
MOVE P1,S1 ;SAVE THE POINTER
HRRZ S1,S1 ;EXTRACT THE ADDRESS
PUSHJ P,FETCH ;GET THE INDIRECT WORD
LDB S2,[POINT 12,P1,11] ;GET POSITION AND SIZE
DPB S2,[POINT 12,S1,11] ;STORE IN NEW POINTER
JRST PROQ.1 ;PROCESS POINTER
PROQ.3: HRRZ S2,S1 ;GET ADDRESS
CAIGE S2,20 ;POINT TO THE AC'S?
ADDI S2,USRACS ;YES..POINT TO OUR COPY
JRST PUTQ ;OUTPUT IT
SUBTTL PROB - Process a GLXLIB object block
PROB: MOVE P1,CALOC ;GET ARG LOC
MOVEI S1,OBJ.TY(P1) ;GET ADDRESS OF TYPE WORD
PUSHJ P,FETCH ;GET ITS CONTENTS
MOVE T1,S1 ;SAVE THE OBJECT TYPE IN T1
MOVSI P2,-OBJLEN ;MAKE AN AOBJN PTR TO TABLE OF OBJECTS
PROB.1: HLRZ S2,OBJTAB(P2) ;GET OBJECT TYPE FROM TABLE
CAME S2,S1 ;MATCH?
AOBJN P2,PROB.1 ;NO, LOOP
JUMPGE P2,.RETF ;AOBJN EXPIRED, LOSE
HRRZ S1,OBJTAB(P2) ;GET ADDRESS OF APPROPRIATE TEXT
PUSHJ P,PUTT ;AND OUTPUT IT
$PUT7(< >) ;OUTPUT A SPACE
MOVEI S1,OBJ.UN(P1) ;GET ADDRESS OF UNIT NUMBER WORD
PUSHJ P,FETCH ;FETCH IT
CAXN T1,.OTMNT ;IS THIS A TAPE/DISK OBJECT TYPE
JRST [PUSHJ P,PUTW ;YES,,PUT OUT THE UNIT AS SIXBIT
PJRST PROB.2 ] ;AND CONTINUE ON
MOVE P2,S1 ;COPY IT
LOAD S1,P2,OU.LRG ;GET LOW END OF RANGE
PUSHJ P,PUTD ;OUTPUT IT IN DECIMAL
LOAD S1,P2,OU.HRG ;GET HIGH END OF RANGE
JUMPE S1,PROB.2 ;SKIP IF NO HIGH UNIT
$PUT7(<:>) ;OUTPUT RANGE SEPARATOR
PUSHJ P,PUTD ;AND THEN HIGH END OF RANGE
PROB.2: MOVEI S1,OBJ.ND(P1) ;GET ADDRESS OF USER'S NODE WORD
PUSHJ P,FETCH ;GO GET ITS CONTENTS
JUMPE S1,.RETT ;QUIT NOW IF NO NODE
MOVE T1,S1 ;SAVE THE NODE
SETOM S1 ;SET FOR MY JOB
MOVX S2,JI.LOC ;GET THE LOCATION
PUSHJ P,I%JINF ;GET THE DATA IN S2
SKIPT ;SKIP IF O.K.
SETZ S2, ;MAKE IT 0
MOVE S1,T1 ;PLACE VALUE IN S1
CAMN S2,S1 ;SAVE AS CURRENT
$RETT ;RETURN
TOPS10< MOVE T3,S2 ;COPY NODE NUMBER TO P2
MOVE T1,[XWD 2,T2] ;AC FOR NODE.
MOVX T2,.NDRNN ;FUNCTION FOR NODE.
NODE. T1, ;GET THE NODE NAME
JRST PROB.3 ;ERROR..PRINT OUT NODE
CAMN T1,S1 ;IS IT SAME NODE
$RETT ;YES..BYPASS NODE OUTPUT
>;END TOPS10
PROB.3: PUSH P,S1 ;SAVE THE NODE SPEC
$PUTT(< [>) ;OPENER
POP P,S1 ;RESTORE IT
PUSHJ P,PUTN ;PUT OUT THE NODE NAME
$PUT7(<]>) ;AND CLOSER
$RETT
SUBTTL PRO1 - Process an object type
PRO1: MOVE S1,CALOC ;GET ADDR OF ARGUMENT
PUSHJ P,FETCH ;FETCH IT
MOVSI P1,-OBJLEN ;MAKE AN AOBJN PTR TO TABLE OF OBJECTS
PRO1.1: HLRZ S2,OBJTAB(P1) ;GET OBJECT TYPE FROM TABLE
CAME S2,S1 ;MATCH?
AOBJN P1,PRO1.1 ;NO, LOOP
JUMPGE P1,.RETF ;AOBJN EXPIRED, LOSE
HRRZ S1,OBJTAB(P1) ;GET ADDRESS OF APPROPRIATE TEXT
PJRST PUTT ;AND OUTPUT IT
;Define the X macro so we can generate the table of strings
; for the object types.
DEFINE X(A,B),<
XWD A,[ASCIZ/B/]
>
;Now generate the table of object type strings.
OBJTAB: OBJCTS
OBJLEN==.-OBJTAB
SUBTTL PRON - Process a node specification
PRON: MOVE S1,CALOC ;GET ADDRESS OF ARGUMENT
PUSHJ P,FETCH ;FETCH FROM USER SPACE
PJRST PUTN ;AND PRINT IT OUT
SUBTTL PROO - Process unsigned octal numbers
PROO: MOVE S1,CALOC ;GET ARGUMENT LOCATION
PUSHJ P,FETCH ;FETCH IT
PJRST PUTO ;JUST PRINT THE NUMBER
SUBTTL PROD - Process a signed decimal number
PROD: MOVE S1,CALOC ;GET ADDRESS OF CURRENT ARGUMENT
PUSHJ P,FETCH ;GET IT
PJRST PUTD ;JUST PRINT THE NUMBER
SUBTTL PROF - Process a system dependent file specification
TOPS10 <
PROF: MOVE P1,CALOC ;GET LOCATION OF THE FD
MOVEI S1,.FDSTR(P1) ;LOCATION OF STRUCTURE NAME
PUSHJ P,FETCH ;GET IT
JUMPE S1,PROF.1 ;IF NULL, FORGET IT
PUSHJ P,PUTW ;PRINT IT
$PUT7(<:>) ;FOLLOW IT WITH COLON
PROF.1: MOVEI S1,.FDNAM(P1) ;GET NAME OF FILE
PUSHJ P,FETCH ;FROM USER
SKIPE S1 ;IF NULL, DON'T PRINT IT
PUSHJ P,PUTW ;PRINT AS SIXBIT WORD
MOVEI S1,.FDEXT(P1) ;NOW GET EXTENSION
PUSHJ P,FETCH ;FROM USER
JUMPE S1,PROF.2 ;IF NULL, IGNORE IT
$PUT7(<.>) ;PUT OUT DOT AS FILE.EXT SEPARATOR
PUSHJ P,PUTW ;NOW PRINT THE SIXBIT EXTENSION
PROF.2: MOVEI S1,.FDPPN(P1) ;GET LOCATION OF PPN
PUSHJ P,FETCH ;GET THE PPN
JUMPE S1,.RETT ;IF NULL,SKIP PPN AND PATH
PUSH P,S1 ;SAVE PPN
$PUT7(<[>) ;PUT OUT A BRACKET TO OPEN PPN
HLRZ S1,0(P) ;ISOLATE PROJECT NUMBER
PUSHJ P,PUTO ;PUT IT OUT
$PUT7(<,>) ;SEPARATE HALVES
POP P,S1 ;RESTORE PPN
ANDI S1,-1 ;ISOLATE THE PROGRAMMER NUMBER
PUSHJ P,PUTO ;PRINT IT
MOVEI S1,.FDLEN(P1) ;GET ADDRESS OF FD LENGTH
PUSHJ P,FETCH ;FETCH IT
LOAD S1,S1,FD.LEN ;GET LENGTH ONLY
CAIG S1,.FDPAT ;IS THERE A PATH?
JRST PROF.4 ;NO
SUBI S1,.FDPAT ;GET NUMBER OF SFDS
MOVNS S1 ;NEGATE IT
HRL P1,S1 ;GET COUNT INTO PLACE
PROF.3: $PUT7(<,>) ;PUT OUT A COMMA
MOVEI S1,.FDPAT(P1) ;GET SFD LOCATION
PUSHJ P,FETCH ;LOAD IT
PUSHJ P,PUTW ;PRINT IT
AOBJN P1,PROF.3 ;LOOP FOR ALL
PROF.4: $PUT7(<]>) ;CLOSE PPN WITH A BRACKET
> ;END TOPS10 CONDITIONAL
TOPS20 <
PROF: MOVEI S1,.FDSTG ;GET OFFSET TO DESCRIPTIVE STRING
PUSH P,CALOC ;SAVE LOCATION OF ARGUMENT
ADDM S1,CALOC ;POINT TO "STRING PART" OF FD
PUSHJ P,PROT ;HANDLE AS ASCIZ TEXT
POP P,CALOC ;RESTORE ORIGINAL LOCATION
> ;END TOPS20 CONDITIONAL
$RETT ;THEN RETURN
SUBTTL PRO7 - Process a single 7 bit ASCII character
PRO7: MOVE S1,CALOC ;GET LOCATION
PUSHJ P,FETCH ;FETCH THE CHARACTER
PJRST PUT7 ;PRINT IT AND RETURN FROM THERE
SUBTTL PRO6 - Process a single 6 bit ASCII character
PRO6: MOVE S1,CALOC ;GET LOCATION
PUSHJ P,FETCH ;LOAD IT
PJRST PUT6 ;PRINT IT AND RETURN FROM THERE
SUBTTL PRO5 - Process ASCIZ single word
PRO5: MOVE S1,CALOC ;GET LOCATION OF WORD TO PRINT
PUSHJ P,FETCH ;LOAD IT
MOVEM S1,TTXBUF ;STORE INTO TEMPORARY BUFFER
SETZM S1,TTXBUF+1 ;INSURE 6TH CHARACTER IS NULL
MOVEI S1,TTXBUF ;GET LOCATION TO PUT OUT STRING AT
PJRST PUTT ;AND PUT OUT THE TEXT
SUBTTL PROW - Process a SIXBIT word
PROW: MOVE S1,CALOC ;GET LOCATION OF ARGUMENT
PUSHJ P,FETCH ;LOAD FROM USER ADDRESS SPACE
SKIPN CAPTR ;IF NOT A BYTE,
PJRST PUTW ;JUST PRINT IT OUT
JUMPE S1,.RETT## ;IF NULL, RETURN NOW
PROW.1: TXNE S1,77B5 ;IS FIELD LEFT JUSTIFIED?
PJRST PUTW ;YES, PRINT IT OUT NOW
LSH S1,6 ;SHIFT OVER ONE PLACE
JRST PROW.1 ;AND TRY AGAIN
SUBTTL PROP - Process a directory ID of either PPN or directory NUMBER
SUBTTL PROU - Process a user ID or either PPN or User number
PROU: SKIPA T1,[EXP JI.USR] ;USE JOB'S USER NUMBER
PROP: MOVX T1,JI.CDN ;USE JOB'S DIRECTORY NUMBER
MOVE S1,CALOC ;GET CURRENT ARGUMENT'S LOCATION
PUSHJ P,FETCH ;NOW FETCH THAT ARGUMENT
CAME S1,[EXP -1] ;DO THEY WANT THE DEFAULT?
PJRST PUTU ;NO,OUTPUT USER INFO
MOVE S2,T1 ;PLACE FUNCTION CODE IN S2
PUSHJ P,I%JINF ;GET THE DATA
MOVE S1,S2 ;PLACE VALUE IN S1
PROP.1: PJRST PUTU ;OUTPUT USER INFO
SUBTTL PROR - Process routine for Job Info Block
;This routine will output the Job Info Block for the Galaxy
; Spoolers or anyone formating a JIB according to GLXMAC
; Specification.
PROR: MOVEI S1,[ASCIZ/Job /] ;START JOBNAME
PUSHJ P,PUTT ;OUTPUT THE TEXT
MOVE P1,CALOC ;GET ADDR OF ARGUMENT
MOVEI S1,JIB.JN(P1) ;GET THE ADDRESS OF JOBNAME FIELD
PUSHJ P,FETCH ;FETCH IT
JUMPE S1,.RETF ;NONE..ERROR..RETURN FALSE
PUSHJ P,PUTW ;DISPLAY THE JOBNAME
MOVEI S1,[ASCIZ/ Req #/] ;REQUEST IDENTIFIER
PUSHJ P,PUTT ;OUTPUT BLOCK
MOVEI S1,JIB.ID(P1) ;GET ADDRESS OF REQUEST ID
PUSHJ P,FETCH ;FETCH IT
JUMPLE S1,.RETF ;ERROR...RETURN
PUSHJ P,PUTD ;OUTPUT THE NUMBER
MOVEI S1,[ASCIZ/ for /] ;USER NAME IDENTIFIER
PUSHJ P,PUTT ;OUTPUT THE TEXT
TOPS10 <
MOVEI S1,JIB.NM(P1) ;GET USER NAME WORD 1
PUSHJ P,FETCH ;FETCH IT
JUMPE S1,PROR.3 ;NO NAME GO TO PPN
MOVE P2,CACCTR ;GET CURRENT CHARACTER COUNT
ADDI P2,6 ;EXPECTED COUNT AFTER OUTPUT
PUSHJ P,PUTW ;OUTPUT THE NAME
SUB P2,CACCTR ;GET COUNT OUTPUT
JUMPE P2,PROR.2 ;ALL OUT CONTINUE ON
PROR.1: MOVEI S1,40 ;GET A BLANK
PUSHJ P,PUT7 ;OUTPUT THE BLANK
SOJG P2,PROR.1 ;FILL TO 6 CHARACTERS
PROR.2: MOVEI S1,JIB.NM+1(P1) ;GET USER NAME WORD 1
PUSHJ P,FETCH ;FETCH IT
SKIPE S1 ;ZERO..IGNORE SECOND WORD
PUSHJ P,PUTW ;OUTPUT THE NAME
PROR.3: MOVEI S1,40 ;GET A BLANK
PUSHJ P,PUT7 ;OUTPUT THE CHARACTER
>;END TOPS10
MOVEI S1,JIB.US(P1) ;GET USER NUMBER OR PPN
PUSHJ P,FETCH ;FETCH THE ARGUMENT
SKIPE S1 ;ZERO ELEMENT..FATAL ERROR
PJRST PUTU ;DISPLAY USER NAME OR PPN AND RETURN
$STOP(IJU,INVALID USER ID IN JOB INFO BLOCK)
PROH: TDZA P1,P1 ;USE FOR FLAG THAT DATE IS WANTED
PROC: SETO P1, ;-1 MEANS TIME ONLY
MOVE S1,CALOC ;GET LOCATION OF ARGUMENT
PUSHJ P,FETCH ;GRAB IT
CAMN S1,[EXP -1] ;IS IT -1, FOR "NOW"?
PUSHJ P,I%NOW ;GET CURRENT DATE AND TIME
TOPS20 <
PUSH P,S1 ;SAVE S1
CAML S1,DSTCHG ;HAVE WE PASSED NEXT 0200?
PUSHJ P,CLCFCT ;YUP, RECOMPUTE LOCAL ADJUSTMENT FACTOR
POP P,S1 ;RESTORE S1
ADD S1,TMFCTR ;MAKE LOCAL TIME ADJUSTMENT
SKIPGE S1 ;GUARD AGAINST GARBAGE DATES
SETZ S1,0 ;AND SET TO EARLIEST POSSIBLE
>;;END OF TOPS20 CONDITIONAL ASSEMBLY
PROH.1: PUSHJ P,CNTDT ;TAKE APART
DMOVE T1,S1 ;GET THE RETURNED VALUES
PUSH P,S1 ;SAVE TIME
JUMPL P1,PROH.2 ;IF FLAG IS UP, GIVE TIME ONLY
MOVE T1,T2 ;POSITION DATE
IDIVI T1,^D31 ;GET DAYS
MOVE T4,T1 ;SAVE REST
MOVEI S1,1(T2) ;GET DAYS AS 1-31
CAIGE S1,^D10 ;IF ONE DIGIT,
$PUT7(< >) ; FILL WITH A SPACE
PUSHJ P,PUTD ;PRINT DECIMAL NUMBER
IDIVI T4,^D12 ;GET MONTHS
MOVEI S1,[ASCIZ /-Jan/
ASCIZ /-Feb/
ASCIZ /-Mar/
ASCIZ /-Apr/
ASCIZ /-May/
ASCIZ /-Jun/
ASCIZ /-Jul/
ASCIZ /-Aug/
ASCIZ /-Sep/
ASCIZ /-Oct/
ASCIZ /-Nov/
ASCIZ /-Dec/](P1) ;GET ASCII
PUSHJ P,PUTT ;TYPE THE ASCIZ STRING
MOVEI S1,^D64(T4) ;GET YEAR SINCE 1900
IDIVI S1,^D100 ;GET JUST YEARS IN CENTURY
MOVN S1,S2 ;NEGATE TO GET - SIGN
PUSHJ P,PUTD ;TYPE IT OUT
$PUT7(< >) ;NOW SPACE OVER ONE
PROH.2: POP P,S1 ;GET TIME BACK
IDIV S1,[DEC 3600] ;GET HOURS
MOVE T4,S2 ;SAVE REST
CAIGE S1,^D10 ;IF ONLY ONE DIGIT,
$PUT7(< >) ;SPACE OVER
PUSHJ P,PUTD ;PUT DECIMAL NUMBER OUT
$PUT7(<:>) ;NOW A COLON TO DIVIDE HOURS FROM MINUTES
MOVE S1,T4 ;RESTORE REST
IDIVI S1,^D60 ;GET MINS
MOVE T4,S2 ;SAVE REST
CAIGE S1,^D10 ;IF NOT TWO DIGITS,
$PUT7(<0>) ;GIVE A ZERO FILL
PUSHJ P,PUTD ;PRINT DECIMAL MINUTES
$PUT7(<:>) ;AND SEPARATING COLON
MOVE S1,T4 ;RESTORE THE REST
CAIGE S1,^D10 ;IF ITS NOT TWO DIGITS,
$PUT7(<0>) ; ZERO FILL IT
PJRST PUTD ;THEN PRINT IT, RETURN
SUBTTL PROE - Process a GLXLIB error number
PROE: MOVE S1,CALOC ;GET LOCATION OF THE ARGUMENT
PUSHJ P,FETCH ;GET IT
TOPS20<
CAMN S1,[EXP -2] ;WANT LAST TOPS20 ERROR
JRST PROE.4 ;YES..SETUP ERRO VALUES
>;END TOPS20
CAMN S1,[EXP -1] ;WANT 'LAST ERROR'?
SKIPA S1,.LGERR## ;YES, PICK UP LAST ERROR PROCESS VIA .ERET
CAIL S1,0 ;IF LESS THAN 0 OR
CAIL S1,ERRSLN ; OFF THE END OF THE TABLE
PJRST PROE.1 ;CHECK FOR -20 ERRORS
HRRZ S1,ERRTAB(S1) ;GET STRING ADDRESS
PJRST PUTT ;RETURN AFTER PUTTING OUT THE STRING
PROE.1:
TOPS20< MOVE S2,S1 ;PLACE CODE IN S2
CAIGE S1,.ERBAS ;CHECK FOR -20 ERROR
PJRST PROE.3 ;BAD ERROR CODE
PROE.2: PUSH P,S2 ;SAVE S2
MOVEI S1,EBFSZ ;SIZE OF THE BUFFER
PUSHJ P,M%GMEM ;GET BUFFER ADDRESS
MOVEM S2,ERRBUF ;SAVE THE ADDRESS
POP P,S2 ;RESTORE ERROR CODE
HRLI S2,.FHSLF ;FOR THIS PROCESS
HRROI S1,@ERRBUF ;STORE IN ERROR BUFFER
HRLZI T1,-<EBFSZ*5> ;MAXIMUM NUMBER OF CHARACTERS
ERSTR ;DO THE FUNCTION
PJRST PROE.3 ;BAD ERROR CODE
$RETF ;BAD STRING SIZE
MOVEI S1,@ERRBUF ;POINT TO ERROR BUFFER
PUSHJ P,PUTT ;DUMP THE TEXT
MOVEI S1,EBFSZ ;SIZE OF AREA
MOVE S2,ERRBUF ;ADDRESS OF BUFFER
PUSHJ P,M%RMEM ;RETURN THE MEMORY
$RETT ;RETURN
PROE.3: PUSH P,S2 ;SAVE S2
MOVEI S1,[ASCIZ/Invalid Error Code /]
PUSHJ P,PUTT ;PUT OUT THE TEXT
POP P,S2 ;RESTORE S2
HRRZ S1,S2 ;GET THE ERROR CODE ONLY
PUSHJ P,PUTO ;DUMP THE NUMBER
$RETT ;RETURN
PROE.4: MOVEI S2,-1 ;GET LAST ERROR
JRST PROE.2 ;FINISH OFF ERROR
>;END TOPS20
TOPS10< $RETF > ;ERROR..JUST RETURN
;Make a table of known errors, for each we have the address
; of expanded string.
DEFINE ERR(A,B)<
Z [ASCIZ \B\]
> ;END OF ERR DEFINITION
ERRTAB: [ASCIZ /No errors yet/] ;0 ENTRY FOR LAST ERROR, BUT NONE SEEN
ERRORS ;PRODUCE THE TABLE
ERRSLN==.-ERRTAB ;LENGTH OF TABLE
SUBTTL PROI - Process an indirect text request
;Just as ^T can be used to include remote ASCIZ strings in a
; $TEXT call, the ^I qualifier can be used to include strings
; that are more complex. The address specified with an ^I
; qualifier specifies the location of a block, built with the
; ITEXT macro, which will be included at this point in the
; $TEXT string. Any qualifier may appear in the ITEXT string,
; including more ^I qualifiers.
PROI: PUSH P,ARGADR ;SAVE CURRENT ARGUMENT LIST LOCATION
MOVE S1,CALOC ;GET ADDRESS GIVEN AS ^I ARGUMENT
MOVEM S1,ARGADR ;MAKE IT NEW ARG ADDR
PUSHJ P,PROBLK ;PROCESS THE BLOCK POINTED TO
POP P,ARGADR ;RESTORE OLD ARG BLOCK ADDRESS
SETZM CASPAC ;CLEAR SPACING WORD[:G014]
$RETT ;THEN RETURN
SUBTTL PROV - Process a program version number
; Type out a specially formatted program version number. This is the
; standard version number, containing version number, major and
; minor edit numbers and a code indicating who editted the code last.
; Define the fields of the version number
VI%WHO==7B2 ;WHO EDITTED LAST
VI%MAJ==777B11 ;MAJOR VERSION NUMBER
VI%MIN==77B17 ;MINOR VERSION NUMBER
VI%EDT==777777B35 ;EDIT NUMBER
PROV: MOVE S1,CALOC ;GET LOCATION OF VERSION NUMBER
PUSHJ P,FETCH ;FETCH IT
MOVE P1,S1 ;GET INTO SAFER PLACE
LOAD S1,P1,VI%MAJ ;GET MAJOR VERSION NUMBER
PUSHJ P,PUTO ;PRINT IT OUT
LOAD P2,P1,VI%MIN ;GET MINOR VERSION NUMBER
JUMPE P2,PROV.2 ;SKIP MINOR VERSION IF ZERO
SUBI P2,1 ;BACK OFF ONE
IDIVI P2,^D26 ;PICK APART LETTERS
JUMPE P2,PROV.1 ;IF FIRST LETTER NULL, SKIP IT
MOVEI S1,"A"-1(P2) ;GET FIRST PART
PUSHJ P,PUT7 ;PUT OUT THE LETTER
PROV.1: MOVEI S1,"A"(P3) ;CONVERT IT
PUSHJ P,PUT7 ;AND PRINT IT
PROV.2: $PUT7(<(>) ;PUT OUT PARENTHESIS
LOAD S1,P1,VI%EDT ;GET THE EDIT NUMBER
PUSHJ P,PUTO ;PRINT IT
$PUT7(<)>) ;AND CLOSE PARENTHESIS
LOAD S1,P1,VI%WHO ;GET FINAL PART
JUMPE S1,.RETT## ;IF NULL, WE ARE DONE
$PUT7(-) ;ELSE SEPARATE "WHO" FIELD AND
PJRST PUTO ;RETURN PRINTING IT
SUBTTL PROM - Process a request for a CONTROL-M (Carriage Ret.)
PROM: MOVEI S1,"M"-100 ;LOAD ^M
PJRST PUT7 ;PUT IT OUT,RETURN
SUBTTL PROJ - Process a request for a CONTROL-J (Line Feed)
PROJ: MOVEI S1,"J"-100 ;LOAD ^J
PJRST PUT7 ;PUT IT OUT,RETURN
SUBTTL PROL - Process a request for a CONTROL-L (Form Feed)
PROL: MOVEI S1,"L"-100 ;LOAD ^L
PJRST PUT7 ;PUT IT OUT, RETURN
SUBTTL PROK - Process a request for a CONTROL-K (Vertical Tab)
PROK: MOVEI S1,"K"-100 ;LOAD ^K
PJRST PUT7 ;PUT IT OUT, RETURN
SUBTTL PRO2 - Process a request for up-arrow
PRO2: MOVEI S1,"^" ;GET UP-ARROW OR CARET
PJRST PUT7 ;AND PUT IT OUT
SUBTTL PROA - Process a request to supress free <CR-LF>
PROA: SETOM ENDFLG ;SET FLAG TO SUPRESS END OF TEXT STUFF
$RETT ;TAKE GOOD RETURN
SUBTTL PRO0 - Process a request to put null (0) at end of line
PRO0: MOVEI S1,1 ;SET END TO PUT NULL INSTEAD
MOVEM S1,ENDFLG ;OF CR-LF AT END OF LINE
$RETT ;AND RETURN
SUBTTL FETCH - Routine to get a word from caller's address space
;FETCH is responsible for getting a word from the user,
; checking for it's being in the AC shadow block and masking
; for proper size and place if the argument has a byte-mode
; address.
; Call: S1/ Address to fetch word from
;
; Return: S1/Contents of that word or byte
FETCH: CAIG S1,17 ;IS THE VALUE IN THE ACS?
SKIPA S1,USRACS(S1) ;YES, FETCH IT FROM THERE
MOVE S1,0(S1) ;OTHERWISE, PICK IT UP FROM MEMORY
SKIPN S2,CAPTR ;IS THERE A POINTER WORD?
$RETT ;NO, SO RETURN NOW
HRRI S2,S1 ;POINT TO REGISTER WITH WHOLE WORD
LDB S1,S2 ;GET PROPER PART
$RETT ;AND TAKE GOOD RETURN
SUBTTL SPACES - Routine to provide any padding requested
;Spaces is actually a misnomer, since the pad character may
; be any character that the user specifies. The spacing
; information is passed in an optional word associated with
; each argument. The user may specify the number of spaces
; that the field will take up, the side to justify to, and the
; character to pad with. Only the width actually must be
; given, as the side and character are defaulted by the $TEXT
; macros. The default justification is right justification
; for numeric items (^D and ^O) and left justification for all
; others. The default padding character is always a blank
; (octal 40).
;This routine places X pad characters into the output stream,
; where X is computed as the difference between the number in
; CACCTR and the user specified width. It also provides the
; centering.
; Call: CASPAC & CACCTR should be set up
;
; Return: Always TRUE
SPACES: PUSHJ P,.SAVE1 ;GET ONE PERMANENT REGISTER
LOAD P1,CASPAC,TXT.SP ;GET THE SPACING CODE WIDTH
SUB P1,CACCTR ;SUBTRACT CHARACTERS FOR OUTPUT
SETZM CACCTR ;THEN CLEAR CHARACTERS OUTPUT
LOAD S1,CASPAC,TXT.SS ;NOW GET THE SPACING CODE
CAXE S1,TXT.SM ;WANT THIS CENTERED?
JRST SPAC.1 ;NO, SO SKIP THIS
ASH P1,-1 ;DIVIDE SPACING NEEDED BY 2
MOVX S1,TXT.SL ;SET NOW FOR LEFT JUSTIFICATION ONLY
STORE S1,CASPAC,TXT.SS ;AND FALL INTO REGULAR SPACING CODE
SPAC.1: JUMPLE P1,.RETT ;CHECK FOR DONENESS
LOAD S1,CASPAC,TXT.SC ;GET THE CHARACTER TO OUTPUT
PUSHJ P,PUT7 ;AND PRINT IT
SOJA P1,SPAC.1 ;REPEAT TILL DONE
SUBTTL CNTDT - Convert UDT to TOPS-10 DATE UUO Time and Seconds
; This routine gratefully stolen from SCAN
;
;Call: MOVE S1,DATE/TIME
; PUSHJ P,.CNTDT
; Return with T1=Seconds since Midnight, T2=Date in system format (.LT. 0 if arg .LT. 0)
;Based on ideas by John Barnaby, David Rosenberg, Peter Conklin
;Uses T1-4
CNTDT:: PUSH P,S1 ;SAVE TIME FOR LATER
JUMPL S1,CNTDT6 ;DEFEND AGAINST JUNK INPUT
HLRZ S1,S1 ;GET DATE PORTION (DAYS SINCE 1858)
RADIX 10 ;**** NOTE WELL ****
ADDI S1,<1857-1500>*365+<1857-1500>/4-<1857-1500>/100+<1857-1500>/400+31+28+31+30+31+30+31+31+30+31+17
;S1=DAYS SINCE JAN 1, 1501
IDIVI S1,400*365+400/4-400/100+400/400
;SPLIT INTO QUADRACENTURY
LSH S2,2 ;CONVERT TO NUMBER OF QUARTER DAYS
IDIVI S2,<100*365+100/4-100/100>*4+400/400
;SPLIT INTO CENTURY
IORI T1,3 ;DISCARD FRACTIONS OF DAY
IDIVI T1,4*365+1 ;SEPARATE INTO YEARS
LSH T2,-2 ;T2=NO DAYS THIS YEAR
LSH S1,2 ;S1=4*NO QUADRACENTURIES
ADD S1,S2 ;S1=NO CENTURIES
IMULI S1,100 ;S1=100*NO CENTURIES
ADDI S1,1501(T1) ;S1 HAS YEAR, S2 HAS DAY IN YEAR
MOVE S2,S1 ;COPY YEAR TO SEE IF LEAP YEAR
TRNE S2,3 ;IS THE YEAR A MULT OF 4?
JRST CNTDT0 ;NO--JUST INDICATE NOT A LEAP YEAR
IDIVI S2,100 ;SEE IF YEAR IS MULT OF 100
SKIPN T1 ;IF NOT, THEN LEAP
TRNN S2,3 ;IS YEAR MULT OF 400?
TDZA T1,T1 ;YES--LEAP YEAR AFTER ALL
CNTDT0: MOVEI T1,1 ;SET LEAP YEAR FLAG
;T1 IS 0 IF LEAP YEAR
;UNDER RADIX 10 **** NOTE WELL ****
CNTDT1: SUBI S1,1964 ;SET TO SYSTEM ORIGIN
IMULI S1,31*12 ;CHANGE TO SYSTEM PSEUDO DAYS
JUMPN T1,CNTDT2 ;IF NOT LEAP YEAR, PROCEED
CAIGE T2,31+29 ;LEAP YEAR--SEE IF BEYOND FEB 29
JRST CNTDT5 ;NO--JUST INCLUDE IN ANSWER
SOS T2 ;YES--BACK OFF ONE DAY
CNTDT2: MOVSI S2,-11 ;LOOP FOR 11 MONTHS
CNTDT3: CAMGE T2,MONTAB+1(S2) ;SEE IF BEYOND THIS MONTH
JRST CNTDT4 ;YES--GO FINISH UP
ADDI S1,31 ;NO--COUNT SYSTEM MONTH
AOBJN S2,CNTDT3 ;LOOP THROUGH NOVEMBER
CNTDT4: SUB T2,MONTAB(S2) ;GET DAYS IN THIS MONTH
CNTDT5: ADD S1,T2 ;INCLUDE IN FINAL RESULT
CNTDT6: SKIPGE S1 ;TEST FOR JUNK
SETZ S1,0
EXCH S1,(P) ;SAVE ANSWER, GET TIME
TLZ S1,-1 ;CLEAR DATE
MULI S1,<EXP 24*60*60> ;CONVERT TO SECONDS/DAY
DIV S1,[1B17] ;SHIFT BINARY POINT
CAIL S2,<EXP 1B18> ;ROUND UP?
ADDI S1,1 ;YES, DO SO
POP P,S2 ;RECOVER DATE
$RETT ;RETURN
MONTAB: EXP 0,31,59,90,120,151,181,212,243,273,304,334,365
RADIX 8 ;BACK TO USUAL RADIX
SUBTTL Local output routines
;These routines are local to the TEXT module and are used to
; do output. GLXTXT cannot use the $TEXT macro because it
; would overwrite the callers AC's with its own.
; PUT7X -- Output a character, called via the $PUT7 macro
PUT7X: PUSH P,S1 ;SAVE S1
PUSH P,S2 ;AND S2
AOS S1,-2(P) ;UPDATE STACK, GET ADDRESS
HRRZ S1,-1(S1) ;GET CHARACTER
PUSHJ P,PUT7 ;PUT OUT THE CHARACTER
S2POPJ: POP P,S2 ;RESTORE THE AC
POP P,S1 ;AND THE OTHER
POPJ P, ;RETURN
; PUT7 -- Output a character, character in S1
PUT7: SKIPE ERREXT ;IF AN ERROR HAS OCCURED,,
$RETT ; THEN JUST RETURN.
ANDI S1,177 ;MAKE SURE ITS ONLY SEVEN BITS
AOS S2,CACCTR ;INCREASE CHARACTER COUNT
SKIPE NOOUTP ;SUPRESSING ACTUAL OUTPUT?
$RETT ;YES, RETURN TRUE NOW
SKIPN CACMAX ;IF FIELD IS NOT COUNTED
MOVX S2,1B0 ;MAKE ALL CHARACTERS BE PRINTED
CAMLE S2,CACMAX ;CHECK FOR MAXIMUM
$RETT ;IF TOO MANY, DON'T PRINT IT
PUSHJ P,@USROUT ;ELSE, OUTPUT IT
JUMPT .RETT ;IF RETURNED OK, RETURN NOW
SETOM ERREXT ;INDICATE AN ERROR OCCURED.
$RETT ;AND RETURN.
; PUTTX -- Output an ASCIZ string, called via the $PUTT macro
PUTTX: PUSH P,S1 ;SAVE ACS S1 AND S2
PUSH P,S2 ;
AOS S1,-2(P) ;UPDATE STACK, GET ADDRESS
HRRZ S1,-1(S1) ;PICK UP ADDRESS OF STRING
PUSHJ P,PUTT ;CALL ROUTINE
PJRST S2POPJ ;RETURN, RESTORING THE ACS
; PUTT -- Output an ASCIZ string, address of string is in S1
PUTT: PUSHJ P,.SAVE1 ;GET ONE PERMANENT AC
HRRZ P1,S1 ;GET ADDRESS INTO IT
HRLI P1,(POINT 7,0) ;CONVERT IT TO A BYTE POINTER
PUTT1: ILDB S1,P1 ;GET A BYTE
JUMPE S1,.RETT ;IF NULL, RETURN
PUSHJ P,PUT7 ;PRINT THE CHARACTER
JRST PUTT1 ;LOOP FOR NEXT ONE
; PUTQ -- Output an ASCIZ string, byte pointer to string is in S1
PUTQ: PUSHJ P,.SAVE1 ;SAVE ONE PERM AC
MOVE P1,S1 ;COPY POINTER
JRST PUTT1 ;AND CONTINUE
; PUTO -- Output an unsigned octal number, number in S1
PUTO: PUSHJ P,.SAVE3 ;GET 3 REGISTERS
MOVEI P1,0 ;CLEAR SHIFT REGISTER
MOVE P2,S1 ;GET INTO GOOD PLACE
MOVEI P3,^D12 ;TWELVE POSSIBLE DIGITS
PUTO.1: LSHC P1,3 ;DELETE LEADING 0
SKIPN P1 ;IF STILL ZERO,
SOJG P3,PUTO.1 ;LOOP
PUTO.2: ANDI P1,7 ;ISOLATE THE BYTE
MOVEI S1,"0"(P1) ;MAKE IT ASCII
PUSHJ P,PUT7 ;PUT OUT THE BYTE
LSHC P1,3 ;GET NEXT BYTE
SOJG P3,PUTO.2 ;REPEAT
$RETT ;OR RETURN NOW
; PUTD -- Put out a signed decimal number, number in S1
PUTD: PUSHJ P,.SAVE2 ;NEED TWO ACS
MOVE P1,S1 ;GET INTO PERMANENT PLACE
JUMPGE P1,PUTD.1 ;IS IT NEGATIVE?
$PUT7(<->) ;YES, SO PRINT A MINUS SIGN
MOVMS P1 ;AND CONVERT TO POSITIVE
PUTD.1: IDIVI P1,^D10 ;PICK OFF A DIGIT
HRLM P2,0(P) ;BET YOU'VE SEEN THIS BEFORE
SKIPE P1 ;ANY DIGITS LEFT?
PUSHJ P,PUTD.1 ;YES, GET NEXT ONE
HLRZ S1,0(P) ;GET A DIGIT
ADDI S1,"0" ;CONVERT TO ASCII
PJRST PUT7 ;PUT OUT DIGIT, LOOP OR RETURN FORM THERE
; PUTW -- Put out a SIXBIT word, word in S1
PUTW: PUSHJ P,.SAVE2 ;NEED TWO ACS
MOVE P2,S1 ;GET WORD INTO SAFE PLACE
PUTW.1: JUMPE P2,.RETT ;RETURN IF ONLY BLANKS LEFT
LSHC P1,6 ;GET A CHARACTER
MOVE S1,P1 ;GET INTO PLACE
PUSHJ P,PUT6 ;PRINT THE CHARACTER
JRST PUTW.1 ;LOOP FOR ALL
; PUT6 -- Put Out A Single SIXBIT character, character in S1
PUT6: ANDI S1,77 ;INSURE ITS SIXBIT
ADDI S1," " ;CONVERT TO ASCII
PJRST PUT7 ;OUTPUT AS AN ASCII CHARACTER
; PEND -- Put proper ending on the text line
PEND: SKIPGE ENDFLG ;WANT SOMETHING DONE?
$RETT ;NO, RETURN NOW
SETZM CACMAX ;NOT PART OF ANY COUNTED FIELD
SKIPG ENDFLG ;WANT A NULL?
JRST PEND.1 ;NO, MUST WANT CR-LF
MOVX S1,0 ;ASCII NULL
PJRST PUT7 ;RETURN, PRINT IT
PEND.1: MOVEI S1,.CHCRT ;GET A 'CARRIAGE-RETURN'
PUSHJ P,PUT7 ;PRINT IT
MOVEI S1,.CHLFD ;GET A 'LINE-FEED'
PJRST PUT7 ;PRINT IT, RETURN
; PUTN -- Put out a node specification (in S1)
TOPS20 <
PUTN: PJRST PUTW ;PUT IT OUT AS SIXBIT AND RETURN
> ;END TOPS20 CONDITIONAL
TOPS10 <
PUTN: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVE P2,S1 ;COPY NODE NUMBER TO P2
MOVE S1,[2,,P1] ;AC FOR NODE.
MOVX P1,.NDRNN ;FUNCTION FOR NODE.
NODE. S1, ;GET THE NODE NAME
JRST [MOVE S1,P2 ;RESTORE THE NODE NUMBER
TLNN S1,770000 ;WAS IT SIXBIT
PJRST PUTO ;JUST OUTPUT THE NODE NUMBER.
PJRST PUTW] ;OUTPUT NODE NAME AND RETURN
TLNN S1,770000 ;WAS IT SIXBIT
EXCH S1,P2 ;GET THE SIXBIT VALUE
PUSHJ P,PUTW ;OUTPUT THE NAME
$PUT7(<(>) ;THEN A LEFT BRACKET
MOVE S1,P2 ;COPY NUMBER TO S1
PUSHJ P,PUTO ;OUTPUT IT IN OCTAL
$PUT7(<)>) ;THEN THE RIGHT BRACKET
$RETT ;AND RETURN
> ;END TOPS10 CONDITIONAL
SUBTTL PUTU -- Output user name or PPN
;This routine will take PPN or user number in S1 and output contents
TOPS10 <
PUTU: PUSH P,S1 ;SAVE IT
$PUT7(<[>) ;GET AN OPEN BRACKET PRINTED
HLRZ S1,0(P) ;GET PROJECT PART OF PPN
PUSHJ P,PUTO ;PRINT IT
$PUT7(<,>) ;SEPARATE THE P FROM THE PN
POP P,S1 ;RESTORE PPN
ANDI S1,-1 ;DISCARD PROJECT NUMBER
PUSHJ P,PUTO ;PRINT IT
MOVEI S1,"]" ;GET CLOSE BRACKET
PJRST PUT7 ;PRINT IT AND RETURN
>;END TOPS10
TOPS20 <
PUTU: MOVE S2,S1 ;GET LOGGED IN DIRECTORY NUMBER
HRROI S1,TTXBUF ;POINT TO TEMPORARY TEXT BUFFER
DIRST ;AND PUT DOWN THE STRING
ERJMP [MOVEI S1,[ASCIZ/User Unknown/] ;IF BAD,,POINT TO 'UNKNOWN'
PJRST PUTT ] ;AND PUT THAT OUT !!!
MOVEI S1,TTXBUF ;POINT TO TEXT BUFFER
PJRST PUTT ;PUT IT OUT AND RETURN
>;END TOPS20
SUBTTL SAVLVL-RSTLVL - Save and restore TEXT levels
;In order to make the $TEXT instruction work at both normal
; and interrupt level, the T%TEXT routine must detect calls
; made while inside itself. IF such a call is made, these
; routines are used to save away the data base.
SAVLVL: PUSH P,S1 ;SAVE AN AC
MOVE S1,TXTLVL ;GET LEVEL
CAIE S1,1 ;ONLY SUPPORT TWO LEVELS
$STOP(TML,Too many levels of call)
MOVE S1,[XWD FSAVE,SAREA] ;PREPARE FOR THE BLT
BLT S1,SAREA+SSAREA-1 ;SAVE AWAY OUR DATA BASE
POP P,S1 ;RESTORE THE AC
POPJ P, ;AND RETURN
RSTLVL: PUSH P,S1 ;SAVE S1
MOVE S1,[XWD SAREA,FSAVE] ;RESTORE THE AREA
BLT S1,LSAVE-1 ;THAT WAS WIPED BY THIS LEVEL
POP P,S1 ;RESTORE S1
POPJ P, ;RETURN
TXT%L:
END