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

unix.superglobalmegacorp.com

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