|
|
1.1 ! root 1: #define FLOAT 0 ! 2: ! 3: /* ! 4: * _doprnt: common code for printf, fprintf, sprintf ! 5: * Floating-point code is included or not, depending ! 6: * on whether the preprocessor variable FLOAT is 1 or 0. ! 7: */ ! 8: ! 9: #include <stdio.h> ! 10: #include <ctype.h> ! 11: #include "param.h" ! 12: ! 13: #define max(a,b) ((a) > (b)? (a): (b)) ! 14: #define min(a,b) ((a) < (b)? (a): (b)) ! 15: ! 16: /* If this symbol is nonzero, allow '0' as a flag */ ! 17: #define FZERO 1 ! 18: ! 19: ! 20: /* ! 21: * System-supplied routines for floating conversion ! 22: */ ! 23: char *fcvt(); ! 24: char *ecvt(); ! 25: ! 26: /* This variable counts output characters. */ ! 27: static int count; ! 28: static FILE *iop; ! 29: ! 30: int _doprnt(format, args, _pfile) ! 31: char *format; ! 32: char *args; ! 33: FILE *_pfile; ! 34: { ! 35: /* Current position in format */ ! 36: char *cp; ! 37: ! 38: /* Starting and ending points for value to be printed */ ! 39: char *bp, *p; ! 40: ! 41: /* Field width and precision */ ! 42: int width, prec; ! 43: ! 44: /* Format code */ ! 45: char fcode; ! 46: ! 47: /* Number of padding zeroes required on the left */ ! 48: int lzero; ! 49: ! 50: /* Flags - nonzero if corresponding character appears in format */ ! 51: bool length; /* l */ ! 52: bool fplus; /* + */ ! 53: bool fminus; /* - */ ! 54: bool fblank; /* blank */ ! 55: bool fsharp; /* # */ ! 56: #if FZERO ! 57: bool fzero; /* 0 */ ! 58: #endif ! 59: ! 60: /* Pointer to sign, "0x", "0X", or empty */ ! 61: char *prefix; ! 62: ! 63: /* Exponent or empty */ ! 64: char *suffix; ! 65: ! 66: /* Buffer to create exponent */ ! 67: char expbuf[MAXESIZ + 1]; ! 68: ! 69: /* Number of padding zeroes required on the right */ ! 70: int rzero; ! 71: ! 72: /* The value being converted, if real */ ! 73: double dval; ! 74: ! 75: /* Output values from fcvt and ecvt */ ! 76: int decpt, sign; ! 77: ! 78: /* Scratch */ ! 79: int k; ! 80: ! 81: /* Values are developed in this buffer */ ! 82: char buf[max (MAXDIGS, max (MAXFCVT + MAXEXP, MAXECVT) + 1)]; ! 83: ! 84: /* The value being converted, if integer */ ! 85: long val; ! 86: ! 87: /* Set to point to a translate table for digits of whatever radix */ ! 88: char *tab; ! 89: ! 90: /* Work variables */ ! 91: int n, hradix, lowbit; ! 92: ! 93: iop = _pfile; ! 94: cp = format; ! 95: count = 0; ! 96: ! 97: /* ! 98: * The main loop -- this loop goes through one iteration ! 99: * for each ordinary character or format specification. ! 100: */ ! 101: while (*cp) ! 102: if (*cp != '%') { ! 103: /* Ordinary (non-%) character */ ! 104: putc (*cp++, _pfile); ! 105: ++count; ! 106: } else { ! 107: /* ! 108: * % has been found. ! 109: * First, parse the format specification. ! 110: */ ! 111: ! 112: /* Scan the <flags> */ ! 113: fplus = fminus = fblank = fsharp = 0; ! 114: #if FZERO ! 115: fzero = 0; ! 116: #endif ! 117: scan: switch (*++cp) { ! 118: case '+': ! 119: fplus = 1; ! 120: goto scan; ! 121: case '-': ! 122: fminus = 1; ! 123: goto scan; ! 124: case ' ': ! 125: fblank = 1; ! 126: goto scan; ! 127: case '#': ! 128: fsharp = 1; ! 129: goto scan; ! 130: #if FZERO ! 131: case '0': ! 132: fzero = 1; ! 133: goto scan; ! 134: #endif ! 135: } ! 136: ! 137: /* Scan the field width */ ! 138: if (*cp == '*') { ! 139: width = *(int *)args; args += sizeof(int); ! 140: if (width < 0) { ! 141: width = -width; ! 142: fminus = 1; ! 143: } ! 144: cp++; ! 145: } else { ! 146: width = 0; ! 147: while (isdigit (*cp)) { ! 148: n = tonumber (*cp++); ! 149: width = width * 10 + n; ! 150: } ! 151: } ! 152: ! 153: /* Scan the precision */ ! 154: if (*cp == '.') { ! 155: ! 156: /* '*' instead of digits? */ ! 157: if (*++cp == '*') { ! 158: prec = *(int *)args; args += sizeof(int); ! 159: cp++; ! 160: } else { ! 161: prec = 0; ! 162: while (isdigit (*cp)) { ! 163: n = tonumber (*cp++); ! 164: prec = prec * 10 + n; ! 165: } ! 166: } ! 167: } else ! 168: prec = -1; ! 169: ! 170: /* Scan the length modifier */ ! 171: length = 0; ! 172: switch (*cp) { ! 173: case 'l': ! 174: length = 1; ! 175: /* No break */ ! 176: case 'h': ! 177: cp++; ! 178: } ! 179: ! 180: /* ! 181: * The character addressed by cp must be the ! 182: * format letter -- there is nothing left for ! 183: * it to be. ! 184: * ! 185: * The status of the +, -, #, blank, and 0 ! 186: * flags are reflected in the variables ! 187: * "fplus", "fminus", "fsharp", "fblank", ! 188: * and "fzero", respectively. ! 189: * "width" and "prec" contain numbers ! 190: * corresponding to the digit strings ! 191: * before and after the decimal point, ! 192: * respectively. If there was no decimal ! 193: * point, "prec" is -1. ! 194: * ! 195: * The following switch sets things up ! 196: * for printing. What ultimately gets ! 197: * printed will be padding blanks, a prefix, ! 198: * left padding zeroes, a value, right padding ! 199: * zeroes, a suffix, and more padding ! 200: * blanks. Padding blanks will not appear ! 201: * simultaneously on both the left and the ! 202: * right. Each case in this switch will ! 203: * compute the value, and leave in several ! 204: * variables the information necessary to ! 205: * construct what is to be printed. ! 206: * ! 207: * The prefix is a sign, a blank, "0x", "0X", ! 208: * or null, and is addressed by "prefix". ! 209: * ! 210: * The suffix is either null or an exponent, ! 211: * and is addressed by "suffix". ! 212: * ! 213: * The value to be printed starts at "bp" ! 214: * and continues up to and not including "p". ! 215: * ! 216: * "lzero" and "rzero" will contain the number ! 217: * of padding zeroes required on the left ! 218: * and right, respectively. If either of ! 219: * these variables is negative, it will be ! 220: * treated as if it were zero. ! 221: * ! 222: * The number of padding blanks, and whether ! 223: * they go on the left or the right, will be ! 224: * computed on exit from the switch. ! 225: */ ! 226: ! 227: lzero = 0; ! 228: prefix = ""; ! 229: rzero = lzero; ! 230: suffix = prefix; ! 231: ! 232: switch (fcode = *cp++) { ! 233: ! 234: /* ! 235: * fixed point representations ! 236: * ! 237: * "hradix" is half the radix for the conversion. ! 238: * Conversion is unsigned unless fcode is 'd'. ! 239: * HIBIT is 1000...000 binary, and is equal to ! 240: * the maximum negative number. ! 241: * We assume a 2's complement machine ! 242: */ ! 243: ! 244: case 'd': ! 245: case 'u': ! 246: hradix = 5; ! 247: goto fixed; ! 248: ! 249: case 'o': ! 250: hradix = 4; ! 251: goto fixed; ! 252: ! 253: case 'X': ! 254: case 'x': ! 255: hradix = 8; ! 256: ! 257: fixed: ! 258: /* Establish default precision */ ! 259: if (prec < 0) ! 260: prec = 1; ! 261: ! 262: /* Fetch the argument to be printed */ ! 263: if (length) ! 264: {val = *(long *)args; args += sizeof(long);} ! 265: else if (fcode == 'd') ! 266: {val = *(int *)args; args += sizeof(int);} ! 267: else ! 268: {val = *(unsigned *)args; args += sizeof(unsigned);} ! 269: ! 270: /* If signed conversion, establish sign */ ! 271: if (fcode == 'd') { ! 272: if (val < 0) { ! 273: prefix = "-"; ! 274: /* ! 275: * Negate, checking in ! 276: * advance for possible ! 277: * overflow. ! 278: */ ! 279: if (val != HIBIT) ! 280: val = -val; ! 281: } else if (fplus) ! 282: prefix = "+"; ! 283: else if (fblank) ! 284: prefix = " "; ! 285: } ! 286: #if FZERO ! 287: if (fzero) { ! 288: int n = width - strlen (prefix); ! 289: if (n > prec) ! 290: prec = n; ! 291: } ! 292: #endif ! 293: /* Set translate table for digits */ ! 294: if (fcode == 'X') ! 295: tab = "0123456789ABCDEF"; ! 296: else ! 297: tab = "0123456789abcdef"; ! 298: ! 299: /* Develop the digits of the value */ ! 300: p = bp = buf + MAXDIGS; ! 301: while (val) { ! 302: lowbit = val & 1; ! 303: val = (val >> 1) & ~HIBIT; ! 304: *--bp = tab[val % hradix * 2 + lowbit]; ! 305: val = val / hradix; ! 306: } ! 307: ! 308: /* Calculate padding zero requirement */ ! 309: lzero = bp - p + prec; ! 310: ! 311: /* Handle the # flag */ ! 312: if (fsharp && bp != p) ! 313: switch (fcode) { ! 314: case 'o': ! 315: if (lzero < 1) ! 316: lzero = 1; ! 317: break; ! 318: case 'x': ! 319: prefix = "0x"; ! 320: break; ! 321: case 'X': ! 322: prefix = "0X"; ! 323: break; ! 324: } ! 325: ! 326: break; ! 327: ! 328: case 'E': ! 329: case 'e': ! 330: /* ! 331: * E-format. The general strategy ! 332: * here is fairly easy: we take ! 333: * what ecvt gives us and re-format it. ! 334: */ ! 335: ! 336: /* Establish default precision */ ! 337: if (prec < 0) ! 338: prec = 6; ! 339: ! 340: /* Fetch the value */ ! 341: dval = *(double *)args; args += sizeof(double); ! 342: ! 343: /* Develop the mantissa */ ! 344: bp = ecvt (dval, ! 345: min (prec + 1, MAXECVT), ! 346: &decpt, ! 347: &sign); ! 348: ! 349: /* Determine the prefix */ ! 350: e_merge: ! 351: if (sign) ! 352: prefix = "-"; ! 353: else if (fplus) ! 354: prefix = "+"; ! 355: else if (fblank) ! 356: prefix = " "; ! 357: ! 358: /* Place the first digit in the buffer */ ! 359: p = &buf[0]; ! 360: *p++ = *bp != '\0'? *bp++: '0'; ! 361: ! 362: /* Put in a decimal point if needed */ ! 363: if (prec != 0 || fsharp) ! 364: *p++ = '.'; ! 365: ! 366: /* Create the rest of the mantissa */ ! 367: rzero = prec; ! 368: while (rzero > 0 && *bp!= '\0') { ! 369: --rzero; ! 370: *p++ = *bp++; ! 371: } ! 372: ! 373: bp = &buf[0]; ! 374: ! 375: /* Create the exponent */ ! 376: suffix = &expbuf[MAXESIZ]; ! 377: *suffix = '\0'; ! 378: if (dval != 0) { ! 379: n = decpt - 1; ! 380: if (n < 0) ! 381: n = -n; ! 382: while (n != 0) { ! 383: *--suffix = todigit (n % 10); ! 384: n /= 10; ! 385: } ! 386: } ! 387: ! 388: /* Prepend leading zeroes to the exponent */ ! 389: while (suffix > &expbuf[MAXESIZ - 2]) ! 390: *--suffix = '0'; ! 391: ! 392: /* Put in the exponent sign */ ! 393: *--suffix = (decpt > 0 || dval == 0)? '+': '-'; ! 394: ! 395: /* Put in the e */ ! 396: *--suffix = isupper(fcode)? 'E' : 'e'; ! 397: ! 398: break; ! 399: ! 400: case 'f': ! 401: /* ! 402: * F-format floating point. This is ! 403: * a good deal less simple than E-format. ! 404: * The overall strategy will be to call ! 405: * fcvt, reformat its result into buf, ! 406: * and calculate how many trailing ! 407: * zeroes will be required. There will ! 408: * never be any leading zeroes needed. ! 409: */ ! 410: ! 411: /* Establish default precision */ ! 412: if (prec < 0) ! 413: prec = 6; ! 414: ! 415: /* Fetch the value */ ! 416: dval = *(double *)args; args += sizeof(double); ! 417: ! 418: /* Do the conversion */ ! 419: bp = fcvt (dval, ! 420: min (prec, MAXFCVT), ! 421: &decpt, ! 422: &sign); ! 423: ! 424: /* Determine the prefix */ ! 425: f_merge: ! 426: if (sign && decpt > -prec && ! 427: *bp != '\0' && *bp != '0') ! 428: prefix = "-"; ! 429: else if (fplus) ! 430: prefix = "+"; ! 431: else if (fblank) ! 432: prefix = " "; ! 433: ! 434: /* Initialize buffer pointer */ ! 435: p = &buf[0]; ! 436: ! 437: /* Emit the digits before the decimal point */ ! 438: n = decpt; ! 439: k = 0; ! 440: if (n <= 0) ! 441: *p++ = '0'; ! 442: else ! 443: do if (*bp == '\0' || k >= MAXFSIG) ! 444: *p++ = '0'; ! 445: else { ! 446: *p++ = *bp++; ! 447: ++k; ! 448: } ! 449: while (--n != 0); ! 450: ! 451: /* Decide whether we need a decimal point */ ! 452: if (fsharp || prec > 0) ! 453: *p++ = '.'; ! 454: ! 455: /* Digits (if any) after the decimal point */ ! 456: n = min (prec, MAXFCVT); ! 457: rzero = prec - n; ! 458: while (--n >= 0) ! 459: if (++decpt <= 0 ! 460: || *bp == '\0' ! 461: || k >= MAXFSIG) ! 462: *p++ = '0'; ! 463: else { ! 464: *p++ = *bp++; ! 465: ++k; ! 466: } ! 467: ! 468: bp = &buf[0]; ! 469: ! 470: break; ! 471: ! 472: case 'G': ! 473: case 'g': ! 474: /* ! 475: * g-format. We play around a bit ! 476: * and then jump into e or f, as needed. ! 477: */ ! 478: ! 479: /* Establish default precision */ ! 480: if (prec < 0) ! 481: prec = 6; ! 482: ! 483: /* Fetch the value */ ! 484: dval = *(double *)args; args += sizeof(double); ! 485: ! 486: /* Do the conversion */ ! 487: bp = ecvt (dval, ! 488: min (prec, MAXECVT), ! 489: &decpt, ! 490: &sign); ! 491: if (dval == 0) ! 492: decpt = 1; ! 493: ! 494: k = prec; ! 495: if (!fsharp) { ! 496: n = strlen (bp); ! 497: if (n < k) ! 498: k = n; ! 499: while (k >= 1 && bp[k-1] == '0') ! 500: --k; ! 501: } ! 502: ! 503: if (decpt < -3 || decpt > prec) { ! 504: prec = k - 1; ! 505: goto e_merge; ! 506: } else { ! 507: prec = k - decpt; ! 508: goto f_merge; ! 509: } ! 510: ! 511: case 'c': ! 512: buf[0] = *(int *)args; args += sizeof(int); ! 513: bp = &buf[0]; ! 514: p = bp + 1; ! 515: break; ! 516: ! 517: case 's': ! 518: bp = *(char **)args; args += sizeof(char **); ! 519: if (prec < 0) ! 520: prec = MAXINT; ! 521: for (n=0; *bp++ != '\0' && n < prec; n++); ! 522: p = --bp; ! 523: bp -= n; ! 524: break; ! 525: ! 526: case '\0': ! 527: cp--; ! 528: break; ! 529: ! 530: /* case '%': */ ! 531: default: ! 532: p = bp = &fcode; ! 533: p++; ! 534: break; ! 535: ! 536: } ! 537: if (fcode != '\0') { ! 538: /* Calculate number of padding blanks */ ! 539: int nblank; ! 540: nblank = width ! 541: - (rzero < 0? 0: rzero) ! 542: - strlen (suffix) ! 543: - (p - bp) ! 544: - (lzero < 0? 0: lzero) ! 545: - strlen (prefix); ! 546: ! 547: /* Blanks on left if required */ ! 548: if (!fminus) ! 549: while (--nblank >= 0) ! 550: emitchar (' '); ! 551: ! 552: /* Prefix, if any */ ! 553: while (*prefix != '\0') ! 554: emitchar (*prefix++); ! 555: ! 556: /* Zeroes on the left */ ! 557: while (--lzero >= 0) ! 558: emitchar ('0'); ! 559: ! 560: /* The value itself */ ! 561: while (bp < p) ! 562: emitchar (*bp++); ! 563: ! 564: /* Zeroes on the right */ ! 565: while (--rzero >= 0) ! 566: emitchar ('0'); ! 567: ! 568: /* The suffix */ ! 569: while (*suffix != '\0') ! 570: emitchar (*suffix++); ! 571: ! 572: /* Blanks on the right if required */ ! 573: if (fminus) ! 574: while (--nblank >= 0) ! 575: emitchar (' '); ! 576: } ! 577: } ! 578: ! 579: return (_pfile != NULL && ferror (_pfile))? EOF: count; ! 580: } ! 581: ! 582: /* Send a character to the output */ ! 583: static ! 584: emitchar (c) ! 585: char c; ! 586: { ! 587: putc (c, iop); ! 588: ++count; ! 589: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.