|
|
1.1 ! root 1: #include <varargs.h> ! 2: ! 3: #define SIZE 1024 ! 4: #define FUNSIGN 4 ! 5: #define FSHORT 2 ! 6: #define FLONG 1 ! 7: #define PTR sizeof (char *) ! 8: #define SHORT sizeof (int) ! 9: #define INT sizeof (int) ! 10: #define LONG sizeof (long) ! 11: #define FLOAT sizeof (double) ! 12: #define FDIGIT 30 ! 13: #define FDEFLT 8 ! 14: #define IDIGIT 40 ! 15: #define MAXCONV 30 ! 16: ! 17: static char *out, *eout; ! 18: static convcount = { 13 }; ! 19: ! 20: static noconv(); ! 21: static cconv(), dconv(), hconv(), lconv(); ! 22: static oconv(), sconv(), uconv(), xconv(); ! 23: ! 24: static econv(), fconv(), gconv(), percent(); ! 25: int printcol; ! 26: static ! 27: int (*fmtconv[MAXCONV])() = ! 28: { ! 29: noconv, ! 30: cconv, dconv, hconv, lconv, ! 31: oconv, sconv, uconv, xconv, ! 32: econv, fconv, gconv, percent, ! 33: }; ! 34: static ! 35: char fmtindex[128] = ! 36: { ! 37: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 38: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 39: 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 40: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 41: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 42: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 43: 0, 0, 0, 1, 2, 9,10,11, 3, 0, 0, 0, 4, 0, 0, 5, ! 44: 0, 0, 0, 6, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, ! 45: }; ! 46: ! 47: fmtinstall(c, f) ! 48: char c; ! 49: int (*f)(); ! 50: { ! 51: ! 52: c &= 0177; ! 53: if(fmtindex[c] == 0) { ! 54: if(convcount >= MAXCONV) ! 55: return 1; ! 56: fmtindex[c] = convcount++; ! 57: } ! 58: fmtconv[fmtindex[c]] = f; ! 59: return 0; ! 60: } ! 61: ! 62: char* ! 63: donprint(s, es, fmt, argpp) ! 64: char *s, *es; ! 65: register char *fmt; ! 66: va_list *argpp; ! 67: { ! 68: register int f1, f2, f3, sf1, c; ! 69: char *sout, *seout; ! 70: ! 71: sout = out; ! 72: seout = eout; ! 73: out = s; ! 74: eout = es-1; ! 75: loop: ! 76: c = *fmt++; ! 77: if(c != '%') { ! 78: if(c == 0) { ! 79: *out = 0; ! 80: s = out; ! 81: out = sout; ! 82: eout = seout; ! 83: return s; ! 84: } ! 85: if(out < eout) ! 86: *out++ = c; ! 87: printcol++; ! 88: if(c == '\n') ! 89: printcol = 0; else ! 90: if(c == '\t') ! 91: printcol = (printcol+7) & ~7; ! 92: goto loop; ! 93: } ! 94: f1 = 0; ! 95: f2 = -1; ! 96: f3 = 0; ! 97: c = *fmt++; ! 98: sf1 = 0; ! 99: if(c == '-') { ! 100: sf1 = 1; ! 101: c = *fmt++; ! 102: } ! 103: while(c >= '0' && c <= '9') { ! 104: f1 = f1*10 + c-'0'; ! 105: c = *fmt++; ! 106: } ! 107: if(sf1) ! 108: f1 = -f1; ! 109: if(c != '.') ! 110: goto l1; ! 111: c = *fmt++; ! 112: while(c >= '0' && c <= '9') { ! 113: if(f2 < 0) ! 114: f2 = 0; ! 115: f2 = f2*10 + c-'0'; ! 116: c = *fmt++; ! 117: } ! 118: l1: ! 119: if(c == 0) ! 120: fmt--; ! 121: /* NB: first arg is now a (va_list *) */ ! 122: c = (*fmtconv[fmtindex[c&0177]])(argpp, f1, f2, f3); ! 123: if(c < 0) { ! 124: f3 |= -c; ! 125: c = *fmt++; ! 126: goto l1; ! 127: } ! 128: #ifdef notdef ! 129: argp += c; /* increment is now done in called routine by va_arg() */ ! 130: #endif ! 131: goto loop; ! 132: } ! 133: ! 134: numbconv(o, f1, f2, f3, b) ! 135: va_list *o; ! 136: { ! 137: char s[IDIGIT]; ! 138: register long v; ! 139: register int i, f, n, r; ! 140: ! 141: switch(f3 & (FLONG|FSHORT|FUNSIGN)) { ! 142: case FLONG: ! 143: v = va_arg(*o, long); ! 144: r = LONG; ! 145: break; ! 146: ! 147: case FUNSIGN|FLONG: ! 148: v = va_arg(*o, unsigned long); ! 149: r = LONG; ! 150: break; ! 151: ! 152: /* NB: a (unsigned) short argument is promoted to an (unsigned) int arg. */ ! 153: case FSHORT: ! 154: v = (short)va_arg(*o, int); ! 155: r = SHORT; ! 156: break; ! 157: ! 158: case FUNSIGN|FSHORT: ! 159: v = (unsigned short)va_arg(*o, unsigned); ! 160: r = SHORT; ! 161: break; ! 162: ! 163: default: ! 164: v = va_arg(*o, int); ! 165: r = INT; ! 166: break; ! 167: ! 168: case FUNSIGN: ! 169: v = va_arg(*o, unsigned); ! 170: r = INT; ! 171: break; ! 172: } ! 173: f = 0; ! 174: if(!(f3 & FUNSIGN) && v < 0) { ! 175: v = -v; ! 176: f = 1; ! 177: } ! 178: s[IDIGIT-1] = 0; ! 179: for(i = IDIGIT-2; i >= 1; i--) { ! 180: n = (unsigned long)v % b; ! 181: n += '0'; ! 182: if(n > '9') ! 183: n += 'a' - ('9'+1); ! 184: s[i] = n; ! 185: v = (unsigned long)v / b; ! 186: if(f2 >= 0 && i >= IDIGIT-f2) ! 187: continue; ! 188: if(v <= 0) ! 189: break; ! 190: } ! 191: if(f) ! 192: s[--i] = '-'; ! 193: strconv(s+i, f1, -1); ! 194: return r; ! 195: } ! 196: ! 197: char* ! 198: doprint(s, fmt, argp) ! 199: char *s, *fmt; ! 200: va_list *argp; ! 201: { ! 202: ! 203: return donprint(s, s+SIZE, fmt, argp); ! 204: } ! 205: ! 206: /* ! 207: if you change this, change chconv ! 208: */ ! 209: ! 210: strconv(o, f1, f2) ! 211: char *o; ! 212: { ! 213: register int n, c; ! 214: register char *s; ! 215: ! 216: n = 0; ! 217: for(s = o; *s++;) ! 218: n++; ! 219: if(f1 >= 0) ! 220: while(n < f1) { ! 221: if(out < eout) ! 222: *out++ = ' '; ! 223: printcol++; ! 224: n++; ! 225: } ! 226: for(s=o; c = *s++;) ! 227: if(f2 != 0) { ! 228: if(out < eout) ! 229: *out++ = c; ! 230: printcol++; ! 231: if(c == '\n') ! 232: printcol = 0; else ! 233: if(c == '\t') ! 234: printcol = (printcol+7) & ~7; ! 235: f2--; ! 236: } ! 237: if(f1 < 0) { ! 238: f1 = -f1; ! 239: while(n < f1) { ! 240: if(out < eout) ! 241: *out++ = ' '; ! 242: printcol++; ! 243: n++; ! 244: } ! 245: } ! 246: } ! 247: ! 248: chconv(o, f1) ! 249: char o; ! 250: { ! 251: register int n; ! 252: ! 253: n = 1; ! 254: if(f1 >= 0) ! 255: while(n < f1) { ! 256: if(out < eout) ! 257: *out++ = ' '; ! 258: printcol++; ! 259: n++; ! 260: } ! 261: if(out < eout) ! 262: *out++ = o; ! 263: printcol++; ! 264: if(o == '\n') ! 265: printcol = 0; else ! 266: if(o == '\t') ! 267: printcol = (printcol+7) & ~7; ! 268: if(f1 < 0) { ! 269: f1 = -f1; ! 270: while(n < f1) { ! 271: if(out < eout) ! 272: *out++ = ' '; ! 273: printcol++; ! 274: n++; ! 275: } ! 276: } ! 277: } ! 278: ! 279: /* ARGSUSED */ ! 280: static ! 281: noconv(o, f1, f2, f3) ! 282: char *o; ! 283: { ! 284: ! 285: strconv("***", 0, -1); ! 286: return 0; ! 287: } ! 288: ! 289: /* ARGSUSED */ ! 290: static ! 291: cconv(o, f1, f2, f3) ! 292: va_list *o; ! 293: { ! 294: chconv((char)va_arg(*o, int), f1); ! 295: return INT; ! 296: } ! 297: ! 298: static ! 299: dconv(o, f1, f2, f3) ! 300: va_list *o; ! 301: { ! 302: int r; ! 303: ! 304: r = numbconv(o, f1, f2, f3, 10); ! 305: return r; ! 306: } ! 307: ! 308: /* ARGSUSED */ ! 309: static ! 310: hconv(o, f1, f2, f3) ! 311: { ! 312: return -FSHORT; ! 313: } ! 314: ! 315: /* ARGSUSED */ ! 316: static ! 317: lconv(o, f1, f2, f3) ! 318: { ! 319: ! 320: return -FLONG; ! 321: } ! 322: ! 323: static ! 324: oconv(o, f1, f2, f3) ! 325: va_list *o; ! 326: { ! 327: int r; ! 328: ! 329: r = numbconv(o, f1, f2, f3, 8); ! 330: return r; ! 331: } ! 332: ! 333: /* ARGSUSED */ ! 334: static ! 335: sconv(o, f1, f2, f3) ! 336: va_list *o; ! 337: { ! 338: ! 339: strconv(va_arg(*o, char *), f1, f2); ! 340: return PTR; ! 341: } ! 342: ! 343: /* ARGSUSED */ ! 344: static ! 345: uconv(o, f1, f2, f3) ! 346: { ! 347: return -FUNSIGN; ! 348: } ! 349: ! 350: static ! 351: xconv(o, f1, f2, f3) ! 352: va_list *o; ! 353: { ! 354: int r; ! 355: ! 356: r = numbconv(o, f1, f2, f3, 16); ! 357: return r; ! 358: } ! 359: ! 360: double pow10(), frexp(); ! 361: /* ARGSUSED */ ! 362: fltconv(f, f1, f2, f3, c) ! 363: register double f; ! 364: { ! 365: char s1[FDIGIT+10], s2[FDIGIT+10]; ! 366: register double g; ! 367: register int d, i, n, s; ! 368: double h; ! 369: int e; ! 370: int c1, c2, c3; ! 371: ! 372: s = 0; ! 373: if(f < 0) { ! 374: f = -f; ! 375: s++; ! 376: } ! 377: ! 378: loop: ! 379: e = 0; ! 380: g = 0; ! 381: if(f != 0) { ! 382: g = frexp(f, &e); ! 383: e = e * .30103; ! 384: d = e/2; ! 385: h = f * pow10(-d); /* 10**-e in 2 parts */ ! 386: g = h * pow10(d-e); ! 387: while(g < 1) { ! 388: e--; ! 389: g = h * pow10(d-e); ! 390: } ! 391: while(g >= 10) { ! 392: e++; ! 393: g = h * pow10(d-e); ! 394: } ! 395: } ! 396: if(f2 < 0) ! 397: f2 = FDEFLT; ! 398: if(c == 'g' && f2 > 0) ! 399: f2--; ! 400: if(f2 > FDIGIT) ! 401: f2 = FDIGIT; ! 402: /* ! 403: * n is number of digits to convert ! 404: * 1 before, f2 after, 1 extra for rounding ! 405: */ ! 406: n = f2 + 2; ! 407: if(c == 'f') { ! 408: /* ! 409: * e+1 before, f2 after, 1 extra ! 410: */ ! 411: n += e; ! 412: if(n <= 0) { ! 413: n = 1; ! 414: g = 0; ! 415: } ! 416: } ! 417: if(n >= FDIGIT+2) { ! 418: if(c == 'e') ! 419: f2 = -1; ! 420: c = 'e'; ! 421: goto loop; ! 422: } ! 423: /* ! 424: * convert n digits ! 425: */ ! 426: for(i=0; i<n; i++) { ! 427: d = g; ! 428: if(d > g) ! 429: d--; ! 430: g -= d; ! 431: s1[i+1] = d + '0'; ! 432: g *= 10; ! 433: } ! 434: /* ! 435: * round by adding .5 into extra digit ! 436: */ ! 437: d = 5; ! 438: for(i=n-1; i>=0; i--) { ! 439: s1[i+1] += d; ! 440: d = 0; ! 441: if(s1[i+1] > '9') { ! 442: s1[i+1] -= 10; ! 443: d++; ! 444: } ! 445: } ! 446: i = 1; ! 447: if(d) { ! 448: s1[0] = '1'; ! 449: e++; ! 450: i = 0; ! 451: } ! 452: /* ! 453: * copy into final place ! 454: * c1 digits of leading '0' ! 455: * c2 digits from conversion ! 456: * c3 digits after '.' ! 457: */ ! 458: d = 0; ! 459: if(s) ! 460: s2[d++] = '-'; ! 461: c1 = 0; ! 462: c2 = f2 + 1; ! 463: c3 = f2; ! 464: if(c == 'g') ! 465: if(e >= -5 && e <= f2) { ! 466: c1 = -e - 1; ! 467: c3 = c1; ! 468: if(c1 < 0) ! 469: c1 = 0; ! 470: c3 = f2 - e; ! 471: c = 'h'; ! 472: } ! 473: if(c == 'f') { ! 474: c1 = -e; ! 475: if(c1 < 0) ! 476: c1 = 0; ! 477: if(c1 > f2) ! 478: c1 = c2; ! 479: c2 += e; ! 480: if(c2 < 0) ! 481: c2 = 0; ! 482: } ! 483: while(c1 > 0) { ! 484: if(c1+c2 == c3) ! 485: s2[d++] = '.'; ! 486: s2[d++] = '0'; ! 487: c1--; ! 488: } ! 489: while(c2 > 0) { ! 490: if(c1+c2 == c3) ! 491: s2[d++] = '.'; ! 492: s2[d++] = s1[i++]; ! 493: c2--; ! 494: } ! 495: /* ! 496: * strip trailing '0' on g conv ! 497: */ ! 498: if(c == 'g' || c == 'h') { ! 499: for(n=d-1; n>=0; n--) ! 500: if(s2[n] != '0') ! 501: break; ! 502: for(i=n; i>=0; i--) ! 503: if(s2[i] == '.') { ! 504: d = n; ! 505: if(i != n) ! 506: d++; ! 507: break; ! 508: } ! 509: } ! 510: if(c == 'e' || c == 'g') { ! 511: s2[d++] = 'e'; ! 512: s2[d++] = '+'; ! 513: c1 = e; ! 514: if(c1 < 0) { ! 515: s2[d-1] = '-'; ! 516: c1 = -c1; ! 517: } ! 518: if(c1 >= 100) { ! 519: s2[d++] = c1/100 + '0'; ! 520: c1 %= 100; ! 521: } ! 522: s2[d++] = c1/10 + '0'; ! 523: s2[d++] = c1%10 + '0'; ! 524: } ! 525: s2[d] = 0; ! 526: strconv(s2, f1, -1); ! 527: return FLOAT; ! 528: } ! 529: ! 530: static ! 531: econv(o, f1, f2, f3) ! 532: va_list *o; ! 533: { ! 534: ! 535: return fltconv(va_arg(*o, double), f1, f2, f3, 'e'); ! 536: } ! 537: ! 538: static ! 539: fconv(o, f1, f2, f3) ! 540: va_list *o; ! 541: { ! 542: ! 543: return fltconv(va_arg(*o, double), f1, f2, f3, 'f'); ! 544: } ! 545: ! 546: static ! 547: gconv(o, f1, f2, f3) ! 548: va_list *o; ! 549: { ! 550: ! 551: return fltconv(va_arg(*o, double), f1, f2, f3, 'g'); ! 552: } ! 553: ! 554: static ! 555: percent() ! 556: { ! 557: ! 558: if(out < eout) ! 559: *out++ = '%'; ! 560: return 0; ! 561: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.