|
|
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: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.