1: 2:
3:
4:
5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36: #define FLOATING_POINT
37: 38: 39: 40: 41:
42:
43: #include <sys/types.h>
44: #include <sys/mman.h>
45:
46: #include <errno.h>
47: #include <limits.h>
48: #include <stdarg.h>
49: #include <stddef.h>
50: #include <stdio.h>
51: #include <stdint.h>
52: #include <stdlib.h>
53: #include <string.h>
54: #include <unistd.h>
55: #include <wchar.h>
56:
57: #include "local.h"
58: #include "fvwrite.h"
59:
60: union arg {
61: int intarg;
62: unsigned int uintarg;
63: long longarg;
64: unsigned long ulongarg;
65: long long longlongarg;
66: unsigned long long ulonglongarg;
67: ptrdiff_t ptrdiffarg;
68: size_t sizearg;
69: ssize_t ssizearg;
70: intmax_t intmaxarg;
71: uintmax_t uintmaxarg;
72: void *pvoidarg;
73: char *pchararg;
74: signed char *pschararg;
75: short *pshortarg;
76: int *pintarg;
77: long *plongarg;
78: long long *plonglongarg;
79: ptrdiff_t *pptrdiffarg;
80: ssize_t *pssizearg;
81: intmax_t *pintmaxarg;
82: #ifdef FLOATING_POINT
83: double doublearg;
84: long double longdoublearg;
85: #endif
86: #ifdef PRINTF_WIDE_CHAR
87: wint_t wintarg;
88: wchar_t *pwchararg;
89: #endif
90: };
91:
92: static int __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
93: size_t *argtablesiz);
94: static int __grow_type_table(unsigned char **typetable, int *tablesize);
95:
96: 97: 98: 99:
100: static int
101: __sprint(FILE *fp, struct __suio *uio)
102: {
103: int err;
104:
105: if (uio->uio_resid == 0) {
106: uio->uio_iovcnt = 0;
107: return (0);
108: }
109: err = __sfvwrite(fp, uio);
110: uio->uio_resid = 0;
111: uio->uio_iovcnt = 0;
112: return (err);
113: }
114:
115: 116: 117: 118: 119:
120: static int
121: __sbprintf(FILE *fp, const char *fmt, va_list ap)
122: {
123: int ret;
124: FILE fake;
125: struct __sfileext fakeext;
126: unsigned char buf[128];
127:
128: _FILEEXT_SETUP(&fake, &fakeext);
129:
130: fake._flags = fp->_flags & ~__SNBF;
131: fake._file = fp->_file;
132: fake._cookie = fp->_cookie;
133: fake._write = fp->_write;
134:
135:
136: fake._bf._base = fake._p = buf;
137: fake._bf._size = fake._w = sizeof(buf);
138: fake._lbfsize = 0;
139:
140:
141: ret = __vfprintf(&fake, fmt, ap);
142: if (ret >= 0 && __sflush(&fake))
143: ret = EOF;
144: if (fake._flags & __SERR)
145: fp->_flags |= __SERR;
146: return (ret);
147: }
148:
149: #ifdef PRINTF_WIDE_CHAR
150: 151: 152: 153: 154: 155:
156: static char *
157: __wcsconv(wchar_t *wcsarg, int prec)
158: {
159: mbstate_t mbs;
160: char buf[MB_LEN_MAX];
161: wchar_t *p;
162: char *convbuf;
163: size_t clen, nbytes;
164:
165:
166: if (prec < 0) {
167: memset(&mbs, 0, sizeof(mbs));
168: p = wcsarg;
169: nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
170: if (nbytes == (size_t)-1) {
171: ;
172: return (NULL);
173: }
174: } else {
175: 176: 177: 178: 179:
180: if (prec < 128)
181: nbytes = prec;
182: else {
183: nbytes = 0;
184: p = wcsarg;
185: memset(&mbs, 0, sizeof(mbs));
186: for (;;) {
187: clen = wcrtomb(buf, *p++, &mbs);
188: if (clen == 0 || clen == (size_t)-1 ||
189: nbytes + clen > (size_t)prec)
190: break;
191: nbytes += clen;
192: }
193: if (clen == (size_t)-1) {
194: ;
195: return (NULL);
196: }
197: }
198: }
199: if ((convbuf = malloc(nbytes + 1)) == NULL)
200: return (NULL);
201:
202:
203: p = wcsarg;
204: memset(&mbs, 0, sizeof(mbs));
205: if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
206: nbytes, &mbs)) == (size_t)-1) {
207: free(convbuf);
208: ;
209: return (NULL);
210: }
211: convbuf[nbytes] = '\0';
212: return (convbuf);
213: }
214: #endif
215:
216: #ifdef FLOATING_POINT
217: #include <float.h>
218: #include <locale.h>
219: #include <math.h>
220: #include "floatio.h"
221:
222: #define DEFPREC 6
223:
224: extern char *__dtoa(double, int, int, int *, int *, char **);
225: extern void __freedtoa(char *);
226: static int exponent(char *, int, int);
227: #endif
228:
229: 230: 231: 232: 233: 234: 235:
236: #define BUF 100
237:
238: #define STATIC_ARG_TBL_SIZE 8
239:
240:
241: 242: 243:
244: #define to_digit(c) ((c) - '0')
245: #define is_digit(c) ((unsigned)to_digit(c) <= 9)
246: #define to_char(n) ((n) + '0')
247:
248: 249: 250:
251: #define ALT 0x0001
252: #define LADJUST 0x0004
253: #define LONGDBL 0x0008
254: #define LONGINT 0x0010
255: #define LLONGINT 0x0020
256: #define SHORTINT 0x0040
257: #define ZEROPAD 0x0080
258: #define FPT 0x0100
259: #define PTRINT 0x0200
260: #define SIZEINT 0x0400
261: #define CHARINT 0x0800
262: #define MAXINT 0x1000
263:
264: int
265: vfprintf(FILE *fp, const char *fmt0, __va_list ap)
266: {
267: int ret;
268:
269: FLOCKFILE(fp);
270: ret = __vfprintf(fp, fmt0, ap);
271: FUNLOCKFILE(fp);
272: return (ret);
273: }
274:
275: int
276: __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
277: {
278: char *fmt;
279: int ch;
280: int n, n2;
281: char *cp;
282: struct __siov *iovp;
283: int flags;
284: int ret;
285: int width;
286: int prec;
287: char sign;
288: wchar_t wc;
289: mbstate_t ps;
290: #ifdef FLOATING_POINT
291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304:
305: char *decimal_point = ".";
306: int signflag;
307: union {
308: double dbl;
309: long double ldbl;
310: } fparg;
311: int expt;
312: char expchar;
313: char *dtoaend;
314: int expsize;
315: int lead;
316: int ndig;
317: char expstr[MAXEXPDIG+2];
318: char *dtoaresult = NULL;
319: #endif
320:
321: uintmax_t _umax;
322: enum { OCT, DEC, HEX } base;
323: int dprec;
324: int realsz;
325: int size;
326: const char *xdigs;
327: #define NIOV 8
328: struct __suio uio;
329: struct __siov iov[NIOV];
330: char buf[BUF];
331: char ox[2];
332: union arg *argtable;
333: union arg statargtable[STATIC_ARG_TBL_SIZE];
334: size_t argtablesiz;
335: int nextarg;
336: va_list orgap;
337: #ifdef PRINTF_WIDE_CHAR
338: char *convbuf;
339: #endif
340:
341: 342: 343: 344: 345:
346: #define PADSIZE 16
347: static char blanks[PADSIZE] =
348: {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
349: static char zeroes[PADSIZE] =
350: {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
351:
352: static const char xdigs_lower[16] = "0123456789abcdef";
353: static const char xdigs_upper[16] = "0123456789ABCDEF";
354:
355: 356: 357:
358: #define PRINT(ptr, len) do { \
359: iovp->iov_base = (ptr); \
360: iovp->iov_len = (len); \
361: uio.uio_resid += (len); \
362: iovp++; \
363: if (++uio.uio_iovcnt >= NIOV) { \
364: if (__sprint(fp, &uio)) \
365: goto error; \
366: iovp = iov; \
367: } \
368: } while (0)
369: #define PAD(howmany, with) do { \
370: if ((n = (howmany)) > 0) { \
371: while (n > PADSIZE) { \
372: PRINT(with, PADSIZE); \
373: n -= PADSIZE; \
374: } \
375: PRINT(with, n); \
376: } \
377: } while (0)
378: #define PRINTANDPAD(p, ep, len, with) do { \
379: n2 = (ep) - (p); \
380: if (n2 > (len)) \
381: n2 = (len); \
382: if (n2 > 0) \
383: PRINT((p), n2); \
384: PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
385: } while(0)
386: #define FLUSH() do { \
387: if (uio.uio_resid && __sprint(fp, &uio)) \
388: goto error; \
389: uio.uio_iovcnt = 0; \
390: iovp = iov; \
391: } while (0)
392:
393: 394: 395: 396:
397: #define SARG() \
398: ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
399: flags&LLONGINT ? GETARG(long long) : \
400: flags&LONGINT ? GETARG(long) : \
401: flags&PTRINT ? GETARG(ptrdiff_t) : \
402: flags&SIZEINT ? GETARG(ssize_t) : \
403: flags&SHORTINT ? (short)GETARG(int) : \
404: flags&CHARINT ? (__signed char)GETARG(int) : \
405: GETARG(int)))
406: #define UARG() \
407: ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
408: flags&LLONGINT ? GETARG(unsigned long long) : \
409: flags&LONGINT ? GETARG(unsigned long) : \
410: flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : \
411: flags&SIZEINT ? GETARG(size_t) : \
412: flags&SHORTINT ? (unsigned short)GETARG(int) : \
413: flags&CHARINT ? (unsigned char)GETARG(int) : \
414: GETARG(unsigned int)))
415:
416: 417: 418:
419: #define APPEND_DIGIT(val, dig) do { \
420: if ((val) > INT_MAX / 10) \
421: goto overflow; \
422: (val) *= 10; \
423: if ((val) > INT_MAX - to_digit((dig))) \
424: goto overflow; \
425: (val) += to_digit((dig)); \
426: } while (0)
427:
428: 429: 430: 431:
432: #define GETASTER(val) \
433: n2 = 0; \
434: cp = fmt; \
435: while (is_digit(*cp)) { \
436: APPEND_DIGIT(n2, *cp); \
437: cp++; \
438: } \
439: if (0) { \
440: int hold = nextarg; \
441: if (argtable == NULL) { \
442: argtable = statargtable; \
443: __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
444: } \
445: nextarg = n2; \
446: val = GETARG(int); \
447: nextarg = hold; \
448: fmt = ++cp; \
449: } else { \
450: val = GETARG(int); \
451: }
452:
453: 454: 455: 456: 457:
458: #define GETARG(type) \
459: ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
460: (nextarg++, va_arg(ap, type)))
461:
462: _SET_ORIENTATION(fp, -1);
463:
464: if (cantwrite(fp)) {
465: ;
466: return (EOF);
467: }
468:
469:
470: if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
471: fp->_file >= 0)
472: return (__sbprintf(fp, fmt0, ap));
473:
474: fmt = (char *)fmt0;
475: argtable = NULL;
476: nextarg = 1;
477: va_copy(orgap, ap);
478: uio.uio_iov = iovp = iov;
479: uio.uio_resid = 0;
480: uio.uio_iovcnt = 0;
481: ret = 0;
482: #ifdef PRINTF_WIDE_CHAR
483: convbuf = NULL;
484: #endif
485:
486: memset(&ps, 0, sizeof(ps));
487: 488: 489:
490: for (;;) {
491: cp = fmt;
492: #ifndef _T2EX_NO_MULTIBYTE
493: while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
494: #else
495: while ((n = ((wc = (wchar_t)(unsigned char)*fmt) != '\0') ? 1 : 0) > 0) {
496: #endif
497: fmt += n;
498: if (wc == '%') {
499: fmt--;
500: break;
501: }
502: }
503: if (fmt != cp) {
504: ptrdiff_t m = fmt - cp;
505: if (m < 0 || m > INT_MAX - ret)
506: goto overflow;
507: PRINT(cp, m);
508: ret += m;
509: }
510: if (n <= 0)
511: goto done;
512: fmt++;
513:
514: flags = 0;
515: dprec = 0;
516: width = 0;
517: prec = -1;
518: sign = '\0';
519: ox[1] = '\0';
520:
521: rflag: ch = *fmt++;
522: reswitch: switch (ch) {
523: case ' ':
524: 525: 526: 527: 528:
529: if (!sign)
530: sign = ' ';
531: goto rflag;
532: case '#':
533: flags |= ALT;
534: goto rflag;
535: case '\'':
536:
537: goto rflag;
538: case '*':
539: 540: 541: 542: 543: 544:
545: GETASTER(width);
546: if (width >= 0)
547: goto rflag;
548: if (width == INT_MIN)
549: goto overflow;
550: width = -width;
551:
552: case '-':
553: flags |= LADJUST;
554: goto rflag;
555: case '+':
556: sign = '+';
557: goto rflag;
558: case '.':
559: if ((ch = *fmt++) == '*') {
560: GETASTER(n);
561: prec = n < 0 ? -1 : n;
562: goto rflag;
563: }
564: n = 0;
565: while (is_digit(ch)) {
566: APPEND_DIGIT(n, ch);
567: ch = *fmt++;
568: }
569: if (0) {
570: nextarg = n;
571: if (argtable == NULL) {
572: argtable = statargtable;
573: __find_arguments(fmt0, orgap,
574: &argtable, &argtablesiz);
575: }
576: goto rflag;
577: }
578: prec = n;
579: goto reswitch;
580: case '0':
581: 582: 583: 584: 585:
586: flags |= ZEROPAD;
587: goto rflag;
588: case '1': case '2': case '3': case '4':
589: case '5': case '6': case '7': case '8': case '9':
590: n = 0;
591: do {
592: APPEND_DIGIT(n, ch);
593: ch = *fmt++;
594: } while (is_digit(ch));
595: if (0) {
596: nextarg = n;
597: if (argtable == NULL) {
598: argtable = statargtable;
599: __find_arguments(fmt0, orgap,
600: &argtable, &argtablesiz);
601: }
602: goto rflag;
603: }
604: width = n;
605: goto reswitch;
606: #ifdef FLOATING_POINT
607: case 'L':
608: flags |= LONGDBL;
609: goto rflag;
610: #endif
611: case 'h':
612: if (*fmt == 'h') {
613: fmt++;
614: flags |= CHARINT;
615: } else {
616: flags |= SHORTINT;
617: }
618: goto rflag;
619: case 'j':
620: flags |= MAXINT;
621: goto rflag;
622: case 'l':
623: if (*fmt == 'l') {
624: fmt++;
625: flags |= LLONGINT;
626: } else {
627: flags |= LONGINT;
628: }
629: goto rflag;
630: case 'q':
631: flags |= LLONGINT;
632: goto rflag;
633: case 't':
634: flags |= PTRINT;
635: goto rflag;
636: case 'z':
637: flags |= SIZEINT;
638: goto rflag;
639: case 'c':
640: #ifdef PRINTF_WIDE_CHAR
641: if (flags & LONGINT) {
642: mbstate_t mbs;
643: size_t mbseqlen;
644:
645: memset(&mbs, 0, sizeof(mbs));
646: mbseqlen = wcrtomb(buf,
647: (wchar_t)GETARG(wint_t), &mbs);
648: if (mbseqlen == (size_t)-1) {
649: fp->_flags |= __SERR;
650: ;
651: goto error;
652: }
653: cp = buf;
654: size = (int)mbseqlen;
655: } else {
656: #endif
657: *(cp = buf) = GETARG(int);
658: size = 1;
659: #ifdef PRINTF_WIDE_CHAR
660: }
661: #endif
662: sign = '\0';
663: break;
664: case 'D':
665: flags |= LONGINT;
666:
667: case 'd':
668: case 'i':
669: _umax = SARG();
670: if ((intmax_t)_umax < 0) {
671: _umax = -_umax;
672: sign = '-';
673: }
674: base = DEC;
675: goto number;
676: #ifdef FLOATING_POINT
677: case 'a':
678: case 'A':
679: if (ch == 'a') {
680: ox[1] = 'x';
681: xdigs = xdigs_lower;
682: expchar = 'p';
683: } else {
684: ox[1] = 'X';
685: xdigs = xdigs_upper;
686: expchar = 'P';
687: }
688: if (prec >= 0)
689: prec++;
690: if (dtoaresult)
691: __freedtoa(dtoaresult);
692: if (flags & LONGDBL) {
693: fparg.ldbl = GETARG(long double);
694: dtoaresult = cp =
695: __hldtoa(fparg.ldbl, xdigs, prec,
696: &expt, &signflag, &dtoaend);
697: if (dtoaresult == NULL) {
698: ;
699: goto error;
700: }
701: } else {
702: fparg.dbl = GETARG(double);
703: dtoaresult = cp =
704: __hdtoa(fparg.dbl, xdigs, prec,
705: &expt, &signflag, &dtoaend);
706: if (dtoaresult == NULL) {
707: ;
708: goto error;
709: }
710: }
711: if (prec < 0)
712: prec = dtoaend - cp;
713: if (expt == INT_MAX)
714: ox[1] = '\0';
715: goto fp_common;
716: case 'e':
717: case 'E':
718: expchar = ch;
719: if (prec < 0)
720: prec = DEFPREC + 1;
721: else
722: prec++;
723: goto fp_begin;
724: case 'f':
725: case 'F':
726: expchar = '\0';
727: goto fp_begin;
728: case 'g':
729: case 'G':
730: expchar = ch - ('g' - 'e');
731: if (prec == 0)
732: prec = 1;
733: fp_begin:
734: if (prec < 0)
735: prec = DEFPREC;
736: if (dtoaresult)
737: __freedtoa(dtoaresult);
738: if (flags & LONGDBL) {
739: fparg.ldbl = GETARG(long double);
740: dtoaresult = cp =
741: __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
742: &expt, &signflag, &dtoaend);
743: if (dtoaresult == NULL) {
744: ;
745: goto error;
746: }
747: } else {
748: fparg.dbl = GETARG(double);
749: dtoaresult = cp =
750: __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
751: &expt, &signflag, &dtoaend);
752: if (dtoaresult == NULL) {
753: ;
754: goto error;
755: }
756: if (expt == 9999)
757: expt = INT_MAX;
758: }
759: fp_common:
760: if (signflag)
761: sign = '-';
762: if (expt == INT_MAX) {
763: if (*cp == 'N') {
764: cp = (ch >= 'a') ? "nan" : "NAN";
765: sign = '\0';
766: } else
767: cp = (ch >= 'a') ? "inf" : "INF";
768: size = 3;
769: flags &= ~ZEROPAD;
770: break;
771: }
772: flags |= FPT;
773: ndig = dtoaend - cp;
774: if (ch == 'g' || ch == 'G') {
775: if (expt > -4 && expt <= prec) {
776:
777: expchar = '\0';
778: if (flags & ALT)
779: prec -= expt;
780: else
781: prec = ndig - expt;
782: if (prec < 0)
783: prec = 0;
784: } else {
785: 786: 787: 788:
789: if (!(flags & ALT))
790: prec = ndig;
791: }
792: }
793: if (expchar) {
794: expsize = exponent(expstr, expt - 1, expchar);
795: size = expsize + prec;
796: if (prec > 1 || flags & ALT)
797: ++size;
798: } else {
799:
800: if (expt > 0)
801: size = expt;
802: else
803: size = 1;
804:
805: if (prec || flags & ALT)
806: size += prec + 1;
807: lead = expt;
808: }
809: break;
810: #endif
811: case 'n':
812: if (flags & LLONGINT)
813: *GETARG(long long *) = ret;
814: else if (flags & LONGINT)
815: *GETARG(long *) = ret;
816: else if (flags & SHORTINT)
817: *GETARG(short *) = ret;
818: else if (flags & CHARINT)
819: *GETARG(__signed char *) = ret;
820: else if (flags & PTRINT)
821: *GETARG(ptrdiff_t *) = ret;
822: else if (flags & SIZEINT)
823: *GETARG(ssize_t *) = ret;
824: else if (flags & MAXINT)
825: *GETARG(intmax_t *) = ret;
826: else
827: *GETARG(int *) = ret;
828: continue;
829: case 'O':
830: flags |= LONGINT;
831:
832: case 'o':
833: _umax = UARG();
834: base = OCT;
835: goto nosign;
836: case 'p':
837: 838: 839: 840: 841: 842: 843:
844:
845: _umax = (u_long)GETARG(void *);
846: base = HEX;
847: xdigs = xdigs_lower;
848: ox[1] = 'x';
849: goto nosign;
850: case 's':
851: #ifdef PRINTF_WIDE_CHAR
852: if (flags & LONGINT) {
853: wchar_t *wcp;
854:
855: if (convbuf != NULL) {
856: free(convbuf);
857: convbuf = NULL;
858: }
859: if ((wcp = GETARG(wchar_t *)) == NULL) {
860: cp = "(null)";
861: } else {
862: convbuf = __wcsconv(wcp, prec);
863: if (convbuf == NULL) {
864: fp->_flags = __SERR;
865: goto error;
866: }
867: cp = convbuf;
868: }
869: } else
870: #endif
871: if ((cp = GETARG(char *)) == NULL)
872: cp = "(null)";
873: if (prec >= 0) {
874: 875: 876: 877: 878:
879: char *p = memchr(cp, 0, prec);
880:
881: size = p ? (p - cp) : prec;
882: } else {
883: size_t len;
884:
885: if ((len = strlen(cp)) > INT_MAX)
886: goto overflow;
887: size = (int)len;
888: }
889: sign = '\0';
890: break;
891: case 'U':
892: flags |= LONGINT;
893:
894: case 'u':
895: _umax = UARG();
896: base = DEC;
897: goto nosign;
898: case 'X':
899: xdigs = xdigs_upper;
900: goto hex;
901: case 'x':
902: xdigs = xdigs_lower;
903: hex: _umax = UARG();
904: base = HEX;
905:
906: if (flags & ALT && _umax != 0)
907: ox[1] = ch;
908:
909:
910: nosign: sign = '\0';
911: 912: 913: 914: 915:
916: number: if ((dprec = prec) >= 0)
917: flags &= ~ZEROPAD;
918:
919: 920: 921: 922: 923:
924: cp = buf + BUF;
925: if (_umax != 0 || prec != 0) {
926: 927: 928: 929: 930:
931: switch (base) {
932: case OCT:
933: do {
934: *--cp = to_char(_umax & 7);
935: _umax >>= 3;
936: } while (_umax);
937:
938: if (flags & ALT && *cp != '0')
939: *--cp = '0';
940: break;
941:
942: case DEC:
943:
944: while (_umax >= 10) {
945: *--cp = to_char(_umax % 10);
946: _umax /= 10;
947: }
948: *--cp = to_char(_umax);
949: break;
950:
951: case HEX:
952: do {
953: *--cp = xdigs[_umax & 15];
954: _umax >>= 4;
955: } while (_umax);
956: break;
957:
958: default:
959: cp = "bug in vfprintf: bad base";
960: size = strlen(cp);
961: goto skipsize;
962: }
963: }
964: size = buf + BUF - cp;
965: if (size > BUF)
966: ;
967: skipsize:
968: break;
969: default:
970: if (ch == '\0')
971: goto done;
972:
973: cp = buf;
974: *cp = ch;
975: size = 1;
976: sign = '\0';
977: break;
978: }
979:
980: 981: 982: 983: 984: 985: 986: 987: 988: 989: 990: 991: 992: 993:
994: realsz = dprec > size ? dprec : size;
995: if (sign)
996: realsz++;
997: if (ox[1])
998: realsz+= 2;
999:
1000:
1001: if ((flags & (LADJUST|ZEROPAD)) == 0)
1002: PAD(width - realsz, blanks);
1003:
1004:
1005: if (sign)
1006: PRINT(&sign, 1);
1007: if (ox[1]) {
1008: ox[0] = '0';
1009: PRINT(ox, 2);
1010: }
1011:
1012:
1013: if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1014: PAD(width - realsz, zeroes);
1015:
1016:
1017: PAD(dprec - size, zeroes);
1018:
1019:
1020: #ifdef FLOATING_POINT
1021: if ((flags & FPT) == 0) {
1022: PRINT(cp, size);
1023: } else {
1024: if (!expchar) {
1025: if (expt <= 0) {
1026: PRINT(zeroes, 1);
1027: if (prec || flags & ALT)
1028: PRINT(decimal_point, 1);
1029: PAD(-expt, zeroes);
1030:
1031: prec += expt;
1032: } else {
1033: PRINTANDPAD(cp, dtoaend, lead, zeroes);
1034: cp += lead;
1035: if (prec || flags & ALT)
1036: PRINT(decimal_point, 1);
1037: }
1038: PRINTANDPAD(cp, dtoaend, prec, zeroes);
1039: } else {
1040: if (prec > 1 || flags & ALT) {
1041: buf[0] = *cp++;
1042: buf[1] = *decimal_point;
1043: PRINT(buf, 2);
1044: PRINT(cp, ndig-1);
1045: PAD(prec - ndig, zeroes);
1046: } else {
1047: PRINT(cp, 1);
1048: }
1049: PRINT(expstr, expsize);
1050: }
1051: }
1052: #else
1053: PRINT(cp, size);
1054: #endif
1055:
1056: if (flags & LADJUST)
1057: PAD(width - realsz, blanks);
1058:
1059:
1060: if (width < realsz)
1061: width = realsz;
1062: if (width > INT_MAX - ret)
1063: goto overflow;
1064: ret += width;
1065:
1066: FLUSH();
1067: }
1068: done:
1069: FLUSH();
1070: error:
1071: va_end(orgap);
1072: if (__sferror(fp))
1073: ret = -1;
1074: goto finish;
1075:
1076: overflow:
1077: ;
1078: ret = -1;
1079:
1080: finish:
1081: #ifdef PRINTF_WIDE_CHAR
1082: if (convbuf)
1083: free(convbuf);
1084: #endif
1085: #ifdef FLOATING_POINT
1086: if (dtoaresult)
1087: __freedtoa(dtoaresult);
1088: #endif
1089: if (argtable != NULL && argtable != statargtable) {
1090: ;
1091: argtable = NULL;
1092: }
1093: return (ret);
1094: }
1095:
1096: 1097: 1098:
1099: #define T_UNUSED 0
1100: #define T_SHORT 1
1101: #define T_U_SHORT 2
1102: #define TP_SHORT 3
1103: #define T_INT 4
1104: #define T_U_INT 5
1105: #define TP_INT 6
1106: #define T_LONG 7
1107: #define T_U_LONG 8
1108: #define TP_LONG 9
1109: #define T_LLONG 10
1110: #define T_U_LLONG 11
1111: #define TP_LLONG 12
1112: #define T_DOUBLE 13
1113: #define T_LONG_DOUBLE 14
1114: #define TP_CHAR 15
1115: #define TP_VOID 16
1116: #define T_PTRINT 17
1117: #define TP_PTRINT 18
1118: #define T_SIZEINT 19
1119: #define T_SSIZEINT 20
1120: #define TP_SSIZEINT 21
1121: #define T_MAXINT 22
1122: #define T_MAXUINT 23
1123: #define TP_MAXINT 24
1124: #define T_CHAR 25
1125: #define T_U_CHAR 26
1126: #define T_WINT 27
1127: #define TP_WCHAR 28
1128:
1129: 1130: 1131: 1132: 1133: 1134: 1135: 1136:
1137: static int
1138: __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
1139: size_t *argtablesiz)
1140: {
1141: char *fmt;
1142: int ch;
1143: int n, n2;
1144: char *cp;
1145: int flags;
1146: unsigned char *typetable;
1147: unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
1148: int tablesize;
1149: int tablemax;
1150: int nextarg;
1151: int ret = 0;
1152: wchar_t wc;
1153: mbstate_t ps;
1154:
1155: 1156: 1157:
1158: #define ADDTYPE(type) \
1159: ((nextarg >= tablesize) ? \
1160: __grow_type_table(&typetable, &tablesize) : 0, \
1161: (nextarg > tablemax) ? tablemax = nextarg : 0, \
1162: typetable[nextarg++] = type)
1163:
1164: #define ADDSARG() \
1165: ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
1166: ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1167: ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
1168: ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1169: ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
1170: ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
1171: ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
1172:
1173: #define ADDUARG() \
1174: ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
1175: ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1176: ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
1177: ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1178: ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
1179: ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
1180: ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
1181:
1182: 1183: 1184:
1185: #define ADDASTER() \
1186: n2 = 0; \
1187: cp = fmt; \
1188: while (is_digit(*cp)) { \
1189: APPEND_DIGIT(n2, *cp); \
1190: cp++; \
1191: } \
1192: if (0) { \
1193: int hold = nextarg; \
1194: nextarg = n2; \
1195: ADDTYPE(T_INT); \
1196: nextarg = hold; \
1197: fmt = ++cp; \
1198: } else { \
1199: ADDTYPE(T_INT); \
1200: }
1201: fmt = (char *)fmt0;
1202: typetable = stattypetable;
1203: tablesize = STATIC_ARG_TBL_SIZE;
1204: tablemax = 0;
1205: nextarg = 1;
1206: memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
1207: memset(&ps, 0, sizeof(ps));
1208:
1209: 1210: 1211:
1212: for (;;) {
1213: cp = fmt;
1214: #ifndef _T2EX_NO_MULTIBYTE
1215: while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
1216: #else
1217: while ((n = ((wc = (wchar_t)(unsigned char)*fmt) != '\0') ? 1 : 0) > 0) {
1218: #endif
1219: fmt += n;
1220: if (wc == '%') {
1221: fmt--;
1222: break;
1223: }
1224: }
1225: if (n <= 0)
1226: goto done;
1227: fmt++;
1228:
1229: flags = 0;
1230:
1231: rflag: ch = *fmt++;
1232: reswitch: switch (ch) {
1233: case ' ':
1234: case '#':
1235: case '\'':
1236: goto rflag;
1237: case '*':
1238: ADDASTER();
1239: goto rflag;
1240: case '-':
1241: case '+':
1242: goto rflag;
1243: case '.':
1244: if ((ch = *fmt++) == '*') {
1245: ADDASTER();
1246: goto rflag;
1247: }
1248: while (is_digit(ch)) {
1249: ch = *fmt++;
1250: }
1251: goto reswitch;
1252: case '0':
1253: goto rflag;
1254: case '1': case '2': case '3': case '4':
1255: case '5': case '6': case '7': case '8': case '9':
1256: n = 0;
1257: do {
1258: APPEND_DIGIT(n ,ch);
1259: ch = *fmt++;
1260: } while (is_digit(ch));
1261: if (0) {
1262: nextarg = n;
1263: goto rflag;
1264: }
1265: goto reswitch;
1266: #ifdef FLOATING_POINT
1267: case 'L':
1268: flags |= LONGDBL;
1269: goto rflag;
1270: #endif
1271: case 'h':
1272: if (*fmt == 'h') {
1273: fmt++;
1274: flags |= CHARINT;
1275: } else {
1276: flags |= SHORTINT;
1277: }
1278: goto rflag;
1279: case 'l':
1280: if (*fmt == 'l') {
1281: fmt++;
1282: flags |= LLONGINT;
1283: } else {
1284: flags |= LONGINT;
1285: }
1286: goto rflag;
1287: case 'q':
1288: flags |= LLONGINT;
1289: goto rflag;
1290: case 't':
1291: flags |= PTRINT;
1292: goto rflag;
1293: case 'z':
1294: flags |= SIZEINT;
1295: goto rflag;
1296: case 'c':
1297: #ifdef PRINTF_WIDE_CHAR
1298: if (flags & LONGINT)
1299: ADDTYPE(T_WINT);
1300: else
1301: #endif
1302: ADDTYPE(T_INT);
1303: break;
1304: case 'D':
1305: flags |= LONGINT;
1306:
1307: case 'd':
1308: case 'i':
1309: ADDSARG();
1310: break;
1311: #ifdef FLOATING_POINT
1312: case 'a':
1313: case 'A':
1314: case 'e':
1315: case 'E':
1316: case 'f':
1317: case 'F':
1318: case 'g':
1319: case 'G':
1320: if (flags & LONGDBL)
1321: ADDTYPE(T_LONG_DOUBLE);
1322: else
1323: ADDTYPE(T_DOUBLE);
1324: break;
1325: #endif
1326: case 'n':
1327: if (flags & LLONGINT)
1328: ADDTYPE(TP_LLONG);
1329: else if (flags & LONGINT)
1330: ADDTYPE(TP_LONG);
1331: else if (flags & SHORTINT)
1332: ADDTYPE(TP_SHORT);
1333: else if (flags & PTRINT)
1334: ADDTYPE(TP_PTRINT);
1335: else if (flags & SIZEINT)
1336: ADDTYPE(TP_SSIZEINT);
1337: else if (flags & MAXINT)
1338: ADDTYPE(TP_MAXINT);
1339: else
1340: ADDTYPE(TP_INT);
1341: continue;
1342: case 'O':
1343: flags |= LONGINT;
1344:
1345: case 'o':
1346: ADDUARG();
1347: break;
1348: case 'p':
1349: ADDTYPE(TP_VOID);
1350: break;
1351: case 's':
1352: #ifdef PRINTF_WIDE_CHAR
1353: if (flags & LONGINT)
1354: ADDTYPE(TP_WCHAR);
1355: else
1356: #endif
1357: ADDTYPE(TP_CHAR);
1358: break;
1359: case 'U':
1360: flags |= LONGINT;
1361:
1362: case 'u':
1363: case 'X':
1364: case 'x':
1365: ADDUARG();
1366: break;
1367: default:
1368: if (ch == '\0')
1369: goto done;
1370: break;
1371: }
1372: }
1373: done:
1374: 1375: 1376:
1377: if (tablemax >= STATIC_ARG_TBL_SIZE) {
1378: *argtablesiz = sizeof(union arg) * (tablemax + 1);
1379: *argtable = 1380: MAP_FAILED;
1381: if (*argtable == MAP_FAILED)
1382: return (-1);
1383: }
1384:
1385: #if 0
1386:
1387: (*argtable)[0].intarg = 0;
1388: #endif
1389: for (n = 1; n <= tablemax; n++) {
1390: switch (typetable[n]) {
1391: case T_UNUSED:
1392: case T_CHAR:
1393: case T_U_CHAR:
1394: case T_SHORT:
1395: case T_U_SHORT:
1396: case T_INT:
1397: (*argtable)[n].intarg = va_arg(ap, int);
1398: break;
1399: case TP_SHORT:
1400: (*argtable)[n].pshortarg = va_arg(ap, short *);
1401: break;
1402: case T_U_INT:
1403: (*argtable)[n].uintarg = va_arg(ap, unsigned int);
1404: break;
1405: case TP_INT:
1406: (*argtable)[n].pintarg = va_arg(ap, int *);
1407: break;
1408: case T_LONG:
1409: (*argtable)[n].longarg = va_arg(ap, long);
1410: break;
1411: case T_U_LONG:
1412: (*argtable)[n].ulongarg = va_arg(ap, unsigned long);
1413: break;
1414: case TP_LONG:
1415: (*argtable)[n].plongarg = va_arg(ap, long *);
1416: break;
1417: case T_LLONG:
1418: (*argtable)[n].longlongarg = va_arg(ap, long long);
1419: break;
1420: case T_U_LLONG:
1421: (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
1422: break;
1423: case TP_LLONG:
1424: (*argtable)[n].plonglongarg = va_arg(ap, long long *);
1425: break;
1426: #ifdef FLOATING_POINT
1427: case T_DOUBLE:
1428: (*argtable)[n].doublearg = va_arg(ap, double);
1429: break;
1430: case T_LONG_DOUBLE:
1431: (*argtable)[n].longdoublearg = va_arg(ap, long double);
1432: break;
1433: #endif
1434: case TP_CHAR:
1435: (*argtable)[n].pchararg = va_arg(ap, char *);
1436: break;
1437: case TP_VOID:
1438: (*argtable)[n].pvoidarg = va_arg(ap, void *);
1439: break;
1440: case T_PTRINT:
1441: (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
1442: break;
1443: case TP_PTRINT:
1444: (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
1445: break;
1446: case T_SIZEINT:
1447: (*argtable)[n].sizearg = va_arg(ap, size_t);
1448: break;
1449: case T_SSIZEINT:
1450: (*argtable)[n].ssizearg = va_arg(ap, ssize_t);
1451: break;
1452: case TP_SSIZEINT:
1453: (*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
1454: break;
1455: case TP_MAXINT:
1456: (*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
1457: break;
1458: #ifdef PRINTF_WIDE_CHAR
1459: case T_WINT:
1460: (*argtable)[n].wintarg = va_arg(ap, wint_t);
1461: break;
1462: case TP_WCHAR:
1463: (*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
1464: break;
1465: #endif
1466: }
1467: }
1468: goto finish;
1469:
1470: overflow:
1471: ;
1472: ret = -1;
1473:
1474: finish:
1475: if (typetable != NULL && typetable != stattypetable) {
1476: ;
1477: typetable = NULL;
1478: }
1479: return (ret);
1480: }
1481:
1482: 1483: 1484:
1485: static int
1486: __grow_type_table(unsigned char **typetable, int *tablesize)
1487: {
1488: unsigned char *oldtable = *typetable;
1489: int newsize = *tablesize * 2;
1490:
1491: if (newsize < 4096)
1492: newsize = 4096;
1493:
1494: if (*tablesize == STATIC_ARG_TBL_SIZE) {
1495: *typetable = 1496: MAP_FAILED;
1497: if (*typetable == MAP_FAILED)
1498: return (-1);
1499: bcopy(oldtable, *typetable, *tablesize);
1500: } else {
1501: unsigned char *new = 1502: MAP_FAILED;
1503: if (new == MAP_FAILED)
1504: return (-1);
1505: memmove(new, *typetable, *tablesize);
1506: ;
1507: *typetable = new;
1508: }
1509: memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
1510:
1511: *tablesize = newsize;
1512: return (0);
1513: }
1514:
1515:
1516: #ifdef FLOATING_POINT
1517: static int
1518: exponent(char *p0, int exp, int fmtch)
1519: {
1520: char *p, *t;
1521: char expbuf[MAXEXPDIG];
1522:
1523: p = p0;
1524: *p++ = fmtch;
1525: if (exp < 0) {
1526: exp = -exp;
1527: *p++ = '-';
1528: } else
1529: *p++ = '+';
1530: t = expbuf + MAXEXPDIG;
1531: if (exp > 9) {
1532: do {
1533: *--t = to_char(exp % 10);
1534: } while ((exp /= 10) > 9);
1535: *--t = to_char(exp);
1536: for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
1537: ;
1538: } else {
1539: 1540: 1541: 1542: 1543: 1544:
1545: if (fmtch == 'e' || fmtch == 'E')
1546: *p++ = '0';
1547: *p++ = to_char(exp);
1548: }
1549: return (p - p0);
1550: }
1551: #endif