Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
utilities/runner.fai
There are no other files named runner.fai in the archive.
Title RUNNER - Run a program
Search Monsym, Macsym
.require sys:macrel.rel
extern .jbsym ;for symbolic pc lookup in error routine
bugs==:0 ;no bugs
pdllen==:100 ;stack size
buflen==:200 ;command and atom buffer size
a=:1
b=:2
c=:3
d=:4
e=:5
ac16=:16
p=:17
sym==:6 ;ac used by error routines for symbol address
.chdqt==:42 ;char defn ala Macsym
define parse (field) <
movei b,field
call parser
>
define putchr (char) <
movei c,char
idpb c,a
>
define putstr (ptr) <
move b,ptr
call cpystr
>
define makptr (ac) <
tlc ac,-1
tlce ac,-1
tlnn ac,-1
hrli ac,(<point 7,0>)
>
define amsg (msg) <
ifn bugs,<
push p,a
tmsg <msg>
pop p,a
>
>
define dmsg (msg) <
ifn bugs,<
push p,a
hrroi a,[asciz \
msg\]
call domsg
pop p,a
>
>
define trace (lbl) <
dmsg <lbl:
>
>
define show (nam,loc) <
ifn bugs,<
dmsg < nam = >
push p,b
ifnb <loc>,<move b,loc>
ifb <loc>,<move b,nam>
call shower
pop p,b
call pcrlf
>
>
define say (nam,loc) <
ifn bugs,<
dmsg < nam = >
push p,sym
ifnb <loc>,<move sym,loc>
ifb <loc>,<move sym,nam>
call what
pop p,sym
call pcrlf
>
>
define saystk (n) <
ifn bugs,<
dmsg < stack = >
push p,b
hlrz b,n-1(p)
call shower
pop p,b
amsg <,,>
push p,sym
hrrz sym,n-1(p)
call what
pop p,sym
call pcrlf
>
>
Subttl Storage
zerbeg==:.
evpt: block 1 ;entry vector point desired
exejfn: block 1 ;file handle on program to run
exefrk: block 1 ;fork handle on program to run
snames: block 2 ;system and program names
rparse: block 1 ;reparse address
rparsp: block 1 ;stack value at reparse
prserr: block 1 ;alternate branch address for parsing error
cmderr: block 1 ;alternate branch address for comndjsys error
cstate: block .cmgjb+1 ;command state block
csbend==:.-1 ;end of CSB
gjfnbk: block .gjatr+1 ;long form get-jfn block
gjbend==:.-1 ;end of GJB
combuf: block buflen ;command buffer
atmbuf: block buflen ;atom buffer
rscbuf: block buflen+9 ;rescan buffer buffer
filnam: block 8 ;put the program filename here
errpc: block 1 ;pc error routine called from
erracs: block 17 ;acs preserved by error routines
pdl: block pdllen ;stack
zerend==:.-1
Subttl Main
start: jsp p,init
call getjcl ;input command line
call putjcl ;load rescan buffer
call runfrk ;run the program in a subfork
stop: HALTF%
jrst stop
;JSP P,INIT [a] !init routine called before stack set up
init: setzm zerbeg ;note that this clears stack, so give
move a,[zerbeg,,zerbeg+1] ; thanks our return address is not there
blt a,zerend
RESET%
movem p,pdl ;store our return address on the stack
move p,pdlini ;init the stack pointer
ret ;and return as if called normally
getjcl: trace getjcl
call inicsb ;initialize parser command state block
movei a,.nulio ;set command jfns not to echo
hrrm a,cstate+.cmioj
hrroi a,zero ;no prompt string needed at this point
movei b,jcltop ;reparse address
call promp1
movei a,.rsini ;look for jcl
RSCAN%
erjmp askjcl ;none if error
jumple a,askjcl ;none if zero chars
jcltop: trace jcltop
movei a,askjcl ;set up so parse error in jcl
movem a,prserr ; will simply go prompt user
parse runcmd ;look for RUNNER
toplvl: trace toplvl
parse evnum ;parse number defaulted to 0
jumpl b,everr ;as entry vector offset, negative is error
movem b,evpt
call prssys ;parse name of system program
movem b,exejfn
parse rscmd ;parse text to pass as command line arg
call cpycmd ;copy atom buffer to rescan buffer
call confrm
ret
;no valid command line, need to prompt user
askjcl: trace askjcl
skipn p,rparsp ;restore stack
move p,pdlini
hrroi a,runner ;print a meaningful prompt
call prompt
jrst toplvl
everr: skipe prserr ;look for non-default error handler
jrst @prserr ;use special handler
hrroi a,[asciz /Entry vector offset cannot be negative/]
ESOUT%
jrst noprs1 ;reprompt
Subttl Utilities
cpycmd: move a,fnptr ;get the filename proper of the program
move b,exejfn
movx c,<fld .jsaof,js%nam>
JFNS%
move a,rscptr ;put the program name in its cmd line
putstr fnptr
ldb b,atmpt1 ;check for no data line
jumpe b,cpycm1
putchr .chspc ;space
putstr atmptr ;plus the specified command line arg
cpycm1: putchr .chlfd ;terminate line with lf
putchr .chnul ;make asciz
ret
putjcl: move a,rscptr ;send it
RSCAN%
ercal warn
ret
;CALL GTSNMS [a-c] !get subsystem/program names into SNAMES
;gives snames/ subsystem name
; snames+1/ program name
gtsnms: skipe snames ;only if we have not done so once
ret
seto a,
move b,[-2,,snames]
movei c,.jisnm ;note .jipnm = .jisnm + 1
GETJI%
ercal fatal
ret
;CALL PCRIF !print a crlf if not at left margin already
pcrif: saveac <a,b>
movei a,.priou ;cursor position as vert,,horiz
RFPOS%
jxn b,.rhalf,pcrlf1 ;print a crlf if rh neq 0
ret
pcrlf: saveac a
pcrlf1: hrroi a,crlf ;print a crlf on primary output
PSOUT%
ret
;CALL DOMSG (a) !print a message
;takes a/ string pointer to message
domsg: saveac b
makptr a ;convert -1 or zero lh in arg into byte ptr
push p,a ;save arg
movei a,.priou ;cursor position as vert,,horiz
RFPOS%
pop p,a ;restore arg
jxn b,.rhalf,domsg1 ;skip crlf if all rh bits 0
ibp a
ibp a
domsg1: PSOUT%
ret
;CALL SHOWER (b) !show numeric value
;takes b/ value
shower: saveac <a,c>
movei a,.priou
movei c,8
NOUT%
ercal warn
ret
;CALL WHAT (sym) !show symbolic value
;takes sym/ value to display symbolically
what: saveac <a,b,c,d,e>
callret symout
;dumb string copy
cpyst1: idpb c,a ;copy an asciz not including the zero
cpystr: ildb c,b
jumpn c,cpyst1
ret
;CALL RLJFNS [a] !releases jfns
rljfns: seto a,
RLJFN% ;release jfns
ercal warn ;just print message on error
ret
Subttl Command processing
;CALL INICSB [b]
inicsb: move b,[csbini,,cstate] ;initialize command state block
blt b,csbend
setzm prserr ;reset error handlers to default
setzm cmderr ; (reparse address must reinitialize)
ret
;CALL PROMPT (a) [b] !usual way of setting up command parse
;takes a/ ptr to prompt string
prompt: trace prompt
call inicsb ;initialize command parser jsys
hrrz b,(p) ;set reparse address automagically
promp1: movem a,cstate+.cmrty ;set prompt
movem b,rparse
move a,p ;save where to restore stack on reparse
adjsp a,-1
movem a,rparsp
promp0: movei b,cmini
jrst parser
;{a-c} = CALL CONFRM !waits for carriage return
confrm: movei b,cmcfm
; jrst parser
;{a-c} = CALL PARSER (b)
;takes b/ address of parse list
; cstate+.cmrty/ prompt string
; rparse/ reparse address
; rparsp/ stack pointer value at reparse address
; prserr/ address of alternate parser error handler
; cmderr/ address of alternate comndjsys error handler
;gives a/ function code of field parsed
; b/ comnd data
; c/ address of field parsed
parser: trace parser
say field,b
movei a,cstate ;command state block
COMND% ;parse a field
erjmp cmdbad
jxn a,cm%nop,nopars ;could we parse it?
hrrzs c ;address of field parsed
load a,cm%fnc,(c) ;yes, fetch what field type we parsed
ret
nopars: trace nopars
skipe prserr ;look for non-default error handler
jrst @prserr
call errout ;print informative error message
ldb a,atmpt1 ;print anything in the atom buffer
jumpe a,noprs1 ;skip it if nothing
tmsg < - ">
hrroi a,atmbuf ;print the guilty typein
PSOUT%
movei a,.chdqt
PBOUT%
noprs1: call promp0 ;reprompt
; jrst repars
repars: trace repars
skipn p,rparsp ;automate stack restore and avoid having to
move p,pdlini ; change reparse address in cstate
call rljfns
setzm prserr ;reset error handlers to default
setzm cmderr ; (reparse address must reinitialize)
skipe rparse ;use reparse address provided if any
jrst @rparse
jrst toplvl ;otherwise try going back to top
cmdbad: trace cmdbad
skipe cmderr ;look for non-default error handler
jrst @cmderr
hlrz a,cstate+.cmioj ;normal input?
cain a,.priin
jrst fatal ;yes, forget possibility of command file eof
movei a,.fhslf
GETER%
camn b,[.fhslf,,iox4] ;end of file?
jrst cmdeof ;command file ended, go fix
jrst fatal ;not just an eof, unrecoverable
cmdeof==:.-1 ;What? But no command files implemented!
Subttl Filename parsing
;parse a system program name
prssys: trace prssys
move a,[gjbini,,gjfnbk] ;set up file parse block
blt a,gjbend
hrroi a,[asciz /SYS/] ;default device SYS:
movem a,gjfnbk+.gjdev
hrroi a,[asciz /EXE/] ;default extension .EXE
movem a,gjfnbk+.gjext
movei a,prsif0 ;retry w/non-exe file
movem a,prserr ;joined here by PRSSYS
parse cmfil ;input filename
ret
;parse an input filename with no defaults
prsif0: trace prsif0
adjsp p,-1 ;here on PRSSYS noparse, avoid recursion
setzm prserr
prsifi: trace prsifi
move a,[gjbini,,gjfnbk] ;set up file parse block
blt a,gjbend
parse cmfil ;input filename
ret
Subttl Fork processing
;CALL RUNFRK
;takes evpt/ entry vector offset to use
; exefrk/ fork handle of existing fork to run, or zero if none
; exejfn/ file handle on program to load into fork, or zero for EXEC
runfrk: call gtsnms ;get system names
skipe a,exefrk ;use existing fork if any
jrst confrk
getexe: skipe exejfn ;use existing file, if any, otherwise run EXEC
jrst getfrk
movx a,gj%old!gj%sht ;try to get an exec
hrroi b,[asciz "SYSTEM:EXEC.EXE"]
GTJFN%
ercal nofork
movem a,exejfn ;save EXEC's jfn
getfrk: movx a,cr%cap ;make an inferior fork
CFORK%
ercal nofork
movem a,exefrk ;remember this program's fork handle
move a,exejfn ;get jfn
hrl a,exefrk ;stuff the fork
GET%
ercal norun
setzm exejfn ;jfn got released on success
movei a,.fhslf ;get my current capabilities
RPCAP%
move a,exefrk ;get back fork handle of inferior
move c,b ;enough already, enable the bloody caps
EPCAP%
ercal norun
move a,exefrk ;run it and wait for it to stop
move b,evpt ;start it at the desired entry point
SFRKV%
ercal norun
waitfk: RFORK% ;resume fork if frozen
WFORK% ;wait for it to finish
ercal norun ;no need to make this a fatal error
move a,exefrk ;short form rfsts to see if fork succeeded
RFSTS%
erjmp endrun ;if we can't diagnose, that's life, give up
load a,rf%sts,a
cain a,.rfhlt ;normal halt condition?
jrst endrun
hrroi a,[asciz/Error in inferior fork - /]
ESOUT%
hrlo b,exefrk ;go print last error in subfork
call error1
endrun: dmove a,snames ;restore system names
SETSN%
ercal warn
ret
confrk: txo a,sf%con ;continue the extant fork
SFORK%
erjmp getexe ;fork vanished or something
jrst waitfk ;wait for it to finish
nofork: setzm exefrk ;no fork
norun: pop p,errpc ;grab the address of our caller
call warn1 ;non-fatal error (?)
skipe a,exejfn ;get jfn back
RLJFN% ;flush it
nop
setzm exejfn
jrst endrun
Subttl Error processing
error: movem ac16,erracs+16 ;save acs
movei ac16,erracs
blt ac16,erracs+15
hrroi a,zero ;?
ESOUT%
hrloi b,.fhslf
error1: movei a,.priou ;print the error
setz c,
ERSTR%
nop
nop
ret
errout: pop p,errpc ;grab the address of our caller
push p,errpc
call error ;error prolog
errend: movsi ac16,erracs ;restore acs and return
blt ac16,ac16
ret
warn: pop p,errpc ;grab the address of our caller
push p,errpc
warn1: sos errpc ;point at jsys
call error ;error prolog
tmsg <, >
move sym,errpc ;get PC
move sym,-1(sym) ;get jsys which lost
call symout ;print it
tmsg < at >
move sym,errpc ;get back pc
movei sym,-1(sym) ;output pc
call symout
callret errend ;and go finish up with the pc
fatal: pop p,errpc ;grab the address of our caller
push p,errpc
call warn1
death: HALTF%
tmsg <?Cannot continue>
jrst death
Subttl Symbol manipulation
;CALL SYMOUT (sym) [a-e] !clever symbol table lookup routine.
;Takes SYM/ desired symbol
;(For details, read "Introduction to DECSYSTEM-20 Assembly Language
; Programming", by Ralph Gorin, published by Digital Press, 1981.)
symout: setzb c,e ;no current program name or best symbol
move d,.jbsym ;symbol table pointer
hlro a,d
sub d,a ;-count,,ending address +1
symlup: ldb a,[point 4,-2(d),3] ;symbol type
jumpe a,nxtsym ;program names are uninteresting
caile a,2 ;0=prog name, 1=global, 2=local
jrst nxtsym ;none of the kind we want
move a,-1(d) ;value of the symbol
camn a,sym ;exact match?
jrst [ move e,d ;yes, select it
jrst fndsym]
caml a,sym ;smaller than value sought?
jrst nxtsym ;too large
skipe b,e ;get best one so far if there is one
caml a,-1(b) ;compare to previous best
move e,d ;current symbol is best match so far
nxtsym: add d,[2000000-2] ;add 2 in the left, sub 2 in the right
jumpl d,symlup ;loop unless control count is exhausted
skipn d,e ;did we find anything helpful?
jrst octsym
;;;Found an entry that looks close. See if it really is and if so use it.
fndsym: move a,sym ;desired value
sub a,-1(d) ;less symbol's value = offset
cail a,200 ;is offset small enough?
jrst octsym ;no, not a good enough match
move d,e ;get the symbol's address
move a,-2(d) ;symbol name
tlz a,740000 ;clear flags
call r50out ;print symbol name
move b,sym ;get desired value
sub b,-1(d) ;less this symbol's value
jumpe b,r ;if no offset, don't print "+0"
movei a,"+" ;add + to the output line
PBOUT%
skipa
octsym: move b,sym ;here if pc must be in octal
movei a,.priou ;and copy numeric offset to output
movei c,8
NOUT%
halt .-1 ;bleah
ret
;CALL R50OUT (a) [b] !output a squoze
;takes a/ radix50 symbol
;This is a more or less standard routine. Snarfed from TELNET.MID (Crispin,
;1981).
r50out: idivi a,50 ;divide by 50
push p,b ;save remainder, a character
skipe a ;if a is now zero, unwind the stack
call r50out ;call self again, reduce a
pop p,a ;get character
adjbp a,[point 7,[ascii/ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.$%/],6]
ldb a,a ;convert squoze code to ascii
PBOUT%
ret
Subttl Pure data
csbini: repars ;the reparse address
.priin,,.priou ;i/o jfns
-1,,zero ;default no prompt
-1,,combuf ;can't edit past this point
-1,,combuf ;pointer to next field
buflen*5-1 ;remaining space in command buffer
0 ;remaining unparsed characters
-1,,atmbuf ;last field parsed
buflen*5-1 ;size of atom buffer
gjfnbk ;address of jfn block
gjbini: gj%old ;to initialize file parse block
block .gjatr+1+gjbini-. ;rest of block
runtbl: 2,,2 ;not intended to have additional entries
[cm%fw!cm%nor
asciz /RUNNE/],,0
[asciz /RUNNER/],,0
cmini: flddb. .cmini
cmcfm: flddb. .cmcfm
cmfil: flddb. .cmfil
runcmd: flddb. .cmkey,,runtbl
evnum: flddb. .cmnum,cm%sdh,<^D10>,<input filespec
or decimal entry vector offset>,<0>
rscmd: flddb. .cmtxt,cm%sdh,,<data line to be sent to program>
rscptr: point 7,rscbuf
atmptr: point 7,atmbuf
atmpt1: point 7,atmbuf,6
fnptr: point 7,filnam
pdlini: iowd pdllen+1,pdl+1
runner: asciz /RUNNER>/
crlf: asciz /
/
zero: 0
end start