/
/ PDP-11 C.
/ Standard Library.
/
/ Run time startoff.
/

	.globl	stdin
	.globl	error
	.globl	exit
	.globl	stdout
	.globl	stderr
	.globl	__main
	.globl	__pro
	.globl	__uic
	.globl	__uic5
	.globl	__luns
	.globl	__nlun
	.globl	__pptr
	.globl	.nluns

	.entry	__main

/
/ Equivalences.
/

MAXMCR	=	80.		/Mcr command line size
MAXARG	=	20.		/Max number of command args.
MAXLUN	=	20.		/Max number of user luns

CR	=	15		/ASCII return
ALT	=	33		/ASCII altmode

/
/ Global data.
/ The `_' symbols are for internal use.
/ The `.' symbols are set by the loader.
/

stdin:	.word	0		/Stdin ioptr
stdout:	.word	0		/Stdout ioptr
stderr:	.word	iov		/Stderror ioptr

__pro:	.word	0		/Protection [rwed,rwed,rwed,rwed]
__uic:	.blkw	1		/Task default uic
__uic5:	.blkw	2		/Task default uic in rad50
__nlun:	.word	0		/Number of luns
__luns:	.blkw	MAXLUN		/Ioptrs on a per lun basis
__pptr:	.word	.+2		/Profiler link.
	return

.nluns:	.blkw	1		/Set to number of user luns

/
/ Local data.
/

iov:	.word	160000		/Stderr IOV
	.word	-1
	.word	0
	.word	iovb
	.word	iovb
	.word	80.
	.blkw	2
iovl:	.blkw	1

filin:	.word	ti		/Stdin file name
filout:	.word	ti		/Stdout file name
argc:	.word	0		/Number of command args
argv:	.blkw	MAXARG		/Ptrs to command args
argve:	.blkw	0		/Endmarker

iovb:	.blkw	41.		/Stderr buffer (also used by GTSK)
aflag:	.byte	0		/Append flag

/
/ Assorted ASCII things.
/ Arg strings for `fopen'.
/ Format strings for `fprintf'.
/

r:	.asciz	"r"
w:	.asciz	"w"
a:	.asciz	"a"
ti:	.asciz	"ti:"
co:	.ascii	"%s: cannot open."
	.byte	12,0
cc:	.ascii	"%s: cannot create."
	.byte	12,0
syn:	.ascii	"Syntax."
	.byte	12,0
mcr:	.ascii	"No core."
	.byte	12,0

	.even

/
/ Run time startoff.
/ Called from RSX-11.
/
/ Set up _luns table.
/ Grab the highest lun for stderr and assign it to TI:
/

__main:	mov	.nluns,r0
	mov	r0,iovl
	clr	-(sp)
	mov	$'T+['I<<8.],-(sp)
	mov	r0,-(sp)
	mov	$7.+[4.<<8.],-(sp)
	emt	377

	dec	r0
	cmp	r0,$MAXLUN
	blos	0f
	mov	$MAXLUN,r0
0:
	mov	r0,__nlun
	mov	$__luns,r1
0:
	dec	r0
	bmi	0f
	clr	(r1)+
	br	0b

/
/ Do a get task to get the task default uic.
/ Save it in binary in `__uic' and in radix 50 in
/ `__uic5'.
/

0:
	mov	$iovb,-(sp)	/GTSK
	mov	$63.+[2<<8.],-(sp)
	emt	377

	mov	iovb+16,r3	/Default uic word (word 07)
	mov	r3,__uic
	call	byto50
	mov	r1,__uic5+2	/First half
	mov	__uic,r3
	swab	r3
	call	byto50
	mov	r1,__uic5	/Last half

/
/ Get command line.
/

	mov	$MAXMCR+2,r0	/Get command line buffer
	call	__aloc
	tst	r0
	bne	0f
	mov	$mcr,-(sp)	/No core
	call	error		/No return

0:
	mov	(pc)+,(r0)	/Get command line
	.byte	127.,41.
	mov	r0,-(sp)
	emt	377
	bcc	0f		/Br if ok
	call	__free		/If no line, release buffer
	br	open		/And go with no args

/
/ Chop up command line.
/ Note redirection.
/

0:
	tst	(r0)+		/Point at command line
	mov	$argv,r1	/Point at the argv

3:
	clr	r3		/Quote flag

0:
	movb	(r0)+,r2	/Skip leading blanks
	cmp	r2,$' 
	beq	0b
	cmp	r2,$CR		/Duck out on delimiters
	beq	open
	cmp	r2,$ALT
	beq	open

	cmp	r2,$''		/Check for quoted argument
	beq	0f
	cmp	r2,$'"		/Both types
	bne	1f		/Not quoted argument
0:
	mov	r2,r3		/Save quote
	cmp	r1,$argve	/Does the arg fit
	bhis	3f
	mov	r0,(r1)+	/Add to argv
	inc	argc
	br	2f

1:
	cmp	r2,$'<		/Stdin redirection
	bne	1f
	mov	r0,filin
	br	2f

1:
	cmp	r2,$'>		/Stdout redirection
	bne	1f
	cmpb	r2,(r0)		/Append
	bne	0f		/No
	inc	r0		/Skip second `>'
	incb	aflag		/Set append flag
0:
	mov	r0,filout
	br	2f

1:
	cmp	r1,$argve	/Does normal arg fit
	bhis	3f		/Too many args
	mov	r0,(r1)		/Add to the argv
	dec	(r1)+
	inc	argc

2:
	movb	(r0)+,r2	/Collect the argument
	cmp	r2,$CR
	beq	1f
	cmp	r2,$ALT
	beq	1f
	tst	r3		/In quoted argument?
	bne	0f		/Yes
	cmp	r2,$' 		/No, blank is a delimiter
	beq	1f
	br	2b
0:
	cmp	r2,r3		/Check for closing quote
	bne	2b

1:
	clrb	-1(r0)		/Make C string
	cmp	r2,$CR		/Test if quitting time
	beq	0f
	cmp	r2,$ALT
	bne	3b		/Br if more to do
0:
	tst	r3		/Cannot quit in a quoted field
	beq	open

3:
	mov	$syn,-(sp)	/Syntax error
	call	error		/No return

/
/ Open standard streams.
/ Note that `stderr' is already open.
/ It has to be to insure diagnostics get out.
/

open:
	mov	$r,-(sp)	/fopen(stdin, "r")
	mov	filin,-(sp)
	call	fopen
	cmp	(sp)+,(sp)+
	mov	r0,stdin	/Save ioptr
	bne	0f		/Ok

	mov	filin,-(sp)	/Cannot open
	mov	$co,-(sp)
	call	error

0:
	mov	$w,-(sp)	/fopen(stdout, "w" or "a")
	tstb	aflag
	beq	0f
	mov	$a,(sp)
0:
	mov	filout,-(sp)
	call	fopen
	cmp	(sp)+,(sp)+
	mov	r0,stdout
	bne	go

	mov	filout,-(sp)	/Cannot create
	mov	$cc,-(sp)
	call	error

/
/ Call main.
/

go:
	mov	$argv,-(sp)
	mov	argc,-(sp)
	call	main
	cmp	(sp)+,(sp)+
	br	exit

/
/ error()
/ Print a message onto the standard error.
/ Then exit.
/

error:
	mov	stderr,(sp)	/Save ioptr over return address
	call	fprintf		/Put out message

/
/ exit()
/ Dropped into by error()
/ Called by user.
/ Jumped to when `main' returns.
/ Main task is to close files.
/

exit:
	call	wrapup		/User wrapup routine
	call	*__pptr		/Profiler

	mov	__nlun,r4	/Close all files
	mov	$__luns,r3
0:
	dec	r4
	bmi	0f
	mov	(r3)+,r2
	beq	0b
	mov	r2,-(sp)
	call	fclose
	tst	(sp)+
	br	0b

0:
	mov	(pc)+,-(sp)	/EXIT$S
	.byte	51.,1.
	emt	377

/
/ Convert a binary byte into rad50 encoded octal
/ ascii.
/ r3=the byte
/ r1=output
/

byto50:
	bic	$!377,r3	/Byte mask
	swab	r3		/ash $7,r3
	asrb	r3
	ror	r3
	clr	r1
	call	0f		/Do three digits
	call	0f
	callr	0f

0:
	clr	r2		/Get octal digit
	asl	r3		/ashc $3,r2
	rol	r2
	asl	r3
	rol	r2
	asl	r3
	rol	r2
	add	$36,r2		/Rad50 numeric offset
	asl	r1		/mul $50,r1
	asl	r1
	asl	r1
	mov	r1,-(sp)
	asl	r1
	asl	r1
	add	(sp)+,r1
	add	r2,r1
	return
