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