/ / 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