	.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,,<gmcr+g.mcrb,CMDLNG-1,,pr,prl,'$>
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
