|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #if defined(LIBC_SCCS) && !defined(lint) ! 21: static char sccsid[] = "@(#)doprnt.c 5.39 (Berkeley) 6/28/90"; ! 22: #endif /* LIBC_SCCS and not lint */ ! 23: ! 24: #include <sys/types.h> ! 25: #include <varargs.h> ! 26: #include <stdio.h> ! 27: #include <ctype.h> ! 28: ! 29: /* 11-bit exponent (VAX G floating point) is 308 decimal digits */ ! 30: #define MAXEXP 308 ! 31: /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ ! 32: #define MAXFRACT 39 ! 33: ! 34: #define DEFPREC 6 ! 35: ! 36: #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ ! 37: ! 38: #define PUTC(ch) (void) putc(ch, fp) ! 39: ! 40: #define ARG(basetype) \ ! 41: _ulong = flags&LONGINT ? va_arg(argp, long basetype) : \ ! 42: flags&SHORTINT ? (short basetype)va_arg(argp, int) : \ ! 43: va_arg(argp, int) ! 44: ! 45: #define todigit(c) ((c) - '0') ! 46: #define tochar(n) ((n) + '0') ! 47: ! 48: /* have to deal with the negative buffer count kludge */ ! 49: #define NEGATIVE_COUNT_KLUDGE ! 50: ! 51: #define LONGINT 0x01 /* long integer */ ! 52: #define LONGDBL 0x02 /* long double; unimplemented */ ! 53: #define SHORTINT 0x04 /* short integer */ ! 54: #define ALT 0x08 /* alternate form */ ! 55: #define LADJUST 0x10 /* left adjustment */ ! 56: #define ZEROPAD 0x20 /* zero (as opposed to blank) pad */ ! 57: #define HEXPREFIX 0x40 /* add 0x or 0X prefix */ ! 58: ! 59: _doprnt(fmt0, argp, fp) ! 60: u_char *fmt0; ! 61: va_list argp; ! 62: register FILE *fp; ! 63: { ! 64: register u_char *fmt; /* format string */ ! 65: register int ch; /* character from fmt */ ! 66: register int cnt; /* return value accumulator */ ! 67: register int n; /* random handy integer */ ! 68: register char *t; /* buffer pointer */ ! 69: double _double; /* double precision arguments %[eEfgG] */ ! 70: u_long _ulong; /* integer arguments %[diouxX] */ ! 71: int base; /* base for [diouxX] conversion */ ! 72: int dprec; /* decimal precision in [diouxX] */ ! 73: int fieldsz; /* field size expanded by sign, etc */ ! 74: int flags; /* flags as above */ ! 75: int fpprec; /* `extra' floating precision in [eEfgG] */ ! 76: int prec; /* precision from format (%.3d), or -1 */ ! 77: int realsz; /* field size expanded by decimal precision */ ! 78: int size; /* size of converted field or string */ ! 79: int width; /* width from format (%8d), or 0 */ ! 80: char sign; /* sign prefix (' ', '+', '-', or \0) */ ! 81: char softsign; /* temporary negative sign for floats */ ! 82: char *digs; /* digits for [diouxX] conversion */ ! 83: char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ ! 84: ! 85: if (fp->_flag & _IORW) { ! 86: fp->_flag |= _IOWRT; ! 87: fp->_flag &= ~(_IOEOF|_IOREAD); ! 88: } ! 89: if ((fp->_flag & _IOWRT) == 0) ! 90: return (EOF); ! 91: ! 92: fmt = fmt0; ! 93: digs = "0123456789abcdef"; ! 94: for (cnt = 0;; ++fmt) { ! 95: n = fp->_cnt; ! 96: for (t = (char *)fp->_ptr; (ch = *fmt) && ch != '%'; ! 97: ++cnt, ++fmt) ! 98: if (--n < 0 ! 99: #ifdef NEGATIVE_COUNT_KLUDGE ! 100: && (!(fp->_flag & _IOLBF) || -n >= fp->_bufsiz) ! 101: #endif ! 102: || ch == '\n' && fp->_flag & _IOLBF) { ! 103: fp->_cnt = n; ! 104: fp->_ptr = t; ! 105: (void) _flsbuf((u_char)ch, fp); ! 106: n = fp->_cnt; ! 107: t = (char *)fp->_ptr; ! 108: } else ! 109: *t++ = ch; ! 110: fp->_cnt = n; ! 111: fp->_ptr = t; ! 112: if (!ch) ! 113: return (cnt); ! 114: ! 115: flags = 0; dprec = 0; fpprec = 0; width = 0; ! 116: prec = -1; ! 117: sign = '\0'; ! 118: ! 119: rflag: switch (*++fmt) { ! 120: case ' ': ! 121: /* ! 122: * ``If the space and + flags both appear, the space ! 123: * flag will be ignored.'' ! 124: * -- ANSI X3J11 ! 125: */ ! 126: if (!sign) ! 127: sign = ' '; ! 128: goto rflag; ! 129: case '#': ! 130: flags |= ALT; ! 131: goto rflag; ! 132: case '*': ! 133: /* ! 134: * ``A negative field width argument is taken as a ! 135: * - flag followed by a positive field width.'' ! 136: * -- ANSI X3J11 ! 137: * They don't exclude field widths read from args. ! 138: */ ! 139: if ((width = va_arg(argp, int)) >= 0) ! 140: goto rflag; ! 141: width = -width; ! 142: /* FALLTHROUGH */ ! 143: case '-': ! 144: flags |= LADJUST; ! 145: goto rflag; ! 146: case '+': ! 147: sign = '+'; ! 148: goto rflag; ! 149: case '.': ! 150: if (*++fmt == '*') ! 151: n = va_arg(argp, int); ! 152: else { ! 153: n = 0; ! 154: while (isascii(*fmt) && isdigit(*fmt)) ! 155: n = 10 * n + todigit(*fmt++); ! 156: --fmt; ! 157: } ! 158: prec = n < 0 ? -1 : n; ! 159: goto rflag; ! 160: case '0': ! 161: /* ! 162: * ``Note that 0 is taken as a flag, not as the ! 163: * beginning of a field width.'' ! 164: * -- ANSI X3J11 ! 165: */ ! 166: flags |= ZEROPAD; ! 167: goto rflag; ! 168: case '1': case '2': case '3': case '4': ! 169: case '5': case '6': case '7': case '8': case '9': ! 170: n = 0; ! 171: do { ! 172: n = 10 * n + todigit(*fmt); ! 173: } while (isascii(*++fmt) && isdigit(*fmt)); ! 174: width = n; ! 175: --fmt; ! 176: goto rflag; ! 177: case 'L': ! 178: flags |= LONGDBL; ! 179: goto rflag; ! 180: case 'h': ! 181: flags |= SHORTINT; ! 182: goto rflag; ! 183: case 'l': ! 184: flags |= LONGINT; ! 185: goto rflag; ! 186: case 'c': ! 187: *(t = buf) = va_arg(argp, int); ! 188: size = 1; ! 189: sign = '\0'; ! 190: goto pforw; ! 191: case 'D': ! 192: flags |= LONGINT; ! 193: /*FALLTHROUGH*/ ! 194: case 'd': ! 195: case 'i': ! 196: ARG(int); ! 197: if ((long)_ulong < 0) { ! 198: _ulong = -_ulong; ! 199: sign = '-'; ! 200: } ! 201: base = 10; ! 202: goto number; ! 203: case 'e': ! 204: case 'E': ! 205: case 'f': ! 206: case 'g': ! 207: case 'G': ! 208: _double = va_arg(argp, double); ! 209: /* ! 210: * don't do unrealistic precision; just pad it with ! 211: * zeroes later, so buffer size stays rational. ! 212: */ ! 213: if (prec > MAXFRACT) { ! 214: if (*fmt != 'g' && *fmt != 'G' || (flags&ALT)) ! 215: fpprec = prec - MAXFRACT; ! 216: prec = MAXFRACT; ! 217: } ! 218: else if (prec == -1) ! 219: prec = DEFPREC; ! 220: /* ! 221: * softsign avoids negative 0 if _double is < 0 and ! 222: * no significant digits will be shown ! 223: */ ! 224: if (_double < 0) { ! 225: softsign = '-'; ! 226: _double = -_double; ! 227: } ! 228: else ! 229: softsign = 0; ! 230: /* ! 231: * cvt may have to round up past the "start" of the ! 232: * buffer, i.e. ``intf("%.2f", (double)9.999);''; ! 233: * if the first char isn't NULL, it did. ! 234: */ ! 235: *buf = NULL; ! 236: size = cvt(_double, prec, flags, &softsign, *fmt, buf, ! 237: buf + sizeof(buf)); ! 238: if (softsign) ! 239: sign = '-'; ! 240: t = *buf ? buf : buf + 1; ! 241: goto pforw; ! 242: case 'n': ! 243: if (flags & LONGINT) ! 244: *va_arg(argp, long *) = cnt; ! 245: else if (flags & SHORTINT) ! 246: *va_arg(argp, short *) = cnt; ! 247: else ! 248: *va_arg(argp, int *) = cnt; ! 249: break; ! 250: case 'O': ! 251: flags |= LONGINT; ! 252: /*FALLTHROUGH*/ ! 253: case 'o': ! 254: ARG(unsigned); ! 255: base = 8; ! 256: goto nosign; ! 257: case 'p': ! 258: /* ! 259: * ``The argument shall be a pointer to void. The ! 260: * value of the pointer is converted to a sequence ! 261: * of printable characters, in an implementation- ! 262: * defined manner.'' ! 263: * -- ANSI X3J11 ! 264: */ ! 265: /* NOSTRICT */ ! 266: _ulong = (u_long)va_arg(argp, void *); ! 267: base = 16; ! 268: goto nosign; ! 269: case 's': ! 270: if (!(t = va_arg(argp, char *))) ! 271: t = "(null)"; ! 272: if (prec >= 0) { ! 273: /* ! 274: * can't use strlen; can only look for the ! 275: * NUL in the first `prec' characters, and ! 276: * strlen() will go further. ! 277: */ ! 278: char *p, *memchr(); ! 279: ! 280: if (p = memchr(t, 0, prec)) { ! 281: size = p - t; ! 282: if (size > prec) ! 283: size = prec; ! 284: } else ! 285: size = prec; ! 286: } else ! 287: size = strlen(t); ! 288: sign = '\0'; ! 289: goto pforw; ! 290: case 'U': ! 291: flags |= LONGINT; ! 292: /*FALLTHROUGH*/ ! 293: case 'u': ! 294: ARG(unsigned); ! 295: base = 10; ! 296: goto nosign; ! 297: case 'X': ! 298: digs = "0123456789ABCDEF"; ! 299: /* FALLTHROUGH */ ! 300: case 'x': ! 301: ARG(unsigned); ! 302: base = 16; ! 303: /* leading 0x/X only if non-zero */ ! 304: if (flags & ALT && _ulong != 0) ! 305: flags |= HEXPREFIX; ! 306: ! 307: /* unsigned conversions */ ! 308: nosign: sign = '\0'; ! 309: /* ! 310: * ``... diouXx conversions ... if a precision is ! 311: * specified, the 0 flag will be ignored.'' ! 312: * -- ANSI X3J11 ! 313: */ ! 314: number: if ((dprec = prec) >= 0) ! 315: flags &= ~ZEROPAD; ! 316: ! 317: /* ! 318: * ``The result of converting a zero value with an ! 319: * explicit precision of zero is no characters.'' ! 320: * -- ANSI X3J11 ! 321: */ ! 322: t = buf + BUF; ! 323: if (_ulong != 0 || prec != 0) { ! 324: do { ! 325: *--t = digs[_ulong % base]; ! 326: _ulong /= base; ! 327: } while (_ulong); ! 328: digs = "0123456789abcdef"; ! 329: if (flags & ALT && base == 8 && *t != '0') ! 330: *--t = '0'; /* octal leading 0 */ ! 331: } ! 332: size = buf + BUF - t; ! 333: ! 334: pforw: ! 335: /* ! 336: * All reasonable formats wind up here. At this point, ! 337: * `t' points to a string which (if not flags&LADJUST) ! 338: * should be padded out to `width' places. If ! 339: * flags&ZEROPAD, it should first be prefixed by any ! 340: * sign or other prefix; otherwise, it should be blank ! 341: * padded before the prefix is emitted. After any ! 342: * left-hand padding and prefixing, emit zeroes ! 343: * required by a decimal [diouxX] precision, then print ! 344: * the string proper, then emit zeroes required by any ! 345: * leftover floating precision; finally, if LADJUST, ! 346: * pad with blanks. ! 347: */ ! 348: ! 349: /* ! 350: * compute actual size, so we know how much to pad ! 351: * fieldsz excludes decimal prec; realsz includes it ! 352: */ ! 353: fieldsz = size + fpprec; ! 354: if (sign) ! 355: fieldsz++; ! 356: if (flags & HEXPREFIX) ! 357: fieldsz += 2; ! 358: realsz = dprec > fieldsz ? dprec : fieldsz; ! 359: ! 360: /* right-adjusting blank padding */ ! 361: if ((flags & (LADJUST|ZEROPAD)) == 0 && width) ! 362: for (n = realsz; n < width; n++) ! 363: PUTC(' '); ! 364: /* prefix */ ! 365: if (sign) ! 366: PUTC(sign); ! 367: if (flags & HEXPREFIX) { ! 368: PUTC('0'); ! 369: PUTC((char)*fmt); ! 370: } ! 371: /* right-adjusting zero padding */ ! 372: if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) ! 373: for (n = realsz; n < width; n++) ! 374: PUTC('0'); ! 375: /* leading zeroes from decimal precision */ ! 376: for (n = fieldsz; n < dprec; n++) ! 377: PUTC('0'); ! 378: ! 379: /* the string or number proper */ ! 380: n = size; ! 381: if (fp->_cnt - n >= 0 && (fp->_flag & _IOLBF) == 0) { ! 382: fp->_cnt -= n; ! 383: bcopy(t, (char *)fp->_ptr, n); ! 384: fp->_ptr += n; ! 385: } else ! 386: while (--n >= 0) ! 387: PUTC(*t++); ! 388: /* trailing f.p. zeroes */ ! 389: while (--fpprec >= 0) ! 390: PUTC('0'); ! 391: /* left-adjusting padding (always blank) */ ! 392: if (flags & LADJUST) ! 393: for (n = realsz; n < width; n++) ! 394: PUTC(' '); ! 395: /* finally, adjust cnt */ ! 396: cnt += width > realsz ? width : realsz; ! 397: break; ! 398: case '\0': /* "%?" prints ?, unless ? is NULL */ ! 399: return (cnt); ! 400: default: ! 401: PUTC((char)*fmt); ! 402: cnt++; ! 403: } ! 404: } ! 405: /* NOTREACHED */ ! 406: } ! 407: ! 408: static ! 409: cvt(number, prec, flags, signp, fmtch, startp, endp) ! 410: double number; ! 411: register int prec; ! 412: int flags; ! 413: u_char fmtch; ! 414: char *signp, *startp, *endp; ! 415: { ! 416: register char *p, *t; ! 417: register double fract; ! 418: int dotrim, expcnt, gformat; ! 419: double integer, tmp, modf(); ! 420: char *exponent(), *round(); ! 421: ! 422: #ifdef hp300 ! 423: if (expcnt = isspecial(number, startp, signp)) ! 424: return(expcnt); ! 425: #endif ! 426: ! 427: dotrim = expcnt = gformat = 0; ! 428: fract = modf(number, &integer); ! 429: ! 430: /* get an extra slot for rounding. */ ! 431: t = ++startp; ! 432: ! 433: /* ! 434: * get integer portion of number; put into the end of the buffer; the ! 435: * .01 is added for modf(356.0 / 10, &integer) returning .59999999... ! 436: */ ! 437: for (p = endp - 1; integer; ++expcnt) { ! 438: tmp = modf(integer / 10, &integer); ! 439: *p-- = tochar((int)((tmp + .01) * 10)); ! 440: } ! 441: switch(fmtch) { ! 442: case 'f': ! 443: /* reverse integer into beginning of buffer */ ! 444: if (expcnt) ! 445: for (; ++p < endp; *t++ = *p); ! 446: else ! 447: *t++ = '0'; ! 448: /* ! 449: * if precision required or alternate flag set, add in a ! 450: * decimal point. ! 451: */ ! 452: if (prec || flags&ALT) ! 453: *t++ = '.'; ! 454: /* if requires more precision and some fraction left */ ! 455: if (fract) { ! 456: if (prec) ! 457: do { ! 458: fract = modf(fract * 10, &tmp); ! 459: *t++ = tochar((int)tmp); ! 460: } while (--prec && fract); ! 461: if (fract) ! 462: startp = round(fract, (int *)NULL, startp, ! 463: t - 1, (char)0, signp); ! 464: } ! 465: for (; prec--; *t++ = '0'); ! 466: break; ! 467: case 'e': ! 468: case 'E': ! 469: eformat: if (expcnt) { ! 470: *t++ = *++p; ! 471: if (prec || flags&ALT) ! 472: *t++ = '.'; ! 473: /* if requires more precision and some integer left */ ! 474: for (; prec && ++p < endp; --prec) ! 475: *t++ = *p; ! 476: /* ! 477: * if done precision and more of the integer component, ! 478: * round using it; adjust fract so we don't re-round ! 479: * later. ! 480: */ ! 481: if (!prec && ++p < endp) { ! 482: fract = 0; ! 483: startp = round((double)0, &expcnt, startp, ! 484: t - 1, *p, signp); ! 485: } ! 486: /* adjust expcnt for digit in front of decimal */ ! 487: --expcnt; ! 488: } ! 489: /* until first fractional digit, decrement exponent */ ! 490: else if (fract) { ! 491: /* adjust expcnt for digit in front of decimal */ ! 492: for (expcnt = -1;; --expcnt) { ! 493: fract = modf(fract * 10, &tmp); ! 494: if (tmp) ! 495: break; ! 496: } ! 497: *t++ = tochar((int)tmp); ! 498: if (prec || flags&ALT) ! 499: *t++ = '.'; ! 500: } ! 501: else { ! 502: *t++ = '0'; ! 503: if (prec || flags&ALT) ! 504: *t++ = '.'; ! 505: } ! 506: /* if requires more precision and some fraction left */ ! 507: if (fract) { ! 508: if (prec) ! 509: do { ! 510: fract = modf(fract * 10, &tmp); ! 511: *t++ = tochar((int)tmp); ! 512: } while (--prec && fract); ! 513: if (fract) ! 514: startp = round(fract, &expcnt, startp, ! 515: t - 1, (char)0, signp); ! 516: } ! 517: /* if requires more precision */ ! 518: for (; prec--; *t++ = '0'); ! 519: ! 520: /* unless alternate flag, trim any g/G format trailing 0's */ ! 521: if (gformat && !(flags&ALT)) { ! 522: while (t > startp && *--t == '0'); ! 523: if (*t == '.') ! 524: --t; ! 525: ++t; ! 526: } ! 527: t = exponent(t, expcnt, fmtch); ! 528: break; ! 529: case 'g': ! 530: case 'G': ! 531: /* a precision of 0 is treated as a precision of 1. */ ! 532: if (!prec) ! 533: ++prec; ! 534: /* ! 535: * ``The style used depends on the value converted; style e ! 536: * will be used only if the exponent resulting from the ! 537: * conversion is less than -4 or greater than the precision.'' ! 538: * -- ANSI X3J11 ! 539: */ ! 540: if (expcnt > prec || !expcnt && fract && fract < .0001) { ! 541: /* ! 542: * g/G format counts "significant digits, not digits of ! 543: * precision; for the e/E format, this just causes an ! 544: * off-by-one problem, i.e. g/G considers the digit ! 545: * before the decimal point significant and e/E doesn't ! 546: * count it as precision. ! 547: */ ! 548: --prec; ! 549: fmtch -= 2; /* G->E, g->e */ ! 550: gformat = 1; ! 551: goto eformat; ! 552: } ! 553: /* ! 554: * reverse integer into beginning of buffer, ! 555: * note, decrement precision ! 556: */ ! 557: if (expcnt) ! 558: for (; ++p < endp; *t++ = *p, --prec); ! 559: else ! 560: *t++ = '0'; ! 561: /* ! 562: * if precision required or alternate flag set, add in a ! 563: * decimal point. If no digits yet, add in leading 0. ! 564: */ ! 565: if (prec || flags&ALT) { ! 566: dotrim = 1; ! 567: *t++ = '.'; ! 568: } ! 569: else ! 570: dotrim = 0; ! 571: /* if requires more precision and some fraction left */ ! 572: if (fract) { ! 573: if (prec) { ! 574: do { ! 575: fract = modf(fract * 10, &tmp); ! 576: *t++ = tochar((int)tmp); ! 577: } while(!tmp); ! 578: while (--prec && fract) { ! 579: fract = modf(fract * 10, &tmp); ! 580: *t++ = tochar((int)tmp); ! 581: } ! 582: } ! 583: if (fract) ! 584: startp = round(fract, (int *)NULL, startp, ! 585: t - 1, (char)0, signp); ! 586: } ! 587: /* alternate format, adds 0's for precision, else trim 0's */ ! 588: if (flags&ALT) ! 589: for (; prec--; *t++ = '0'); ! 590: else if (dotrim) { ! 591: while (t > startp && *--t == '0'); ! 592: if (*t != '.') ! 593: ++t; ! 594: } ! 595: } ! 596: return(t - startp); ! 597: } ! 598: ! 599: static char * ! 600: round(fract, exp, start, end, ch, signp) ! 601: double fract; ! 602: int *exp; ! 603: register char *start, *end; ! 604: char ch, *signp; ! 605: { ! 606: double tmp; ! 607: ! 608: if (fract) ! 609: (void)modf(fract * 10, &tmp); ! 610: else ! 611: tmp = todigit(ch); ! 612: if (tmp > 4) ! 613: for (;; --end) { ! 614: if (*end == '.') ! 615: --end; ! 616: if (++*end <= '9') ! 617: break; ! 618: *end = '0'; ! 619: if (end == start) { ! 620: if (exp) { /* e/E; increment exponent */ ! 621: *end = '1'; ! 622: ++*exp; ! 623: } ! 624: else { /* f; add extra digit */ ! 625: *--end = '1'; ! 626: --start; ! 627: } ! 628: break; ! 629: } ! 630: } ! 631: /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ ! 632: else if (*signp == '-') ! 633: for (;; --end) { ! 634: if (*end == '.') ! 635: --end; ! 636: if (*end != '0') ! 637: break; ! 638: if (end == start) ! 639: *signp = 0; ! 640: } ! 641: return(start); ! 642: } ! 643: ! 644: static char * ! 645: exponent(p, exp, fmtch) ! 646: register char *p; ! 647: register int exp; ! 648: u_char fmtch; ! 649: { ! 650: register char *t; ! 651: char expbuf[MAXEXP]; ! 652: ! 653: *p++ = fmtch; ! 654: if (exp < 0) { ! 655: exp = -exp; ! 656: *p++ = '-'; ! 657: } ! 658: else ! 659: *p++ = '+'; ! 660: t = expbuf + MAXEXP; ! 661: if (exp > 9) { ! 662: do { ! 663: *--t = tochar(exp % 10); ! 664: } while ((exp /= 10) > 9); ! 665: *--t = tochar(exp); ! 666: for (; t < expbuf + MAXEXP; *p++ = *t++); ! 667: } ! 668: else { ! 669: *p++ = '0'; ! 670: *p++ = tochar(exp); ! 671: } ! 672: return(p); ! 673: } ! 674: ! 675: #ifdef hp300 ! 676: isspecial(d, bufp, signp) ! 677: double d; ! 678: char *bufp, *signp; ! 679: { ! 680: register struct IEEEdp { ! 681: unsigned sign:1; ! 682: unsigned exp:11; ! 683: unsigned manh:20; ! 684: unsigned manl:32; ! 685: } *ip = (struct IEEEdp *)&d; ! 686: ! 687: if (ip->exp != 0x7ff) ! 688: return(0); ! 689: if (ip->manh || ip->manl) ! 690: (void)strcpy(bufp, "NaN"); ! 691: else ! 692: (void)strcpy(bufp, "Inf"); ! 693: return(3); ! 694: } ! 695: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.