Annotation of researchv10no/cmd/cfront/optcfront/doprint.c, revision 1.1

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

unix.superglobalmegacorp.com

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