/
/ Printf (and friends).
/

	.globl	printf
	.globl	fprint
	.globl	sprint
 
/
/ Autos.
/
 
FUNC	=	-2
ARGP	=	-4
LJUST	=	-6
PREC	=	-10
WIDE	=	-12
FILL	=	-14
HORD	=	-16
LORD	=	-20
BUF	=	-44		/ 20 bytes.
OLDP	=	-46
 
null:	.asciz	"{Null}"
	.even

 
printf:	jsr	r0,__csav
	sub	$46,sp
	mov	$__putc,FUNC(r5)
	mov	stdout,r4
	mov	$12,r0
	br	1f
 
fprint:	jsr	r0,__csav
	sub	$46,sp
	mov	$__putc,FUNC(r5)
	br	0f
 
sprint:	jsr	r0,__csav
	sub	$46,sp
	mov	$putsc,FUNC(r5)

0:	mov	12(r5),r4
	mov	$14,r0

1:	add	r5,r0
	mov	(r0)+,r3
	mov	r0,ARGP(r5)
 
/
/ Get next character from the
/ format string.
/ If not a `%' just send it to the
/ output.
/

prf01:	movb	(r3)+,r0
	beq	prf03

	cmp	r0,$'%
	beq	0f
	call	*FUNC(r5)
	br	prf01
 
/
/ Get widths and flags.
/

0:	clr	LJUST(r5)
	clr	WIDE(r5)
	mov	$-1,PREC(r5)
	mov	$' ,FILL(r5)
 
	movb	(r3)+,r0
	cmp	r0,$'-
	bne	0f
	inc	LJUST(r5)
	movb	(r3)+,r0

0:	cmp	r0,$'0
	bne	0f
	mov	r0,FILL(r5)
	movb	(r3)+,r0

0:	call	num
	mov	r1,WIDE(r5)
 
	cmp	r0,$'.
	bne	1f
	movb	(r3)+,r0
	call	num
	mov	r1,PREC(r5)

/
/ %r
/

1:	cmp	r0,$'r
	bne	1f
	mov	*ARGP(r5),ARGP(r5)
	mov	*ARGP(r5),r3
	add	$2,ARGP(r5)
	br	prf01

/
/ %e, %f, %g
/ All of the dirty work is done
/ by `__dtoa'.
/ The PREC is set to -1 because these
/ items use the PREC field in an
/ unstandard way.
/

1:	mov	r5,r2
	add	$BUF,r2

	cmp	r0,$'e
	beq	0f
	cmp	r0,$'f
	beq	0f
	cmp	r0,$'g
	bne	1f

0:	mov	ARGP(r5),r1
	add	$10,r1
	mov	r1,ARGP(r5)
	mov	-(r1),-(sp)
	mov	-(r1),-(sp)
	mov	-(r1),-(sp)
	mov	-(r1),-(sp)
	mov	PREC(r5),-(sp)
	mov	WIDE(r5),-(sp)
	mov	r0,-(sp)
	mov	r2,-(sp)
	call	__dtoa
	add	$20,sp
	mov	$-1,PREC(r5)
	br	prf02

/
/ Get the data. If there is an `l' in 
/ the format copy a long to HORD and
/ LORD. Otherwise copy the integer to
/ LORD and sign extend if %d.
/

1:	mov	ARGP(r5),OLDP(r5)
	mov	*ARGP(r5),r1
	add	$2,ARGP(r5)

	cmp	r0,$'l
	bne	0f
	mov	r1,HORD(r5)
	mov	*ARGP(r5),LORD(r5)
	add	$2,ARGP(r5)
	movb	(r3)+,r0
	br	1f

0:	cmp	r0,$'d
	beq	0f
	mov	r1,LORD(r5)
	clr	HORD(r5)
	br	1f

0:	clr	HORD(r5)
	mov	r1,LORD(r5)
	bpl	1f
	com	HORD(r5)

/
/ %c
/

1:	cmp	r0,$'c
	bne	1f
	mov	r5,r2
	add	$LORD,r2
	clrb	LORD+1(r5)
	br	prf02
 
/
/ %s
/ If pointer is 0, print {Null}
/

1:	cmp	r0,$'s
	bne	1f
	mov	LORD(r5),r2
	bne	prf02
	mov	$null,r2
	br	prf02

/
/ %d, %o, %u, %x, %X
/ Only %d gets integers sign extended.
/ All done with common routine.
/

1:	cmp	r0,$'d
	beq	0f
	cmp	r0,$'o
	beq	0f
	cmp	r0,$'u
	beq	0f
	cmp	r0,$'x
	beq	0f
	cmp	r0,$'X
	bne	1f

0:	mov	LORD(r5),-(sp)
	mov	HORD(r5),-(sp)
	mov	r0,-(sp)
	mov	r2,-(sp)
	call	__ltoa
	add	$10,sp
	br	prf02

/
/ None of the above.
/ Restore ARGP so an argument is not
/ eaten.
/

1:	mov	OLDP(r5),ARGP(r5)
	call	*FUNC(r5)
	br	prf01
 
/
/ Send out the null terminated ascii
/ string pointed to by r2.
/ Inserted any required fills and
/ pads.
/
 
prf02:	mov	r2,r1

0:	tstb	(r1)+
	bne	0b
	dec	r1
	sub	r2,r1

	tst	PREC(r5)
	bmi	0f
	cmp	PREC(r5),r1
	bhis	0f
	mov	PREC(r5),r1

0:	mov	r1,PREC(r5)

	tst	LJUST(r5)
	bne	0f
	call	fills

0:	mov	PREC(r5),r1

0:	dec	r1
	bmi	0f
	movb	(r2)+,r0
	call	*FUNC(r5)
	br	0b

0:	tst	LJUST(r5)
	beq	prf01
	call	fills
	br	prf01

/
/ All done.
/ If this is a call to sprintf append
/ the null byte.
/

prf03:	cmp	FUNC(r5),$putsc
	bne	0f
	clrb	(r4)

0:	jmp	__cret
 
/
/ This is the putchar routine used by
/ sprintf.
/ On entry, r0 is the character and
/ r4 is the string pointer.
/
 
putsc:	movb	r0,(r4)+
	return
 
/
/ Output WIDE - PREC copies of the
/ FILL character.
/
 
fills:	mov	WIDE(r5),r1
	sub	PREC(r5),r1
	ble	1f

	mov	FILL(r5),r0

0:	call	*FUNC(r5)
	dec	r1
	bne	0b

1:	return
 
/
/ Read in a field width.
/ The first character of the width is
/ in r0.
/ The width is returned in r1.
/ If the width specifier is `?' then the
/ width is obtained from the args.
/
 
num:	cmp	r0,$'?
	bne	0f
	mov	*ARGP(r5),r1
	add	$2,ARGP(r5)
	movb	(r3)+,r0
	br	1f

0:	clr	r1

0:	cmp	r0,$'0
	blo	1f
	cmp	r0,$'9
	bhi	1f

	asl	r1
	mov	r1,-(sp)
	asl	r1
	asl	r1
	add	(sp)+,r1

/	mul	$10.,r1
	add	r0,r1
	sub	$'0,r1
	movb	(r3)+,r0
	br	0b

1:	return
