|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 5756 (0x167c) Types: TextFile Names: »doprnt.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/euug-87hel/sec3/doprnt/doprnt.c«
/* * Common code for printf et al. * * The calling routine typically takes a variable number of arguments, * and passes the address of the first one. This implementation * assumes a straightforward, stack implementation, aligned to the * machine's wordsize. Increasing addresses are assumed to point to * successive arguments (left-to-right), as is the case for a machine * with a downward-growing stack with arguments pushed right-to-left. * * To write, for example, fprintf() using this routine, the code * * fprintf(fd, format, args) * FILE *fd; * char *format; * { * _doprnt(format, &args, fd); * } * * would suffice. (This example does not handle the fprintf's "return * value" correctly, but who looks at the return value of fprintf * anyway?) * * This version implements the following printf features: * * %d decimal conversion * %u unsigned conversion * %x hexadecimal conversion * %X hexadecimal conversion with capital letters * %o octal conversion * %c character * %s string * %m.n field width, precision * %-m.n left adjustment * %0m.n zero-padding * %*.* width and precision taken from arguments * * This version does not implement %f, %e, or %g. It accepts, but * ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not * work correctly on machines for which sizeof(long) != sizeof(int). * It does not even parse %D, %O, or %U; you should be using %ld, %o and * %lu if you mean long conversion. * * This version implements the following nonstandard features: * * %b binary conversion * %r roman numeral conversion * %R roman numeral conversion with capital letters * * As mentioned, this version does not return any reasonable value. * * Permission is granted to use, modify, or propagate this code as * long as this notice is incorporated. * * Steve Summit 3/25/87 */ #include <stdio.h> #define TRUE 1 #define FALSE 0 #define ROMAN #define isdigit(d) ((d) >= '0' && (d) <= '9') #define Ctod(c) ((c) - '0') #define MAXBUF (sizeof(long int) * 8) /* enough for binary */ #ifdef ROMAN static tack(); static doit(); #endif _doprnt(fmt, argp, fd) register char *fmt; register int *argp; FILE *fd; { register char *p; char *p2; int size; int length; int prec; int ladjust; char padc; int n; unsigned int u; int base; char buf[MAXBUF]; int negflag; char *digs; #ifdef ROMAN char *rdigs; int d; #endif while(*fmt != '\0') { if(*fmt != '%') { putc(*fmt++, fd); continue; } fmt++; if(*fmt == 'l') fmt++; /* need to use it if sizeof(int) < sizeof(long) */ length = 0; prec = -1; ladjust = FALSE; padc = ' '; if(*fmt == '-') { ladjust = TRUE; fmt++; } if(*fmt == '0') { padc = '0'; fmt++; } if(isdigit(*fmt)) { while(isdigit(*fmt)) length = 10 * length + Ctod(*fmt++); } else if(*fmt == '*') { length = *argp++; fmt++; if(length < 0) { ladjust = !ladjust; length = -length; } } if(*fmt == '.') { fmt++; if(isdigit(*fmt)) { prec = 0; while(isdigit(*fmt)) prec = 10 * prec + Ctod(*fmt++); } else if(*fmt == '*') { prec = *argp++; fmt++; } } negflag = FALSE; digs = "0123456789abcdef"; #ifdef ROMAN rdigs = " mdclxvi"; #endif switch(*fmt) { case 'b': case 'B': u = *argp++; base = 2; goto donum; case 'c': putc(*argp++, fd); break; case 'd': case 'D': n = *argp++; if(n >= 0) u = n; else { u = -n; negflag = TRUE; } base = 10; goto donum; case 'o': case 'O': u = *argp++; base = 8; goto donum; #ifdef ROMAN case 'R': rdigs = " MDCLXVI"; case 'r': n = *argp++; p2 = &buf[MAXBUF - 1]; d = n % 10; tack(d, &rdigs[6], &p2); n = n / 10; d = n % 10; tack(d, &rdigs[4], &p2); n = n / 10; d = n % 10; tack(d, &rdigs[2], &p2); n /= 10; d = n % 10; tack(d, rdigs, &p2); p = p2; goto putpad; #endif case 's': p = (char *)(*argp++); if(p == NULL) p = "(NULL)"; if(length > 0 && !ladjust) { n = 0; p2 = p; for(; *p != '\0' && (prec == -1 || n < prec); p++) n++; p = p2; while(n < length) { putc(' ', fd); n++; } } n = 0; while(*p != '\0') { if(++n > prec && prec != -1) break; putc(*p++, fd); } if(n < length && ladjust) { while(n < length) { putc(' ', fd); n++; } } break; case 'u': case 'U': u = *argp++; base = 10; goto donum; case 'X': digs = "0123456789ABCDEF"; case 'x': u = *argp++; base = 16; donum: p = &buf[MAXBUF - 1]; do { *p-- = digs[u % base]; u /= base; } while(u != 0); if(negflag) putc('-', fd); putpad: size = &buf[MAXBUF - 1] - p; if(size < length && !ladjust) { while(length > size) { putc(padc, fd); length--; } } while(++p != &buf[MAXBUF]) putc(*p, fd); if(size < length) /* must be ladjust */ { while(length > size) { putc(padc, fd); length--; } } break; case '\0': fmt--; break; default: putc(*fmt, fd); } fmt++; } } #ifdef ROMAN static tack(d, digs, p) int d; char *digs; char **p; { if(d == 0) return; if(d >= 1 && d <= 3) { doit(d, digs[2], p); return; } if(d == 4 || d == 5) { **p = digs[1]; (*p)--; } if(d == 4) { **p = digs[2]; (*p)--; return; } if(d == 5) return; if(d >= 6 && d <= 8) { doit(d - 5, digs[2], p); **p = digs[1]; (*p)--; return; } /* d == 9 */ **p = digs[0]; (*p)--; **p = digs[2]; (*p)--; return; } static doit(d, one, p) int d; char one; char **p; { int i; for(i = 0; i < d; i++) { **p = one; (*p)--; } } #endif