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