.title $asetu .ident /x01/ .enabl lc .nlist bex ; ; Utility Routines ; Assembly Language Setup ; ; Version x01 ; ; David G. Conroy 12-Dec-77 ; .globl $asetu, $exit, $msg, $fmsg .globl $argc, $argv, $stdin, $stdou .globl $mdspt, $csibk, $dfnb .mcall gmcr$, exit$s, qiow$, nmblk$ .mcall fdbdf$, fdop$a, fdat$a, csi$ .mcall call, return, csi$1, csi$2 .mcall close$, open$a, open$w, open$r .mcall dir$ csi$ ; ; Equivalences ; MAXARG = 20. ;Size of $ARGV CMDLNG = 80. ;Size of buffer in GMCR$ TILUN = 1 ;TI: lun SILUN = 2 ;Standard input lun SOLUN = 3 ;Standard output lun ALT = 33 ;Ascii ALTMODE CR = 15 ;Ascii RETURN BL = 40 ;Ascii BLANK ; ; Global Data ; $argc: .word 0 ;Argument count. $argv: .blkw MAXARG ;Argument vector. $stdin: fdbdf$ ;Standard input fdb fdop$a SILUN,$csibk+c.dsds,$dfnb $stdou: fdbdf$ ;Standard output fdb fdat$a r.var,fd.cr fdop$a SOLUN,$csibk+c.dsds,$dfnb $dfnb: nmblk$ ,,,SY ;Default name block $csibk: .blkb c.size ;CSI work block .even ; ; Local Data ; aflag: .word 0 ;Append flag stdin: .word ti ;Standard input filename stdout: .word ti ;Standard output filename iostat: .blkw 2 ;i/o status return ; ; Directive Blocks ; gmcr: gmcr$ ;Get MCR command line rpr: qiow$ io.rpr,TILUN,1,,iostat,, out: qiow$ io.wlb,TILUN,1,,,,<0,0,BL> ; ; Ascii Things ; pr: .ascii "Gmcr: " ;Prompt string if GMCR$ fails prl = .-pr ti: .asciz "TI:" ;Default stdin and stdout msg01: .asciz "No command" msg02: .asciz "Syntax error" msg03: .asciz ": not found" msg04: .asciz ": cannot create" .even ;+ ; ** $asetu - Assembly Language Setup ; ; This routine and his subordinates prepare a somewhat standard ; world for the execution of user commands. ; First a command line is read from MCR; if this fails (this ; happens a lot during testing) it will prompt for the command ; line on TI: ; The command line is then broken up into its arguments. The ; number of arguments is saved in $ARGC; a vector of pointers ; to the arguments (in asciz) is built in $ARGV. ; Two files are then opened on fdb's $STDIN and $STDOU. Usually ; these files are opened on TI:; however they may be redirected ; using the ">", ">>" and "<" conventions. ; The user is then called at $MAIN. ; ; The user must set lun 1 to the TI: during the task build. ; This routine requires 2 fcs block buffers. ;- $asetu: dir$ #gmcr ;Get MCR command line bcc 20$ ;Successful dir$ #rpr ;If failure, try to read it cmpb iostat,#is.suc ;If the status is good beq 10$ ;Go put the newline on the end mov #msg01,r0 ;Otherwise br 100$ ;Give up 10$: mov iostat+2,r0 ;Append a newline movb #CR,gmcr+g.mcrb(r0) ;To the command line 20$: mov #gmcr+g.mcrb,r0 ;Get pointer to command line call chop ;Chop it up bcc 30$ ;If there is an error mov #msg02,r0 ;Its br 100$ ;Fatal 30$: mov stdin,r0 ;Open standard input call $mdspt bcs 40$ ;Bad file name open$r #$stdin bcc 50$ 40$: mov #msg03,r0 ;Cannot open file mov stdin,r1 br 90$ 50$: mov stdout,r0 ;Open standard output call $mdspt bcs 70$ ;Bad file name tst aflag ;Is it open for append ">>" beq 60$ ;Br if not open$a #$stdou bcc 80$ cmpb f.err(r0),#ie.nsf ;If the file is nonexistant bne 70$ ;Append is just write 60$: open$w #$stdou bcc 80$ 70$: mov #msg04,r0 ;Cannot create mov stdout,r1 br 90$ 80$: call $main ;Invoke user's mainline br $exit ;Then go away 90$: call $fmsg ;File open error br $exit 100$: call $msg ;Other error ;+ ; ** $exit - exit ; ; This routine closes the standard files. If you wish to abort ; you should jump to $exit (rather than doing an exit$s) thus ; closing the files. ;- $exit: close$ #$stdin ;Close standard input close$ #$stdou ;Close standard output exit$s ;Exit ;+ ; ** $fmsg -- write message for file accesses, etc. ; ; Inputs: ; r0=pointer to asciz message ; r1=pointer to asciz file name ;- $fmsg: mov r0,-(sp) ;Save message text mov r1,r0 ;File name mov #'$,out+q.iopl+4;Change slew to 'prompt' and call $msg ;Put out file name mov (sp)+,r0 ;Get message mov #'+,out+q.iopl+4;Put in overprint slew call $msg ;Put out message (and a newline) mov #BL,out+q.iopl+4;Put back normal slew return ;Return ;+ ; ** $msg -- write message ; ; Inputs: ; r0=pointer to asciz message ;- $msg: mov r0,out+q.iopl ;Buffer address 10$: tstb (r0)+ ;Compute length bne 10$ ;Of dec r0 ;The sub out+q.iopl,r0 ;Message mov r0,out+q.iopl+2 ;Save in the QIOW$ dir$ #out ;Fire it off, and mov out+q.iopl,r0 ;Recover original r0 return ;Return ;+ ; chop -- chop up command line ; ; Inputs: ; r0=pointer to string ; ; Outputs: ; $argv, $argc, stdin, stdout, aflag set up ; r0=junk ; r1=junk ; r2=junk ; r3=junk ;- chop: mov #$argv,r1 ;R1 is output working pointer 10$: clr r3 ;New field, clear quote flag 15$: movb (r0)+,r2 ;Skip over leading blanks cmpb r2,#BL beq 15$ cmpb r2,#CR ;Stop scan on return beq 120$ cmpb r2,#ALT ;Or altmode beq 120$ cmpb r2,#'' ;Quoted argument? beq 20$ ;Yes cmpb r2,#'" ;Both kinds work bne 30$ ;Not quoted argument 20$: mov r2,r3 ;Save delimiter cmp r1,#$argv+<2*MAXARG> ;Will another fit? bhis 110$ ;No mov r0,(r1)+ ;Yes, save pointer inc $argc ;Count up an argument br 70$ ;Go collect 30$: cmpb r2,#'< ;Redirect standard input? bne 40$ ;No mov r0,stdin ;Yes, save pointer to string br 70$ ;Go collect name 40$: cmpb r2,#'> ;Redirect standard output bne 60$ ;Br if not cmpb (r0),r2 ;Is it ">>" for append? bne 50$ ;No inc r0 ;Yes, skip the second ">" inc aflag ;Set appending flag 50$: mov r0,stdout ;Save the file name and br 70$ ;Go collect the field 60$: cmp r1,#$argv+<2*MAXARG> ;Will another argument fit? bhis 110$ ;Br if not mov r0,(r1) ;Save dec (r1)+ ;Pointer and inc $argc ;Count up an argument 70$: movb (r0)+,r2 ;Collect a field cmpb r2,#CR ;Stop on return beq 90$ cmpb r2,#ALT ;And altmode beq 90$ tst r3 ;Quoted argument? bne 80$ ;Br if yes cmpb r2,#BL ;If not quoted, stop on blank beq 90$ br 70$ ;Keep collecting 80$: cmp r2,r3 ;Is it the right kind of quote bne 70$ ;No, keep collecting 90$: clrb -1(r0) ;Make argument asciz cmpb r2,#CR ;Quit on cr field beq 100$ cmpb r2,#ALT ;Or altmode field bne 10$ 100$: tst r3 ;Still in a quoted field beq 120$ ;No, ok 110$: sec ;Yes, error return ;Return to caller 120$: clc ;Good return return ;To caller ;+ ; ** $mdspt -- make a dspt in the csi block ; ; Inputs: ; r0=pointer to asciz name ;- $mdspt: mov r0,$csibk+c.cmld+2 ;Pointer 10$: tstb (r0)+ ;Get length bne 10$ dec r0 sub $csibk+c.cmld+2,r0 mov r0,$csibk+c.cmld;Put in the csi block csi$1 #$csibk ;Syntax check bcs 20$ ;Error csi$2 ,output ;Make name 20$: return ;Done .end $asetu