Annotation of researchv10no/cmd/cfront/ooptcfront/doprint.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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