Annotation of 43BSDReno/lib/libc/stdio/doprnt.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.