From utstat.toronto.edu!geoff Sun May 13 03:36:46 EDT 1990 Received: by pyxis; Sun May 13 03:37 EDT 1990 Received: by inet.att.com; Sun May 13 03:36 EDT 1990 From: geoff@utstat.toronto.edu Date: Sun, 13 May 90 03:36:46 EDT To: andrew@research.att.com Here are the files I changed in mk to make it use varargs (fio/fioprint.c, libc/doprint.c, libc/print.c). The new version of mk seems to work fine on our Suns and SGI (for the first time on the SGI) and lints more cleanly than before. I didn't make it use stdarg.h, but that should be fairly mechanical. The functions called from within doprint now get a va_list* as first argument instead of a char* and the size they return isn't used to advance along the stack (va_arg does that now). This will mean some changes to manual pages (sorry). # To unbundle, sh this file mkdir fio libc echo fio/fioprint.c 1>&2 sed 's/^-//' >fio/fioprint.c <<'!' -#define FIO_IMP -#include <varargs.h> -#include <fio.h> -/* VARARGS 2 */ -Fprint(f, fmt, va_alist) int f; char *fmt; va_dcl -{ - char buf[FIOBSIZE], *out; - register long n; - va_list ap; - extern char *doprint(); - va_start(ap); - out = doprint(buf, fmt, &ap); - va_end(ap); - n = out-buf; - if(Fwrite(f, buf, n) != n) - return(-1); - else - return((int)n); -} ! echo libc/doprint.c 1>&2 sed 's/^-//' >libc/doprint.c <<'!' -#include <varargs.h> -#define SIZE 1024 -#define FUNSIGN 4 -#define FSHORT 2 -#define FLONG 1 -#define PTR sizeof (char *) -#define SHORT sizeof (int) -#define INT sizeof (int) -#define LONG sizeof (long) -#define FLOAT sizeof (double) -#define FDIGIT 30 -#define FDEFLT 8 -#define IDIGIT 40 -#define MAXCONV 30 static char *out, *eout; static convcount = { 13 }; static noconv(); static cconv(), dconv(), hconv(), lconv(); static oconv(), sconv(), uconv(), xconv(); static econv(), fconv(), gconv(), percent(); int printcol; static int (*fmtconv[MAXCONV])() = -{ - noconv, - cconv, dconv, hconv, lconv, - oconv, sconv, uconv, xconv, - econv, fconv, gconv, percent, -}; static char fmtindex[128] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 9,10,11, 3, 0, 0, 0, 4, 0, 0, 5, - 0, 0, 0, 6, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, -}; fmtinstall(c, f) char c; int (*f)(); -{ - c &= 0177; - if(fmtindex[c] == 0) { - if(convcount >= MAXCONV) - return 1; - fmtindex[c] = convcount++; - } - fmtconv[fmtindex[c]] = f; - return 0; -} char* donprint(s, es, fmt, argpp) char *s, *es; register char *fmt; va_list *argpp; -{ - register int f1, f2, f3, sf1, c; - char *sout, *seout; - sout = out; - seout = eout; - out = s; - eout = es-1; loop: - c = *fmt++; - if(c != '%') { - if(c == 0) { - *out = 0; - s = out; - out = sout; - eout = seout; - return s; - } - if(out < eout) - *out++ = c; - printcol++; - if(c == '\n') - printcol = 0; else - if(c == '\t') - printcol = (printcol+7) & ~7; - goto loop; - } - f1 = 0; - f2 = -1; - f3 = 0; - c = *fmt++; - sf1 = 0; - if(c == '-') { - sf1 = 1; - c = *fmt++; - } - while(c >= '0' && c <= '9') { - f1 = f1*10 + c-'0'; - c = *fmt++; - } - if(sf1) - f1 = -f1; - if(c != '.') - goto l1; - c = *fmt++; - while(c >= '0' && c <= '9') { - if(f2 < 0) - f2 = 0; - f2 = f2*10 + c-'0'; - c = *fmt++; - } l1: - if(c == 0) - fmt--; - /* NB: first arg is now a (va_list *) */ - c = (*fmtconv[fmtindex[c&0177]])(argpp, f1, f2, f3); - if(c < 0) { - f3 |= -c; - c = *fmt++; - goto l1; - } -#ifdef notdef - argp += c; /* increment is now done in called routine by va_arg() */ -#endif - goto loop; -} numbconv(o, f1, f2, f3, b) va_list *o; -{ - char s[IDIGIT]; - register long v; - register int i, f, n, r; - switch(f3 & (FLONG|FSHORT|FUNSIGN)) { - case FLONG: - v = va_arg(*o, long); - r = LONG; - break; - case FUNSIGN|FLONG: - v = va_arg(*o, unsigned long); - r = LONG; - break; - /* NB: a (unsigned) short argument is promoted to an (unsigned) int arg. */ - case FSHORT: - v = (short)va_arg(*o, int); - r = SHORT; - break; - case FUNSIGN|FSHORT: - v = (unsigned short)va_arg(*o, unsigned); - r = SHORT; - break; - default: - v = va_arg(*o, int); - r = INT; - break; - case FUNSIGN: - v = va_arg(*o, unsigned); - r = INT; - break; - } - f = 0; - if(!(f3 & FUNSIGN) && v < 0) { - v = -v; - f = 1; - } - s[IDIGIT-1] = 0; - for(i = IDIGIT-2; i >= 1; i--) { - n = (unsigned long)v % b; - n += '0'; - if(n > '9') - n += 'a' - ('9'+1); - s[i] = n; - v = (unsigned long)v / b; - if(f2 >= 0 && i >= IDIGIT-f2) - continue; - if(v <= 0) - break; - } - if(f) - s[--i] = '-'; - strconv(s+i, f1, -1); - return r; -} char* doprint(s, fmt, argp) char *s, *fmt; va_list *argp; -{ - return donprint(s, s+SIZE, fmt, argp); -} -/* - if you change this, change chconv -*/ strconv(o, f1, f2) char *o; -{ - register int n, c; - register char *s; - n = 0; - for(s = o; *s++;) - n++; - if(f1 >= 0) - while(n < f1) { - if(out < eout) - *out++ = ' '; - printcol++; - n++; - } - for(s=o; c = *s++;) - if(f2 != 0) { - if(out < eout) - *out++ = c; - printcol++; - if(c == '\n') - printcol = 0; else - if(c == '\t') - printcol = (printcol+7) & ~7; - f2--; - } - if(f1 < 0) { - f1 = -f1; - while(n < f1) { - if(out < eout) - *out++ = ' '; - printcol++; - n++; - } - } -} chconv(o, f1) char o; -{ - register int n; - n = 1; - if(f1 >= 0) - while(n < f1) { - if(out < eout) - *out++ = ' '; - printcol++; - n++; - } - if(out < eout) - *out++ = o; - printcol++; - if(o == '\n') - printcol = 0; else - if(o == '\t') - printcol = (printcol+7) & ~7; - if(f1 < 0) { - f1 = -f1; - while(n < f1) { - if(out < eout) - *out++ = ' '; - printcol++; - n++; - } - } -} -/* ARGSUSED */ static noconv(o, f1, f2, f3) char *o; -{ - strconv("***", 0, -1); - return 0; -} -/* ARGSUSED */ static cconv(o, f1, f2, f3) va_list *o; -{ - chconv((char)va_arg(*o, int), f1); - return INT; -} static dconv(o, f1, f2, f3) va_list *o; -{ - int r; - r = numbconv(o, f1, f2, f3, 10); - return r; -} -/* ARGSUSED */ static hconv(o, f1, f2, f3) -{ - return -FSHORT; -} -/* ARGSUSED */ static lconv(o, f1, f2, f3) -{ - return -FLONG; -} static oconv(o, f1, f2, f3) va_list *o; -{ - int r; - r = numbconv(o, f1, f2, f3, 8); - return r; -} -/* ARGSUSED */ static sconv(o, f1, f2, f3) va_list *o; -{ - strconv(va_arg(*o, char *), f1, f2); - return PTR; -} -/* ARGSUSED */ static uconv(o, f1, f2, f3) -{ - return -FUNSIGN; -} static xconv(o, f1, f2, f3) va_list *o; -{ - int r; - r = numbconv(o, f1, f2, f3, 16); - return r; -} double pow10(), frexp(); -/* ARGSUSED */ fltconv(f, f1, f2, f3, c) register double f; -{ - char s1[FDIGIT+10], s2[FDIGIT+10]; - register double g; - register int d, i, n, s; - double h; - int e; - int c1, c2, c3; - s = 0; - if(f < 0) { - f = -f; - s++; - } loop: - e = 0; - g = 0; - if(f != 0) { - g = frexp(f, &e); - e = e * .30103; - d = e/2; - h = f * pow10(-d); /* 10**-e in 2 parts */ - g = h * pow10(d-e); - while(g < 1) { - e--; - g = h * pow10(d-e); - } - while(g >= 10) { - e++; - g = h * pow10(d-e); - } - } - if(f2 < 0) - f2 = FDEFLT; - if(c == 'g' && f2 > 0) - f2--; - if(f2 > FDIGIT) - f2 = FDIGIT; - /* - * n is number of digits to convert - * 1 before, f2 after, 1 extra for rounding - */ - n = f2 + 2; - if(c == 'f') { - /* - * e+1 before, f2 after, 1 extra - */ - n += e; - if(n <= 0) { - n = 1; - g = 0; - } - } - if(n >= FDIGIT+2) { - if(c == 'e') - f2 = -1; - c = 'e'; - goto loop; - } - /* - * convert n digits - */ - for(i=0; i<n; i++) { - d = g; - if(d > g) - d--; - g -= d; - s1[i+1] = d + '0'; - g *= 10; - } - /* - * round by adding .5 into extra digit - */ - d = 5; - for(i=n-1; i>=0; i--) { - s1[i+1] += d; - d = 0; - if(s1[i+1] > '9') { - s1[i+1] -= 10; - d++; - } - } - i = 1; - if(d) { - s1[0] = '1'; - e++; - i = 0; - } - /* - * copy into final place - * c1 digits of leading '0' - * c2 digits from conversion - * c3 digits after '.' - */ - d = 0; - if(s) - s2[d++] = '-'; - c1 = 0; - c2 = f2 + 1; - c3 = f2; - if(c == 'g') - if(e >= -5 && e <= f2) { - c1 = -e - 1; - c3 = c1; - if(c1 < 0) - c1 = 0; - c3 = f2 - e; - c = 'h'; - } - if(c == 'f') { - c1 = -e; - if(c1 < 0) - c1 = 0; - if(c1 > f2) - c1 = c2; - c2 += e; - if(c2 < 0) - c2 = 0; - } - while(c1 > 0) { - if(c1+c2 == c3) - s2[d++] = '.'; - s2[d++] = '0'; - c1--; - } - while(c2 > 0) { - if(c1+c2 == c3) - s2[d++] = '.'; - s2[d++] = s1[i++]; - c2--; - } - /* - * strip trailing '0' on g conv - */ - if(c == 'g' || c == 'h') { - for(n=d-1; n>=0; n--) - if(s2[n] != '0') - break; - for(i=n; i>=0; i--) - if(s2[i] == '.') { - d = n; - if(i != n) - d++; - break; - } - } - if(c == 'e' || c == 'g') { - s2[d++] = 'e'; - s2[d++] = '+'; - c1 = e; - if(c1 < 0) { - s2[d-1] = '-'; - c1 = -c1; - } - if(c1 >= 100) { - s2[d++] = c1/100 + '0'; - c1 %= 100; - } - s2[d++] = c1/10 + '0'; - s2[d++] = c1%10 + '0'; - } - s2[d] = 0; - strconv(s2, f1, -1); - return FLOAT; -} static econv(o, f1, f2, f3) va_list *o; -{ - return fltconv(va_arg(*o, double), f1, f2, f3, 'e'); -} static fconv(o, f1, f2, f3) va_list *o; -{ - return fltconv(va_arg(*o, double), f1, f2, f3, 'f'); -} static gconv(o, f1, f2, f3) va_list *o; -{ - return fltconv(va_arg(*o, double), f1, f2, f3, 'g'); -} static percent() -{ - if(out < eout) - *out++ = '%'; - return 0; -} ! echo libc/print.c 1>&2 sed 's/^-//' >libc/print.c <<'!' -#include <varargs.h> -#define SIZE 1024 extern int printcol; char *doprint(); -/* VARARGS 1 */ print(fmt, va_alist) char *fmt; va_dcl -{ - char buf[SIZE], *out; - va_list ap; - va_start(ap); - out = doprint(buf, fmt, &ap); - va_end(ap); - return write(1, buf, (int)(out-buf)); -} -/* VARARGS 2 */ fprint(fd, fmt, va_alist) char *fmt; va_dcl -{ - char buf[SIZE], *out; - va_list ap; - va_start(ap); - out = doprint(buf, fmt, &ap); - va_end(ap); - return write(fd, buf, (int)(out-buf)); -} -/* VARARGS 2 */ sprint(buf, fmt, va_alist) char *buf; char *fmt; va_dcl -{ - char *out; - int scol; - va_list ap; - scol = printcol; - va_start(ap); - out = doprint(buf, fmt, &ap); - va_end(ap); - printcol = scol; - return out-buf; -} !