00001
00016 #define __FORMATTER__
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include <stdarg.h>
00071 #include <memory.h>
00072
00073 #include "config.h"
00074 #include "compat/fpclassify.h"
00075
00076
00077 #if defined(LIBC_SCCS) && !defined(lint)
00078 static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
00079 #endif
00080
00081 #ifdef HAVE_SYS_CDEFS_H
00082 #include <sys/cdefs.h>
00083 #endif
00084
00085 #define __FBSDID(x)
00086 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.69 2005/04/16 22:36:51 das Exp $");
00087
00088
00089
00090
00091
00092
00093
00094 #ifndef __FORMATTER__
00095 #include "namespace.h"
00096 #endif
00097 #include <sys/types.h>
00098
00099 #include <ctype.h>
00100 #include <limits.h>
00101 #include <locale.h>
00102 #include <stddef.h>
00103 #ifdef HAVE_STDINT_H
00104 #include <stdint.h>
00105 #endif
00106 #include <stdio.h>
00107 #include <stdlib.h>
00108 #include <string.h>
00109 #include <wchar.h>
00110
00111 #include <stdarg.h>
00112
00113 #ifndef __FORMATTER__
00114 #include "un-namespace.h"
00115
00116 #include "libc_private.h"
00117 #include "local.h"
00118 #include "fvwrite.h"
00119
00120 #else
00121
00122 extern size_t formatter_format(void* fmtobj, char* str, size_t strsz);
00123
00124
00125
00126
00127 struct __siov {
00128 void *iov_base;
00129 size_t iov_len;
00130 };
00131 struct __suio {
00132 struct __siov *uio_iov;
00133 int uio_iovcnt;
00134 int uio_resid;
00135
00136 };
00137 #endif // __FORMATTER__
00138
00139 #ifndef INTMAX_MAX
00140
00141 #include <limits.h>
00142
00143 #if defined(LLONG_MAX)
00144 #define INTMAX_MAX LLONG_MAX
00145 #elif defined(LONG_LONG_MAX)
00146 #define INTMAX_MAX LONG_LONG_MAX
00147 #else
00148 #define INTMAX_MAX INT_MAX
00149 #endif
00150
00151 #endif // INTMAX_MAX
00152
00153 #ifdef __FORMATTER__
00154 #define reallocf realloc
00155 #endif
00156
00157 #ifndef __THROW
00158 #define __THROW
00159 #endif
00160
00161 union arg {
00162 int intarg;
00163 u_int uintarg;
00164 long longarg;
00165 u_long ulongarg;
00166 long long longlongarg;
00167 unsigned long long ulonglongarg;
00168 ptrdiff_t ptrdiffarg;
00169 size_t sizearg;
00170 intmax_t intmaxarg;
00171 uintmax_t uintmaxarg;
00172 void *pvoidarg;
00173 char *pchararg;
00174 signed char *pschararg;
00175 short *pshortarg;
00176 int *pintarg;
00177 long *plongarg;
00178 long long *plonglongarg;
00179 ptrdiff_t *pptrdiffarg;
00180 size_t *psizearg;
00181 intmax_t *pintmaxarg;
00182 #ifndef NO_FLOATING_POINT
00183 double doublearg;
00184 long double longdoublearg;
00185 #endif
00186 wint_t wintarg;
00187 wchar_t *pwchararg;
00188 };
00189
00190
00191
00192
00193 enum typeid {
00194 T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
00195 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
00196 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
00197 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
00198 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
00199 };
00200
00201 #ifndef __FORMATTER__
00202 static int __sprint(FILE *, struct __suio *);
00203 static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
00204 #endif // __FORMATTER__
00205 static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char,
00206 const char *);
00207 static char *__ultoa(u_long, char *, int, int, const char *, int, char,
00208 const char *);
00209 static char *__wcsconv(wchar_t *, int);
00210 static void __find_arguments(const char *, va_list, union arg **);
00211 static void __grow_type_table(int, enum typeid **, int *);
00212
00213
00214
00215
00216
00217 #ifndef __FORMATTER__
00218 static int
00219 __sprint(FILE *fp, struct __suio *uio)
00220 {
00221 int err;
00222
00223 if (uio->uio_resid == 0) {
00224 uio->uio_iovcnt = 0;
00225 return (0);
00226 }
00227 err = __sfvwrite(fp, uio);
00228 uio->uio_resid = 0;
00229 uio->uio_iovcnt = 0;
00230 return (err);
00231 }
00232 #endif // __FORMATTER__
00233
00234
00235
00236
00237
00238
00239 #ifndef __FORMATTER__
00240 static int
00241 __sbprintf(FILE *fp, const char *fmt, va_list ap)
00242 {
00243 int ret;
00244 FILE fake;
00245 unsigned char buf[BUFSIZ];
00246
00247
00248 fake._flags = fp->_flags & ~__SNBF;
00249 fake._file = fp->_file;
00250 fake._cookie = fp->_cookie;
00251 fake._write = fp->_write;
00252 fake._extra = fp->_extra;
00253
00254
00255 fake._bf._base = fake._p = buf;
00256 fake._bf._size = fake._w = sizeof(buf);
00257 fake._lbfsize = 0;
00258
00259
00260 ret = __vfprintf(&fake, fmt, ap);
00261 if (ret >= 0 && __fflush(&fake))
00262 ret = EOF;
00263 if (fake._flags & __SERR)
00264 fp->_flags |= __SERR;
00265 return (ret);
00266 }
00267 #endif // __FORMATTER__
00268
00269
00270
00271
00272 #define to_digit(c) ((c) - '0')
00273 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
00274 #define to_char(n) ((n) + '0')
00275
00276
00277
00278
00279
00280
00281
00282 static char *
00283 __ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs,
00284 int needgrp, char thousep, const char *grp)
00285 {
00286 char *cp = endp;
00287 long sval;
00288 int ndig;
00289
00290
00291
00292
00293
00294 switch (base) {
00295 case 10:
00296 if (val < 10) {
00297 *--cp = to_char(val);
00298 return (cp);
00299 }
00300 ndig = 0;
00301
00302
00303
00304
00305
00306
00307 if (val > LONG_MAX) {
00308 *--cp = to_char(val % 10);
00309 ndig++;
00310 sval = val / 10;
00311 } else
00312 sval = val;
00313 do {
00314 *--cp = to_char(sval % 10);
00315 ndig++;
00316
00317
00318
00319
00320 if (needgrp && ndig == *grp && *grp != CHAR_MAX
00321 && sval > 9) {
00322 *--cp = thousep;
00323 ndig = 0;
00324
00325
00326
00327
00328
00329 if (*(grp+1) != '\0')
00330 grp++;
00331 }
00332 sval /= 10;
00333 } while (sval != 0);
00334 break;
00335
00336 case 8:
00337 do {
00338 *--cp = to_char(val & 7);
00339 val >>= 3;
00340 } while (val);
00341 if (octzero && *cp != '0')
00342 *--cp = '0';
00343 break;
00344
00345 case 16:
00346 do {
00347 *--cp = xdigs[val & 15];
00348 val >>= 4;
00349 } while (val);
00350 break;
00351
00352 default:
00353 abort();
00354 }
00355 return (cp);
00356 }
00357
00358
00359 static char *
00360 __ujtoa(uintmax_t val, char *endp, int base, int octzero, const char *xdigs,
00361 int needgrp, char thousep, const char *grp)
00362 {
00363 char *cp = endp;
00364 intmax_t sval;
00365 int ndig;
00366
00367
00368
00369 if (val <= ULONG_MAX)
00370 return (__ultoa((u_long)val, endp, base, octzero, xdigs,
00371 needgrp, thousep, grp));
00372 switch (base) {
00373 case 10:
00374 if (val < 10) {
00375 *--cp = to_char(val % 10);
00376 return (cp);
00377 }
00378 ndig = 0;
00379 if (val > INTMAX_MAX) {
00380 *--cp = to_char(val % 10);
00381 ndig++;
00382 sval = val / 10;
00383 } else
00384 sval = val;
00385 do {
00386 *--cp = to_char(sval % 10);
00387 ndig++;
00388
00389
00390
00391
00392 if (needgrp && *grp != CHAR_MAX && ndig == *grp
00393 && sval > 9) {
00394 *--cp = thousep;
00395 ndig = 0;
00396
00397
00398
00399
00400
00401 if (*(grp+1) != '\0')
00402 grp++;
00403 }
00404 sval /= 10;
00405 } while (sval != 0);
00406 break;
00407
00408 case 8:
00409 do {
00410 *--cp = to_char(val & 7);
00411 val >>= 3;
00412 } while (val);
00413 if (octzero && *cp != '0')
00414 *--cp = '0';
00415 break;
00416
00417 case 16:
00418 do {
00419 *--cp = xdigs[val & 15];
00420 val >>= 4;
00421 } while (val);
00422 break;
00423
00424 default:
00425 abort();
00426 }
00427 return (cp);
00428 }
00429
00430
00431
00432
00433
00434
00435
00436 static char *
00437 __wcsconv(wchar_t *wcsarg, int prec)
00438 {
00439 static const mbstate_t initial;
00440 mbstate_t mbs;
00441 char buf[MB_LEN_MAX];
00442 wchar_t *p;
00443 char *convbuf, *mbp;
00444 size_t clen, nbytes;
00445
00446
00447
00448
00449
00450 if (prec >= 0) {
00451 nbytes = 0;
00452 p = wcsarg;
00453 mbs = initial;
00454 for (;;) {
00455 clen = wcrtomb(buf, *p++, &mbs);
00456 if (clen == 0 || clen == (size_t)-1 ||
00457 nbytes + clen > prec)
00458 break;
00459 nbytes += clen;
00460 }
00461 } else {
00462 p = wcsarg;
00463 mbs = initial;
00464 nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
00465 if (nbytes == (size_t)-1)
00466 return (NULL);
00467 }
00468 if ((convbuf = malloc(nbytes + 1)) == NULL)
00469 return (NULL);
00470
00471
00472
00473
00474
00475 mbp = convbuf;
00476 p = wcsarg;
00477 mbs = initial;
00478 while (mbp - convbuf < nbytes) {
00479 clen = wcrtomb(mbp, *p++, &mbs);
00480 if (clen == 0 || clen == (size_t)-1)
00481 break;
00482 mbp += clen;
00483 }
00484 if (clen == (size_t)-1) {
00485 free(convbuf);
00486 return (NULL);
00487 }
00488 *mbp = '\0';
00489
00490 return (convbuf);
00491 }
00492
00493
00494
00495
00496 #ifndef __FORMATTER__
00497 int
00498 vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
00499
00500 {
00501 int ret;
00502
00503 FLOCKFILE(fp);
00504 ret = __vfprintf(fp, fmt0, ap);
00505 FUNLOCKFILE(fp);
00506 return (ret);
00507 }
00508 #endif // __FORMATTER__
00509
00510 #ifndef NO_FLOATING_POINT
00511
00512 #ifndef __FORMATTER__
00513 #define dtoa __dtoa
00514 #define freedtoa __freedtoa
00515 #endif // __FORMATTER__
00516
00517 #include <float.h>
00518 #include <math.h>
00519
00520 #include "floatio.h"
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 #include "gdtoa.h"
00541
00542 #define DEFPREC 6
00543
00544 static int exponent(char *, int, int);
00545
00546 #endif
00547
00548
00549
00550
00551
00552
00553
00554
00555 #define BUF 100
00556
00557 #define STATIC_ARG_TBL_SIZE 8
00558
00559
00560
00561
00562 #define ALT 0x001
00563 #define LADJUST 0x004
00564 #define LONGDBL 0x008
00565 #define LONGINT 0x010
00566 #define LLONGINT 0x020
00567 #define SHORTINT 0x040
00568 #define ZEROPAD 0x080
00569 #define FPT 0x100
00570 #define GROUPING 0x200
00571
00572 #define SIZET 0x400
00573 #define PTRDIFFT 0x800
00574 #define INTMAXT 0x1000
00575 #define CHARINT 0x2000
00576
00577
00578
00579
00580 int
00581
00582 vsnprintf(char *str, size_t strsz, const char *fmt0, va_list ap)
00583 {
00584 char *fmt;
00585 int ch;
00586 int n, n2;
00587 char *cp;
00588 #ifndef __FORMATTER__
00589 struct __siov *iovp;
00590 #endif // __FORMATTER__
00591 int flags;
00592 int ret;
00593 int width;
00594 int prec;
00595 char sign;
00596 char thousands_sep;
00597 const char *grouping;
00598 #ifndef NO_FLOATING_POINT
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 char *decimal_point;
00614 int signflag;
00615 union {
00616 double dbl;
00617 long double ldbl;
00618 } fparg;
00619 int expt;
00620 char expchar;
00621 char *dtoaend;
00622 int expsize;
00623 int lead;
00624 int ndig;
00625 char expstr[MAXEXPDIG+2];
00626 char *dtoaresult;
00627 int nseps;
00628 int nrepeats;
00629 #endif
00630 u_long ulval;
00631 uintmax_t ujval;
00632 int base;
00633 int dprec;
00634 int realsz;
00635 int size;
00636 int prsize;
00637 const char *xdigs;
00638 #ifndef __FORMATTER__
00639 #define NIOV 8
00640 struct __suio uio;
00641 struct __siov iov[NIOV];
00642 #endif // __FORMATTER__
00643 char buf[BUF];
00644 char ox[2];
00645 union arg *argtable;
00646 union arg statargtable [STATIC_ARG_TBL_SIZE];
00647 int nextarg;
00648 va_list orgap;
00649 char *convbuf;
00650 #ifdef __FORMATTER__
00651 size_t sz;
00652 void* fmtobj;
00653 #endif
00654
00655
00656
00657
00658
00659
00660 #define PADSIZE 16
00661 static char blanks[PADSIZE] =
00662 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
00663 static char zeroes[PADSIZE] =
00664 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
00665
00666 static const char xdigs_lower[16] = "0123456789abcdef";
00667 static const char xdigs_upper[16] = "0123456789ABCDEF";
00668
00669
00670
00671
00672 #ifndef __FORMATTER__
00673 #define PRINT(ptr, len) { \
00674 iovp->iov_base = (ptr); \
00675 iovp->iov_len = (len); \
00676 uio.uio_resid += (len); \
00677 iovp++; \
00678 if (++uio.uio_iovcnt >= NIOV) { \
00679 if (__sprint(fp, &uio)) \
00680 goto error; \
00681 iovp = iov; \
00682 } \
00683 }
00684 #else
00685 #define PRINT(ptr, len) { \
00686 sz = (((size_t)len) <= strsz) ? len : strsz; \
00687 memcpy(str, ptr, sz); \
00688 str += sz; \
00689 strsz -= sz; \
00690 }
00691 #endif
00692
00693 #define PAD(howmany, with) { \
00694 if ((n = (howmany)) > 0) { \
00695 while (n > PADSIZE) { \
00696 PRINT(with, PADSIZE); \
00697 n -= PADSIZE; \
00698 } \
00699 PRINT(with, n); \
00700 } \
00701 }
00702 #define PRINTANDPAD(p, ep, len, with) do { \
00703 n2 = (ep) - (p); \
00704 if (n2 > (len)) \
00705 n2 = (len); \
00706 if (n2 > 0) \
00707 PRINT((p), n2); \
00708 PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
00709 } while(0)
00710 #ifndef __FORMATTER__
00711 #define FLUSH() { \
00712 if (uio.uio_resid && __sprint(fp, &uio)) \
00713 goto error; \
00714 uio.uio_iovcnt = 0; \
00715 iovp = iov; \
00716 }
00717 #else
00718 #define FLUSH() {}
00719 #endif
00720
00721
00722
00723
00724
00725 #define GETARG(type) \
00726 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
00727 (nextarg++, va_arg(ap, type)))
00728
00729
00730
00731
00732
00733 #define SARG() \
00734 (flags&LONGINT ? GETARG(long) : \
00735 flags&SHORTINT ? (long)(short)GETARG(int) : \
00736 flags&CHARINT ? (long)(signed char)GETARG(int) : \
00737 (long)GETARG(int))
00738 #define UARG() \
00739 (flags&LONGINT ? GETARG(u_long) : \
00740 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
00741 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
00742 (u_long)GETARG(u_int))
00743 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
00744 #define SJARG() \
00745 (flags&INTMAXT ? GETARG(intmax_t) : \
00746 flags&SIZET ? (intmax_t)GETARG(size_t) : \
00747 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
00748 (intmax_t)GETARG(long long))
00749 #define UJARG() \
00750 (flags&INTMAXT ? GETARG(uintmax_t) : \
00751 flags&SIZET ? (uintmax_t)GETARG(size_t) : \
00752 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
00753 (uintmax_t)GETARG(unsigned long long))
00754
00755
00756
00757
00758
00759 #define GETASTER(val) \
00760 n2 = 0; \
00761 cp = fmt; \
00762 while (is_digit(*cp)) { \
00763 n2 = 10 * n2 + to_digit(*cp); \
00764 cp++; \
00765 } \
00766 if (*cp == '$') { \
00767 int hold = nextarg; \
00768 if (argtable == NULL) { \
00769 argtable = statargtable; \
00770 __find_arguments (fmt0, orgap, &argtable); \
00771 } \
00772 nextarg = n2; \
00773 val = GETARG (int); \
00774 nextarg = hold; \
00775 fmt = ++cp; \
00776 } else { \
00777 val = GETARG (int); \
00778 }
00779
00780
00781 thousands_sep = '\0';
00782 grouping = NULL;
00783 convbuf = NULL;
00784 #ifndef NO_FLOATING_POINT
00785 dtoaresult = NULL;
00786 decimal_point = localeconv()->decimal_point;
00787 #endif
00788 #ifndef __FORMATTER__
00789
00790 if (prepwrite(fp) != 0)
00791 return (EOF);
00792
00793
00794 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
00795 fp->_file >= 0)
00796 return (__sbprintf(fp, fmt0, ap));
00797 #endif // __FORMATTER__
00798
00799 fmt = (char *)fmt0;
00800 argtable = NULL;
00801 nextarg = 1;
00802 va_copy(orgap, ap);
00803 #ifndef __FORMATTER__
00804 uio.uio_iov = iovp = iov;
00805 uio.uio_resid = 0;
00806 uio.uio_iovcnt = 0;
00807 #endif
00808 ret = 0;
00809
00810 if (strsz == 0) {
00811 return -1;
00812 }
00813
00814
00815
00816
00817
00818
00819 strsz -= 1;
00820
00821
00822
00823
00824 for (;;) {
00825 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
00826 ;
00827 if ((n = fmt - cp) != 0) {
00828 if ((unsigned)ret + n > INT_MAX) {
00829 ret = EOF;
00830 goto error;
00831 }
00832 PRINT(cp, n);
00833 ret += n;
00834 }
00835 if (ch == '\0')
00836 goto done;
00837 fmt++;
00838
00839 flags = 0;
00840 dprec = 0;
00841 width = 0;
00842 prec = -1;
00843 sign = '\0';
00844 ox[1] = '\0';
00845
00846 rflag: ch = *fmt++;
00847 reswitch: switch (ch) {
00848 case ' ':
00849
00850
00851
00852
00853
00854 if (!sign)
00855 sign = ' ';
00856 goto rflag;
00857 case '#':
00858 flags |= ALT;
00859 goto rflag;
00860 case '*':
00861
00862
00863
00864
00865
00866
00867 GETASTER (width);
00868 if (width >= 0)
00869 goto rflag;
00870 width = -width;
00871
00872 case '-':
00873 flags |= LADJUST;
00874 goto rflag;
00875 case '+':
00876 sign = '+';
00877 goto rflag;
00878 case '\'':
00879 flags |= GROUPING;
00880 thousands_sep = *(localeconv()->thousands_sep);
00881 grouping = localeconv()->grouping;
00882 goto rflag;
00883 case '.':
00884 if ((ch = *fmt++) == '*') {
00885 GETASTER (prec);
00886 goto rflag;
00887 }
00888 prec = 0;
00889 while (is_digit(ch)) {
00890 prec = 10 * prec + to_digit(ch);
00891 ch = *fmt++;
00892 }
00893 goto reswitch;
00894 case '0':
00895
00896
00897
00898
00899
00900 flags |= ZEROPAD;
00901 goto rflag;
00902 case '1': case '2': case '3': case '4':
00903 case '5': case '6': case '7': case '8': case '9':
00904 n = 0;
00905 do {
00906 n = 10 * n + to_digit(ch);
00907 ch = *fmt++;
00908 } while (is_digit(ch));
00909 if (ch == '$') {
00910 nextarg = n;
00911 if (argtable == NULL) {
00912 argtable = statargtable;
00913 __find_arguments (fmt0, orgap,
00914 &argtable);
00915 }
00916 goto rflag;
00917 }
00918 width = n;
00919 goto reswitch;
00920 #ifndef NO_FLOATING_POINT
00921 case 'L':
00922 flags |= LONGDBL;
00923 goto rflag;
00924 #endif
00925 case 'h':
00926 if (flags & SHORTINT) {
00927 flags &= ~SHORTINT;
00928 flags |= CHARINT;
00929 } else
00930 flags |= SHORTINT;
00931 goto rflag;
00932 case 'j':
00933 flags |= INTMAXT;
00934 goto rflag;
00935 case 'l':
00936 if (flags & LONGINT) {
00937 flags &= ~LONGINT;
00938 flags |= LLONGINT;
00939 } else
00940 flags |= LONGINT;
00941 goto rflag;
00942 case 'q':
00943 flags |= LLONGINT;
00944 goto rflag;
00945 case 't':
00946 flags |= PTRDIFFT;
00947 goto rflag;
00948 case 'z':
00949 flags |= SIZET;
00950 goto rflag;
00951 case 'C':
00952 flags |= LONGINT;
00953
00954 case 'c':
00955 if (flags & LONGINT) {
00956 static const mbstate_t initial;
00957 mbstate_t mbs;
00958 size_t mbseqlen;
00959
00960 mbs = initial;
00961 mbseqlen = wcrtomb(cp = buf,
00962 (wchar_t)GETARG(wint_t), &mbs);
00963 if (mbseqlen == (size_t)-1) {
00964 #ifndef __FORMATTER__
00965 fp->_flags |= __SERR;
00966 #endif
00967 goto error;
00968 }
00969 size = (int)mbseqlen;
00970 } else {
00971 *(cp = buf) = GETARG(int);
00972 size = 1;
00973 }
00974 sign = '\0';
00975 break;
00976 case 'D':
00977 flags |= LONGINT;
00978
00979 case 'd':
00980 case 'i':
00981 if (flags & INTMAX_SIZE) {
00982 ujval = SJARG();
00983 if ((intmax_t)ujval < 0) {
00984 ujval = -ujval;
00985 sign = '-';
00986 }
00987 } else {
00988 ulval = SARG();
00989 if ((long)ulval < 0) {
00990 ulval = -ulval;
00991 sign = '-';
00992 }
00993 }
00994 base = 10;
00995 goto number;
00996 #ifndef NO_FLOATING_POINT
00997 case 'a':
00998 case 'A':
00999 if (ch == 'a') {
01000 ox[1] = 'x';
01001 xdigs = xdigs_lower;
01002 expchar = 'p';
01003 } else {
01004 ox[1] = 'X';
01005 xdigs = xdigs_upper;
01006 expchar = 'P';
01007 }
01008 if (prec >= 0)
01009 prec++;
01010 if (dtoaresult != NULL)
01011 freedtoa(dtoaresult);
01012 if (flags & LONGDBL) {
01013 fparg.ldbl = GETARG(long double);
01014 dtoaresult = cp =
01015 __hldtoa(fparg.ldbl, xdigs, prec,
01016 &expt, &signflag, &dtoaend);
01017 } else {
01018 fparg.dbl = GETARG(double);
01019 dtoaresult = cp =
01020 __hdtoa(fparg.dbl, xdigs, prec,
01021 &expt, &signflag, &dtoaend);
01022 }
01023 if (prec < 0)
01024 prec = dtoaend - cp;
01025 if (expt == INT_MAX)
01026 ox[1] = '\0';
01027 goto fp_common;
01028 case 'e':
01029 case 'E':
01030 expchar = ch;
01031 if (prec < 0)
01032 prec = DEFPREC + 1;
01033 else
01034 prec++;
01035 goto fp_begin;
01036 case 'f':
01037 case 'F':
01038 expchar = '\0';
01039 goto fp_begin;
01040 case 'g':
01041 case 'G':
01042 expchar = ch - ('g' - 'e');
01043 if (prec == 0)
01044 prec = 1;
01045 fp_begin:
01046 if (prec < 0)
01047 prec = DEFPREC;
01048 if (dtoaresult != NULL)
01049 freedtoa(dtoaresult);
01050 if (flags & LONGDBL) {
01051 fparg.ldbl = GETARG(long double);
01052 dtoaresult = cp =
01053 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
01054 &expt, &signflag, &dtoaend);
01055 } else {
01056 fparg.dbl = GETARG(double);
01057 dtoaresult = cp =
01058 dtoa(fparg.dbl, expchar ? 2 : 3, prec,
01059 &expt, &signflag, &dtoaend);
01060 if (expt == 9999)
01061 expt = INT_MAX;
01062 }
01063 fp_common:
01064 if (signflag)
01065 sign = '-';
01066 if (expt == INT_MAX) {
01067 if (*cp == 'N') {
01068 cp = (ch >= 'a') ? "nan" : "NAN";
01069 sign = '\0';
01070 } else
01071 cp = (ch >= 'a') ? "inf" : "INF";
01072 size = 3;
01073 break;
01074 }
01075 flags |= FPT;
01076 ndig = dtoaend - cp;
01077 if (ch == 'g' || ch == 'G') {
01078 if (expt > -4 && expt <= prec) {
01079
01080 expchar = '\0';
01081 if (flags & ALT)
01082 prec -= expt;
01083 else
01084 prec = ndig - expt;
01085 if (prec < 0)
01086 prec = 0;
01087 } else {
01088
01089
01090
01091
01092 if (!(flags & ALT))
01093 prec = ndig;
01094 }
01095 }
01096 if (expchar) {
01097 expsize = exponent(expstr, expt - 1, expchar);
01098 size = expsize + prec;
01099 if (prec > 1 || flags & ALT)
01100 ++size;
01101 } else {
01102
01103 if (expt > 0)
01104 size = expt;
01105 else
01106 size = 1;
01107
01108 if (prec || flags & ALT)
01109 size += prec + 1;
01110 if (grouping && expt > 0) {
01111
01112 nseps = nrepeats = 0;
01113 lead = expt;
01114 while (*grouping != CHAR_MAX) {
01115 if (lead <= *grouping)
01116 break;
01117 lead -= *grouping;
01118 if (*(grouping+1)) {
01119 nseps++;
01120 grouping++;
01121 } else
01122 nrepeats++;
01123 }
01124 size += nseps + nrepeats;
01125 } else
01126 lead = expt;
01127 }
01128 break;
01129 #endif
01130 case 'n':
01131
01132
01133
01134
01135
01136 if (flags & LLONGINT)
01137 *GETARG(long long *) = ret;
01138 else if (flags & SIZET)
01139 *GETARG(ssize_t *) = (ssize_t)ret;
01140 else if (flags & PTRDIFFT)
01141 *GETARG(ptrdiff_t *) = ret;
01142 else if (flags & INTMAXT)
01143 *GETARG(intmax_t *) = ret;
01144 else if (flags & LONGINT)
01145 *GETARG(long *) = ret;
01146 else if (flags & SHORTINT)
01147 *GETARG(short *) = ret;
01148 else if (flags & CHARINT)
01149 *GETARG(signed char *) = ret;
01150 else
01151 *GETARG(int *) = ret;
01152 continue;
01153 case 'O':
01154 flags |= LONGINT;
01155
01156 case 'o':
01157 if (flags & INTMAX_SIZE)
01158 ujval = UJARG();
01159 else
01160 ulval = UARG();
01161 base = 8;
01162 goto nosign;
01163 case 'p':
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173 if (ret > 0 && str[-1] == '*') {
01174 str--;
01175 strsz++;
01176 ret--;
01177
01178 fmtobj = GETARG(void*);
01179 sz = formatter_format(fmtobj, str, strsz);
01180
01181 if (sz < strsz) {
01182 str += sz;
01183 strsz -= sz;
01184 } else {
01185 str += strsz;
01186 strsz = 0;
01187 }
01188 ret += sz;
01189 continue;
01190 }
01191
01192
01193
01194
01195
01196
01197
01198 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
01199 base = 16;
01200 xdigs = xdigs_lower;
01201 flags = flags | INTMAXT;
01202 ox[1] = 'x';
01203 goto nosign;
01204 case 'S':
01205 flags |= LONGINT;
01206
01207 case 's':
01208 if (flags & LONGINT) {
01209 wchar_t *wcp;
01210
01211 if (convbuf != NULL)
01212 free(convbuf);
01213 if ((wcp = GETARG(wchar_t *)) == NULL)
01214 cp = "(null)";
01215 else {
01216 convbuf = __wcsconv(wcp, prec);
01217 if (convbuf == NULL) {
01218 #ifndef __FORMATTER__
01219 fp->_flags |= __SERR;
01220 #endif
01221 goto error;
01222 }
01223 cp = convbuf;
01224 }
01225 } else if ((cp = GETARG(char *)) == NULL)
01226 cp = "(null)";
01227 if (prec >= 0) {
01228
01229
01230
01231
01232
01233 char *p = memchr(cp, 0, (size_t)prec);
01234
01235 if (p != NULL) {
01236 size = p - cp;
01237 if (size > prec)
01238 size = prec;
01239 } else
01240 size = prec;
01241 } else
01242 size = strlen(cp);
01243 sign = '\0';
01244 break;
01245 case 'U':
01246 flags |= LONGINT;
01247
01248 case 'u':
01249 if (flags & INTMAX_SIZE)
01250 ujval = UJARG();
01251 else
01252 ulval = UARG();
01253 base = 10;
01254 goto nosign;
01255 case 'X':
01256 xdigs = xdigs_upper;
01257 goto hex;
01258 case 'x':
01259 xdigs = xdigs_lower;
01260 hex:
01261 if (flags & INTMAX_SIZE)
01262 ujval = UJARG();
01263 else
01264 ulval = UARG();
01265 base = 16;
01266
01267 if (flags & ALT &&
01268 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
01269 ox[1] = ch;
01270
01271 flags &= ~GROUPING;
01272
01273 nosign: sign = '\0';
01274
01275
01276
01277
01278
01279 number: if ((dprec = prec) >= 0)
01280 flags &= ~ZEROPAD;
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 cp = buf + BUF;
01292 if (flags & INTMAX_SIZE) {
01293 if (ujval != 0 || prec != 0 ||
01294 (flags & ALT && base == 8))
01295 cp = __ujtoa(ujval, cp, base,
01296 flags & ALT, xdigs,
01297 flags & GROUPING, thousands_sep,
01298 grouping);
01299 } else {
01300 if (ulval != 0 || prec != 0 ||
01301 (flags & ALT && base == 8))
01302 cp = __ultoa(ulval, cp, base,
01303 flags & ALT, xdigs,
01304 flags & GROUPING, thousands_sep,
01305 grouping);
01306 }
01307 size = buf + BUF - cp;
01308 if (size > BUF)
01309 abort();
01310 break;
01311 default:
01312 if (ch == '\0')
01313 goto done;
01314
01315 cp = buf;
01316 *cp = ch;
01317 size = 1;
01318 sign = '\0';
01319 break;
01320 }
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 realsz = dprec > size ? dprec : size;
01337 if (sign)
01338 realsz++;
01339 if (ox[1])
01340 realsz += 2;
01341
01342 prsize = width > realsz ? width : realsz;
01343 if ((unsigned)ret + prsize > INT_MAX) {
01344 ret = EOF;
01345 goto error;
01346 }
01347
01348
01349 if ((flags & (LADJUST|ZEROPAD)) == 0)
01350 PAD(width - realsz, blanks);
01351
01352
01353 if (sign)
01354 PRINT(&sign, 1);
01355
01356 if (ox[1]) {
01357 ox[0] = '0';
01358 PRINT(ox, 2);
01359 }
01360
01361
01362 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
01363 PAD(width - realsz, zeroes);
01364
01365
01366 PAD(dprec - size, zeroes);
01367
01368
01369 #ifndef NO_FLOATING_POINT
01370 if ((flags & FPT) == 0) {
01371 PRINT(cp, size);
01372 } else {
01373 if (!expchar) {
01374 if (expt <= 0) {
01375 PRINT(zeroes, 1);
01376 if (prec || flags & ALT)
01377 PRINT(decimal_point, 1);
01378 PAD(-expt, zeroes);
01379
01380 prec += expt;
01381 } else {
01382 PRINTANDPAD(cp, dtoaend, lead, zeroes);
01383 cp += lead;
01384 if (grouping) {
01385 while (nseps>0 || nrepeats>0) {
01386 if (nrepeats > 0)
01387 nrepeats--;
01388 else {
01389 grouping--;
01390 nseps--;
01391 }
01392 PRINT(&thousands_sep,
01393 1);
01394 PRINTANDPAD(cp,dtoaend,
01395 *grouping, zeroes);
01396 cp += *grouping;
01397 }
01398 if (cp > dtoaend)
01399 cp = dtoaend;
01400 }
01401 if (prec || flags & ALT)
01402 PRINT(decimal_point,1);
01403 }
01404 PRINTANDPAD(cp, dtoaend, prec, zeroes);
01405 } else {
01406 if (prec > 1 || flags & ALT) {
01407 buf[0] = *cp++;
01408 buf[1] = *decimal_point;
01409 PRINT(buf, 2);
01410 PRINT(cp, ndig-1);
01411 PAD(prec - ndig, zeroes);
01412 } else
01413 PRINT(cp, 1);
01414 PRINT(expstr, expsize);
01415 }
01416 }
01417 #else
01418 PRINT(cp, size);
01419 #endif
01420
01421 if (flags & LADJUST)
01422 PAD(width - realsz, blanks);
01423
01424
01425 ret += prsize;
01426
01427 FLUSH();
01428 }
01429 done:
01430 FLUSH();
01431 error:
01432 va_end(orgap);
01433 #ifndef NO_FLOATING_POINT
01434 if (dtoaresult != NULL)
01435 freedtoa(dtoaresult);
01436 #endif
01437 if (convbuf != NULL)
01438 free(convbuf);
01439 #ifndef __FORMATTER__
01440 if (__sferror(fp))
01441 ret = EOF;
01442 #endif
01443 if ((argtable != NULL) && (argtable != statargtable))
01444 free (argtable);
01445
01446 #ifdef __FORMATTER__
01447
01448 *str = '\0';
01449 #endif
01450
01451 return (ret);
01452
01453 }
01454
01455
01456
01457
01458 int
01459 snprintf(char *str, size_t strsz, const char *fmt, ...)
01460 {
01461 va_list ap;
01462 int ret;
01463
01464 va_start(ap, fmt);
01465 ret = vsnprintf(str, strsz, fmt, ap);
01466 va_end(ap);
01467
01468 return ret;
01469 }
01470
01471
01472
01473
01474
01475
01476
01477 static void
01478 __find_arguments (const char *fmt0, va_list ap, union arg **argtable)
01479 {
01480 char *fmt;
01481 int ch;
01482 int n, n2;
01483 char *cp;
01484 int flags;
01485 int width;
01486 enum typeid *typetable;
01487 enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
01488 int tablesize;
01489 int tablemax;
01490 int nextarg;
01491
01492
01493
01494
01495 #define ADDTYPE(type) \
01496 ((nextarg >= tablesize) ? \
01497 __grow_type_table(nextarg, &typetable, &tablesize) : (void)0, \
01498 (nextarg > tablemax) ? tablemax = nextarg : 0, \
01499 typetable[nextarg++] = type)
01500
01501 #define ADDSARG() \
01502 ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
01503 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
01504 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
01505 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
01506 ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
01507
01508 #define ADDUARG() \
01509 ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
01510 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
01511 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
01512 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
01513 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
01514
01515
01516
01517
01518 #define ADDASTER() \
01519 n2 = 0; \
01520 cp = fmt; \
01521 while (is_digit(*cp)) { \
01522 n2 = 10 * n2 + to_digit(*cp); \
01523 cp++; \
01524 } \
01525 if (*cp == '$') { \
01526 int hold = nextarg; \
01527 nextarg = n2; \
01528 ADDTYPE (T_INT); \
01529 nextarg = hold; \
01530 fmt = ++cp; \
01531 } else { \
01532 ADDTYPE (T_INT); \
01533 }
01534 fmt = (char *)fmt0;
01535 typetable = stattypetable;
01536 tablesize = STATIC_ARG_TBL_SIZE;
01537 tablemax = 0;
01538 nextarg = 1;
01539 for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
01540 typetable[n] = T_UNUSED;
01541
01542
01543
01544
01545 for (;;) {
01546 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
01547 ;
01548 if (ch == '\0')
01549 goto done;
01550 fmt++;
01551
01552 flags = 0;
01553 width = 0;
01554
01555 rflag: ch = *fmt++;
01556 reswitch: switch (ch) {
01557 case ' ':
01558 case '#':
01559 goto rflag;
01560 case '*':
01561 ADDASTER ();
01562 goto rflag;
01563 case '-':
01564 case '+':
01565 case '\'':
01566 goto rflag;
01567 case '.':
01568 if ((ch = *fmt++) == '*') {
01569 ADDASTER ();
01570 goto rflag;
01571 }
01572 while (is_digit(ch)) {
01573 ch = *fmt++;
01574 }
01575 goto reswitch;
01576 case '0':
01577 goto rflag;
01578 case '1': case '2': case '3': case '4':
01579 case '5': case '6': case '7': case '8': case '9':
01580 n = 0;
01581 do {
01582 n = 10 * n + to_digit(ch);
01583 ch = *fmt++;
01584 } while (is_digit(ch));
01585 if (ch == '$') {
01586 nextarg = n;
01587 goto rflag;
01588 }
01589 width = n;
01590 goto reswitch;
01591 #ifndef NO_FLOATING_POINT
01592 case 'L':
01593 flags |= LONGDBL;
01594 goto rflag;
01595 #endif
01596 case 'h':
01597 if (flags & SHORTINT) {
01598 flags &= ~SHORTINT;
01599 flags |= CHARINT;
01600 } else
01601 flags |= SHORTINT;
01602 goto rflag;
01603 case 'j':
01604 flags |= INTMAXT;
01605 goto rflag;
01606 case 'l':
01607 if (flags & LONGINT) {
01608 flags &= ~LONGINT;
01609 flags |= LLONGINT;
01610 } else
01611 flags |= LONGINT;
01612 goto rflag;
01613 case 'q':
01614 flags |= LLONGINT;
01615 goto rflag;
01616 case 't':
01617 flags |= PTRDIFFT;
01618 goto rflag;
01619 case 'z':
01620 flags |= SIZET;
01621 goto rflag;
01622 case 'C':
01623 flags |= LONGINT;
01624
01625 case 'c':
01626 if (flags & LONGINT)
01627 ADDTYPE(T_WINT);
01628 else
01629 ADDTYPE(T_INT);
01630 break;
01631 case 'D':
01632 flags |= LONGINT;
01633
01634 case 'd':
01635 case 'i':
01636 ADDSARG();
01637 break;
01638 #ifndef NO_FLOATING_POINT
01639 case 'a':
01640 case 'A':
01641 case 'e':
01642 case 'E':
01643 case 'f':
01644 case 'g':
01645 case 'G':
01646 if (flags & LONGDBL)
01647 ADDTYPE(T_LONG_DOUBLE);
01648 else
01649 ADDTYPE(T_DOUBLE);
01650 break;
01651 #endif
01652 case 'n':
01653 if (flags & INTMAXT)
01654 ADDTYPE(TP_INTMAXT);
01655 else if (flags & PTRDIFFT)
01656 ADDTYPE(TP_PTRDIFFT);
01657 else if (flags & SIZET)
01658 ADDTYPE(TP_SIZET);
01659 else if (flags & LLONGINT)
01660 ADDTYPE(TP_LLONG);
01661 else if (flags & LONGINT)
01662 ADDTYPE(TP_LONG);
01663 else if (flags & SHORTINT)
01664 ADDTYPE(TP_SHORT);
01665 else if (flags & CHARINT)
01666 ADDTYPE(TP_SCHAR);
01667 else
01668 ADDTYPE(TP_INT);
01669 continue;
01670 case 'O':
01671 flags |= LONGINT;
01672
01673 case 'o':
01674 ADDUARG();
01675 break;
01676 case 'p':
01677 ADDTYPE(TP_VOID);
01678 break;
01679 case 'S':
01680 flags |= LONGINT;
01681
01682 case 's':
01683 if (flags & LONGINT)
01684 ADDTYPE(TP_WCHAR);
01685 else
01686 ADDTYPE(TP_CHAR);
01687 break;
01688 case 'U':
01689 flags |= LONGINT;
01690
01691 case 'u':
01692 case 'X':
01693 case 'x':
01694 ADDUARG();
01695 break;
01696 default:
01697 if (ch == '\0')
01698 goto done;
01699 break;
01700 }
01701 }
01702 done:
01703
01704
01705
01706 if (tablemax >= STATIC_ARG_TBL_SIZE) {
01707 *argtable = (union arg *)
01708 malloc (sizeof (union arg) * (tablemax + 1));
01709 }
01710
01711 (*argtable) [0].intarg = 0;
01712 for (n = 1; n <= tablemax; n++) {
01713 switch (typetable [n]) {
01714 case T_UNUSED:
01715 (*argtable) [n].intarg = va_arg (ap, int);
01716 break;
01717 case TP_SCHAR:
01718 (*argtable) [n].pschararg = va_arg (ap, signed char *);
01719 break;
01720 case TP_SHORT:
01721 (*argtable) [n].pshortarg = va_arg (ap, short *);
01722 break;
01723 case T_INT:
01724 (*argtable) [n].intarg = va_arg (ap, int);
01725 break;
01726 case T_U_INT:
01727 (*argtable) [n].uintarg = va_arg (ap, unsigned int);
01728 break;
01729 case TP_INT:
01730 (*argtable) [n].pintarg = va_arg (ap, int *);
01731 break;
01732 case T_LONG:
01733 (*argtable) [n].longarg = va_arg (ap, long);
01734 break;
01735 case T_U_LONG:
01736 (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
01737 break;
01738 case TP_LONG:
01739 (*argtable) [n].plongarg = va_arg (ap, long *);
01740 break;
01741 case T_LLONG:
01742 (*argtable) [n].longlongarg = va_arg (ap, long long);
01743 break;
01744 case T_U_LLONG:
01745 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
01746 break;
01747 case TP_LLONG:
01748 (*argtable) [n].plonglongarg = va_arg (ap, long long *);
01749 break;
01750 case T_PTRDIFFT:
01751 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
01752 break;
01753 case TP_PTRDIFFT:
01754 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
01755 break;
01756 case T_SIZET:
01757 (*argtable) [n].sizearg = va_arg (ap, size_t);
01758 break;
01759 #ifndef __FORMATTER__
01760 case TP_SIZET:
01761 (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
01762 break;
01763 #endif
01764 case T_INTMAXT:
01765 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
01766 break;
01767 case T_UINTMAXT:
01768 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
01769 break;
01770 case TP_INTMAXT:
01771 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
01772 break;
01773 #ifndef NO_FLOATING_POINT
01774 case T_DOUBLE:
01775 (*argtable) [n].doublearg = va_arg (ap, double);
01776 break;
01777 case T_LONG_DOUBLE:
01778 (*argtable) [n].longdoublearg = va_arg (ap, long double);
01779 break;
01780 #endif
01781 case TP_CHAR:
01782 (*argtable) [n].pchararg = va_arg (ap, char *);
01783 break;
01784 case TP_VOID:
01785 (*argtable) [n].pvoidarg = va_arg (ap, void *);
01786 break;
01787 case T_WINT:
01788 (*argtable) [n].wintarg = va_arg (ap, wint_t);
01789 break;
01790 case TP_WCHAR:
01791 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
01792 break;
01793 }
01794 }
01795
01796 if ((typetable != NULL) && (typetable != stattypetable))
01797 free (typetable);
01798 }
01799
01800
01801
01802
01803 static void
01804 __grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
01805 {
01806 enum typeid *const oldtable = *typetable;
01807 const int oldsize = *tablesize;
01808 enum typeid *newtable;
01809 int n, newsize = oldsize * 2;
01810
01811 if (newsize < nextarg + 1)
01812 newsize = nextarg + 1;
01813 if (oldsize == STATIC_ARG_TBL_SIZE) {
01814 if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
01815 abort();
01816 bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
01817 } else {
01818 newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
01819 if (newtable == NULL)
01820 abort();
01821 }
01822 for (n = oldsize; n < newsize; n++)
01823 newtable[n] = T_UNUSED;
01824
01825 *typetable = newtable;
01826 *tablesize = newsize;
01827 }
01828
01829
01830 #ifndef NO_FLOATING_POINT
01831
01832 static int
01833 exponent(char *p0, int exp, int fmtch)
01834 {
01835 char *p, *t;
01836 char expbuf[MAXEXPDIG];
01837
01838 p = p0;
01839 *p++ = fmtch;
01840 if (exp < 0) {
01841 exp = -exp;
01842 *p++ = '-';
01843 }
01844 else
01845 *p++ = '+';
01846 t = expbuf + MAXEXPDIG;
01847 if (exp > 9) {
01848 do {
01849 *--t = to_char(exp % 10);
01850 } while ((exp /= 10) > 9);
01851 *--t = to_char(exp);
01852 for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
01853 }
01854 else {
01855
01856
01857
01858
01859
01860
01861 if (fmtch == 'e' || fmtch == 'E')
01862 *p++ = '0';
01863 *p++ = to_char(exp);
01864 }
01865 return (p - p0);
01866 }
01867 #endif