[comp.os.minix] NYUMINIX:KERNEL\LIB.C

jai@lab.ultra.nyu.edu (Benchiao Jai) (02/24/91)

/*
 * three compile time options:
 *	STACKUP 	fetch arguments using *p-- instead of *p++
 *	NO_LONGD	%d and %ld/%D are equal
 *	NO_FLOAT	abort on %e, %f and %g
 */

#define NO_FLOAT
#define MAXDIG		11	/* 32 bits in radix 8 */

static char *
itoa(p, num, radix)
register char *p;
register unsigned 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) != 0);
	i = p + MAXDIG - q;
	do
		*p++ = *q++;
	while (--i);
	return(p);
}

#ifndef NO_LONGD
static 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) != 0);
	i = p + MAXDIG - q;
	do
		*p++ = *q++;
	while (--i);
	return(p);
}
#endif

#ifdef STACKUP
#define GETARG(typ)	*((typ *)args)--
#else
#define GETARG(typ)	*((typ *)args)++
#endif STACKUP

printk(fmt, arg1)
register char *fmt;
{
	char		buf[MAXDIG+1];	/* +1 for sign */
	register int	*args = &arg1;
	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

	for (;;) {
		c = *fmt++;
		if (c == 0)
			return;
		if (c != '%') {
			putc(c);
			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, GETARG(long), c);
				break;
			}
#endif
			p = itoa(p, 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, l, 10);
				break;
			}
#endif
			if ((i = GETARG(int)) < 0) {
				*p++ = '-';
				i = -i;
			}
			p = itoa(p, i, 10);
			break;
		case 'e':
		case 'f':
		case 'g':
			zfill = ' ';
			*p++ = '?';
			break;
		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++);
				i--;
			}
			do
				putc(zfill);
			while (++width != 0);
		}
		while (--i >= 0)
			putc(*s++);
		while (width) {
			putc(zfill);
			width--;
		}
	}
}