|
|
1.1 ! root 1: /* ! 2: * Standard I/O library printf/fprint/sprintf. ! 3: * Non-portable things: ! 4: * 1) alignment of arguments is assumed to be completely contiguous. ! 5: * 2) the smallest number is assumed to negate to itself. ! 6: * 3) All of long, int, char*, and double are assumed to ! 7: * be held in an exact number of ints. ! 8: */ ! 9: ! 10: #include <stdio.h> ! 11: #include <sys/mdata.h> ! 12: #include <ctype.h> ! 13: ! 14: /* Avoid calling the new style toupper() function on MSDOS and GEMDOS */ ! 15: #ifdef _toupper ! 16: #define toupper(c) _toupper(c) ! 17: #endif ! 18: ! 19: union alltypes { ! 20: char c; ! 21: int i; ! 22: unsigned u; ! 23: long l; ! 24: double d; ! 25: char *s; ! 26: }; ! 27: ! 28: #define bump(p,s) (p+=sizeof(s)/sizeof(int)) ! 29: ! 30: char *printi(); ! 31: char *printl(); ! 32: char *_dtefg(); ! 33: ! 34: static readonly char null[] = "{NULL}"; ! 35: ! 36: /* ! 37: * Formatted print to standard output. ! 38: */ ! 39: printf(args) ! 40: union alltypes args; ! 41: { ! 42: xprintf(stdout, &args); ! 43: } ! 44: ! 45: /* ! 46: * Formatted print to a specific file. ! 47: */ ! 48: fprintf(fp, args) ! 49: FILE *fp; ! 50: union alltypes args; ! 51: { ! 52: xprintf(fp, &args); ! 53: } ! 54: ! 55: /* ! 56: * Formatted print into given string. ! 57: * Handcrafted file structure created for putc. ! 58: */ ! 59: sprintf(sp, args) ! 60: char *sp; ! 61: union alltypes args; ! 62: { ! 63: FILE file; ! 64: ! 65: _stropen(sp, -MAXINT-1, &file); ! 66: xprintf(&file, &args); ! 67: putc('\0', &file); ! 68: } ! 69: ! 70: static ! 71: xprintf(fp, argp) ! 72: FILE *fp; ! 73: union alltypes *argp; ! 74: { ! 75: register char *cbp; ! 76: int *iap; ! 77: register c; ! 78: char *s; ! 79: char *cbs; ! 80: int adj, pad; ! 81: int prec; ! 82: int fwidth; ! 83: int pwidth; ! 84: int isnumeric; ! 85: register char *fmt; ! 86: union alltypes elem; ! 87: char cbuf[64]; ! 88: ! 89: iap = (int *)argp; ! 90: fmt = *(char **)iap; ! 91: bump(iap, char*); ! 92: for (;;) { ! 93: while((c = *fmt++) != '%') { ! 94: if(c == '\0') { ! 95: return; ! 96: } ! 97: putc(c, fp); ! 98: } ! 99: pad = ' '; ! 100: fwidth = -1; ! 101: prec = -1; ! 102: c = *fmt++; ! 103: if (c == '-') { ! 104: adj = 1; ! 105: c = *fmt++; ! 106: } else ! 107: adj = 0; ! 108: if (c == '0') { ! 109: pad = '0'; ! 110: c = *fmt++; ! 111: } ! 112: if (c == '*') { ! 113: if ((fwidth = *iap++) < 0) { ! 114: adj = 1; ! 115: fwidth = -fwidth; ! 116: } ! 117: c = *fmt++; ! 118: } else ! 119: for (fwidth = 0; c>='0' && c<='9'; c = *fmt++) ! 120: fwidth = fwidth*10 + c-'0'; ! 121: if (c == '.') { ! 122: c = *fmt++; ! 123: if (c == '*') { ! 124: prec = *iap++; ! 125: c = *fmt++; ! 126: } else ! 127: for (prec=0; c>='0' && c<='9'; c=*fmt++) ! 128: prec = prec*10 + c-'0'; ! 129: } ! 130: if (c == 'l') { ! 131: c = *fmt++; ! 132: if (c=='d' || c=='o' || c=='u' || c=='x') ! 133: c = toupper(c); ! 134: } ! 135: cbp = cbs = cbuf; ! 136: isnumeric = 1; ! 137: switch (c) { ! 138: ! 139: case 'd': ! 140: elem.i = *iap++; ! 141: if (elem.i < 0) { ! 142: elem.i = -elem.i; ! 143: *cbp++ = '-'; ! 144: } ! 145: cbp = printi(cbp, elem.i, 10); ! 146: break; ! 147: ! 148: case 'u': ! 149: cbp = printi(cbp, *iap++, 10); ! 150: break; ! 151: ! 152: case 'o': ! 153: cbp = printi(cbp, *iap++, 8); ! 154: break; ! 155: ! 156: case 'x': ! 157: cbp = printi(cbp, *iap++, 16); ! 158: break; ! 159: ! 160: case 'D': ! 161: elem.l = *(long *)iap; ! 162: bump(iap, long); ! 163: if (elem.l < 0) { ! 164: elem.l = -elem.l; ! 165: *cbp++ = '-'; ! 166: } ! 167: cbp = printl(cbp, elem.l, 10); ! 168: break; ! 169: ! 170: case 'U': ! 171: cbp = printl(cbp, *(long *)iap, 10); ! 172: bump(iap, long); ! 173: break; ! 174: ! 175: case 'O': ! 176: cbp = printl(cbp, *(long *)iap, 8); ! 177: bump(iap, long); ! 178: break; ! 179: ! 180: case 'X': ! 181: cbp = printl(cbp, *(long *)iap, 16); ! 182: bump(iap, long); ! 183: break; ! 184: ! 185: case 'e': ! 186: case 'f': ! 187: case 'g': ! 188: cbp = _dtefg(c, iap, prec, cbp); ! 189: bump(iap, double); ! 190: break; ! 191: ! 192: case 's': ! 193: isnumeric = 0; ! 194: if ((s = *(char **)iap) == NULL) ! 195: s = null; ! 196: bump(iap, char*); ! 197: cbp = cbs = s; ! 198: while (*cbp++ != '\0') ! 199: if (prec>=0 && cbp-s>prec) ! 200: break; ! 201: cbp--; ! 202: break; ! 203: ! 204: case 'c': ! 205: isnumeric = 0; ! 206: *cbp++ = *iap++; ! 207: break; ! 208: ! 209: case 'r': ! 210: xprintf(fp, *(char ***)iap); ! 211: bump(iap, char**); ! 212: break; ! 213: ! 214: default: ! 215: putc(c, fp); ! 216: continue; ! 217: } ! 218: if ((pwidth = fwidth + cbs-cbp) < 0) ! 219: pwidth = 0; ! 220: if (!adj) { ! 221: if (isnumeric && pad == '0' && *cbs == '-') ! 222: putc(*cbs++, fp); ! 223: while (pwidth-- != 0) ! 224: putc(pad, fp); ! 225: } ! 226: while (cbs < cbp) ! 227: putc(*cbs++, fp); ! 228: if (adj) ! 229: while (pwidth-- != 0) ! 230: putc(pad, fp); ! 231: } ! 232: } ! 233: ! 234: static readonly char digits[] = { ! 235: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ! 236: 'A', 'B', 'C', 'D', 'E', 'F' ! 237: }; ! 238: ! 239: /* ! 240: * Print an unsigned integer in base b. ! 241: */ ! 242: static ! 243: char * ! 244: printi(cp, n, b) ! 245: char *cp; ! 246: register unsigned n; ! 247: { ! 248: register a; ! 249: register char *ep; ! 250: char pbuf[10]; ! 251: ! 252: ep = &pbuf[10]; ! 253: *--ep = 0; ! 254: for ( ; a = n/b; n=a) ! 255: *--ep = digits[n%b]; ! 256: *--ep = digits[n]; ! 257: while (*ep) ! 258: *cp++ = *ep++; ! 259: return (cp); ! 260: } ! 261: ! 262: /* ! 263: * Print an unsigned long in base b. ! 264: */ ! 265: static ! 266: char * ! 267: printl(cp, n, b) ! 268: register char *cp; ! 269: unsigned long n; ! 270: register b; ! 271: { ! 272: char pbuf[13]; ! 273: unsigned long a; ! 274: register char *ep; ! 275: ! 276: ep = &pbuf[13]; ! 277: *--ep = '\0'; ! 278: for ( ; (a = n/b) != 0; n = a) ! 279: *--ep = digits[n%b]; ! 280: *--ep = digits[n]; ! 281: while (*ep) ! 282: *cp++ = *ep++; ! 283: return (cp); ! 284: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.