Minix1.5/lib/other/doprintf.c
#include <lib.h>
#include <stdarg.h>
#include <stdio.h>
/* three compile time options:
* NO_LONGD %d and %ld/%D are equal
* NO_FLOAT abort on %e, %f and %g
*/
#define NO_FLOAT
#ifdef NO_FLOAT
#define MAXDIG 11 /* 32 bits in radix 8 */
#else
#define MAXDIG 128 /* this must be enough */
#endif
PRIVATE _PROTOTYPE( char *_itoa, (char *p, unsigned num, int radix));
#ifndef NO_LONGD
PRIVATE _PROTOTYPE( char *ltoa, (char *p, unsigned long num, int radix));
#endif
PRIVATE char *_itoa(p, num, radix)
register char *p;
register unsigned int num;
register radix;
{
register i;
register char *q;
q = p + MAXDIG;
do {
i = (int) (num % radix);
i += '0';
if (i > '9') i += 'A' - '0' - 10;
*--q = i;
} while (num = num / radix);
i = p + MAXDIG - q;
do
*p++ = *q++;
while (--i);
return(p);
}
#ifndef NO_LONGD
PRIVATE char *ltoa(p, num, radix)
register char *p;
register unsigned long num;
register radix;
{
register i;
register char *q;
q = p + MAXDIG;
do {
i = (int) (num % radix);
i += '0';
if (i > '9') i += 'A' - '0' - 10;
*--q = i;
} while (num = num / radix);
i = p + MAXDIG - q;
do
*p++ = *q++;
while (--i);
return(p);
}
#endif
#ifndef NO_FLOAT
extern char *_ecvt();
extern char *_fcvt();
extern char *_gcvt();
#endif
#define GETARG(typ) va_arg(args, typ)
void _doprintf(iop, fmt, argsfix)
FILE *iop;
_CONST register char *fmt;
va_list argsfix;
{
char buf[MAXDIG + 1]; /* +1 for sign */
register char *p;
register char *s;
register c;
register i;
register short width;
register short ndigit;
register ndfnd;
register ljust;
register zfill;
#ifndef NO_LONGD
register lflag;
register long l;
#endif
register int *args = (int *) argsfix;
for (;;) {
c = *fmt++;
if (c == 0) return;
if (c != '%') {
putc(c, iop);
continue;
}
p = buf;
s = buf;
ljust = 0;
if (*fmt == '-') {
fmt++;
ljust++;
}
zfill = ' ';
if (*fmt == '0') {
fmt++;
zfill = '0';
}
for (width = 0;;) {
c = *fmt++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
c = GETARG(int);
else
break;
width *= 10;
width += c;
}
ndfnd = 0;
ndigit = 0;
if (c == '.') {
for (;;) {
c = *fmt++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c == '*')
c = GETARG(int);
else
break;
ndigit *= 10;
ndigit += c;
ndfnd++;
}
}
#ifndef NO_LONGD
lflag = 0;
#endif
if (c == 'l' || c == 'L') {
#ifndef NO_LONGD
lflag++;
#endif
if (*fmt) c = *fmt++;
}
switch (c) {
case 'X':
#ifndef NO_LONGD
lflag++;
#endif
case 'x':
c = 16;
goto oxu;
case 'U':
#ifndef NO_LONGD
lflag++;
#endif
case 'u':
c = 10;
goto oxu;
case 'O':
#ifndef NO_LONGD
lflag++;
#endif
case 'o':
c = 8;
oxu:
#ifndef NO_LONGD
if (lflag) {
p = ltoa(p, (unsigned long)GETARG(long), c);
break;
}
#endif
p = _itoa(p, (unsigned int)GETARG(int), c);
break;
case 'D':
#ifndef NO_LONGD
lflag++;
#endif
case 'd':
#ifndef NO_LONGD
if (lflag) {
if ((l = GETARG(long)) < 0) {
*p++ = '-';
l = -l;
}
p = ltoa(p, (unsigned long)l, 10);
break;
}
#endif
if ((i = GETARG(int)) < 0) {
*p++ = '-';
i = -i;
}
p = _itoa(p, (unsigned int)i, 10);
break;
#ifdef NO_FLOAT
case 'e':
case 'f':
case 'g':
zfill = ' ';
*p++ = '?';
break;
#else
case 'e':
if (ndfnd == 0) ndigit = 6;
ndigit++;
p = _ecvt(p, GETARG(double), ndigit);
break;
case 'f':
if (ndfnd == 0) ndigit = 6;
p = _fcvt(p, GETARG(double), ndigit);
break;
case 'g':
if (ndfnd == 0) ndigit = 6;
p = _gcvt(p, GETARG(double), ndigit);
break;
#endif
case 'c':
zfill = ' ';
*p++ = GETARG(int);
break;
case 's':
zfill = ' ';
if ((s = GETARG(char *)) == 0) s = "(null)";
if (ndigit == 0) ndigit = 32767;
for (p = s; *p && --ndigit >= 0; p++);
break;
default: *p++ = c; break;
}
i = p - s;
if ((width -= i) < 0) width = 0;
if (ljust == 0) width = -width;
if (width < 0) {
if (*s == '-' && zfill == '0') {
putc(*s++, iop);
i--;
}
do
putc(zfill, iop);
while (++width != 0);
}
while (--i >= 0) putc(*s++, iop);
while (width) {
putc(zfill, iop);
width--;
}
}
}