/* C library - printf/scanf guts */ #define FILE char #define EOF -1 #define EOS 0 #define NULL 0L /* printf's (see below for the guts) */ char *_dopf(); fprintf(fp, fmt, args) FILE *fp; char *fmt; int args; { extern char _pfb[256]; _dopf(_pfb, fmt, &args); return fputs(_pfb, fp); } printf(fmt, args) char *fmt; int args; { extern char _pfb[256]; extern FILE *stdout; _dopf(_pfb, fmt, &args); return fputs(_pfb, stdout); } /* scanf routines */ fscanf(f, fmt, args) FILE *f; char *fmt; int *args; { extern char *_sfcp; extern FILE *_sffp; _sffp = f; _sfcp = NULL; return _dosf(fmt, &args); } scanf(fmt, args) char *fmt; int *args; { extern char *_sfcp; extern FILE *_sffp, *stdin; _sffp = stdin; _sfcp = NULL; return _dosf(fmt, &args); } sscanf(s, fmt, args) char *s; char *fmt; int *args; { extern char *_sfcp; extern FILE *_sffp; _sffp = NULL; _sfcp = s; return _dosf(fmt, &args); } /* the guts of the scanf's */ _dosf(fmt, args) char *fmt; int **args; { int assigned, wid, lng, skip, *ip, f, c, m, base; extern char _pfb[1]; long n, *lp, atof(); char *cp; assigned = 0; c = _sfget(); while ((f = *fmt++) && c != EOF) { if (f <= ' ') { /* skip spaces */ while (c <= ' ' && c != EOF) c = _sfget(); } else if (f != '%') { /* match character */ if (c != f) return assigned; c = _sfget(); } else { wid = lng = skip = 0; if ((f = *fmt++) == '*') { /* skip assignment */ skip++; f = *fmt++; } while (f >= '0' && f <= '9') { /* width of value */ wid = wid * 10 + f - '0'; f = *fmt++; } if (f == 'l') { /* long */ lng++; f = *fmt++; } else if (f == 'h') { /* short */ f = *fmt++; } switch (f) { /* conversion spec */ case '%': if (c != '%') return assigned; c = _sfget(); break; case 'c': if (wid == 0) { cp = *args++; if (!skip) { *cp = c; assigned++; } c = _sfget(); break; } case 's': cp = *args++; while (c <= ' ' && c != EOF) c = _sfget(); while (c > ' ' && c != EOF) { if (!skip) *cp++ = c; c = _sfget(); if (--wid == 0) break; } *cp = 0; if (!skip) assigned++; break; case 'D': case 'X': case 'O': lng = 1; f = f - 'A' + 'a'; case 'd': case 'x': case 'o': base = (f == 'x' ? 16 : f == 'o' ? 8 : 10); n = 0L; while (c != EOF && c <= ' ') c = _sfget(); if ((m = _sfnum(c, base)) < 0) return assigned; do { n = n * base + m; c = _sfget(); m = _sfnum(c, base); if (--wid == 0) break; } while (m >= 0); if (m >= 0) c = _sfget(); if (!skip) { if (lng) { lp = *args++; *lp = n; } else { ip = *args++; *ip = n; } assigned++; } break; case 'e': case 'f': case 'E': case 'F': while (c <= ' ' && c != EOF) c = _sfget(); if (!_sfflt(c)) return assigned; for (cp = _pfb; _sfflt(c); ) { *cp++ = c; c = _sfget(); } *cp = 0; if (!skip) { lp = *args++; *lp = atof(_pfb); assigned++; } break; default: return assigned; } } } return f == 0 ? assigned : EOF; } _sfnum(c, base) { if (c >= '0' && c <= '9') return c - '0'; else if (base == 16 && c >= 'a' && c <= 'f') return c - 'a' + 10; else if (base == 16 && c >= 'A' && c <= 'F') return c - 'A' + 10; else return -1; } _sfflt(c) { /* pretty lame parser for float numbers, but so it goes */ if (c >= '0' && c <= '9') return 1; if (c == '+' || c == '-' || c == '.') return 1; if (c == 'e' || c == 'E') return 1; return 0; } _sfget() { extern char *_sfcp; extern FILE *_sffp; if (_sffp) return getc(_sffp); if (_sfcp && *_sfcp) return *_sfcp++; return EOF; } char *_sfcp; /* char pointer for scanf input string */ FILE *_sffp; /* FILE pointer for scanf input stream */ /* guts of the printf stuff */ #define MINUSFLG 1 #define PLUSFLG 2 #define BLANKFLG 4 #define POUNDFLG 8 #define ZEROFLG 16 #define LONGFLG 32 #define SIGNFLG 64 #define LOWERFLG 128 #define MAXINT 32767 char _pfb[256]; /* in case someone needs a buffer */ sprintf(buf, fmt, args) char *buf, *fmt; int args; { return _dopf(buf, fmt, &args) - buf; } char *_numcnv(), *_fltcnv(); char * _dopf(buf, fmt, i_p) char *buf, *fmt; int *i_p; { char c, **s_p, *s; long strtol(); int i, lng, precision, minfldw, flags; for (c = *fmt; ; c = *++fmt) { /* scan to next conversion specification */ while (c != '%') { *buf++ = c; if (c == EOS) { return buf - 1; } c = *++fmt; } c = *++fmt; /* scan flags */ for (flags = 0; ; c = *++fmt) { if (c == '-') flags |= MINUSFLG; else if (c == '+') flags |= PLUSFLG; else if (c == ' ') flags |= BLANKFLG; else if (c == '#') flags |= POUNDFLG; else break; } /* scan minimum field width */ if (c == '*') { minfldw = *i_p++; c = *++fmt; } else { if (c == '0') flags |= ZEROFLG; minfldw = (int)strtol(fmt, &fmt, 10); c = *fmt; } /* scan precision */ precision = -1; if (c == '.') { c = *++fmt; if (c == '*') { precision = *i_p++; c = *++fmt; } else { precision = (int)strtol(fmt, &fmt, 10); c = *fmt; } } if (c == 'l') { flags |= LONGFLG; c = *++fmt; } switch (c) { case 'd': buf = _numcnv(buf, 10, flags | SIGNFLG, &i_p, precision, minfldw); break; case 'o': buf = _numcnv(buf, 8, flags, &i_p, precision, minfldw); break; case 'u': buf = _numcnv(buf, 10, flags, &i_p, precision, minfldw); break; case 'x': flags |= LOWERFLG; case 'X': buf = _numcnv(buf, 16, flags, &i_p, precision, minfldw); break; case 'f': buf = _fltcnv(buf, 'f', flags, &i_p, precision, minfldw); break; case 'e': flags |= LOWERFLG; case 'E': buf = _fltcnv(buf, 'E', flags, &i_p, precision, minfldw); break; case 'g': flags |= LOWERFLG; case 'G': buf = _fltcnv(buf, 'G', flags, &i_p, precision, minfldw); break; case 'c': *buf++ = *i_p++; break; case 's': if (precision < 0) precision = MAXINT; s_p = (char **)i_p; s = *s_p++; i_p = (int *)s_p; for (lng = 0; s[lng] != EOS && lng < precision; ++lng); i = minfldw - lng; if ((flags & MINUSFLG) == 0) { /* right justify */ while (i-- > 0) *buf++ = ' '; } while (lng--) *buf++ = *s++; while (i-- > 0) *buf++ = ' '; break; case '%': default: *buf++ = c; break; } } } /* * convert float to ascii for my 32 bit floating point format * bit function * 31 sign * 24-30 exponent (excess 64) * 0-23 fraction */ #define EXCESS 64 #define DIGITS 24 #define MAXFRAC 0xFFFFFF #define MAXEXP 0x7F #define MAXBITS 32 #define sign(x) ((x >> 31) & 1) #define exp(x) (((x >> 24) & MAXEXP) - EXCESS) #define frac(x) (x & MAXFRAC) #define negate(x) (x ^ 0x80000000L) char * _fltcnv(buf, style, flags, f_p, precision, minfldw) char *buf; int style; int flags; long **f_p; int precision; int minfldw; { long x; int e, ee, len; char ibuf[15], fbuf[15], ebuf[6], sbuf[2], *p, *r; unsigned long f, t, b, d; x = **f_p; *f_p += 1; *ibuf = *fbuf = *sbuf = *ebuf = 0; if (precision < 0) precision = 6; else if (precision > 13) precision = 13; if (x == 0L) { strcpy(ibuf, "0"); if (precision > 0) strcpy(fbuf, ".0"); } else { if (sign(x)) strcpy(sbuf, "-"); else if (flags & PLUSFLG) strcpy(sbuf, "+"); else if (flags & BLANKFLG) strcpy(sbuf, " "); e = exp(x); f = frac(x); if (style == 'E' || e >= MAXBITS || e <= -DIGITS) { ee = 0; while (e > 2) { d = f % 10L; f = f / 10L; while (f && (f & 0x800000L) == 0) { f <<= 1; e--; } f += d; ee++; } while (e < 0) { f = f * 10L; d = 0L; while (f & 0xFF000000L) { d |= (f & 1L); f >>= 1; e++; } f += d; ee--; } ebuf[0] = flags & LOWERFLG ? 'e' : 'E'; if (ee < 0) { ebuf[1] = '-'; ee = -ee; } else ebuf[1] = '+'; ebuf[2] = (ee / 10) + '0'; ebuf[3] = (ee % 10) + '0'; ebuf[4] = 0; } /* now get the integer part */ if (e > 0) { if (e > DIGITS) t = f << (e - DIGITS); else t = f >> (DIGITS - e); _ltoc(t, ibuf); f = (f << e) & MAXFRAC; e = 0; } else { strcpy(ibuf, "0"); if (e < 0) f = f >> -e; } /* now get the fraction part */ if (precision > 0) { if (f) { b = 0x800000; d = 500000000; t = 1000000000; while (b) { if (f & b) t += d; b >>= 1; d >>= 1; } _ltoc(t, fbuf); fbuf[0] = '.'; } else strcpy(fbuf, ".0"); } } /* adjust the fraction part, trailing 0's, etc */ if (*fbuf) { for (e = strlen(fbuf); e < 15; e++) fbuf[e] = '0'; fbuf[precision+1] = 0; if (!((flags & POUNDFLG) && style == 'G')) { /* drop trailing 0's */ for (e = precision; e > 0 && fbuf[e] == '0'; e--) fbuf[e] = 0; if (e == 0) *fbuf = 0; } } /* okay, now fill out buf with the number */ r = buf; len = strlen(ibuf) + strlen(fbuf) + strlen(ebuf) + strlen(sbuf); if (flags & MINUSFLG) { while (len < minfldw) { *buf++ = ' '; len++; } } if (*sbuf) *buf++ = *sbuf; for (p = ibuf; *buf = *p++; ) buf++; if (*fbuf) { for (p = fbuf; *buf = *p++; ) buf++; } else if (flags & BLANKFLG) *buf++ = '.'; if (*ebuf) { for (p = ebuf; *buf = *p++; ) buf++; } if ((flags & MINUSFLG) == 0) { while (len < minfldw) { *buf++ = ' '; len++; } } *buf = 0; return buf; } _ltoc(x, p) long x; char *p; { char *r; int i, j, t; r = p; if (x == 0) { *p++ = '0'; *p = 0; } else { if (x < 0) { *p++ = '-'; x = -x; } for (i = 0; x > 0; x = x / 10L) p[i++] = (x % 10L) + '0'; p[i--] = 0; for (j = 0; j < i; ) { t = p[i]; p[i--] = p[j]; p[j++] = t; } } } char * _numcnv(buf, base, flags, ip_p, precision, minfldw) char *buf; unsigned int base; int **ip_p; { char numbuf[20], prefix[5], *s, *p, *strncpy(); int n, pad, lng, d; long value, *l_p; unsigned long uvalue; s = numbuf; p = prefix; if (flags & LONGFLG) { l_p = (long *)*ip_p; value = *l_p++; *ip_p = (int *)l_p; } else { value = (long)**ip_p; *ip_p += 1; } if (flags & SIGNFLG) { if (value < 0) { *p++ = '-'; value = -value; } else { if (flags & PLUSFLG) *p++ = '+'; else if (flags & BLANKFLG) *p++ = ' '; } } uvalue = (unsigned long) value; while (uvalue) { d = uvalue % base; *s++ = (d < 10) ? d + '0' : d - 10 + ((flags & LOWERFLG) ? 'a' : 'A'); uvalue /= base; } lng = (int)(s - numbuf); n = (int)(p - prefix); pad = minfldw - n; if (flags & ZEROFLG) precision = minfldw - n; if (precision < 0) precision = 1; if (flags & POUNDFLG) { if (base == 8 && lng >= precision) precision = lng + 1; else if (base == 16) { *p++ = '0'; *p++ = flags & LOWERFLG ? 'x' : 'X'; n += 2; precision -= 2; } } pad -= lng > precision ? lng : precision; if (pad < 0) pad = 0; if ((flags & MINUSFLG) == 0) { while (pad--) *buf++ = ' '; pad = 0; } strncpy(buf, prefix, n); buf += n; while (precision-- > lng) *buf++ = '0'; while (lng--) *buf++ = *--s; while (pad--) *buf++ = ' '; return buf; }