Annotation of researchv10dc/ncurses/screen/doprnt.c, revision 1.1

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

unix.superglobalmegacorp.com

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