12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517 |
- #include <sys/types.h>
- #include <errno.h>
- #include <limits.h>
- #include <stdarg.h>
- #include <stddef.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <wchar.h>
- #include "local.h"
- #include "fvwrite.h"
- union arg {
- int intarg;
- unsigned int uintarg;
- long longarg;
- unsigned long ulongarg;
- long long longlongarg;
- unsigned long long ulonglongarg;
- ptrdiff_t ptrdiffarg;
- size_t sizearg;
- ssize_t ssizearg;
- intmax_t intmaxarg;
- uintmax_t uintmaxarg;
- void *pvoidarg;
- char *pchararg;
- signed char *pschararg;
- short *pshortarg;
- int *pintarg;
- long *plongarg;
- long long *plonglongarg;
- ptrdiff_t *pptrdiffarg;
- ssize_t *pssizearg;
- intmax_t *pintmaxarg;
- #ifdef FLOATING_POINT
- double doublearg;
- long double longdoublearg;
- #endif
- #ifdef PRINTF_WIDE_CHAR
- wint_t wintarg;
- wchar_t *pwchararg;
- #endif
- };
- static int __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
- size_t *argtablesiz);
- static int __grow_type_table(unsigned char **typetable, int *tablesize);
- static int
- __sprint(FILE *fp, struct __suio *uio)
- {
- int err;
- if (uio->uio_resid == 0) {
- uio->uio_iovcnt = 0;
- return (0);
- }
- err = __sfvwrite(fp, uio);
- uio->uio_resid = 0;
- uio->uio_iovcnt = 0;
- return (err);
- }
- #ifdef PRINTF_WIDE_CHAR
- static char *
- __wcsconv(wchar_t *wcsarg, int prec)
- {
- mbstate_t mbs;
- char buf[MB_LEN_MAX];
- wchar_t *p;
- char *convbuf;
- size_t clen, nbytes;
-
- if (prec < 0) {
- memset(&mbs, 0, sizeof(mbs));
- p = wcsarg;
- nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
- if (nbytes == (size_t)-1) {
- errno = EILSEQ;
- return (NULL);
- }
- } else {
-
- if (prec < 128)
- nbytes = prec;
- else {
- nbytes = 0;
- p = wcsarg;
- memset(&mbs, 0, sizeof(mbs));
- for (;;) {
- clen = wcrtomb(buf, *p++, &mbs);
- if (clen == 0 || clen == (size_t)-1 ||
- nbytes + clen > (size_t)prec)
- break;
- nbytes += clen;
- }
- if (clen == (size_t)-1) {
- errno = EILSEQ;
- return (NULL);
- }
- }
- }
- if ((convbuf = (char *)malloc(nbytes + 1)) == NULL)
- return (NULL);
-
- p = wcsarg;
- memset(&mbs, 0, sizeof(mbs));
- if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
- nbytes, &mbs)) == (size_t)-1) {
- free(convbuf);
- errno = EILSEQ;
- return (NULL);
- }
- convbuf[nbytes] = '\0';
- return (convbuf);
- }
- #endif
- #ifdef FLOATING_POINT
- #include <float.h>
- #include <math.h>
- #include "floatio.h"
- #define DEFPREC 6
- extern char *__dtoa(double, int, int, int *, int *, char **);
- extern void __freedtoa(char *);
- static int exponent(char *, int, int);
- #endif
- #define BUF 100
- #define STATIC_ARG_TBL_SIZE 8
- #define to_digit(c) ((c) - '0')
- #define is_digit(c) ((unsigned)to_digit(c) <= 9)
- #define to_char(n) ((n) + '0')
- #define ALT 0x0001
- #define LADJUST 0x0004
- #define LONGDBL 0x0008
- #define LONGINT 0x0010
- #define LLONGINT 0x0020
- #define SHORTINT 0x0040
- #define ZEROPAD 0x0080
- #define FPT 0x0100
- #define PTRINT 0x0200
- #define SIZEINT 0x0400
- #define CHARINT 0x0800
- #define MAXINT 0x1000
- int
- __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
- {
- char *fmt;
- int ch;
- int n, n2;
- char *cp;
- struct __siov *iovp;
- int flags;
- int ret;
- int width;
- int prec;
- char sign;
- wchar_t wc;
- mbstate_t ps;
- #ifdef FLOATING_POINT
-
- char *decimal_point = ".";
- int signflag;
- union {
- double dbl;
- long double ldbl;
- } fparg;
- int expt;
- char expchar;
- char *dtoaend;
- int expsize;
- int lead;
- int ndig;
- char expstr[MAXEXPDIG+2];
- char *dtoaresult = NULL;
- #endif
- uintmax_t _umax;
- enum { OCT, DEC, HEX } base;
- int dprec;
- int realsz;
- int size;
- const char *xdigs;
- #define NIOV 8
- struct __suio uio;
- struct __siov iov[NIOV];
- char buf[BUF];
- char ox[2];
- union arg *argtable;
- union arg statargtable[STATIC_ARG_TBL_SIZE];
- size_t argtablesiz;
- int nextarg;
- va_list orgap;
- #ifdef PRINTF_WIDE_CHAR
- char *convbuf;
- #endif
-
- #define PADSIZE 16
- static char blanks[PADSIZE] =
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static char zeroes[PADSIZE] =
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
- static const char xdigs_lower[16] = "0123456789abcdef";
- static const char xdigs_upper[16] = "0123456789ABCDEF";
-
- #define PRINT(ptr, len) do { \
- iovp->iov_base = (ptr); \
- iovp->iov_len = (len); \
- uio.uio_resid += (len); \
- iovp++; \
- if (++uio.uio_iovcnt >= NIOV) { \
- if (__sprint(fp, &uio)) \
- goto error; \
- iovp = iov; \
- } \
- } while (0)
- #define PAD(howmany, with) do { \
- if ((n = (howmany)) > 0) { \
- while (n > PADSIZE) { \
- PRINT(with, PADSIZE); \
- n -= PADSIZE; \
- } \
- PRINT(with, n); \
- } \
- } while (0)
- #define PRINTANDPAD(p, ep, len, with) do { \
- n2 = (ep) - (p); \
- if (n2 > (len)) \
- n2 = (len); \
- if (n2 > 0) \
- PRINT((p), n2); \
- PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
- } while(0)
- #define FLUSH() do { \
- if (uio.uio_resid && __sprint(fp, &uio)) \
- goto error; \
- uio.uio_iovcnt = 0; \
- iovp = iov; \
- } while (0)
-
- #define SARG() \
- ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
- flags&LLONGINT ? GETARG(long long) : \
- flags&LONGINT ? GETARG(long) : \
- flags&PTRINT ? GETARG(ptrdiff_t) : \
- flags&SIZEINT ? GETARG(ssize_t) : \
- flags&SHORTINT ? (short)GETARG(int) : \
- flags&CHARINT ? (signed char)GETARG(int) : \
- GETARG(int)))
- #define UARG() \
- ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
- flags&LLONGINT ? GETARG(unsigned long long) : \
- flags&LONGINT ? GETARG(unsigned long) : \
- flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : \
- flags&SIZEINT ? GETARG(size_t) : \
- flags&SHORTINT ? (unsigned short)GETARG(int) : \
- flags&CHARINT ? (unsigned char)GETARG(int) : \
- GETARG(unsigned int)))
-
- #define APPEND_DIGIT(val, dig) do { \
- if ((val) > INT_MAX / 10) \
- goto overflow; \
- (val) *= 10; \
- if ((val) > INT_MAX - to_digit((dig))) \
- goto overflow; \
- (val) += to_digit((dig)); \
- } while (0)
-
- #define GETASTER(val) \
- n2 = 0; \
- cp = fmt; \
- while (is_digit(*cp)) { \
- APPEND_DIGIT(n2, *cp); \
- cp++; \
- } \
- if (*cp == '$') { \
- int hold = nextarg; \
- if (argtable == NULL) { \
- argtable = statargtable; \
- __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
- } \
- nextarg = n2; \
- val = GETARG(int); \
- nextarg = hold; \
- fmt = ++cp; \
- } else { \
- val = GETARG(int); \
- }
- #define GETARG(type) \
- ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
- (nextarg++, va_arg(ap, type)))
- _SET_ORIENTATION(fp, -1);
-
- if (cantwrite(fp)) {
- errno = EBADF;
- return (EOF);
- }
-
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0) {
-
- errno = EBADF;
- return (EOF);
- }
- fmt = (char *)fmt0;
- argtable = NULL;
- nextarg = 1;
- va_copy(orgap, ap);
- uio.uio_iov = iovp = iov;
- uio.uio_resid = 0;
- uio.uio_iovcnt = 0;
- ret = 0;
- #ifdef PRINTF_WIDE_CHAR
- convbuf = NULL;
- #endif
- memset(&ps, 0, sizeof(ps));
-
- for (;;) {
- cp = fmt;
- while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
- fmt += n;
- if (wc == '%') {
- fmt--;
- break;
- }
- }
- if (fmt != cp) {
- ptrdiff_t m = fmt - cp;
- if (m < 0 || m > INT_MAX - ret)
- goto overflow;
- PRINT(cp, m);
- ret += m;
- }
- if (n <= 0)
- goto done;
- fmt++;
- flags = 0;
- dprec = 0;
- width = 0;
- prec = -1;
- sign = '\0';
- ox[1] = '\0';
- rflag: ch = *fmt++;
- reswitch: switch (ch) {
- case ' ':
-
- if (!sign)
- sign = ' ';
- goto rflag;
- case '#':
- flags |= ALT;
- goto rflag;
- case '\'':
-
- goto rflag;
- case '*':
-
- GETASTER(width);
- if (width >= 0)
- goto rflag;
- if (width == INT_MIN)
- goto overflow;
- width = -width;
-
- case '-':
- flags |= LADJUST;
- goto rflag;
- case '+':
- sign = '+';
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- GETASTER(n);
- prec = n < 0 ? -1 : n;
- goto rflag;
- }
- n = 0;
- while (is_digit(ch)) {
- APPEND_DIGIT(n, ch);
- ch = *fmt++;
- }
- if (ch == '$') {
- nextarg = n;
- if (argtable == NULL) {
- argtable = statargtable;
- __find_arguments(fmt0, orgap,
- &argtable, &argtablesiz);
- }
- goto rflag;
- }
- prec = n;
- goto reswitch;
- case '0':
-
- flags |= ZEROPAD;
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- APPEND_DIGIT(n, ch);
- ch = *fmt++;
- } while (is_digit(ch));
- if (ch == '$') {
- nextarg = n;
- if (argtable == NULL) {
- argtable = statargtable;
- __find_arguments(fmt0, orgap,
- &argtable, &argtablesiz);
- }
- goto rflag;
- }
- width = n;
- goto reswitch;
- #ifdef FLOATING_POINT
- case 'L':
- flags |= LONGDBL;
- goto rflag;
- #endif
- case 'h':
- if (*fmt == 'h') {
- fmt++;
- flags |= CHARINT;
- } else {
- flags |= SHORTINT;
- }
- goto rflag;
- case 'j':
- flags |= MAXINT;
- goto rflag;
- case 'l':
- if (*fmt == 'l') {
- fmt++;
- flags |= LLONGINT;
- } else {
- flags |= LONGINT;
- }
- goto rflag;
- case 'q':
- flags |= LLONGINT;
- goto rflag;
- case 't':
- flags |= PTRINT;
- goto rflag;
- case 'z':
- flags |= SIZEINT;
- goto rflag;
- case 'c':
- #ifdef PRINTF_WIDE_CHAR
- if (flags & LONGINT) {
- mbstate_t mbs;
- size_t mbseqlen;
- memset(&mbs, 0, sizeof(mbs));
- mbseqlen = wcrtomb(buf,
- (wchar_t)GETARG(wint_t), &mbs);
- if (mbseqlen == (size_t)-1) {
- fp->_flags |= __SERR;
- errno = EILSEQ;
- goto error;
- }
- cp = buf;
- size = (int)mbseqlen;
- } else {
- #endif
- *(cp = buf) = GETARG(int);
- size = 1;
- #ifdef PRINTF_WIDE_CHAR
- }
- #endif
- sign = '\0';
- break;
- case 'D':
- flags |= LONGINT;
-
- case 'd':
- case 'i':
- _umax = SARG();
- if ((intmax_t)_umax < 0) {
- _umax = -_umax;
- sign = '-';
- }
- base = DEC;
- goto number;
- #ifdef FLOATING_POINT
- case 'a':
- case 'A':
- if (ch == 'a') {
- ox[1] = 'x';
- xdigs = xdigs_lower;
- expchar = 'p';
- } else {
- ox[1] = 'X';
- xdigs = xdigs_upper;
- expchar = 'P';
- }
- if (prec >= 0)
- prec++;
- if (dtoaresult)
- __freedtoa(dtoaresult);
- if (flags & LONGDBL) {
- fparg.ldbl = GETARG(long double);
- dtoaresult = cp =
- __hldtoa(fparg.ldbl, xdigs, prec,
- &expt, &signflag, &dtoaend);
- if (dtoaresult == NULL) {
- errno = ENOMEM;
- goto error;
- }
- } else {
- fparg.dbl = GETARG(double);
- dtoaresult = cp =
- __hdtoa(fparg.dbl, xdigs, prec,
- &expt, &signflag, &dtoaend);
- if (dtoaresult == NULL) {
- errno = ENOMEM;
- goto error;
- }
- }
- if (prec < 0)
- prec = dtoaend - cp;
- if (expt == INT_MAX)
- ox[1] = '\0';
- goto fp_common;
- case 'e':
- case 'E':
- expchar = ch;
- if (prec < 0)
- prec = DEFPREC + 1;
- else
- prec++;
- goto fp_begin;
- case 'f':
- case 'F':
- expchar = '\0';
- goto fp_begin;
- case 'g':
- case 'G':
- expchar = ch - ('g' - 'e');
- if (prec == 0)
- prec = 1;
- fp_begin:
- if (prec < 0)
- prec = DEFPREC;
- if (dtoaresult)
- __freedtoa(dtoaresult);
- if (flags & LONGDBL) {
- fparg.ldbl = GETARG(long double);
- dtoaresult = cp =
- __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
- &expt, &signflag, &dtoaend);
- if (dtoaresult == NULL) {
- errno = ENOMEM;
- goto error;
- }
- } else {
- fparg.dbl = GETARG(double);
- dtoaresult = cp =
- __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
- &expt, &signflag, &dtoaend);
- if (dtoaresult == NULL) {
- errno = ENOMEM;
- goto error;
- }
- if (expt == 9999)
- expt = INT_MAX;
- }
- fp_common:
- if (signflag)
- sign = '-';
- if (expt == INT_MAX) {
- if (*cp == 'N') {
- cp = (ch >= 'a') ? "nan" : "NAN";
- sign = '\0';
- } else
- cp = (ch >= 'a') ? "inf" : "INF";
- size = 3;
- flags &= ~ZEROPAD;
- break;
- }
- flags |= FPT;
- ndig = dtoaend - cp;
- if (ch == 'g' || ch == 'G') {
- if (expt > -4 && expt <= prec) {
-
- expchar = '\0';
- if (flags & ALT)
- prec -= expt;
- else
- prec = ndig - expt;
- if (prec < 0)
- prec = 0;
- } else {
-
- if (!(flags & ALT))
- prec = ndig;
- }
- }
- if (expchar) {
- expsize = exponent(expstr, expt - 1, expchar);
- size = expsize + prec;
- if (prec > 1 || flags & ALT)
- ++size;
- } else {
-
- if (expt > 0)
- size = expt;
- else
- size = 1;
-
- if (prec || flags & ALT)
- size += prec + 1;
- lead = expt;
- }
- break;
- #endif
- case 'n':
- abort();
- #if 0
- if (flags & LLONGINT)
- *GETARG(long long *) = ret;
- else if (flags & LONGINT)
- *GETARG(long *) = ret;
- else if (flags & SHORTINT)
- *GETARG(short *) = ret;
- else if (flags & CHARINT)
- *GETARG(signed char *) = ret;
- else if (flags & PTRINT)
- *GETARG(ptrdiff_t *) = ret;
- else if (flags & SIZEINT)
- *GETARG(ssize_t *) = ret;
- else if (flags & MAXINT)
- *GETARG(intmax_t *) = ret;
- else
- *GETARG(int *) = ret;
- continue;
- #endif
- case 'O':
- flags |= LONGINT;
-
- case 'o':
- _umax = UARG();
- base = OCT;
- goto nosign;
- case 'p':
-
-
- _umax = (size_t)GETARG(void *);
- base = HEX;
- xdigs = xdigs_lower;
- ox[1] = 'x';
- goto nosign;
- case 's':
- #ifdef PRINTF_WIDE_CHAR
- if (flags & LONGINT) {
- wchar_t *wcp;
- if (convbuf != NULL) {
- free(convbuf);
- convbuf = NULL;
- }
- if ((wcp = GETARG(wchar_t *)) == NULL) {
- cp = "(null)";
- } else {
- convbuf = __wcsconv(wcp, prec);
- if (convbuf == NULL) {
- fp->_flags = __SERR;
- goto error;
- }
- cp = convbuf;
- }
- } else
- #endif
- if ((cp = GETARG(char *)) == NULL)
- cp = "(null)";
- if (prec >= 0) {
-
- char *p = (char *)memchr(cp, 0, prec);
- size = p ? (p - cp) : prec;
- } else {
- size_t len;
- if ((len = strlen(cp)) > INT_MAX)
- goto overflow;
- size = (int)len;
- }
- sign = '\0';
- break;
- case 'U':
- flags |= LONGINT;
-
- case 'u':
- _umax = UARG();
- base = DEC;
- goto nosign;
- case 'X':
- xdigs = xdigs_upper;
- goto hex;
- case 'x':
- xdigs = xdigs_lower;
- hex: _umax = UARG();
- base = HEX;
-
- if (flags & ALT && _umax != 0)
- ox[1] = ch;
-
- nosign: sign = '\0';
-
- number: if ((dprec = prec) >= 0)
- flags &= ~ZEROPAD;
-
- cp = buf + BUF;
- if (_umax != 0 || prec != 0) {
-
- switch (base) {
- case OCT:
- do {
- *--cp = to_char(_umax & 7);
- _umax >>= 3;
- } while (_umax);
-
- if (flags & ALT && *cp != '0')
- *--cp = '0';
- break;
- case DEC:
-
- while (_umax >= 10) {
- *--cp = to_char(_umax % 10);
- _umax /= 10;
- }
- *--cp = to_char(_umax);
- break;
- case HEX:
- do {
- *--cp = xdigs[_umax & 15];
- _umax >>= 4;
- } while (_umax);
- break;
- default:
- cp = "bug in vfprintf: bad base";
- size = strlen(cp);
- goto skipsize;
- }
- }
- size = buf + BUF - cp;
- if (size > BUF)
- abort();
- skipsize:
- break;
- default:
- if (ch == '\0')
- goto done;
-
- cp = buf;
- *cp = ch;
- size = 1;
- sign = '\0';
- break;
- }
-
- realsz = dprec > size ? dprec : size;
- if (sign)
- realsz++;
- if (ox[1])
- realsz+= 2;
-
- if ((flags & (LADJUST|ZEROPAD)) == 0)
- PAD(width - realsz, blanks);
-
- if (sign)
- PRINT(&sign, 1);
- if (ox[1]) {
- ox[0] = '0';
- PRINT(ox, 2);
- }
-
- if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
- PAD(width - realsz, zeroes);
-
- PAD(dprec - size, zeroes);
-
- #ifdef FLOATING_POINT
- if ((flags & FPT) == 0) {
- PRINT(cp, size);
- } else {
- if (!expchar) {
- if (expt <= 0) {
- PRINT(zeroes, 1);
- if (prec || flags & ALT)
- PRINT(decimal_point, 1);
- PAD(-expt, zeroes);
-
- prec += expt;
- } else {
- PRINTANDPAD(cp, dtoaend, lead, zeroes);
- cp += lead;
- if (prec || flags & ALT)
- PRINT(decimal_point, 1);
- }
- PRINTANDPAD(cp, dtoaend, prec, zeroes);
- } else {
- if (prec > 1 || flags & ALT) {
- buf[0] = *cp++;
- buf[1] = *decimal_point;
- PRINT(buf, 2);
- PRINT(cp, ndig-1);
- PAD(prec - ndig, zeroes);
- } else {
- PRINT(cp, 1);
- }
- PRINT(expstr, expsize);
- }
- }
- #else
- PRINT(cp, size);
- #endif
-
- if (flags & LADJUST)
- PAD(width - realsz, blanks);
-
- if (width < realsz)
- width = realsz;
- if (width > INT_MAX - ret)
- goto overflow;
- ret += width;
- FLUSH();
- }
- done:
- FLUSH();
- error:
- va_end(orgap);
- if (__sferror(fp))
- ret = -1;
- goto finish;
- overflow:
- errno = ENOMEM;
- ret = -1;
- finish:
- #ifdef PRINTF_WIDE_CHAR
- if (convbuf)
- free(convbuf);
- #endif
- #ifdef FLOATING_POINT
- if (dtoaresult)
- __freedtoa(dtoaresult);
- #endif
- if (argtable != NULL && argtable != statargtable) {
- free(argtable);
- argtable = NULL;
- }
- return (ret);
- }
- #define T_UNUSED 0
- #define T_SHORT 1
- #define T_U_SHORT 2
- #define TP_SHORT 3
- #define T_INT 4
- #define T_U_INT 5
- #define TP_INT 6
- #define T_LONG 7
- #define T_U_LONG 8
- #define TP_LONG 9
- #define T_LLONG 10
- #define T_U_LLONG 11
- #define TP_LLONG 12
- #define T_DOUBLE 13
- #define T_LONG_DOUBLE 14
- #define TP_CHAR 15
- #define TP_VOID 16
- #define T_PTRINT 17
- #define TP_PTRINT 18
- #define T_SIZEINT 19
- #define T_SSIZEINT 20
- #define TP_SSIZEINT 21
- #define T_MAXINT 22
- #define T_MAXUINT 23
- #define TP_MAXINT 24
- #define T_CHAR 25
- #define T_U_CHAR 26
- #define T_WINT 27
- #define TP_WCHAR 28
- static int
- __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
- size_t *argtablesiz)
- {
- char *fmt;
- int ch;
- int n, n2;
- char *cp;
- int flags;
- unsigned char *typetable;
- unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
- int tablesize;
- int tablemax;
- int nextarg;
- int ret = 0;
- int rc = 0;
- wchar_t wc;
- mbstate_t ps;
- #define check_rc(rc) if (rc == -1) goto overflow
-
- #define ADDTYPE(type) \
- ((nextarg >= tablesize) ? \
- rc = __grow_type_table(&typetable, &tablesize) : 0, \
- (nextarg > tablemax) ? tablemax = nextarg : 0, \
- rc == -1 ? 0 : (typetable[nextarg++] = type))
- #define ADDTYPE_CHECK(type) \
- ADDTYPE(type); check_rc(rc)
- #define ADDSARG() \
- ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
- ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
- ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
- ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
- ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT)))))))); \
- check_rc(rc);
- #define ADDUARG() \
- ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
- ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
- ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
- ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
- ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
- ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
- ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT)))))))); \
- check_rc(rc);
-
- #define ADDASTER() \
- n2 = 0; \
- cp = fmt; \
- while (is_digit(*cp)) { \
- APPEND_DIGIT(n2, *cp); \
- cp++; \
- } \
- if (*cp == '$') { \
- int hold = nextarg; \
- nextarg = n2; \
- ADDTYPE_CHECK(T_INT); \
- nextarg = hold; \
- fmt = ++cp; \
- } else { \
- ADDTYPE_CHECK(T_INT); \
- }
- fmt = (char *)fmt0;
- typetable = stattypetable;
- tablesize = STATIC_ARG_TBL_SIZE;
- tablemax = 0;
- nextarg = 1;
- memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
- memset(&ps, 0, sizeof(ps));
-
- for (;;) {
- cp = fmt;
- while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
- fmt += n;
- if (wc == '%') {
- fmt--;
- break;
- }
- }
- if (n <= 0)
- goto done;
- fmt++;
- flags = 0;
- rflag: ch = *fmt++;
- reswitch: switch (ch) {
- case ' ':
- case '#':
- case '\'':
- goto rflag;
- case '*':
- ADDASTER();
- goto rflag;
- case '-':
- case '+':
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- ADDASTER();
- goto rflag;
- }
- while (is_digit(ch)) {
- ch = *fmt++;
- }
- goto reswitch;
- case '0':
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- APPEND_DIGIT(n ,ch);
- ch = *fmt++;
- } while (is_digit(ch));
- if (ch == '$') {
- nextarg = n;
- goto rflag;
- }
- goto reswitch;
- #ifdef FLOATING_POINT
- case 'L':
- flags |= LONGDBL;
- goto rflag;
- #endif
- case 'h':
- if (*fmt == 'h') {
- fmt++;
- flags |= CHARINT;
- } else {
- flags |= SHORTINT;
- }
- goto rflag;
- case 'j':
- flags |= MAXINT;
- goto rflag;
- case 'l':
- if (*fmt == 'l') {
- fmt++;
- flags |= LLONGINT;
- } else {
- flags |= LONGINT;
- }
- goto rflag;
- case 'q':
- flags |= LLONGINT;
- goto rflag;
- case 't':
- flags |= PTRINT;
- goto rflag;
- case 'z':
- flags |= SIZEINT;
- goto rflag;
- case 'c':
- #ifdef PRINTF_WIDE_CHAR
- if (flags & LONGINT)
- ADDTYPE_CHECK(T_WINT);
- else
- #endif
- ADDTYPE_CHECK(T_INT);
- break;
- case 'D':
- flags |= LONGINT;
-
- case 'd':
- case 'i':
- ADDSARG();
- break;
- #ifdef FLOATING_POINT
- case 'a':
- case 'A':
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- if (flags & LONGDBL)
- ADDTYPE_CHECK(T_LONG_DOUBLE);
- else
- ADDTYPE_CHECK(T_DOUBLE);
- break;
- #endif
- case 'n':
- if (flags & LLONGINT)
- ADDTYPE_CHECK(TP_LLONG);
- else if (flags & LONGINT)
- ADDTYPE_CHECK(TP_LONG);
- else if (flags & SHORTINT)
- ADDTYPE_CHECK(TP_SHORT);
- else if (flags & PTRINT)
- ADDTYPE_CHECK(TP_PTRINT);
- else if (flags & SIZEINT)
- ADDTYPE_CHECK(TP_SSIZEINT);
- else if (flags & MAXINT)
- ADDTYPE_CHECK(TP_MAXINT);
- else
- ADDTYPE_CHECK(TP_INT);
- continue;
- case 'O':
- flags |= LONGINT;
-
- case 'o':
- ADDUARG();
- break;
- case 'p':
- ADDTYPE_CHECK(TP_VOID);
- break;
- case 's':
- #ifdef PRINTF_WIDE_CHAR
- if (flags & LONGINT)
- ADDTYPE_CHECK(TP_WCHAR);
- else
- #endif
- ADDTYPE_CHECK(TP_CHAR);
- break;
- case 'U':
- flags |= LONGINT;
-
- case 'u':
- case 'X':
- case 'x':
- ADDUARG();
- break;
- default:
- if (ch == '\0')
- goto done;
- break;
- }
- }
- done:
-
- if (tablemax >= STATIC_ARG_TBL_SIZE) {
- *argtablesiz = sizeof(union arg) * (tablemax + 1);
- *argtable = (union arg *)malloc(*argtablesiz);
- if (*argtable == NULL)
- goto overflow;
- }
- #if 0
-
- (*argtable)[0].intarg = 0;
- #endif
- for (n = 1; n <= tablemax; n++) {
- switch (typetable[n]) {
- case T_UNUSED:
- case T_CHAR:
- case T_U_CHAR:
- case T_SHORT:
- case T_U_SHORT:
- case T_INT:
- (*argtable)[n].intarg = va_arg(ap, int);
- break;
- case TP_SHORT:
- (*argtable)[n].pshortarg = va_arg(ap, short *);
- break;
- case T_U_INT:
- (*argtable)[n].uintarg = va_arg(ap, unsigned int);
- break;
- case TP_INT:
- (*argtable)[n].pintarg = va_arg(ap, int *);
- break;
- case T_LONG:
- (*argtable)[n].longarg = va_arg(ap, long);
- break;
- case T_U_LONG:
- (*argtable)[n].ulongarg = va_arg(ap, unsigned long);
- break;
- case TP_LONG:
- (*argtable)[n].plongarg = va_arg(ap, long *);
- break;
- case T_LLONG:
- (*argtable)[n].longlongarg = va_arg(ap, long long);
- break;
- case T_U_LLONG:
- (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
- break;
- case TP_LLONG:
- (*argtable)[n].plonglongarg = va_arg(ap, long long *);
- break;
- #ifdef FLOATING_POINT
- case T_DOUBLE:
- (*argtable)[n].doublearg = va_arg(ap, double);
- break;
- case T_LONG_DOUBLE:
- (*argtable)[n].longdoublearg = va_arg(ap, long double);
- break;
- #endif
- case TP_CHAR:
- (*argtable)[n].pchararg = va_arg(ap, char *);
- break;
- case TP_VOID:
- (*argtable)[n].pvoidarg = va_arg(ap, void *);
- break;
- case T_PTRINT:
- (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
- break;
- case TP_PTRINT:
- (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
- break;
- case T_SIZEINT:
- (*argtable)[n].sizearg = va_arg(ap, size_t);
- break;
- case T_SSIZEINT:
- (*argtable)[n].ssizearg = va_arg(ap, ssize_t);
- break;
- case TP_SSIZEINT:
- (*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
- break;
- case T_MAXINT:
- (*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
- break;
- case T_MAXUINT:
- (*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t);
- break;
- case TP_MAXINT:
- (*argtable)[n].pintmaxarg = va_arg(ap, intmax_t *);
- break;
- #ifdef PRINTF_WIDE_CHAR
- case T_WINT:
- (*argtable)[n].wintarg = va_arg(ap, wint_t);
- break;
- case TP_WCHAR:
- (*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
- break;
- #endif
- }
- }
- goto finish;
- overflow:
- errno = ENOMEM;
- ret = -1;
- finish:
- if (typetable != NULL && typetable != stattypetable) {
- free(typetable);
- typetable = NULL;
- }
- return (ret);
- }
- static int
- __grow_type_table(unsigned char **typetable, int *tablesize)
- {
- unsigned char *oldtable = *typetable;
- int newsize = *tablesize * 2;
- if (newsize < SE_PAGE_SIZE)
- newsize = SE_PAGE_SIZE;
- if (*tablesize == STATIC_ARG_TBL_SIZE) {
- *typetable = (unsigned char *)malloc(newsize);
- if (*typetable == NULL)
- return (-1);
- memmove(*typetable, oldtable, *tablesize);
- } else {
- unsigned char *new1 = (unsigned char *)malloc(newsize);
- if (new1 == NULL)
- return (-1);
- memmove(new1, *typetable, *tablesize);
- free(*typetable);
- *typetable = new1;
- }
- memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
- *tablesize = newsize;
- return (0);
- }
-
- #ifdef FLOATING_POINT
- static int
- exponent(char *p0, int exp, int fmtch)
- {
- char *p, *t;
- char expbuf[MAXEXPDIG];
- p = p0;
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- } else
- *p++ = '+';
- t = expbuf + MAXEXPDIG;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
- ;
- } else {
-
- if (fmtch == 'e' || fmtch == 'E')
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p - p0);
- }
- #endif
|