Annotation of cci/usr/src/lib/libc/tahoe/stdio/doprnt.c, revision 1.1.1.2

1.1.1.2 ! root        1: /* doprnt.c    Tahoe version 8/22/85
        !             2:  *
        !             3:  *     _doprnt: common code for printf, fprintf, sprintf
        !             4:  */
        !             5: 
1.1       root        6: #include <stdio.h>
1.1.1.2 ! root        7: #include <ctype.h>
        !             8: #include <varargs.h>
        !             9: 
        !            10: /* Maximum negative number */
        !            11: #define        HIBITL  (1 << sizeof(long)*8 - 1)
        !            12: 
        !            13: /* Maximum number of digits in any integer representation */
        !            14: #define MAXDIGS 11
        !            15: 
        !            16: /* Maximum total number of digits in E format */
        !            17: #define MAXECVT 17
        !            18: 
        !            19: /* Maximum number of digits after decimal point in F format */
        !            20: #define MAXFCVT MAXECVT
        !            21: 
        !            22: /* Maximum significant figures in a floating-point number */
        !            23: #define MAXFSIG MAXECVT
        !            24: 
        !            25: /* Maximum number of characters in an exponent */
        !            26: #define MAXESIZ 4
        !            27: 
        !            28: /* Maximum (positive) exponent */
        !            29: #define MAXEXP 40
        !            30: 
        !            31: /* Data type for flags */
        !            32: typedef char bool;
        !            33: 
        !            34: /* Convert a digit character to the corresponding number */
        !            35: #define tonumber(x) ((x)-'0')
        !            36: 
        !            37: /* Convert a number between 0 and 9 to the corresponding digit */
        !            38: #define todigit(x) ((x)+'0')
        !            39: 
        !            40: /* Max and Min macros */
        !            41: #define max(a,b) ((a) > (b)? (a): (b))
        !            42: #define min(a,b) ((a) < (b)? (a): (b))
        !            43: 
        !            44: /*
        !            45:  * 'csh' contains its own printf, which calls _doprnt directly,
        !            46:  *     and its own _strout/putchar, which uses non-standard
        !            47:  *     files for stdin, stdout, stderr.
        !            48:  * the 'csh' call to _doprnt passes iop == 0, and in that case,
        !            49:  *     all output calls from _doprnt must be to _strout.
        !            50:  */
        !            51: #define PUT(p, n)     { if ((long)iop) \
        !            52:                                _dowrite(p, n, iop); \
        !            53:                        else \
        !            54:                                _strout(n, p, 0, 0, 0); \
        !            55:                      }
        !            56: 
        !            57: #define PAD(s, n)     { register int nn; \
        !            58:                        for (nn = n; nn > 20; nn -= 20) \
        !            59:                                PUT(s, 20); \
        !            60:                        PUT(s, nn); \
        !            61:                      }
        !            62: 
        !            63: /* bit positions for flags used in doprnt */
        !            64: #define LENGTH 1       /* l */
        !            65: #define FPLUS  2       /* + */
        !            66: #define FMINUS 4       /* - */
        !            67: #define FBLANK 8       /* blank */
        !            68: #define FSHARP 16      /* # */
        !            69: #define PADZERO 32     /* padding zeroes requested via '0' */
        !            70: #define DOTSEEN 64     /* dot appeared in format specification */
        !            71: #define SUFFIX 128     /* a suffix is to appear in the output */
        !            72: #define RZERO  256     /* there will be trailing zeros in output */
        !            73: #define LZERO  512     /* there will be leading zeroes in output */
        !            74: 
        !            75: /*
        !            76:  *     C-Library routines for floating conversion
        !            77:  */
        !            78: 
        !            79: extern char *fcvt(), *ecvt();
        !            80: 
        !            81: static int
        !            82: _lowdigit(valptr)
        !            83: long *valptr;
        !            84: {      /* This function computes the decimal low-order digit of the number */
        !            85:        /* pointed to by valptr, and returns this digit after dividing   */
        !            86:        /* *valptr by ten.  This function is called ONLY to compute the */
        !            87:        /* low-order digit of a long whose high-order bit is set. */
1.1       root       88: 
1.1.1.2 ! root       89:        int lowbit = *valptr & 1;
        !            90:        long value = (*valptr >> 1) & ~HIBITL;
1.1       root       91: 
1.1.1.2 ! root       92:        *valptr = value / 5;
        !            93:        return(value % 5 * 2 + lowbit + '0');
        !            94: }
        !            95: 
        !            96: static
        !            97: _dowrite(p, n, iop)
        !            98: register char *p;
        !            99: register int   n;
        !           100: register FILE  *iop;
1.1       root      101: {
1.1.1.2 ! root      102:        register int i;
1.1       root      103: 
1.1.1.2 ! root      104:        for (i = 0; i < n; i++)
        !           105:                putc(*p++, iop);
        !           106: }
1.1       root      107: 
1.1.1.2 ! root      108: int
        !           109: _doprnt(format, args, iop)
        !           110: register char  *format;
        !           111: va_list        args;
        !           112: register FILE  *iop;
        !           113: {
        !           114:        static char _blanks[] = "                    ";
        !           115:        static char _zeroes[] = "00000000000000000000";
        !           116: 
        !           117:        /* This variable counts output characters. */
        !           118:        int     count = 0;
        !           119: 
        !           120:        /* Starting and ending points for value to be printed */
        !           121:        register char   *bp;
        !           122:        char *p;
        !           123: 
        !           124:        /* Field width and precision */
        !           125:        int     width, prec;
        !           126: 
        !           127:        /* Format code */
        !           128:        register int    fcode;
        !           129: 
        !           130:        /* Number of padding zeroes required on the left and right */
        !           131:        int     lzero, rzero;
        !           132: 
        !           133:        /* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */
        !           134:        /* and FSHARP are set if corresponding character is in format */
        !           135:        /* Bit position defined by PADZERO means extra space in the field */
        !           136:        /* should be padded with leading zeroes rather than with blanks */
        !           137:        register int    flagword;
        !           138: 
        !           139:        /* Values are developed in this buffer */
        !           140:        char    buf[max(MAXDIGS, 1+max(MAXFCVT+MAXEXP, MAXECVT))];
        !           141: 
        !           142:        /* Pointer to sign, "0x", "0X", or empty */
        !           143:        char    *prefix;
        !           144: 
        !           145:        /* Exponent or empty */
        !           146:        char    *suffix;
        !           147: 
        !           148:        /* Buffer to create exponent */
        !           149:        char    expbuf[MAXESIZ + 1];
        !           150: 
        !           151:        /* Length of prefix and of suffix */
        !           152:        int     prefixlength, suffixlength;
        !           153: 
        !           154:        /* combined length of leading zeroes, trailing zeroes, and suffix */
        !           155:        int     otherlength;
        !           156: 
        !           157:        /* The value being converted, if integer */
        !           158:        long    val;
        !           159: 
        !           160:        /* The value being converted, if real */
        !           161:        double  dval;
        !           162: 
        !           163:        /* Output values from fcvt and ecvt */
        !           164:        int     decpt, sign;
        !           165: 
        !           166:        /* Pointer to translate table for digits of whatever radix */
        !           167:        char    *tab;
        !           168: 
        !           169:        /* Work variables */
        !           170:        int     k, lradix, mradix;
        !           171: 
        !           172:        /*
        !           173:         *      The main loop -- this loop goes through one iteration
        !           174:         *      for each string of ordinary characters or format specification.
        !           175:         */
        !           176:        for ( ; ; ) {
        !           177:                register int n;
        !           178: 
        !           179:                bp = format;
        !           180:                while((fcode = *format++) && fcode != '%')
        !           181:                                ;
        !           182:                if ((count = format - bp - 1))
        !           183:                        PUT(bp, count);
        !           184:                if (fcode == '\0')
        !           185:                        return;
        !           186: 
        !           187:                /*
        !           188:                 *      % has been found.
        !           189:                 *      The following switch is used to parse the format
        !           190:                 *      specification and to perform the operation specified
        !           191:                 *      by the format letter.  The program repeatedly goes
        !           192:                 *      back to this switch until the format letter is
        !           193:                 *      encountered.
        !           194:                 */
        !           195:                width = prefixlength = otherlength = flagword = 0;
        !           196: 
        !           197:        charswitch:
        !           198: 
        !           199:                switch (fcode = *format++) {
        !           200: 
        !           201:                case '+':
        !           202:                        flagword |= FPLUS;
        !           203:                        goto charswitch;
        !           204:                case '-':
        !           205:                        flagword |= FMINUS;
        !           206:                        goto charswitch;
        !           207:                case ' ':
        !           208:                        flagword |= FBLANK;
        !           209:                        goto charswitch;
        !           210:                case '#':
        !           211:                        flagword |= FSHARP;
        !           212:                        goto charswitch;
        !           213: 
        !           214:                /* Scan the field width and precision */
        !           215:                case '.':
        !           216:                        flagword |= DOTSEEN;
        !           217:                        prec = 0;
        !           218:                        goto charswitch;
        !           219: 
        !           220:                case '*':
        !           221:                        if (!(flagword & DOTSEEN)) {
        !           222:                                width = va_arg(args, int);
        !           223:                                if (width < 0) {
        !           224:                                        width = -width;
        !           225:                                        flagword ^= FMINUS;
        !           226:                                }
        !           227:                        } else {
        !           228:                                prec = va_arg(args, int);
        !           229:                                if (prec < 0)
        !           230:                                        prec = 0;
        !           231:                        }
        !           232:                        goto charswitch;
        !           233: 
        !           234:                case '0':       /* obsolescent spec:  leading zero in width */
        !           235:                                /* means pad with leading zeros */
        !           236:                        if (!(flagword & (DOTSEEN | FMINUS)))
        !           237:                                flagword |= PADZERO;
        !           238:                case '1':
        !           239:                case '2':
        !           240:                case '3':
        !           241:                case '4':
        !           242:                case '5':
        !           243:                case '6':
        !           244:                case '7':
        !           245:                case '8':
        !           246:                case '9':
        !           247:                      { register num = fcode - '0';
        !           248:                        while (isdigit(fcode = *format)) {
        !           249:                                num = num * 10 + fcode - '0';
        !           250:                                format++;
        !           251:                        }
        !           252:                        if (flagword & DOTSEEN)
        !           253:                                prec = num;
        !           254:                        else
        !           255:                                width = num;
        !           256:                        goto charswitch;
        !           257:                      }
        !           258: 
        !           259:                /* Scan the length modifier */
        !           260:                case 'l':
        !           261:                case 'L':
        !           262:                        flagword |= LENGTH;
        !           263:                        /* No break */
        !           264:                case 'h':
        !           265:                        goto charswitch;
        !           266: 
        !           267:                /*
        !           268:                 *      The character addressed by format must be
        !           269:                 *      the format letter -- there is nothing
        !           270:                 *      left for it to be.
        !           271:                 *
        !           272:                 *      The status of the +, -, #, and blank
        !           273:                 *      flags are reflected in the variable
        !           274:                 *      "flagword".  "width" and "prec" contain
        !           275:                 *      numbers corresponding to the digit
        !           276:                 *      strings before and after the decimal
        !           277:                 *      point, respectively. If there was no
        !           278:                 *      decimal point, then flagword & DOTSEEN
        !           279:                 *      is false and the value of prec is meaningless.
        !           280:                 *
        !           281:                 *      The following switch cases set things up
        !           282:                 *      for printing.  What ultimately gets
        !           283:                 *      printed will be padding blanks, a
        !           284:                 *      prefix, left padding zeroes, a value,
        !           285:                 *      right padding zeroes, a suffix, and
        !           286:                 *      more padding blanks.  Padding blanks
        !           287:                 *      will not appear simultaneously on both
        !           288:                 *      the left and the right.  Each case in
        !           289:                 *      this switch will compute the value, and
        !           290:                 *      leave in several variables the informa-
        !           291:                 *      tion necessary to construct what is to
        !           292:                 *      be printed.  
        !           293:                 *
        !           294:                 *      The prefix is a sign, a blank, "0x",
        !           295:                 *      "0X", or null, and is addressed by
        !           296:                 *      "prefix".
        !           297:                 *
        !           298:                 *      The suffix is either null or an
        !           299:                 *      exponent, and is addressed by "suffix".
        !           300:                 *      If there is a suffix, the flagword bit
        !           301:                 *      SUFFIX will be set.
        !           302:                 *
        !           303:                 *      The value to be printed starts at "bp"
        !           304:                 *      and continues up to and not including
        !           305:                 *      "p".
        !           306:                 *
        !           307:                 *      "lzero" and "rzero" will contain the
        !           308:                 *      number of padding zeroes required on
        !           309:                 *      the left and right, respectively.
        !           310:                 *      The flagword bits LZERO and RZERO tell
        !           311:                 *      whether padding zeros are required.
        !           312:                 *
        !           313:                 *      The number of padding blanks, and
        !           314:                 *      whether they go on the left or the
        !           315:                 *      right, will be computed on exit from
        !           316:                 *      the switch.
        !           317:                 */
        !           318: 
        !           319: 
        !           320: 
        !           321:                
        !           322:                /*
        !           323:                 *      decimal fixed point representations
        !           324:                 *
        !           325:                 *      HIBITL is 100...000
        !           326:                 *      binary, and is equal to the maximum
        !           327:                 *      negative number.
        !           328:                 *      We assume a 2's complement machine
        !           329:                 */
        !           330: 
        !           331:                case 'D':
        !           332:                        flagword |= LENGTH;
        !           333:                        /* No break */
1.1       root      334:                case 'd':
1.1.1.2 ! root      335:                        /* Fetch the argument to be printed */
        !           336:                        if (flagword & LENGTH)
        !           337:                                val = va_arg(args, long);
        !           338:                        else
        !           339:                                val = va_arg(args, int);
        !           340: 
        !           341:                        /* Set buffer pointer to last digit */
        !           342:                        p = bp = buf + MAXDIGS;
        !           343: 
        !           344:                        /* If signed conversion, make sign */
        !           345:                        if (val < 0) {
        !           346:                                prefix = "-";
        !           347:                                prefixlength = 1;
        !           348:                                /*
        !           349:                                 * Negate, checking in
        !           350:                                 * advance for possible
        !           351:                                 * overflow.
        !           352:                                 */
        !           353:                                if (val != HIBITL)
        !           354:                                        val = -val;
        !           355:                                else    /* number is -HIBITL; convert last */
        !           356:                                        /* digit now and get positive number */
        !           357:                                        *--bp = _lowdigit(&val);
        !           358:                        } else if (flagword & FPLUS) {
        !           359:                                prefix = "+";
        !           360:                                prefixlength = 1;
        !           361:                        } else if (flagword & FBLANK) {
        !           362:                                prefix = " ";
        !           363:                                prefixlength = 1;
        !           364:                        }
        !           365: 
        !           366:                decimal:
        !           367:                        { register long qval = val;
        !           368:                                if (qval <= 9) {
        !           369:                                        if (qval != 0 || !(flagword & DOTSEEN))
        !           370:                                                *--bp = qval + '0';
        !           371:                                } else {
        !           372:                                        do {
        !           373:                                                n = qval;
        !           374:                                                qval /= 10;
        !           375:                                                *--bp = n - qval * 10 + '0';
        !           376:                                        } while (qval > 9);
        !           377:                                        *--bp = qval + '0';
        !           378:                                }
        !           379:                        }
        !           380: 
        !           381:                        /* Calculate minimum padding zero requirement */
        !           382:                        if (flagword & DOTSEEN) {
        !           383:                                register leadzeroes = prec - (p - bp);
        !           384:                                if (leadzeroes > 0) {
        !           385:                                        otherlength = lzero = leadzeroes;
        !           386:                                        flagword |= LZERO;
        !           387:                                }
        !           388:                        }
        !           389: 
        !           390:                        break;
        !           391: 
        !           392:                case 'U':
        !           393:                        flagword |= LENGTH;
        !           394:                        /* No break */
        !           395:                case 'u':
        !           396:                        /* Fetch the argument to be printed */
        !           397:                        if (flagword & LENGTH)
        !           398:                                val = va_arg(args, long);
        !           399:                        else
        !           400:                                val = va_arg(args, unsigned);
        !           401: 
        !           402:                        p = bp = buf + MAXDIGS;
        !           403: 
        !           404:                        if (val & HIBITL)
        !           405:                                *--bp = _lowdigit(&val);
        !           406: 
        !           407:                        goto decimal;
        !           408: 
        !           409:                /*
        !           410:                 *      non-decimal fixed point representations
        !           411:                 *      for radix equal to a power of two
        !           412:                 *
        !           413:                 *      "mradix" is one less than the radix for the conversion.
        !           414:                 *      "lradix" is one less than the base 2 log
        !           415:                 *      of the radix for the conversion. Conversion is unsigned.
        !           416:                 *      HIBITL is 100...000
        !           417:                 *      binary, and is equal to the maximum
        !           418:                 *      negative number.
        !           419:                 *      We assume a 2's complement machine
        !           420:                 */
        !           421: 
        !           422:                case 'O':
        !           423:                        flagword |= LENGTH;
        !           424:                        /* No break */
1.1       root      425:                case 'o':
1.1.1.2 ! root      426:                        mradix = 7;
        !           427:                        lradix = 2;
        !           428:                        goto fixed;
        !           429: 
        !           430:                case 'X':
1.1       root      431:                case 'x':
1.1.1.2 ! root      432:                        mradix = 15;
        !           433:                        lradix = 3;
        !           434: 
        !           435:                fixed:
        !           436:                        /* Fetch the argument to be printed */
        !           437:                        if (flagword & LENGTH)
        !           438:                                val = va_arg(args, long);
        !           439:                        else
        !           440:                                val = va_arg(args, unsigned);
        !           441: 
        !           442:                        /* Set translate table for digits */
        !           443: /*                     tab = (fcode == 'X') ?
        !           444:                            "0123456789ABCDEF" : "0123456789abcdef";*/
        !           445:                        tab = "0123456789ABCDEF";
        !           446: 
        !           447:                        /* Develop the digits of the value */
        !           448:                        p = bp = buf + MAXDIGS;
        !           449:                        { register long qval = val;
        !           450:                                if (qval == 0) {
        !           451:                                        if (!(flagword & DOTSEEN)) {
        !           452:                                                otherlength = lzero = 1;
        !           453:                                                flagword |= LZERO;
        !           454:                                        }
        !           455:                                } else
        !           456:                                        do {
        !           457:                                                *--bp = tab[qval & mradix];
        !           458:                                                qval = ((qval >> 1) & ~HIBITL)
        !           459:                                                                 >> lradix;
        !           460:                                        } while (qval != 0);
        !           461:                        }
        !           462: 
        !           463:                        /* Calculate minimum padding zero requirement */
        !           464:                        if (flagword & DOTSEEN) {
        !           465:                                register leadzeroes = prec - (p - bp);
        !           466:                                if (leadzeroes > 0) {
        !           467:                                        otherlength = lzero = leadzeroes;
        !           468:                                        flagword |= LZERO;
        !           469:                                }
        !           470:                        }
        !           471: 
        !           472:                        /* Handle the # flag */
        !           473:                        if (flagword & FSHARP && val != 0)
        !           474:                                switch (fcode) {
        !           475:                                case 'o':
        !           476:                                        if (!(flagword & LZERO)) {
        !           477:                                                otherlength = lzero = 1;
        !           478:                                                flagword |= LZERO;
        !           479:                                        }
        !           480:                                        break;
        !           481:                                case 'x':
        !           482:                                        prefix = "0x";
        !           483:                                        prefixlength = 2;
        !           484:                                        break;
        !           485:                                case 'X':
        !           486:                                        prefix = "0X";
        !           487:                                        prefixlength = 2;
        !           488:                                        break;
        !           489:                                }
        !           490: 
        !           491:                        break;
        !           492: 
        !           493:                case 'E':
        !           494:                case 'e':
        !           495:                        /*
        !           496:                         * E-format.  The general strategy
        !           497:                         * here is fairly easy: we take
        !           498:                         * what ecvt gives us and re-format it.
        !           499:                         */
        !           500: 
        !           501:                        /* Establish default precision */
        !           502:                        if (!(flagword & DOTSEEN))
        !           503:                                prec = 6;
        !           504: 
        !           505:                        /* Fetch the value */
        !           506:                        dval = va_arg(args, double);
        !           507: 
        !           508:                        /* Develop the mantissa */
        !           509:                        bp = ecvt(dval, min(prec + 1, MAXECVT), &decpt, &sign);
        !           510: 
        !           511:                        /* Determine the prefix */
        !           512:                e_merge:
        !           513:                        if (sign) {
        !           514:                                prefix = "-";
        !           515:                                prefixlength = 1;
        !           516:                        } else if (flagword & FPLUS) {
        !           517:                                prefix = "+";
        !           518:                                prefixlength = 1;
        !           519:                        } else if (flagword & FBLANK) {
        !           520:                                prefix = " ";
        !           521:                                prefixlength = 1;
        !           522:                        }
        !           523: 
        !           524:                        /* Place the first digit in the buffer*/
        !           525:                        p = &buf[0];
        !           526:                        *p++ = (*bp != '\0') ? *bp++ : '0';
        !           527: 
        !           528:                        /* Put in a decimal point if needed */
        !           529:                        if (prec != 0 || (flagword & FSHARP))
        !           530:                                *p++ = '.';
        !           531: 
        !           532:                        /* Create the rest of the mantissa */
        !           533:                        { register rz = prec;
        !           534:                                for ( ; rz > 0 && *bp != '\0'; --rz)
        !           535:                                        *p++ = *bp++;
        !           536:                                if (rz > 0) {
        !           537:                                        otherlength = rzero = rz;
        !           538:                                        flagword |= RZERO;
        !           539:                                }
        !           540:                        }
        !           541: 
        !           542:                        bp = &buf[0];
        !           543: 
        !           544:                        /* Create the exponent */
        !           545:                        *(suffix = &expbuf[MAXESIZ]) = '\0';
        !           546:                        if (dval != 0) {
        !           547:                                register int nn = decpt - 1;
        !           548:                                if (nn < 0)
        !           549:                                    nn = -nn;
        !           550:                                for ( ; nn > 9; nn /= 10)
        !           551:                                        *--suffix = todigit(nn % 10);
        !           552:                                *--suffix = todigit(nn);
        !           553:                        }
        !           554: 
        !           555:                        /* Prepend leading zeroes to the exponent */
        !           556:                        while (suffix > &expbuf[MAXESIZ - 2])
        !           557:                                *--suffix = '0';
        !           558: 
        !           559:                        /* Put in the exponent sign */
        !           560:                        *--suffix = (decpt > 0 || dval == 0) ? '+' : '-';
        !           561: 
        !           562:                        /* Put in the e */
        !           563:                        *--suffix = isupper(fcode) ? 'E'  : 'e';
        !           564: 
        !           565:                        /* compute size of suffix */
        !           566:                        otherlength += (suffixlength = &expbuf[MAXESIZ]
        !           567:                                                                 - suffix);
        !           568:                        flagword |= SUFFIX;
        !           569: 
        !           570:                        break;
        !           571: 
1.1       root      572:                case 'f':
1.1.1.2 ! root      573:                        /*
        !           574:                         * F-format floating point.  This is a
        !           575:                         * good deal less simple than E-format.
        !           576:                         * The overall strategy will be to call
        !           577:                         * fcvt, reformat its result into buf,
        !           578:                         * and calculate how many trailing
        !           579:                         * zeroes will be required.  There will
        !           580:                         * never be any leading zeroes needed.
        !           581:                         */
        !           582: 
        !           583:                        /* Establish default precision */
        !           584:                        if (!(flagword & DOTSEEN))
        !           585:                                prec = 6;
        !           586: 
        !           587:                        /* Fetch the value */
        !           588:                        dval = va_arg(args, double);
        !           589: 
        !           590:                        /* Do the conversion */
        !           591:                        bp = fcvt(dval, min(prec + 1, MAXFCVT), &decpt, &sign);
        !           592: 
        !           593:                        /* Determine the prefix */
        !           594:                f_merge:
        !           595:                        if (sign && decpt > -prec && *bp != '0') {
        !           596:                                prefix = "-";
        !           597:                                prefixlength = 1;
        !           598:                        } else if (flagword & FPLUS) {
        !           599:                                prefix = "+";
        !           600:                                prefixlength = 1;
        !           601:                        } else if (flagword & FBLANK) {
        !           602:                                prefix = " ";
        !           603:                                prefixlength = 1;
        !           604:                        }
        !           605: 
        !           606:                        /* Initialize buffer pointer */
        !           607:                        p = &buf[0];
        !           608: 
        !           609:                        { register int nn = decpt;
        !           610: 
        !           611:                                /* Emit the digits before the decimal point */
        !           612:                                k = 0;
        !           613:                                do {
        !           614:                                        *p++ = (nn <= 0 || *bp == '\0' 
        !           615:                                                || k >= MAXFSIG) ?
        !           616:                                                '0' : (k++, *bp++);
        !           617:                                } while (--nn > 0);
        !           618: 
        !           619:                                /* Decide whether we need a decimal point */
        !           620:                                if ((flagword & FSHARP) || prec > 0)
        !           621:                                        *p++ = '.';
        !           622: 
        !           623:                                /* Digits (if any) after the decimal point */
        !           624:                                nn = min(prec, MAXFCVT);
        !           625:                                if (prec > nn) {
        !           626:                                        flagword |= RZERO;
        !           627:                                        otherlength = rzero = prec - nn;
        !           628:                                }
        !           629:                                while (--nn >= 0)
        !           630:                                        *p++ = (++decpt <= 0 || *bp == '\0' ||
        !           631:                                            k >= MAXFSIG) ? '0' : (k++, *bp++);
        !           632:                        }
        !           633: 
        !           634:                        bp = &buf[0];
        !           635: 
        !           636:                        break;
        !           637: 
        !           638:                case 'G':
        !           639:                case 'g':
        !           640:                        /*
        !           641:                         * g-format.  We play around a bit
        !           642:                         * and then jump into e or f, as needed.
        !           643:                         */
        !           644:                
        !           645:                        /* Establish default precision */
        !           646:                        if (!(flagword & DOTSEEN))
        !           647:                                prec = 6;
        !           648:                        else if (prec == 0)
        !           649:                                prec = 1;
        !           650: 
        !           651:                        /* Fetch the value */
        !           652:                        dval = va_arg(args, double);
        !           653: 
        !           654:                        /* Do the conversion */
        !           655:                        bp = ecvt(dval, min(prec + 1, MAXECVT), &decpt, &sign);
        !           656:                        if (dval == 0)
        !           657:                                decpt = 1;
        !           658: 
        !           659:                        { register int kk = prec;
        !           660:                                if (!(flagword & FSHARP)) {
        !           661:                                        n = strlen(bp);
        !           662:                                        if (n < kk)
        !           663:                                                kk = n;
        !           664:                                        while (kk >= 1 && bp[kk-1] == '0')
        !           665:                                                --kk;
        !           666:                                }
        !           667:                                
        !           668:                                if (decpt < -3 || decpt > prec) {
        !           669:                                        prec = kk - 1;
        !           670:                                        goto e_merge;
        !           671:                                }
        !           672:                                prec = kk - decpt;
        !           673:                                goto f_merge;
        !           674:                        }
        !           675: 
        !           676:                case '%':
        !           677:                        buf[0] = fcode;
        !           678:                        goto c_merge;
        !           679: 
        !           680:                case 'c':
        !           681:                        buf[0] = va_arg(args, int);
        !           682:                c_merge:
        !           683:                        p = (bp = &buf[0]) + 1;
        !           684:                        break;
        !           685: 
        !           686:                case 's':
        !           687:                        bp = va_arg(args, char *);
        !           688:                        if (!(flagword & DOTSEEN))
        !           689:                                p = bp + strlen(bp);
        !           690:                        else { /* a strnlen function would  be useful here! */
        !           691:                                register char *qp = bp;
        !           692:                                while (*qp++ != '\0' && --prec >= 0)
        !           693:                                        ;
        !           694:                                p = qp - 1;
        !           695:                        }
        !           696:                        break;
        !           697: 
        !           698:                default: /* this is technically an error; what we do is to */
        !           699:                        /* back up the format pointer to the offending char */
        !           700:                        /* and continue with the format scan */
        !           701:                        format--;
        !           702:                        continue;
        !           703: 
1.1       root      704:                }
1.1.1.2 ! root      705: 
        !           706:                /* Calculate number of padding blanks */
        !           707:                k = (n = p - bp) + prefixlength + otherlength;
        !           708:                if (width <= k)
        !           709:                        count += k;
        !           710:                else {
        !           711:                        count += width;
        !           712: 
        !           713:                        /* Set up for padding zeroes if requested */
        !           714:                        /* Otherwise emit padding blanks unless output is */
        !           715:                        /* to be left-justified.  */
        !           716: 
        !           717:                        if (flagword & PADZERO) {
        !           718:                                if (!(flagword & LZERO)) {
        !           719:                                        flagword |= LZERO;
        !           720:                                        lzero = width - k;
        !           721:                                }
        !           722:                                else
        !           723:                                        lzero += width - k;
        !           724:                                k = width; /* cancel padding blanks */
        !           725:                        } else
        !           726:                                /* Blanks on left if required */
        !           727:                                if (!(flagword & FMINUS))
        !           728:                                        PAD(_blanks, width - k);
1.1       root      729:                }
                    730: 
1.1.1.2 ! root      731:                /* Prefix, if any */
        !           732:                if (prefixlength != 0)
        !           733:                        PUT(prefix, prefixlength);
        !           734: 
        !           735:                /* Zeroes on the left */
        !           736:                if (flagword & LZERO)
        !           737:                        PAD(_zeroes, lzero);
        !           738:                
        !           739:                /* The value itself */
        !           740:                if (n > 0)
        !           741:                        PUT(bp, n);
        !           742: 
        !           743:                if (flagword & (RZERO | SUFFIX | FMINUS)) {
        !           744:                        /* Zeroes on the right */
        !           745:                        if (flagword & RZERO)
        !           746:                                PAD(_zeroes, rzero);
        !           747: 
        !           748:                        /* The suffix */
        !           749:                        if (flagword & SUFFIX)
        !           750:                                PUT(suffix, suffixlength);
        !           751: 
        !           752:                        /* Blanks on the right if required */
        !           753:                        if (flagword & FMINUS && width > k)
        !           754:                                PAD(_blanks, width - k);
        !           755:                }
1.1       root      756:        }
                    757: }

unix.superglobalmegacorp.com

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