/
/ PDP-11 C.
/ Standard Library.
/
/ Printf.
/
 
	.globl	printf
	.globl	fprintf
	.globl	sprintf
 
/
/ Format of the stack frame
/
 
FUNC	=	-2		/Output function
ARGP	=	-4		/Argument pointer
LJUST	=	-6		/Left justification flag
MAX	=	-10		/Max field width
MIN	=	-12		/Min field width
FILL	=	-14		/Fill byte
BUF	=	-22		/Six byte buffer
 
HUGE	=	1000.		/Huge max width
 
printf:				/printf(fmt, arg, ...)
	jsr	r0,_save	/C linkage
	sub	$22,sp		/
	mov	stdout,r4	/Ioptr
	mov	$_putc,FUNC(r5)	/Output function
	mov	$12,r0		/Location of first arg
	br	0f
 
fprintf:			/fprintf(ioptr, fmt, arg, ...)
	jsr	r0,_save	/C linkage
	sub	$22,sp		/
	mov	12(r5),r4	/Ioptr
	mov	$_putc,FUNC(r5)	/Output function
	mov	$14,r0		/Location of first arg
	br	0f
 
sprintf:			/sprintf(str, fmt, arg, ...)
	jsr	r0,_save	/C linkage
	sub	$22,sp		/
	mov	12(r5),r4	/String pointer
	mov	$putsc,FUNC(r5)	/Output function
	mov	$14,r0		/Location of first arg
0:
	add	r5,r0		/Get pointer to args
	mov	(r0)+,r3	/Get pointer to format string
	mov	r0,ARGP(r5)	/Save argument pointer
 
next:
	movb	(r3)+,r0	/Format character
	beq	3f		/End
	cmpb	r0,$'%		/Is this a format specification
	beq	0f		/Yes
	call	*FUNC(r5)	/No, just put it out
	br	next
 
0:
	clr	LJUST(r5)	/Left justify flag
	clr	MIN(r5)		/Min width is small
	mov	$HUGE,MAX(r5)	/Max width is huge
	mov	$' ,FILL(r5)	/Fill character is a blank
 
	movb	(r3)+,r0	/Get character from format
	cmpb	r0,$'-		/Is it '-'
	bne	0f		/No
	inc	LJUST(r5)	/Yes, set left
	movb	(r3)+,r0	/Justification
0:
	cmpb	r0,$'0		/Is it '0'
	bne	0f		/No
	mov	r0,FILL(r5)	/Yes, set zero
	movb	(r3)+,r0	/Fill
0:
	call	num		/Get minimum
	mov	r1,MIN(r5)	/Width
 
	cmpb	r0,$'.		/If the delimiter is a '.'
	bne	0f		/Then
	movb	(r3)+,r0	/Get
	call	num		/Maximum
	mov	r1,MAX(r5)	/Width
0:
	mov	*ARGP(r5),r2	/Pick up argument
	add	$2,ARGP(r5)	/Fix arg. pointer
 
/
/ r0=format character (c, s, d, o)
/ Set up:
/	r2=pointer to string to output
/	r1=length of string to output
/
 
	cmpb	r0,$'c		/%c
	bne	1f		/No
	movb	r2,BUF(r5)	/Store byte in the buffer
	mov	r5,r2		/Set pointer
	add	$BUF,r2		/
	mov	$1,r1		/Length is 1 byte
	br	2f
 
1:
	cmpb	r0,$'s		/%s
	bne	1f		/No
	mov	r2,r1		/Compute the length
0:
	tstb	(r1)+		/Of
	bne	0b		/The
	dec	r1		/Argument
	sub	r2,r1		/String
	cmp	r1,MAX(r5)	/If too long
	blos	2f		/Then
	mov	MAX(r5),r1	/Set the actual number to do
	br	2f
 
1:
	cmpb	r0,$'d		/%d
	bne	1f		/No
	mov	r2,r0		/Number
	mov	r5,r2		/Buffer
	add	$BUF,r2		/Address
	mov	r2,r1		/Convert to ASCII
	call	_itoc
	sub	r2,r1		/Set length
	br	2f
 
1:
	cmpb	r0,$'o		/%o
	bne	1f		/No
	mov	r2,r0		/Number
	mov	r5,r2		/Buffer
	add	$BUF,r2		/Address
	mov	r2,r1		/Convert to ASCII
	call	_itoc8
	sub	r2,r1		/Set length
	br	2f
 
1:
	cmpb	r0,$'x		/%x
	bne	1f		/No
	mov	r2,r0		/Number
	mov	r5,r2		/Buffer 
	add	$BUF,r2		/Address
	mov	r2,r1		/Convert to ASCII
	call	_itox
	sub	r2,r1		/Set length
	br	2f

1:
	call	*FUNC(r5)	/Not a format character
	br	next
 
/
/ Put out the string
/ Perform filling as required
/
 
2:
	mov	r1,MAX(r5)	/Save width
	tst	LJUST(r5)	/If not left justified
	bne	0f		/Then
	mov	MIN(r5),r1	/Put
	sub	MAX(r5),r1	/out
	call	fills		/fills
 
0:
	mov	MAX(r5),r1	/Put out stuff
0:
	dec	r1		/
	bmi	0f		/
	movb	(r2)+,r0	/
	call	*FUNC(r5)	/
	br	0b
 
0:
	tst	LJUST(r5)	/If left justification
	beq	0f		/Then
	mov	MIN(r5),r1	/Put
	sub	MAX(r5),r1	/Out
	call	fills		/Fills
0:
	br	next		/Go get next format item
 
3:
	cmp	FUNC(r5),$putsc	/If sprintf
	bne	0f		/Then
	clrb	(r4)		/Append a null
0:
	jmp	_ret		/Exit
 
/
/ Putsc
/ Putc routine used by sprintf
/
 
putsc:
	movb	r0,(r4)+	/Store character in string
	return			/Done
 
/
/ Fills
/ Output r1 fill bytes
/
 
fills:
	mov	FILL(r5),r0	/Get the fill byte
0:
	dec	r1		/Need more
	bmi	0f		/Br if not
	call	*FUNC(r5)	/Output a fill byte and
	br	0b		/Try again
0:
	return			/Done
 
/
/ Num
/ Get a decimal number
/ r0 is the first character if the number
/
 
num:
	clr	r1		/Number starts as 0
0:
	cmpb	r0,$'0		/Test
	blo	0f		/For
	cmpb	r0,$'9		/Legal
	bhi	0f		/Digits
	asl	r1		/Old times 10
	mov	r1,-(sp)
	asl	r1
	asl	r1
	add	(sp)+,r1
	add	r0,r1		/Add the
	sub	$'0,r1		/New
	movb	(r3)+,r0	/Get the next digit and
	br	0b		/Repeat
0:
	return			/Done
