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