|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 4487 (0x1187) Types: TextFile Notes: UNIX file Names: »printf.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »libc/stdio/printf.c«
/* * Standard I/O library printf/fprintf/sprintf. * Non-portable things: * 1) alignment of arguments is assumed to be completely contiguous. * 2) the smallest number is assumed to negate to itself. * 3) All of long, int, char*, and double are assumed to * be held in an exact number of ints. */ #include <stdio.h> #include <mdata.h> #include <ctype.h> union alltypes { char c; int i; unsigned u; long l; double d; char *s; }; #define bump(p,s) (p+=sizeof(s)/sizeof(int)) char *printi(); char *printl(); char *_dtefg(); static char null[] = "{NULL}"; /* * formatted print on standard output */ printf(args) union alltypes args; { xprintf(stdout, &args); } /* * Formatted print on given file */ fprintf(fp, args) FILE *fp; union alltypes args; { xprintf(fp, &args); } /* * Formatted print into given string. * Handcrafted file structure created for putc. */ char * sprintf(sp, args) char *sp; union alltypes args; { FILE file; _stropen(sp, -MAXINT-1, &file); xprintf(&file, &args); putc('\0', &file); return (sp); } static xprintf(fp, argp) FILE *fp; union alltypes *argp; { register char *cbp; int *iap; register c; char *s; char *cbs; char adj, pad; int prec; int fwidth; int pwidth; register char *fmt; union alltypes elem; char cbuf[64]; iap = (int *)argp; fmt = *(char **)iap; bump(iap, char*); for (;;) { while((c = *fmt++) != '%') { if(c == '\0') { return; } putc(c, fp); } pad = ' '; fwidth = -1; prec = -1; c = *fmt++; if (c == '-') { adj = 1; c = *fmt++; } else adj = 0; if (c == '0') { pad = '0'; c = *fmt++; } if (c == '*') { /* * I made it check for a negative field width and set adj accordingly - * John Thomas */ if ((fwidth = *iap++) < 0) { adj = 1; fwidth *= -1; } c = *fmt++; } else for (fwidth = 0; c>='0' && c<='9'; c = *fmt++) fwidth = fwidth*10 + c-'0'; if (c == '.') { c = *fmt++; if (c == '*') { prec = *iap++; c = *fmt++; } else for (prec=0; c>='0' && c<='9'; c=*fmt++) prec = prec*10 + c-'0'; } if (c == 'l') { c = *fmt++; if (c=='d' || c=='o' || c=='u' || c=='x') c = toupper(c); } cbp = cbs = cbuf; switch (c) { case 'd': elem.i = *iap++; if (elem.i < 0) { elem.i = -elem.i; *cbp++ = '-'; } cbp = printi(cbp, elem.i, 10); break; case 'u': cbp = printi(cbp, *iap++, 10); break; case 'o': cbp = printi(cbp, *iap++, 8); break; case 'x': cbp = printi(cbp, *iap++, 16); break; case 'D': elem.l = *(long *)iap; bump(iap, long); if (elem.l < 0) { elem.l = -elem.l; *cbp++ = '-'; } cbp = printl(cbp, elem.l, 10); break; case 'U': cbp = printl(cbp, *(long *)iap, 10); bump(iap, long); break; case 'O': cbp = printl(cbp, *(long *)iap, 8); bump(iap, long); break; case 'X': cbp = printl(cbp, *(long *)iap, 16); bump(iap, long); break; case 'e': case 'g': case 'f': elem.d = *(double *) iap; bump(iap, double); cbp = _dtefg(c, elem.d, prec, cbp); break; case 's': if ((s = *(char **)iap) == NULL) s = null; bump(iap, char*); /* * Do %s specially so it can be longer. */ cbp = cbs = s; while (*cbp++ != '\0') if (prec>=0 && cbp-s>prec) break; cbp--; break; case 'c': elem.c = *iap++; *cbp++ = elem.c; break; case 'r': xprintf(fp, *(char ***)iap); bump(iap, char**); break; default: putc(c, fp); continue; } if ((pwidth = fwidth + cbs-cbp) < 0) pwidth = 0; if (!adj) while (pwidth-- != 0) putc(pad, fp); while (cbs < cbp) putc(*cbs++, fp); if (adj) while (pwidth-- != 0) putc(pad, fp); } } static char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', }; /* * Print an unsigned integer in base b. */ static char * printi(cp, n, b) char *cp; register unsigned n; { register a; register char *ep; char pbuf[10]; ep = &pbuf[10]; *--ep = 0; for ( ; a = n/b; n=a) *--ep = digits[n%b]; *--ep = digits[n]; while (*ep) *cp++ = *ep++; return (cp); } /* * Print an unsigned long in base b. */ static char * printl(cp, n, b) register char *cp; unsigned long n; register b; { char pbuf[13]; unsigned long a; register char *ep; ep = &pbuf[13]; *--ep = '\0'; for ( ; (a = n/b) != 0; n = a) *--ep = digits[n%b]; *--ep = digits[n]; while (*ep) *cp++ = *ep++; return (cp); }