vfwprintf.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487
  1. /* $OpenBSD: vfwprintf.c,v 1.8 2013/11/12 07:04:35 deraadt Exp $ */
  2. /*-
  3. * Copyright (c) 1990 The Regents of the University of California.
  4. * All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Chris Torek.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. /*
  34. * Actual wprintf innards.
  35. *
  36. * This code is large and complicated...
  37. */
  38. #include <sys/types.h>
  39. //#include <sys/mman.h>
  40. #include <errno.h>
  41. //#include <langinfo.h>
  42. #include <limits.h>
  43. #include <stdarg.h>
  44. #include <stddef.h>
  45. #include <stdio.h>
  46. #include <stdint.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <unistd.h>
  50. #include "local.h"
  51. #include "fvwrite.h"
  52. union arg {
  53. int intarg;
  54. unsigned int uintarg;
  55. long longarg;
  56. unsigned long ulongarg;
  57. long long longlongarg;
  58. unsigned long long ulonglongarg;
  59. ptrdiff_t ptrdiffarg;
  60. size_t sizearg;
  61. ssize_t ssizearg;
  62. intmax_t intmaxarg;
  63. uintmax_t uintmaxarg;
  64. void *pvoidarg;
  65. char *pchararg;
  66. signed char *pschararg;
  67. short *pshortarg;
  68. int *pintarg;
  69. long *plongarg;
  70. long long *plonglongarg;
  71. ptrdiff_t *pptrdiffarg;
  72. ssize_t *pssizearg;
  73. intmax_t *pintmaxarg;
  74. #ifdef FLOATING_POINT
  75. double doublearg;
  76. long double longdoublearg;
  77. #endif
  78. wint_t wintarg;
  79. wchar_t *pwchararg;
  80. };
  81. static int __find_arguments(const wchar_t *fmt0, va_list ap, union arg **argtable,
  82. size_t *argtablesiz);
  83. static int __grow_type_table(unsigned char **typetable, int *tablesize);
  84. /*
  85. * Like __fputwc_unlock, but handles fake string (__SSTR) files properly.
  86. * File must already be locked.
  87. */
  88. static wint_t
  89. __xfputwc(wchar_t wc, FILE *fp)
  90. {
  91. mbstate_t mbs;
  92. char buf[MB_LEN_MAX];
  93. struct __suio uio;
  94. struct __siov iov;
  95. size_t len;
  96. //if ((fp->_flags & __SSTR) == 0)
  97. // return (__fputwc_unlock(wc, fp));
  98. memset(&mbs, 0x0, sizeof(mbs));
  99. len = wcrtomb(buf, wc, &mbs);
  100. if (len == (size_t)-1) {
  101. fp->_flags |= __SERR;
  102. errno = EILSEQ;
  103. return (WEOF);
  104. }
  105. uio.uio_iov = &iov;
  106. uio.uio_resid = len;
  107. uio.uio_iovcnt = 1;
  108. iov.iov_base = buf;
  109. iov.iov_len = len;
  110. return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF);
  111. }
  112. /*
  113. * Convert a multibyte character string argument for the %s format to a wide
  114. * string representation. ``prec'' specifies the maximum number of bytes
  115. * to output. If ``prec'' is greater than or equal to zero, we can't assume
  116. * that the multibyte character string ends in a null character.
  117. *
  118. * Returns NULL on failure.
  119. * To find out what happened check errno for ENOMEM, EILSEQ and EINVAL.
  120. */
  121. static wchar_t *
  122. __mbsconv(char *mbsarg, int prec)
  123. {
  124. mbstate_t mbs;
  125. wchar_t *convbuf, *wcp;
  126. const char *p;
  127. size_t insize, nchars, nconv;
  128. if (mbsarg == NULL)
  129. return (NULL);
  130. /*
  131. * Supplied argument is a multibyte string; convert it to wide
  132. * characters first.
  133. */
  134. if (prec >= 0) {
  135. /*
  136. * String is not guaranteed to be NUL-terminated. Find the
  137. * number of characters to print.
  138. */
  139. p = mbsarg;
  140. insize = nchars = nconv = 0;
  141. memset(&mbs, 0x0, sizeof(mbs));
  142. while (nchars != (size_t)prec) {
  143. nconv = mbrlen(p, MB_CUR_MAX, &mbs);
  144. if (nconv == (size_t)0 || nconv == (size_t)-1 ||
  145. nconv == (size_t)-2)
  146. break;
  147. p += nconv;
  148. nchars++;
  149. insize += nconv;
  150. }
  151. if (nconv == (size_t)-1 || nconv == (size_t)-2)
  152. return (NULL);
  153. } else
  154. insize = strlen(mbsarg);
  155. /*
  156. * Allocate buffer for the result and perform the conversion,
  157. * converting at most `size' bytes of the input multibyte string to
  158. * wide characters for printing.
  159. */
  160. convbuf = calloc(insize + 1, sizeof(*convbuf));
  161. if (convbuf == NULL)
  162. return (NULL);
  163. wcp = convbuf;
  164. p = mbsarg;
  165. memset(&mbs, 0x0, sizeof(mbs));
  166. nconv = 0;
  167. while (insize != 0) {
  168. nconv = mbrtowc(wcp, p, insize, &mbs);
  169. if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
  170. break;
  171. wcp++;
  172. p += nconv;
  173. insize -= nconv;
  174. }
  175. if (nconv == (size_t)-1 || nconv == (size_t)-2) {
  176. free(convbuf);
  177. return (NULL);
  178. }
  179. *wcp = '\0';
  180. return (convbuf);
  181. }
  182. #ifdef FLOATING_POINT
  183. #include <float.h>
  184. //#include <locale.h>
  185. #include <math.h>
  186. #include "floatio.h"
  187. #include "gdtoa.h"
  188. #define DEFPREC 6
  189. static int exponent(wchar_t *, int, int);
  190. #endif /* FLOATING_POINT */
  191. /*
  192. * The size of the buffer we use as scratch space for integer
  193. * conversions, among other things. Technically, we would need the
  194. * most space for base 10 conversions with thousands' grouping
  195. * characters between each pair of digits. 100 bytes is a
  196. * conservative overestimate even for a 128-bit uintmax_t.
  197. */
  198. #define BUF 100
  199. #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
  200. /*
  201. * Macros for converting digits to letters and vice versa
  202. */
  203. #define to_digit(c) ((c) - '0')
  204. #define is_digit(c) ((unsigned)to_digit(c) <= 9)
  205. #define to_char(n) ((wchar_t)((n) + '0'))
  206. /*
  207. * Flags used during conversion.
  208. */
  209. #define ALT 0x0001 /* alternate form */
  210. #define LADJUST 0x0004 /* left adjustment */
  211. #define LONGDBL 0x0008 /* long double */
  212. #define LONGINT 0x0010 /* long integer */
  213. #define LLONGINT 0x0020 /* long long integer */
  214. #define SHORTINT 0x0040 /* short integer */
  215. #define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */
  216. #define FPT 0x0100 /* Floating point number */
  217. #define PTRINT 0x0200 /* (unsigned) ptrdiff_t */
  218. #define SIZEINT 0x0400 /* (signed) size_t */
  219. #define CHARINT 0x0800 /* 8 bit integer */
  220. #define MAXINT 0x1000 /* largest integer size (intmax_t) */
  221. int
  222. __vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, __va_list ap)
  223. {
  224. wchar_t *fmt; /* format string */
  225. wchar_t ch; /* character from fmt */
  226. int n, n2, n3; /* handy integers (short term usage) */
  227. wchar_t *cp; /* handy char pointer (short term usage) */
  228. int flags; /* flags as above */
  229. int ret; /* return value accumulator */
  230. int width; /* width from format (%8d), or 0 */
  231. int prec; /* precision from format; <0 for N/A */
  232. wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
  233. #ifdef FLOATING_POINT
  234. /*
  235. * We can decompose the printed representation of floating
  236. * point numbers into several parts, some of which may be empty:
  237. *
  238. * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
  239. * A B ---C--- D E F
  240. *
  241. * A: 'sign' holds this value if present; '\0' otherwise
  242. * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
  243. * C: cp points to the string MMMNNN. Leading and trailing
  244. * zeros are not in the string and must be added.
  245. * D: expchar holds this character; '\0' if no exponent, e.g. %f
  246. * F: at least two digits for decimal, at least one digit for hex
  247. */
  248. char *decimal_point = ".";
  249. int signflag; /* true if float is negative */
  250. union { /* floating point arguments %[aAeEfFgG] */
  251. double dbl;
  252. long double ldbl;
  253. } fparg;
  254. int expt; /* integer value of exponent */
  255. char expchar; /* exponent character: [eEpP\0] */
  256. char *dtoaend; /* pointer to end of converted digits */
  257. int expsize; /* character count for expstr */
  258. int lead; /* sig figs before decimal or group sep */
  259. int ndig; /* actual number of digits returned by dtoa */
  260. wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
  261. char *dtoaresult = NULL;
  262. #endif
  263. uintmax_t _umax; /* integer arguments %[diouxX] */
  264. enum { OCT, DEC, HEX } base; /* base for %[diouxX] conversion */
  265. int dprec; /* a copy of prec if %[diouxX], 0 otherwise */
  266. int realsz; /* field size expanded by dprec */
  267. int size; /* size of converted field or string */
  268. const char *xdigs; /* digits for %[xX] conversion */
  269. #define NIOV 8
  270. struct __suio uio; /* output information: summary */
  271. struct __siov iov[NIOV];/* ... and individual io vectors */
  272. wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */
  273. wchar_t ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
  274. union arg *argtable; /* args, built due to positional arg */
  275. union arg statargtable[STATIC_ARG_TBL_SIZE];
  276. size_t argtablesiz;
  277. int nextarg; /* 1-based argument index */
  278. va_list orgap; /* original argument pointer */
  279. wchar_t *convbuf; /* buffer for multibyte to wide conversion */
  280. /*
  281. * Choose PADSIZE to trade efficiency vs. size. If larger printf
  282. * fields occur frequently, increase PADSIZE and make the initialisers
  283. * below longer.
  284. */
  285. #define PADSIZE 16 /* pad chunk size */
  286. static wchar_t blanks[PADSIZE] =
  287. {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
  288. static wchar_t zeroes[PADSIZE] =
  289. {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
  290. static const char xdigs_lower[16] = "0123456789abcdef";
  291. static const char xdigs_upper[16] = "0123456789ABCDEF";
  292. /*
  293. * BEWARE, these `goto error' on error, PRINT uses 'n3',
  294. * PAD uses `n' and 'n3', and PRINTANDPAD uses 'n', 'n2', and 'n3'.
  295. */
  296. #define PRINT(ptr, len) do { \
  297. for (n3 = 0; n3 < (len); n3++) { \
  298. if ((__xfputwc((ptr)[n3], fp)) == WEOF) \
  299. goto error; \
  300. } \
  301. } while (0)
  302. #define PAD(howmany, with) do { \
  303. if ((n = (howmany)) > 0) { \
  304. while (n > PADSIZE) { \
  305. PRINT(with, PADSIZE); \
  306. n -= PADSIZE; \
  307. } \
  308. PRINT(with, n); \
  309. } \
  310. } while (0)
  311. #define PRINTANDPAD(p, ep, len, with) do { \
  312. n2 = (ep) - (p); \
  313. if (n2 > (len)) \
  314. n2 = (len); \
  315. if (n2 > 0) \
  316. PRINT((p), n2); \
  317. PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
  318. } while(0)
  319. /*
  320. * To extend shorts properly, we need both signed and unsigned
  321. * argument extraction methods.
  322. */
  323. #define SARG() \
  324. ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
  325. flags&LLONGINT ? GETARG(long long) : \
  326. flags&LONGINT ? GETARG(long) : \
  327. flags&PTRINT ? GETARG(ptrdiff_t) : \
  328. flags&SIZEINT ? GETARG(ssize_t) : \
  329. flags&SHORTINT ? (short)GETARG(int) : \
  330. flags&CHARINT ? (signed char)GETARG(int) : \
  331. GETARG(int)))
  332. #define UARG() \
  333. ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
  334. flags&LLONGINT ? GETARG(unsigned long long) : \
  335. flags&LONGINT ? GETARG(unsigned long) : \
  336. flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
  337. flags&SIZEINT ? GETARG(size_t) : \
  338. flags&SHORTINT ? (unsigned short)GETARG(int) : \
  339. flags&CHARINT ? (unsigned char)GETARG(int) : \
  340. GETARG(unsigned int)))
  341. /*
  342. * Append a digit to a value and check for overflow.
  343. */
  344. #define APPEND_DIGIT(val, dig) do { \
  345. if ((val) > INT_MAX / 10) \
  346. goto overflow; \
  347. (val) *= 10; \
  348. if ((val) > INT_MAX - to_digit((dig))) \
  349. goto overflow; \
  350. (val) += to_digit((dig)); \
  351. } while (0)
  352. /*
  353. * Get * arguments, including the form *nn$. Preserve the nextarg
  354. * that the argument can be gotten once the type is determined.
  355. */
  356. #define GETASTER(val) \
  357. n2 = 0; \
  358. cp = fmt; \
  359. while (is_digit(*cp)) { \
  360. APPEND_DIGIT(n2, *cp); \
  361. cp++; \
  362. } \
  363. if (*cp == '$') { \
  364. int hold = nextarg; \
  365. if (argtable == NULL) { \
  366. argtable = statargtable; \
  367. __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
  368. } \
  369. nextarg = n2; \
  370. val = GETARG(int); \
  371. nextarg = hold; \
  372. fmt = ++cp; \
  373. } else { \
  374. val = GETARG(int); \
  375. }
  376. /*
  377. * Get the argument indexed by nextarg. If the argument table is
  378. * built, use it to get the argument. If its not, get the next
  379. * argument (and arguments must be gotten sequentially).
  380. */
  381. #define GETARG(type) \
  382. ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
  383. (nextarg++, va_arg(ap, type)))
  384. _SET_ORIENTATION(fp, 1);
  385. /* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
  386. if (cantwrite(fp)) {
  387. errno = EBADF;
  388. return (EOF);
  389. }
  390. /* optimise fwprintf(stderr) (and other unbuffered Unix files) */
  391. if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
  392. fp->_file >= 0) {
  393. //return (__sbprintf(fp, fmt0, ap));
  394. errno = EBADF;
  395. return (EOF);
  396. }
  397. fmt = (wchar_t *)fmt0;
  398. argtable = NULL;
  399. nextarg = 1;
  400. va_copy(orgap, ap);
  401. uio.uio_iov = iov;
  402. uio.uio_resid = 0;
  403. uio.uio_iovcnt = 0;
  404. ret = 0;
  405. convbuf = NULL;
  406. /*
  407. * Scan the format for conversions (`%' character).
  408. */
  409. for (;;) {
  410. for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
  411. continue;
  412. if (fmt != cp) {
  413. ptrdiff_t m = fmt - cp;
  414. if (m < 0 || m > INT_MAX - ret)
  415. goto overflow;
  416. PRINT(cp, m);
  417. ret += m;
  418. }
  419. if (ch == '\0')
  420. goto done;
  421. fmt++; /* skip over '%' */
  422. flags = 0;
  423. dprec = 0;
  424. width = 0;
  425. prec = -1;
  426. sign = '\0';
  427. ox[1] = '\0';
  428. rflag: ch = *fmt++;
  429. reswitch: switch (ch) {
  430. case ' ':
  431. /*
  432. * ``If the space and + flags both appear, the space
  433. * flag will be ignored.''
  434. * -- ANSI X3J11
  435. */
  436. if (!sign)
  437. sign = ' ';
  438. goto rflag;
  439. case '#':
  440. flags |= ALT;
  441. goto rflag;
  442. case '\'':
  443. /* grouping not implemented */
  444. goto rflag;
  445. case '*':
  446. /*
  447. * ``A negative field width argument is taken as a
  448. * - flag followed by a positive field width.''
  449. * -- ANSI X3J11
  450. * They don't exclude field widths read from args.
  451. */
  452. GETASTER(width);
  453. if (width >= 0)
  454. goto rflag;
  455. if (width == INT_MIN)
  456. goto overflow;
  457. width = -width;
  458. /* FALLTHROUGH */
  459. case '-':
  460. flags |= LADJUST;
  461. goto rflag;
  462. case '+':
  463. sign = '+';
  464. goto rflag;
  465. case '.':
  466. if ((ch = *fmt++) == '*') {
  467. GETASTER(n);
  468. prec = n < 0 ? -1 : n;
  469. goto rflag;
  470. }
  471. n = 0;
  472. while (is_digit(ch)) {
  473. APPEND_DIGIT(n, ch);
  474. ch = *fmt++;
  475. }
  476. if (ch == '$') {
  477. nextarg = n;
  478. if (argtable == NULL) {
  479. argtable = statargtable;
  480. __find_arguments(fmt0, orgap,
  481. &argtable, &argtablesiz);
  482. }
  483. goto rflag;
  484. }
  485. prec = n;
  486. goto reswitch;
  487. case '0':
  488. /*
  489. * ``Note that 0 is taken as a flag, not as the
  490. * beginning of a field width.''
  491. * -- ANSI X3J11
  492. */
  493. flags |= ZEROPAD;
  494. goto rflag;
  495. case '1': case '2': case '3': case '4':
  496. case '5': case '6': case '7': case '8': case '9':
  497. n = 0;
  498. do {
  499. APPEND_DIGIT(n, ch);
  500. ch = *fmt++;
  501. } while (is_digit(ch));
  502. if (ch == '$') {
  503. nextarg = n;
  504. if (argtable == NULL) {
  505. argtable = statargtable;
  506. __find_arguments(fmt0, orgap,
  507. &argtable, &argtablesiz);
  508. }
  509. goto rflag;
  510. }
  511. width = n;
  512. goto reswitch;
  513. #ifdef FLOATING_POINT
  514. case 'L':
  515. flags |= LONGDBL;
  516. goto rflag;
  517. #endif
  518. case 'h':
  519. if (*fmt == 'h') {
  520. fmt++;
  521. flags |= CHARINT;
  522. } else {
  523. flags |= SHORTINT;
  524. }
  525. goto rflag;
  526. case 'j':
  527. flags |= MAXINT;
  528. goto rflag;
  529. case 'l':
  530. if (*fmt == 'l') {
  531. fmt++;
  532. flags |= LLONGINT;
  533. } else {
  534. flags |= LONGINT;
  535. }
  536. goto rflag;
  537. case 'q':
  538. flags |= LLONGINT;
  539. goto rflag;
  540. case 't':
  541. flags |= PTRINT;
  542. goto rflag;
  543. case 'z':
  544. flags |= SIZEINT;
  545. goto rflag;
  546. case 'C':
  547. flags |= LONGINT;
  548. /*FALLTHROUGH*/
  549. case 'c':
  550. if (flags & LONGINT)
  551. *(cp = buf) = (wchar_t)GETARG(wint_t);
  552. else
  553. *(cp = buf) = (wchar_t)btowc(GETARG(int));
  554. size = 1;
  555. sign = '\0';
  556. break;
  557. case 'D':
  558. flags |= LONGINT;
  559. /*FALLTHROUGH*/
  560. case 'd':
  561. case 'i':
  562. _umax = SARG();
  563. if ((intmax_t)_umax < 0) {
  564. _umax = -_umax;
  565. sign = '-';
  566. }
  567. base = DEC;
  568. goto number;
  569. #ifdef FLOATING_POINT
  570. case 'a':
  571. case 'A':
  572. if (ch == 'a') {
  573. ox[1] = 'x';
  574. xdigs = xdigs_lower;
  575. expchar = 'p';
  576. } else {
  577. ox[1] = 'X';
  578. xdigs = xdigs_upper;
  579. expchar = 'P';
  580. }
  581. if (prec >= 0)
  582. prec++;
  583. if (dtoaresult)
  584. __freedtoa(dtoaresult);
  585. if (flags & LONGDBL) {
  586. fparg.ldbl = GETARG(long double);
  587. dtoaresult =
  588. __hldtoa(fparg.ldbl, xdigs, prec,
  589. &expt, &signflag, &dtoaend);
  590. if (dtoaresult == NULL) {
  591. errno = ENOMEM;
  592. goto error;
  593. }
  594. } else {
  595. fparg.dbl = GETARG(double);
  596. dtoaresult =
  597. __hdtoa(fparg.dbl, xdigs, prec,
  598. &expt, &signflag, &dtoaend);
  599. if (dtoaresult == NULL) {
  600. errno = ENOMEM;
  601. goto error;
  602. }
  603. }
  604. if (prec < 0)
  605. prec = dtoaend - dtoaresult;
  606. if (expt == INT_MAX)
  607. ox[1] = '\0';
  608. if (convbuf) {
  609. free(convbuf);
  610. convbuf = NULL;
  611. }
  612. cp = convbuf = __mbsconv(dtoaresult, -1);
  613. if (cp == NULL)
  614. goto error;
  615. ndig = dtoaend - dtoaresult;
  616. goto fp_common;
  617. case 'e':
  618. case 'E':
  619. expchar = ch;
  620. if (prec < 0) /* account for digit before decpt */
  621. prec = DEFPREC + 1;
  622. else
  623. prec++;
  624. goto fp_begin;
  625. case 'f':
  626. case 'F':
  627. expchar = '\0';
  628. goto fp_begin;
  629. case 'g':
  630. case 'G':
  631. expchar = ch - ('g' - 'e');
  632. if (prec == 0)
  633. prec = 1;
  634. fp_begin:
  635. if (prec < 0)
  636. prec = DEFPREC;
  637. if (dtoaresult)
  638. __freedtoa(dtoaresult);
  639. if (flags & LONGDBL) {
  640. fparg.ldbl = GETARG(long double);
  641. dtoaresult =
  642. __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
  643. &expt, &signflag, &dtoaend);
  644. if (dtoaresult == NULL) {
  645. errno = ENOMEM;
  646. goto error;
  647. }
  648. } else {
  649. fparg.dbl = GETARG(double);
  650. dtoaresult =
  651. __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
  652. &expt, &signflag, &dtoaend);
  653. if (dtoaresult == NULL) {
  654. errno = ENOMEM;
  655. goto error;
  656. }
  657. if (expt == 9999)
  658. expt = INT_MAX;
  659. }
  660. if (convbuf) {
  661. free(convbuf);
  662. convbuf = NULL;
  663. }
  664. cp = convbuf = __mbsconv(dtoaresult, -1);
  665. if (cp == NULL)
  666. goto error;
  667. ndig = dtoaend - dtoaresult;
  668. fp_common:
  669. if (signflag)
  670. sign = '-';
  671. if (expt == INT_MAX) { /* inf or nan */
  672. if (*cp == 'N') {
  673. cp = (ch >= 'a') ? L"nan" : L"NAN";
  674. sign = '\0';
  675. } else
  676. cp = (ch >= 'a') ? L"inf" : L"INF";
  677. size = 3;
  678. flags &= ~ZEROPAD;
  679. break;
  680. }
  681. flags |= FPT;
  682. if (ch == 'g' || ch == 'G') {
  683. if (expt > -4 && expt <= prec) {
  684. /* Make %[gG] smell like %[fF] */
  685. expchar = '\0';
  686. if (flags & ALT)
  687. prec -= expt;
  688. else
  689. prec = ndig - expt;
  690. if (prec < 0)
  691. prec = 0;
  692. } else {
  693. /*
  694. * Make %[gG] smell like %[eE], but
  695. * trim trailing zeroes if no # flag.
  696. */
  697. if (!(flags & ALT))
  698. prec = ndig;
  699. }
  700. }
  701. if (expchar) {
  702. expsize = exponent(expstr, expt - 1, expchar);
  703. size = expsize + prec;
  704. if (prec > 1 || flags & ALT)
  705. ++size;
  706. } else {
  707. /* space for digits before decimal point */
  708. if (expt > 0)
  709. size = expt;
  710. else /* "0" */
  711. size = 1;
  712. /* space for decimal pt and following digits */
  713. if (prec || flags & ALT)
  714. size += prec + 1;
  715. lead = expt;
  716. }
  717. break;
  718. #endif /* FLOATING_POINT */
  719. case 'n':
  720. abort();
  721. #if 0
  722. if (flags & LLONGINT)
  723. *GETARG(long long *) = ret;
  724. else if (flags & LONGINT)
  725. *GETARG(long *) = ret;
  726. else if (flags & SHORTINT)
  727. *GETARG(short *) = ret;
  728. else if (flags & CHARINT)
  729. *GETARG(signed char *) = ret;
  730. else if (flags & PTRINT)
  731. *GETARG(ptrdiff_t *) = ret;
  732. else if (flags & SIZEINT)
  733. *GETARG(ssize_t *) = ret;
  734. else if (flags & MAXINT)
  735. *GETARG(intmax_t *) = ret;
  736. else
  737. *GETARG(int *) = ret;
  738. continue; /* no output */
  739. #endif
  740. case 'O':
  741. flags |= LONGINT;
  742. /*FALLTHROUGH*/
  743. case 'o':
  744. _umax = UARG();
  745. base = OCT;
  746. goto nosign;
  747. case 'p':
  748. /*
  749. * ``The argument shall be a pointer to void. The
  750. * value of the pointer is converted to a sequence
  751. * of printable characters, in an implementation-
  752. * defined manner.''
  753. * -- ANSI X3J11
  754. */
  755. /* NOSTRICT */
  756. _umax = (size_t)GETARG(void *);
  757. base = HEX;
  758. xdigs = xdigs_lower;
  759. ox[1] = 'x';
  760. goto nosign;
  761. case 'S':
  762. flags |= LONGINT;
  763. /*FALLTHROUGH*/
  764. case 's':
  765. if (flags & LONGINT) {
  766. if ((cp = GETARG(wchar_t *)) == NULL)
  767. cp = L"(null)";
  768. } else {
  769. char *mbsarg;
  770. if ((mbsarg = GETARG(char *)) == NULL)
  771. mbsarg = "(null)";
  772. if (convbuf) {
  773. free(convbuf);
  774. convbuf = NULL;
  775. }
  776. convbuf = __mbsconv(mbsarg, prec);
  777. if (convbuf == NULL) {
  778. fp->_flags |= __SERR;
  779. goto error;
  780. } else
  781. cp = convbuf;
  782. }
  783. if (prec >= 0) {
  784. /*
  785. * can't use wcslen; can only look for the
  786. * NUL in the first `prec' characters, and
  787. * wcslen() will go further.
  788. */
  789. wchar_t *p = wmemchr(cp, 0, prec);
  790. size = p ? (p - cp) : prec;
  791. } else {
  792. size_t len;
  793. if ((len = wcslen(cp)) > INT_MAX)
  794. goto overflow;
  795. size = (int)len;
  796. }
  797. sign = '\0';
  798. break;
  799. case 'U':
  800. flags |= LONGINT;
  801. /*FALLTHROUGH*/
  802. case 'u':
  803. _umax = UARG();
  804. base = DEC;
  805. goto nosign;
  806. case 'X':
  807. xdigs = xdigs_upper;
  808. goto hex;
  809. case 'x':
  810. xdigs = xdigs_lower;
  811. hex: _umax = UARG();
  812. base = HEX;
  813. /* leading 0x/X only if non-zero */
  814. if (flags & ALT && _umax != 0)
  815. ox[1] = ch;
  816. /* unsigned conversions */
  817. nosign: sign = '\0';
  818. /*
  819. * ``... diouXx conversions ... if a precision is
  820. * specified, the 0 flag will be ignored.''
  821. * -- ANSI X3J11
  822. */
  823. number: if ((dprec = prec) >= 0)
  824. flags &= ~ZEROPAD;
  825. /*
  826. * ``The result of converting a zero value with an
  827. * explicit precision of zero is no characters.''
  828. * -- ANSI X3J11
  829. */
  830. cp = buf + BUF;
  831. if (_umax != 0 || prec != 0) {
  832. /*
  833. * Unsigned mod is hard, and unsigned mod
  834. * by a constant is easier than that by
  835. * a variable; hence this switch.
  836. */
  837. switch (base) {
  838. case OCT:
  839. do {
  840. *--cp = to_char(_umax & 7);
  841. _umax >>= 3;
  842. } while (_umax);
  843. /* handle octal leading 0 */
  844. if (flags & ALT && *cp != '0')
  845. *--cp = '0';
  846. break;
  847. case DEC:
  848. /* many numbers are 1 digit */
  849. while (_umax >= 10) {
  850. *--cp = to_char(_umax % 10);
  851. _umax /= 10;
  852. }
  853. *--cp = to_char(_umax);
  854. break;
  855. case HEX:
  856. do {
  857. *--cp = xdigs[_umax & 15];
  858. _umax >>= 4;
  859. } while (_umax);
  860. break;
  861. default:
  862. cp = L"bug in vfwprintf: bad base";
  863. size = wcslen(cp);
  864. goto skipsize;
  865. }
  866. }
  867. size = buf + BUF - cp;
  868. if (size > BUF) /* should never happen */
  869. abort();
  870. skipsize:
  871. break;
  872. default: /* "%?" prints ?, unless ? is NUL */
  873. if (ch == '\0')
  874. goto done;
  875. /* pretend it was %c with argument ch */
  876. cp = buf;
  877. *cp = ch;
  878. size = 1;
  879. sign = '\0';
  880. break;
  881. }
  882. /*
  883. * All reasonable formats wind up here. At this point, `cp'
  884. * points to a string which (if not flags&LADJUST) should be
  885. * padded out to `width' places. If flags&ZEROPAD, it should
  886. * first be prefixed by any sign or other prefix; otherwise,
  887. * it should be blank padded before the prefix is emitted.
  888. * After any left-hand padding and prefixing, emit zeroes
  889. * required by a decimal %[diouxX] precision, then print the
  890. * string proper, then emit zeroes required by any leftover
  891. * floating precision; finally, if LADJUST, pad with blanks.
  892. *
  893. * Compute actual size, so we know how much to pad.
  894. * size excludes decimal prec; realsz includes it.
  895. */
  896. realsz = dprec > size ? dprec : size;
  897. if (sign)
  898. realsz++;
  899. if (ox[1])
  900. realsz+= 2;
  901. /* right-adjusting blank padding */
  902. if ((flags & (LADJUST|ZEROPAD)) == 0)
  903. PAD(width - realsz, blanks);
  904. /* prefix */
  905. if (sign)
  906. PRINT(&sign, 1);
  907. if (ox[1]) { /* ox[1] is either x, X, or \0 */
  908. ox[0] = '0';
  909. PRINT(ox, 2);
  910. }
  911. /* right-adjusting zero padding */
  912. if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
  913. PAD(width - realsz, zeroes);
  914. /* leading zeroes from decimal precision */
  915. PAD(dprec - size, zeroes);
  916. /* the string or number proper */
  917. #ifdef FLOATING_POINT
  918. if ((flags & FPT) == 0) {
  919. PRINT(cp, size);
  920. } else { /* glue together f_p fragments */
  921. if (!expchar) { /* %[fF] or sufficiently short %[gG] */
  922. if (expt <= 0) {
  923. PRINT(zeroes, 1);
  924. if (prec || flags & ALT)
  925. PRINT(decimal_point, 1);
  926. PAD(-expt, zeroes);
  927. /* already handled initial 0's */
  928. prec += expt;
  929. } else {
  930. PRINTANDPAD(cp, convbuf + ndig,
  931. lead, zeroes);
  932. cp += lead;
  933. if (prec || flags & ALT)
  934. PRINT(decimal_point, 1);
  935. }
  936. PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
  937. } else { /* %[eE] or sufficiently long %[gG] */
  938. if (prec > 1 || flags & ALT) {
  939. buf[0] = *cp++;
  940. buf[1] = *decimal_point;
  941. PRINT(buf, 2);
  942. PRINT(cp, ndig-1);
  943. PAD(prec - ndig, zeroes);
  944. } else { /* XeYYY */
  945. PRINT(cp, 1);
  946. }
  947. PRINT(expstr, expsize);
  948. }
  949. }
  950. #else
  951. PRINT(cp, size);
  952. #endif
  953. /* left-adjusting padding (always blank) */
  954. if (flags & LADJUST)
  955. PAD(width - realsz, blanks);
  956. /* finally, adjust ret */
  957. if (width < realsz)
  958. width = realsz;
  959. if (width > INT_MAX - ret)
  960. goto overflow;
  961. ret += width;
  962. }
  963. done:
  964. error:
  965. va_end(orgap);
  966. if (__sferror(fp))
  967. ret = -1;
  968. goto finish;
  969. overflow:
  970. errno = ENOMEM;
  971. ret = -1;
  972. finish:
  973. if (convbuf)
  974. free(convbuf);
  975. #ifdef FLOATING_POINT
  976. if (dtoaresult)
  977. __freedtoa(dtoaresult);
  978. #endif
  979. if (argtable != NULL && argtable != statargtable) {
  980. free(argtable);
  981. argtable = NULL;
  982. }
  983. return (ret);
  984. }
  985. /*
  986. * Type ids for argument type table.
  987. */
  988. #define T_UNUSED 0
  989. #define T_SHORT 1
  990. #define T_U_SHORT 2
  991. #define TP_SHORT 3
  992. #define T_INT 4
  993. #define T_U_INT 5
  994. #define TP_INT 6
  995. #define T_LONG 7
  996. #define T_U_LONG 8
  997. #define TP_LONG 9
  998. #define T_LLONG 10
  999. #define T_U_LLONG 11
  1000. #define TP_LLONG 12
  1001. #define T_DOUBLE 13
  1002. #define T_LONG_DOUBLE 14
  1003. #define TP_CHAR 15
  1004. #define TP_VOID 16
  1005. #define T_PTRINT 17
  1006. #define TP_PTRINT 18
  1007. #define T_SIZEINT 19
  1008. #define T_SSIZEINT 20
  1009. #define TP_SSIZEINT 21
  1010. #define T_MAXINT 22
  1011. #define T_MAXUINT 23
  1012. #define TP_MAXINT 24
  1013. #define T_CHAR 25
  1014. #define T_U_CHAR 26
  1015. #define T_WINT 27
  1016. #define TP_WCHAR 28
  1017. /*
  1018. * Find all arguments when a positional parameter is encountered. Returns a
  1019. * table, indexed by argument number, of pointers to each arguments. The
  1020. * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
  1021. * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
  1022. * used since we are attempting to make snprintf thread safe, and alloca is
  1023. * problematic since we have nested functions..)
  1024. */
  1025. static int
  1026. __find_arguments(const wchar_t *fmt0, va_list ap, union arg **argtable,
  1027. size_t *argtablesiz)
  1028. {
  1029. wchar_t *fmt; /* format string */
  1030. int ch; /* character from fmt */
  1031. int n, n2; /* handy integer (short term usage) */
  1032. wchar_t *cp; /* handy char pointer (short term usage) */
  1033. int flags; /* flags as above */
  1034. unsigned char *typetable; /* table of types */
  1035. unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
  1036. int tablesize; /* current size of type table */
  1037. int tablemax; /* largest used index in table */
  1038. int nextarg; /* 1-based argument index */
  1039. int ret = 0; /* return value */
  1040. int rc = 0; /* save return code from __grow_type_table */
  1041. #define check_rc(rc) if (rc == -1) goto overflow
  1042. /*
  1043. * Add an argument type to the table, expanding if necessary.
  1044. */
  1045. #define ADDTYPE(type) \
  1046. ((nextarg >= tablesize) ? \
  1047. rc = __grow_type_table(&typetable, &tablesize) : 0, \
  1048. (nextarg > tablemax) ? tablemax = nextarg : 0, \
  1049. rc == -1 ? 0 : (typetable[nextarg++] = type))
  1050. #define ADDTYPE_CHECK(type) \
  1051. ADDTYPE(type); check_rc(rc)
  1052. #define ADDSARG() \
  1053. ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
  1054. ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
  1055. ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
  1056. ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
  1057. ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
  1058. ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
  1059. ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT)))))))); \
  1060. check_rc(rc);
  1061. #define ADDUARG() \
  1062. ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
  1063. ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
  1064. ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
  1065. ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
  1066. ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
  1067. ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
  1068. ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT)))))))); \
  1069. check_rc(rc);
  1070. /*
  1071. * Add * arguments to the type array.
  1072. */
  1073. #define ADDASTER() \
  1074. n2 = 0; \
  1075. cp = fmt; \
  1076. while (is_digit(*cp)) { \
  1077. APPEND_DIGIT(n2, *cp); \
  1078. cp++; \
  1079. } \
  1080. if (*cp == '$') { \
  1081. int hold = nextarg; \
  1082. nextarg = n2; \
  1083. ADDTYPE_CHECK(T_INT); \
  1084. nextarg = hold; \
  1085. fmt = ++cp; \
  1086. } else { \
  1087. ADDTYPE_CHECK(T_INT); \
  1088. }
  1089. fmt = (wchar_t *)fmt0;
  1090. typetable = stattypetable;
  1091. tablesize = STATIC_ARG_TBL_SIZE;
  1092. tablemax = 0;
  1093. nextarg = 1;
  1094. memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
  1095. /*
  1096. * Scan the format for conversions (`%' character).
  1097. */
  1098. for (;;) {
  1099. for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
  1100. continue;
  1101. if (ch == '\0')
  1102. goto done;
  1103. fmt++; /* skip over '%' */
  1104. flags = 0;
  1105. rflag: ch = *fmt++;
  1106. reswitch: switch (ch) {
  1107. case ' ':
  1108. case '#':
  1109. case '\'':
  1110. goto rflag;
  1111. case '*':
  1112. ADDASTER();
  1113. goto rflag;
  1114. case '-':
  1115. case '+':
  1116. goto rflag;
  1117. case '.':
  1118. if ((ch = *fmt++) == '*') {
  1119. ADDASTER();
  1120. goto rflag;
  1121. }
  1122. while (is_digit(ch)) {
  1123. ch = *fmt++;
  1124. }
  1125. goto reswitch;
  1126. case '0':
  1127. goto rflag;
  1128. case '1': case '2': case '3': case '4':
  1129. case '5': case '6': case '7': case '8': case '9':
  1130. n = 0;
  1131. do {
  1132. APPEND_DIGIT(n ,ch);
  1133. ch = *fmt++;
  1134. } while (is_digit(ch));
  1135. if (ch == '$') {
  1136. nextarg = n;
  1137. goto rflag;
  1138. }
  1139. goto reswitch;
  1140. #ifdef FLOATING_POINT
  1141. case 'L':
  1142. flags |= LONGDBL;
  1143. goto rflag;
  1144. #endif
  1145. case 'h':
  1146. if (*fmt == 'h') {
  1147. fmt++;
  1148. flags |= CHARINT;
  1149. } else {
  1150. flags |= SHORTINT;
  1151. }
  1152. goto rflag;
  1153. case 'l':
  1154. if (*fmt == 'l') {
  1155. fmt++;
  1156. flags |= LLONGINT;
  1157. } else {
  1158. flags |= LONGINT;
  1159. }
  1160. goto rflag;
  1161. case 'q':
  1162. flags |= LLONGINT;
  1163. goto rflag;
  1164. case 't':
  1165. flags |= PTRINT;
  1166. goto rflag;
  1167. case 'z':
  1168. flags |= SIZEINT;
  1169. goto rflag;
  1170. case 'C':
  1171. flags |= LONGINT;
  1172. /*FALLTHROUGH*/
  1173. case 'c':
  1174. if (flags & LONGINT)
  1175. ADDTYPE_CHECK(T_WINT);
  1176. else
  1177. ADDTYPE_CHECK(T_INT);
  1178. break;
  1179. case 'D':
  1180. flags |= LONGINT;
  1181. /*FALLTHROUGH*/
  1182. case 'd':
  1183. case 'i':
  1184. ADDSARG();
  1185. break;
  1186. #ifdef FLOATING_POINT
  1187. case 'a':
  1188. case 'A':
  1189. case 'e':
  1190. case 'E':
  1191. case 'f':
  1192. case 'F':
  1193. case 'g':
  1194. case 'G':
  1195. if (flags & LONGDBL)
  1196. ADDTYPE_CHECK(T_LONG_DOUBLE);
  1197. else
  1198. ADDTYPE_CHECK(T_DOUBLE);
  1199. break;
  1200. #endif /* FLOATING_POINT */
  1201. case 'n':
  1202. if (flags & LLONGINT)
  1203. ADDTYPE_CHECK(TP_LLONG);
  1204. else if (flags & LONGINT)
  1205. ADDTYPE_CHECK(TP_LONG);
  1206. else if (flags & SHORTINT)
  1207. ADDTYPE_CHECK(TP_SHORT);
  1208. else if (flags & PTRINT)
  1209. ADDTYPE_CHECK(TP_PTRINT);
  1210. else if (flags & SIZEINT)
  1211. ADDTYPE_CHECK(TP_SSIZEINT);
  1212. else if (flags & MAXINT)
  1213. ADDTYPE_CHECK(TP_MAXINT);
  1214. else
  1215. ADDTYPE_CHECK(TP_INT);
  1216. continue; /* no output */
  1217. case 'O':
  1218. flags |= LONGINT;
  1219. /*FALLTHROUGH*/
  1220. case 'o':
  1221. ADDUARG();
  1222. break;
  1223. case 'p':
  1224. ADDTYPE_CHECK(TP_VOID);
  1225. break;
  1226. case 'S':
  1227. flags |= LONGINT;
  1228. /*FALLTHROUGH*/
  1229. case 's':
  1230. if (flags & LONGINT)
  1231. ADDTYPE_CHECK(TP_CHAR);
  1232. else
  1233. ADDTYPE_CHECK(TP_WCHAR);
  1234. break;
  1235. case 'U':
  1236. flags |= LONGINT;
  1237. /*FALLTHROUGH*/
  1238. case 'u':
  1239. case 'X':
  1240. case 'x':
  1241. ADDUARG();
  1242. break;
  1243. default: /* "%?" prints ?, unless ? is NUL */
  1244. if (ch == '\0')
  1245. goto done;
  1246. break;
  1247. }
  1248. }
  1249. done:
  1250. /*
  1251. * Build the argument table.
  1252. */
  1253. if (tablemax >= STATIC_ARG_TBL_SIZE) {
  1254. *argtablesiz = sizeof(union arg) * (tablemax + 1);
  1255. *argtable = (union arg *)malloc(*argtablesiz);
  1256. if (*argtable == NULL)
  1257. goto overflow; //return (-1);
  1258. }
  1259. #if 0
  1260. /* XXX is this required? */
  1261. (*argtable)[0].intarg = 0;
  1262. #endif
  1263. for (n = 1; n <= tablemax; n++) {
  1264. switch (typetable[n]) {
  1265. case T_UNUSED:
  1266. case T_CHAR:
  1267. case T_U_CHAR:
  1268. case T_SHORT:
  1269. case T_U_SHORT:
  1270. case T_INT:
  1271. (*argtable)[n].intarg = va_arg(ap, int);
  1272. break;
  1273. case TP_SHORT:
  1274. (*argtable)[n].pshortarg = va_arg(ap, short *);
  1275. break;
  1276. case T_U_INT:
  1277. (*argtable)[n].uintarg = va_arg(ap, unsigned int);
  1278. break;
  1279. case TP_INT:
  1280. (*argtable)[n].pintarg = va_arg(ap, int *);
  1281. break;
  1282. case T_LONG:
  1283. (*argtable)[n].longarg = va_arg(ap, long);
  1284. break;
  1285. case T_U_LONG:
  1286. (*argtable)[n].ulongarg = va_arg(ap, unsigned long);
  1287. break;
  1288. case TP_LONG:
  1289. (*argtable)[n].plongarg = va_arg(ap, long *);
  1290. break;
  1291. case T_LLONG:
  1292. (*argtable)[n].longlongarg = va_arg(ap, long long);
  1293. break;
  1294. case T_U_LLONG:
  1295. (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
  1296. break;
  1297. case TP_LLONG:
  1298. (*argtable)[n].plonglongarg = va_arg(ap, long long *);
  1299. break;
  1300. #ifdef FLOATING_POINT
  1301. case T_DOUBLE:
  1302. (*argtable)[n].doublearg = va_arg(ap, double);
  1303. break;
  1304. case T_LONG_DOUBLE:
  1305. (*argtable)[n].longdoublearg = va_arg(ap, long double);
  1306. break;
  1307. #endif
  1308. case TP_CHAR:
  1309. (*argtable)[n].pchararg = va_arg(ap, char *);
  1310. break;
  1311. case TP_VOID:
  1312. (*argtable)[n].pvoidarg = va_arg(ap, void *);
  1313. break;
  1314. case T_PTRINT:
  1315. (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
  1316. break;
  1317. case TP_PTRINT:
  1318. (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
  1319. break;
  1320. case T_SIZEINT:
  1321. (*argtable)[n].sizearg = va_arg(ap, size_t);
  1322. break;
  1323. case T_SSIZEINT:
  1324. (*argtable)[n].ssizearg = va_arg(ap, ssize_t);
  1325. break;
  1326. case TP_SSIZEINT:
  1327. (*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
  1328. break;
  1329. case TP_MAXINT:
  1330. (*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
  1331. break;
  1332. case T_WINT:
  1333. (*argtable)[n].wintarg = va_arg(ap, wint_t);
  1334. break;
  1335. case TP_WCHAR:
  1336. (*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
  1337. break;
  1338. }
  1339. }
  1340. goto finish;
  1341. overflow:
  1342. errno = ENOMEM;
  1343. ret = -1;
  1344. finish:
  1345. if (typetable != NULL && typetable != stattypetable) {
  1346. free(typetable);
  1347. typetable = NULL;
  1348. }
  1349. return (ret);
  1350. }
  1351. /*
  1352. * Increase the size of the type table.
  1353. */
  1354. static int
  1355. __grow_type_table(unsigned char **typetable, int *tablesize)
  1356. {
  1357. unsigned char *oldtable = *typetable;
  1358. int newsize = *tablesize * 2;
  1359. if (newsize < SE_PAGE_SIZE)
  1360. newsize = SE_PAGE_SIZE;
  1361. if (*tablesize == STATIC_ARG_TBL_SIZE) {
  1362. *typetable = (unsigned char *)malloc(newsize);
  1363. if (*typetable == NULL)
  1364. return (-1);
  1365. memmove(*typetable, oldtable, *tablesize);
  1366. } else {
  1367. unsigned char *new1 = (unsigned char *)malloc(newsize);
  1368. if (new1 == NULL)
  1369. return (-1);
  1370. memmove(new1, *typetable, *tablesize);
  1371. free(*typetable);
  1372. *typetable = new1;
  1373. }
  1374. memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
  1375. *tablesize = newsize;
  1376. return (0);
  1377. }
  1378. #ifdef FLOATING_POINT
  1379. static int
  1380. exponent(wchar_t *p0, int exp, int fmtch)
  1381. {
  1382. wchar_t *p, *t;
  1383. wchar_t expbuf[MAXEXPDIG];
  1384. p = p0;
  1385. *p++ = fmtch;
  1386. if (exp < 0) {
  1387. exp = -exp;
  1388. *p++ = '-';
  1389. } else
  1390. *p++ = '+';
  1391. t = expbuf + MAXEXPDIG;
  1392. if (exp > 9) {
  1393. do {
  1394. *--t = to_char(exp % 10);
  1395. } while ((exp /= 10) > 9);
  1396. *--t = to_char(exp);
  1397. for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
  1398. /* nothing */;
  1399. } else {
  1400. /*
  1401. * Exponents for decimal floating point conversions
  1402. * (%[eEgG]) must be at least two characters long,
  1403. * whereas exponents for hexadecimal conversions can
  1404. * be only one character long.
  1405. */
  1406. if (fmtch == 'e' || fmtch == 'E')
  1407. *p++ = '0';
  1408. *p++ = to_char(exp);
  1409. }
  1410. return (p - p0);
  1411. }
  1412. #endif /* FLOATING_POINT */