Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
utilities/boise.mac
There are no other files named boise.mac in the archive.
TITLE BOISE Print files on the Boise printer
SUBTTL Written by Mark Crispin/MRC 3-Jun-83
SEARCH MACSYM,MONSYM ; system definitions
SALL ; suppress macro expansions
.DIRECTIVE FLBLST ; sane listings for ASCIZ, etc.
.TEXT "/NOINITIAL" ; suppress loading of JOBDAT
.TEXT "BOISE/SAVE" ; save as BOISE.EXE
.TEXT "/SYMSEG:PSECT:CODE" ; put symbol table and patch area in CODE
.REQUIRE MM:HSTNAM ; host name routines
.REQUIRE MM:TCPIO ; TCP/IP I/O routines
.REQUIRE SYS:MACREL ; MACSYM support routines
; Version components
BOIWHO==4 ; who last edited BOISE (4=MRC)
BOIVER==5 ; BOISE's release version (matches monitor's)
BOIMIN==2 ; BOISE's minor version
BOIEDT==^D45 ; BOISE's edit version
IFNDEF FILPGS,FILPGS==^D10 ; number of file pages to map at a time
; Routines invoked externally
EXTERN $GTPRO,$GTNAM,$GTLCL,$RMREL,$CPYST
EXTERN $GTHSN,$GTHNS,$PUPSN,$PUPNS,$CHSSN,$CHSNS,$DECSN,$DECNS
EXTERN $TCOPN,$TCPSI,$TCCLS,$TCABT,$TCSOU,$TCBOU,$TCSND,$TCSIN,$TCBIN
SUBTTL Definitions
; AC definitions
A=1 ; temporary, JSYS AC's
B=2
C=3
D=4
P=17 ; stack pointer
IFNDEF PDLLEN,PDLLEN==^D100 ; stack length
IFNDEF STRBSZ,STRBSZ==^D515 ; string buffer length
IFNDEF PERNSZ,PERNSZ==^D19 ; number of characters in personal name
IFNDEF FILNSZ,<FILNSZ==^D<2*39+1+1+2*39+1+2*39+1+2*39+1+6>>
IFNDEF USRNSZ,USRNSZ==^D39 ; number of characters in a user name
IFNDEF CMDBSZ,CMDBSZ==^D200 ; size of command text buffer
; *** Temporary definitions ***
SUNETN==:^D36 ; SUnet's Internet network number
; *** End temporary definitions
; EMSG string
; Outputs an error message
DEFINE EMSG (STRING) <
HRROI A,[ASCIZ&STRING&]
ESOUT%
>;DEFINE EMSG
SUBTTL Boise definitions
Magic==:<BYTE (8) 164,61,115,241> ; Boise magic number: 74 31 4D A1
RADIX ^D10 ; Boise definitions are defined in decimal
BOIPRT==:35 ; TCP port Boise listens on
AEnd==:0 ; end of attributes
AFiller==:1 ; filler before next attribute
AUserName==:2 ; user (personal) name
AHostName==:3 ; host name
AFileName==:4 ; file name
APrintMode==:5 ; print mode
PmLinePrinter==:0 ; LPT format
PmDvi==:1 ; DVI format
PmPress==:2 ; Press format
PmHpSpoolFile==:3 ; HP spool file format
ANotification==:6 ; notification option
NNever==:0 ; never notify
NFailure==:1 ; notify on failure
NAlways==:2 ; always notify
NNothing==:0 ; nothing in notification
NSend==:1 ; Send notification
NSendOrMail==:2 ; Send or Mail notification
NSendAndMail==:3 ; Send and Mail notification
ACharacterSet==:7 ; character set to use
CsAscii==:0 ; use ASCII character set
CsSail==:1 ; use SAIL character set
ANewLine==:8 ; what constitutes newline
NlLf==:0 ; LF is newline
NlCr==:1 ; CR is newline
NlCrLf==2 ; CRLF is newline
ARotation==:9 ; what rotation to use
RPortrait==:0 ; portrait
RLandscape==:1 ; landscape
ALeftMargin==:10 ; left margin in 1/16 inch increments
ALineLength==:11 ; line length in number of characters
ATopMargin==:12 ; top margin in 1/16 inch increments
ALinesPerPage==:13 ; lines per page in number of lines
AFontSize==:14 ; font size
AUserId==:15 ; user (login) id
RADIX ^D8 ; back to octal
SUBTTL Data area
.PSECT DATA,1000 ; impure data
MEMBEG==. ; first location zeroed at initialization time
MONCMP: BLOCK 1 ; non-zero if command line invocation
PDL: BLOCK PDLLEN ; stack
STRBUF: BLOCK <STRBSZ/5>+1 ; string buffer
CMDBUF: BLOCK <CMDBSZ/5>+1 ; command buffer
CMDBLK: BLOCK .CMGJB+1 ; COMND% block
GTJBLK: BLOCK .GJATR+1 ; GTJFN% block
TCPJCN: BLOCK 1 ; TCP JFN
FILJFN: BLOCK 1 ; JFN on file to output
FILSIZ: BLOCK 2 ; .FBBYV and .FBSIZ words from FDB
CURPAG: BLOCK 1 ; current page being PMAP%'d
HSTNAM: BLOCK 15 ; local host name
HSTLEN: BLOCK 1 ; local host length
PERNAM: BLOCK <PERNSZ/5>+1 ; personal name
PERLEN: BLOCK 1 ; personal name length
FILNAM: BLOCK <FILNSZ/5>+1 ; file name
FILLEN: BLOCK 1 ; file name length
CHRSET: BLOCK 1 ; character set
NEWLIN: BLOCK 1 ; newline
ROTATE: BLOCK 1 ; rotation
USRNAM: BLOCK <USRNSZ/5>+1 ; user name
USRLEN: BLOCK 1 ; user name length
MEMEND==.-1 ; last location zeroed at initialization time
LEVTAB::LEV1PC ; PSI level 1 PC
0 ; PSI level 2 PC
0 ; PSI level 3 PC
LEV1PC: BLOCK 1 ; level 1 PC stored here
CHNTAB::PHASE 0
TCPCHN::!0 ; TCP/IP PSI channel
REPEAT <^D36-.>,<0>
DEPHASE
.ENDPS
.PSECT DATPAG,600000 ; enter paged data
FNGPAG: BLOCK 1000 ; shared page with FINGER
FILPAG: BLOCK FILPGS*1000 ; pages of file to print
.ENDPS
SUBTTL Printing options
.PSECT CODE,400000 ; pure code
SWITAB: SWITBL,,SWITBL ; table of switches
[ASCIZ/CHARACTER-SET:/],,ACharacterSet
[ASCIZ/NEW-LINE:/],,ANewLine
[ASCIZ/ROTATION:/],,ARotation
SWITBL==<.-SWITAB>-1 ; number of switches
CHSTAB: CHSTBL,,CHSTBL ; table of character sets
[ASCIZ/ASCII/],,CsAscii
[ASCIZ/SAIL/],,CsSail
CHSTBL==<.-CHSTAB>-1 ; number of character sets
NWLTAB: NWLTBL,,NWLTBL ; table of new lines
[ASCIZ/ALTO/],,NlCr
[ASCIZ/CRLF/],,NlCrLf
[ASCIZ/LINEFEED-ONLY/],,NlLf
[ASCIZ/RETURN-ONLY/],,NlCr
[ASCIZ/TOPS-20/],,NlCrLf
[ASCIZ/UNIX/],,NlLf
NWLTBL==<.-NWLTAB>-1 ; number of new lines
ROTTAB: ROTTBL,,ROTTBL ; table of rotations
[ASCIZ/LANDSCAPE/],,RLandscape
[ASCIZ/PORTRAIT/],,RPortrait
ROTTBL==<.-ROTTAB>-1 ; number of rotations
SUBTTL Start of program
BOISE: RESET% ; initialize fork
SETZM MEMBEG ; clear data area
MOVE A,[MEMBEG,,MEMBEG+1]
BLT A,MEMEND
MOVE P,[IOWD PDLLEN,PDL]
MOVX A,.FHSLF ; set up PSI tables
MOVE B,[LEVTAB,,CHNTAB]
SIR%
EIR% ; enable PSI system
HRROI A,HSTNAM ; get local host name
CALL $GTLCL
IFNSK.
EMSG <Unable to get local host name>
JRST STOP
ENDIF.
MOVEI B,HSTNAM ; figure out its length
CALL STRLEN
MOVEM A,HSTLEN ; save for later
GJINF% ; get user number
MOVE B,A ; set up for DIRST%
HRROI A,USRNAM ; put user name in USRNAM
DIRST%
IFJER.
EMSG <Unable to get user name - >
CALL LSTERR
JRST STOP
ENDIF.
MOVEI B,USRNAM ; figure its length
CALL STRLEN
MOVEM A,USRLEN ; save for later
; falls through
SUBTTL Set up default attributes
MOVX A,CsAscii ; default Character set
MOVEM A,CHRSET
MOVX A,NlCrLf ; default New Line
MOVEM A,NEWLIN
MOVX A,RLandscape ; default Rotation
MOVEM A,ROTATE
; falls through
SUBTTL Get personal name from FINGER if possible
MOVX A,GJ%OLD!GJ%SHT ; look up FINGER
HRROI B,[ASCIZ/SYS:FINGER.EXE/]
GTJFN%
IFNJE.
PUSH P,A ; save JFN
MOVX A,CR%CAP ; create a new fork
CFORK%
IFJER.
EMSG <Failed to get a fork for FINGER - >
CALL LSTERR
JRST STOP
ENDIF.
EXCH A,(P) ; save fork handle, get JFN
HRL A,(P) ; get prog into fork
GET%
MOVE A,[.FHSLF,,FNGPAG/1000] ; map page FNGPAG of this fork
HRLZ B,(P) ; from page 777 of FINGER
HRRI B,777
MOVX C,PM%RD!PM%WR!PM%PLD ; read/write/preload
PMAP%
HRROI A,USRNAM ; give our user name to FINGER
HRROI B,FNGPAG
MOVX C,USRNSZ ; up to this many characters
CALL $CPYST
JRST STOP ; can't happen
MOVE A,(P) ; get back fork handle
MOVEI B,3 ; start inferior at offset 3
SFRKV%
RFORK% ; resume, in case it didn't get going
WFORK% ; sleep until fork is finished
; falls through
; drops in
MOVX A,SIXBIT/BOISE/ ; restore our name
SETNM%
MOVE A,(P) ; see if it finished okay
RFSTS%
LOAD A,RF%STS,A ; just get status
CAIE A,.RFHLT ; fork halted normally?
IFSKP.
HRROI A,FNGPAG ; now copy personal name into PERNAM
HRROI B,PERNAM
MOVX C,PERNSZ ; up to this many characters
CALL $CPYST
JRST STOP ; can't happen
MOVE A,B ; get current destination
MOVEI B,PERNAM ; figure its length
CALL STRLEN
MOVEM A,PERLEN ; save for later
ENDIF.
SETO A, ; unmap shared page
MOVE B,[.FHSLF,,FNGPAG/1000] ; mapped to this fork's FNGPAG
SETZ C,
PMAP%
POP P,A ; now kill the fork
KFORK%
ENDIF.
; falls through
SUBTTL Rescan EXEC command
; Process BOISE "monitor" command
MOVX A,.RSINI ; get RSCAN% buffer if any
RSCAN%
ERJMP STOP
IFN. A ; have an RSCAN% buffer?
DO. ; yes
PBIN% ; flush leading whitespace
CAIE A,.CHTAB
CAIN A,.CHSPC
JRST TOP.
ENDDO.
DO.
CAIE A,.CHFFD
CAIN A,.CHLFD ; this shouldn't happen, but...
EXIT.
CAIE A,"B" ; look like a BOISE command?
CAIN A,"b"
TDZA B,B ; yes, alright to scan for delimiters
SETO B, ; no, just flush command line
DO.
PBIN% ; flush to LF or delimiter
CAIE A,.CHFFD
CAIN A,.CHLFD
EXIT. ; obviously no command
JUMPN B,TOP.
CAIE A,.CHTAB ; saw whitespace?
CAIN A,.CHSPC
SOSA MONCMP ; yes, flag a command seen
LOOP. ; otherwise keep on looking
ENDDO.
ENDDO.
ENDIF.
SUBTTL Parse command
; Initialize COMND% block
MOVX A,<.PRIIN,,.PRIOU> ; use primary I/O
MOVEM A,CMDBLK+.CMIOJ
SKIPE MONCMP ; monitor command?
SKIPA A,[-1,,[ASCIZ//]] ; yes, no prompt
HRROI A,[ASCIZ/BOISE>/] ; otherwise set up standard prompt
MOVEM A,CMDBLK+.CMRTY ; ^R buffer
HRROI A,CMDBUF ; start of text buffer
MOVEM A,CMDBLK+.CMBFP
MOVEM A,CMDBLK+.CMPTR ; and initial pointer to next input
MOVX A,CMDBSZ ; size of command buffer
MOVEM A,CMDBLK+.CMCNT
SETZM CMDBLK+.CMINC ; initially no unparsed characters
HRROI A,STRBUF ; start of atom buffer
MOVEM A,CMDBLK+.CMABP
MOVX A,STRBSZ ; size of atom buffer
MOVEM A,CMDBLK+.CMABC
MOVEI A,GTJBLK ; GTJFN% block
MOVEM A,CMDBLK+.CMGJB
; Start parse
DO.
MOVEI A,CMDBLK ; pointer to command block
MOVEI B,[FLDDB. .CMINI] ; initialize parser
COMND%
DO.
MOVEI B,ENDLP. ; reparse address
MOVEM B,CMDBLK+.CMFLG
ENDDO.
RESET% ; flush JFN's in event of reparse
; falls through
; Parse file name
MOVEI B,[FLDDB. .CMNOI,,<-1,,[ASCIZ/FILE/]>]
COMND%
TXNN A,CM%NOP
IFSKP.
EMSG <>
CALL LSTERR
SKIPE MONCMP ; monitor command?
JRST STOP ; yes, return to EXEC
LOOP.
ENDIF.
MOVEI B,[FLDDB. .CMIFI] ; get an input file
COMND%
TXNN A,CM%NOP ; error?
IFSKP.
EMSG <Unable to parse file name - >
CALL LSTERR ; output error string
SKIPE MONCMP ; monitor command?
JRST STOP ; yes, return to EXEC
LOOP.
ENDIF.
MOVEM B,FILJFN ; save JFN for later
; drops in
; Parse switches
DO.
MOVEI B,[FLDDB. .CMCFM,,,,,<[FLDDB. .CMSWI,,SWITAB,<attribute switch,>]>]
COMND%
TXNE A,CM%NOP ; error?
EXIT. ; yes, don't go any further
LOAD C,CM%FNC,(C) ; no, get the function code which parsed
CAIN C,.CMCFM ; confirmation?
EXIT. ; yes, send file
HRRZ B,(B) ; get attribute type
CAIE B,ACharacterSet ; specifying character set?
IFSKP.
MOVEI B,[FLDDB. .CMKEY,,CHSTAB,<character set,>,ASCII]
COMND%
TXNE A,CM%NOP ; error?
EXIT. ; lose
HRRZ B,(B) ; get attribute data
MOVEM B,CHRSET
LOOP.
ENDIF.
CAIE B,ANewLine ; specifying new line type?
IFSKP.
MOVEI B,[FLDDB. .CMKEY,,NWLTAB,<new line type,>,TOPS-20]
COMND%
TXNE A,CM%NOP ; error?
EXIT. ; lose
HRRZ B,(B) ; get attribute data
MOVEM B,NEWLIN
LOOP.
ENDIF.
; falls through
; drops in
CAIE B,ARotation ; specifying rotation?
IFSKP.
MOVEI B,[FLDDB. .CMKEY,,ROTTAB,<rotation,>,LANDSCAPE]
COMND%
TXNE A,CM%NOP ; error?
EXIT. ; lose
HRRZ B,(B) ; get attribute data
MOVEM B,ROTATE
LOOP.
ENDIF.
JRST STOP ; can't happen
ENDDO.
TXNN A,CM%NOP ; last atom parsed successfully?
IFSKP.
EMSG <> ; no, error
CALL LSTERR ; output error string
SKIPE MONCMP ; monitor command?
JRST STOP ; yes, return to EXEC
LOOP.
ENDIF.
ENDDO.
; drops in
SUBTTL Open file and compute size
MOVE A,FILJFN ; open file
MOVX B,OF%RD ; for read
OPENF%
IFJER.
EMSG <Unable to open file - >
CALL LSTERR
MOVE A,FILJFN ; flush the losing JFN
RLJFN%
NOP
JRST DONE ; restart
ENDIF.
; Depends upon .FBSIZ=.FBBYV+1
MOVE B,[2,,.FBBYV] ; get file I/O and byte size info
MOVEI C,FILSIZ ; into FILSIZ/FILSIZ+1
GTFDB%
LOAD C,FB%BSZ,FILSIZ ; get file byte size
CAIN C,7 ; seven-bit bytes?
IFSKP.
MOVEI B,^D36 ; no, compute total bytes per word
IDIVI B,(C)
EXCH B,FILSIZ+1
IDIV B,FILSIZ+1 ; compute number of words
IMULI B,5 ; compute # of bytes
ELSE.
MOVE B,FILSIZ+1 ; use exact byte count if 7 bit bytes
ENDIF.
MOVEM B,FILSIZ ; save file size
HRROI A,FILNAM ; put file name in FILNAM
MOVE B,FILJFN ; JFN to output
MOVX C,JS%SPC ; output entire specification
JFNS%
MOVEI B,FILNAM ; figure its length
CALL STRLEN
MOVEM A,FILLEN ; save for later
; falls through
SUBTTL Get Boise's address and open connection
HRROI A,[ASCIZ/SU-BOISE/] ; get Boise's Internet address
CALL $GTHSN
IFSKP.
MOVE A,B ; success, get address in A for $TCOPN
ELSE.
HRROI A,[ASCIZ/Boise/] ; failed, look up in Pup registry
CALL $PUPSN
IFNSK.
EMSG <Can't get Boise's host address>
JRST STOP
ENDIF.
;;; This code assumes SUnet is an Internet Class A network, which will not
;;;always be the case.
HRRZ A,B ; copy Ethernet host address
HLRZS B ; get Ethernet network number
DPB B,[POINT 8,A,19] ; set as subnet number
MOVX B,SUNETN ; get Stanford Ethernet's IP network number
DPB B,[POINT 8,A,11] ; set it
ENDIF.
MOVX B,BOIPRT ; port Boise listens on
SETZ C, ; needn't bother with unique code
CALL $TCOPN ; open connection to Boise
IFNSK.
EMSG <Boise is not up, try again later>
JRST DONE ; restart
ENDIF.
MOVEM A,TCPJCN ; save TCP JCN
MOVX B,TCPCHN ; set up PSI's
CALL $TCPSI
IFNSK.
EMSG <$TCPSI failed>
JRST STOP ; failed, give up
ENDIF.
; falls through
SUBTTL Get Boise greeting message
MOVE A,TCPJCN ; get greeting message
HRROI B,STRBUF ; into string buffer
MOVX C,STRBSZ ; up to this many bytes
MOVX D,.CHLFD ; or end of line
CALL $TCSIN ; get greeting message
IFNSK.
EMSG <Failed to get greeting message from Boise>
JRST ABTCON
ENDIF.
MOVE A,[POINT 7,STRBUF] ; pointer to buffer
SETZ B, ; initial reply code
DO.
ILDB C,A ; get byte of reply code
CAIL C,"0" ; out of range?
CAILE C,"9"
EXIT. ; yes, punt
IMULI B,^D10 ; no, add this digit to the tally
ADDI B,-"0"(C)
LOOP. ; try for another digit
ENDDO.
CAIN B,^D220 ; print server ready?
IFSKP.
ESOUT% ; no, output Boise's human-readable string
JRST ABTCON ; give up
ENDIF.
SKIPN MONCMP
PSOUT% ; output greeting message
; falls through
SUBTTL Send header for Boise file
MOVE A,TCPJCN ; output Boise "magic number"
MOVE B,[POINT 8,[Magic]]
MOVNI C,4 ; 4 bytes to output
CALL BOISOU
; Send attributes
MOVX B,AUserNAME ; output personal name
CALL BOIBOU
SKIPN B,PERLEN ; personal name length
IFSKP.
CALL BOIBOU
HRROI B,PERNAM ; send personal name
CALL BOISOU
ELSE.
MOVE B,USRLEN ; user name length
CALL BOIBOU
HRROI B,USRNAM ; send user name
CALL BOISOU
ENDIF.
MOVX B,AHostName ; output host name
CALL BOIBOU
MOVE B,HSTLEN ; host name length
CALL BOIBOU ; send it
HRROI B,HSTNAM ; send host name
CALL BOISOU
MOVX B,AFileName ; output file name
CALL BOIBOU
MOVE B,FILLEN ; file name length
CALL BOIBOU
HRROI B,FILNAM ; send file name
CALL BOISOU
; falls through
; drops in
MOVX B,ACharacterSet ; output character set
CALL BOIBOU
MOVX B,1 ; 1-byte attribute length
CALL BOIBOU
MOVE B,CHRSET ; get character set
CALL BOIBOU
MOVX B,ANewLine ; output newline type
CALL BOIBOU
MOVX B,1 ; 1-byte attribute length
CALL BOIBOU
MOVE B,NEWLIN ; get newline type
CALL BOIBOU
MOVX B,ARotation ; output rotation
CALL BOIBOU
MOVX B,1 ; 1-byte attribute length
CALL BOIBOU
MOVE B,ROTATE ; get rotation
CALL BOIBOU
MOVX B,AUserID ; output user name
CALL BOIBOU
MOVE B,USRLEN ; user name length
CALL BOIBOU
HRROI B,USRNAM ; send user name
CALL BOISOU
MOVX B,AEnd ; end of attributes
CALL BOIBOU
; falls through
SUBTTL Send file to Boise
; Note: this routine isn't very robust in dealing with holey files. Tough.
DO.
MOVS A,FILJFN ; file to map from
HRR A,CURPAG ; current page to map from (initially 0)
MOVX B,<.FHSLF,,<FILPAG/1000>> ; map into this process at FILPAG
MOVX C,PM%CNT!PM%RD!PM%PLD!FILPGS ; preload FILPGS pages for read
PMAP% ; map the pages
MOVE A,TCPJCN ; where to send the data to
HRROI B,FILPAG ; 7-bit bytes
MOVX C,FILPGS*5*^D512 ; number of bytes in this page set
EXCH C,FILSIZ ; bytes to do yet in C
CAMG C,FILSIZ ; more bytes after this page set?
IFSKP.
SUB C,FILSIZ ; yes, account for this page set in count
EXCH C,FILSIZ ; full page set to output
ELSE.
SETZM FILSIZ ; no, this is the last page set to do
ENDIF.
MOVNS C ; output exactly that number of bytes
CALL BOISOU ; send it out
SKIPE MONCMP
IFSKP.
MOVEI A,"!" ; indicate progress
PBOUT%
ENDIF.
SKIPG FILSIZ ; more to do yet?
IFSKP.
MOVEI A,FILPGS ; yes, bump CURPAG by number of pages just done
ADDM A,CURPAG
LOOP. ; do next set of pages
ENDIF.
ENDDO.
MOVE A,TCPJCN ; force out buffer
CALL $TCSND
JRST OUTERR
; falls through
SUBTTL Close connection and get reply
MOVE A,TCPJCN ; close the connection
CLOSE%
ERJMP .+1 ; don't worry about failure
MOVE A,TCPJCN ; get ready to read reply
SETZ C, ; initial reply code
DO.
CALL $TCBIN
EXIT.
CAIL B,"0" ; out of range?
CAILE B,"9"
EXIT. ; yes, punt
IMULI C,^D10 ; no, add this digit to the tally
ADDI C,-"0"(B)
LOOP. ; try for another digit
ENDDO.
CAIN C,^D221 ; success?
IFSKP.
EMSG <> ; no, output error indication
DO.
MOVE A,TCPJCN ; get byte of error info
CALL $TCBIN
EXIT. ; once closed, can punt
MOVX A,.PRIOU ; output it to terminal
BOUT%
LOOP.
ENDDO.
ELSE.
DO.
MOVE A,TCPJCN ; get byte of success info
CALL $TCBIN
EXIT. ; once closed, can punt
SKIPE MONCMP
IFSKP.
MOVX A,.PRIOU ; type it
BOUT%
ENDIF.
CAIE B,.CHLFD ; saw the last byte (known to be LF)?
LOOP. ; continue reading until closed
ENDDO.
ENDIF.
ABTCON: MOVE A,TCPJCN ; get JCN back
CALL $TCABT ; abort the connection
DONE: SKIPE MONCMP ; exit if invoked by monitor command
STOP: HALTF% ; end of program
SETZM MONCMP ; not invoked by monitor command any more
JRST BOISE ; get another command
SUBTTL Subroutines
STRLEN: SAVEAC <B,C>
SUBI A,-1(B) ; number of words in string +1
LDB B,[POINT 6,A,5] ; get position of byte within last word
IDIVI B,^D7 ; get number of unused bytes in this word
HRRZS A ; discard byte pointer stuff
IMULI A,5 ; convert words into number of bytes
SUBI A,(B) ; minus unused bytes
RET
BOIBOU: CALL $TCBOU ; output byte
JRST OUTERR
RET
BOISOU: CALL $TCSOU ; output string
JRST OUTERR
RET
OUTERR: EMSG <Output to Boise failed>
JRST ABTCON
; Output last JSYS error
LSTERR: MOVX A,.PRIOU ; output to terminal
HRLOI B,.FHSLF ; this fork,,last error
SETZ C, ; no limit
ERSTR%
JRST ERRUND ; undefined error number
NOP ; can't happen
RET
ERRUND: EMSG <Undefined error >
MOVX A,.FHSLF ; get error number
GETER%
MOVX A,.PRIOU ; output it
HRRZS B ; only right half where error code is
MOVX C,^D8 ; in octal
NOUT%
ERJMP R ; ignore error here
RET
SUBTTL Other stuff
EVEC: JRST BOISE ; START address
JRST BOISE ; REENTER address
<FLD BOIWHO,VI%WHO>!<FLD BOIVER,VI%MAJ>!<FLD BOIMIN,VI%MIN>!<FLD BOIEDT,VI%EDN>
EVECL==.-EVEC
...LIT: XLIST
LIT
LIST
END <EVECL,,EVEC>