vasnprintf.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. /* vsprintf with automatic memory allocation.
  2. Copyright (C) 1999, 2002-2006 Free Software Foundation, Inc.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with this program; if not, write to the Free Software Foundation,
  13. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  14. /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
  15. This must come before <config.h> because <config.h> may include
  16. <features.h>, and once <features.h> has been included, it's too late. */
  17. #ifndef _GNU_SOURCE
  18. # define _GNU_SOURCE 1
  19. #endif
  20. #include <config.h>
  21. #ifndef IN_LIBINTL
  22. # include <alloca.h>
  23. #endif
  24. /* Specification. */
  25. #if WIDE_CHAR_VERSION
  26. # include "vasnwprintf.h"
  27. #else
  28. # include "vasnprintf.h"
  29. #endif
  30. #include <stdio.h> /* snprintf(), sprintf() */
  31. #include <stdlib.h> /* abort(), malloc(), realloc(), free() */
  32. #include <string.h> /* memcpy(), strlen() */
  33. #include <errno.h> /* errno */
  34. #include <limits.h> /* CHAR_BIT */
  35. #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
  36. #if WIDE_CHAR_VERSION
  37. # include "wprintf-parse.h"
  38. #else
  39. # include "printf-parse.h"
  40. #endif
  41. /* Checked size_t computations. */
  42. #include "xsize.h"
  43. #ifdef HAVE_WCHAR_T
  44. # ifdef HAVE_WCSLEN
  45. # define local_wcslen wcslen
  46. # else
  47. /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
  48. a dependency towards this library, here is a local substitute.
  49. Define this substitute only once, even if this file is included
  50. twice in the same compilation unit. */
  51. # ifndef local_wcslen_defined
  52. # define local_wcslen_defined 1
  53. static size_t
  54. local_wcslen (const wchar_t *s)
  55. {
  56. const wchar_t *ptr;
  57. for (ptr = s; *ptr != (wchar_t) 0; ptr++)
  58. ;
  59. return ptr - s;
  60. }
  61. # endif
  62. # endif
  63. #endif
  64. #if WIDE_CHAR_VERSION
  65. # define VASNPRINTF vasnwprintf
  66. # define CHAR_T wchar_t
  67. # define DIRECTIVE wchar_t_directive
  68. # define DIRECTIVES wchar_t_directives
  69. # define PRINTF_PARSE wprintf_parse
  70. # define USE_SNPRINTF 1
  71. # if HAVE_DECL__SNWPRINTF
  72. /* On Windows, the function swprintf() has a different signature than
  73. on Unix; we use the _snwprintf() function instead. */
  74. # define SNPRINTF _snwprintf
  75. # else
  76. /* Unix. */
  77. # define SNPRINTF swprintf
  78. # endif
  79. #else
  80. # define VASNPRINTF vasnprintf
  81. # define CHAR_T char
  82. # define DIRECTIVE char_directive
  83. # define DIRECTIVES char_directives
  84. # define PRINTF_PARSE printf_parse
  85. # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
  86. # if HAVE_DECL__SNPRINTF
  87. /* Windows. */
  88. # define SNPRINTF _snprintf
  89. # else
  90. /* Unix. */
  91. # define SNPRINTF snprintf
  92. # endif
  93. #endif
  94. CHAR_T *
  95. VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
  96. {
  97. DIRECTIVES d;
  98. arguments a;
  99. if (PRINTF_PARSE (format, &d, &a) < 0)
  100. {
  101. errno = EINVAL;
  102. return NULL;
  103. }
  104. #define CLEANUP() \
  105. free (d.dir); \
  106. if (a.arg) \
  107. free (a.arg);
  108. if (printf_fetchargs (args, &a) < 0)
  109. {
  110. CLEANUP ();
  111. errno = EINVAL;
  112. return NULL;
  113. }
  114. {
  115. size_t buf_neededlength;
  116. CHAR_T *buf;
  117. CHAR_T *buf_malloced;
  118. const CHAR_T *cp;
  119. size_t i;
  120. DIRECTIVE *dp;
  121. /* Output string accumulator. */
  122. CHAR_T *result;
  123. size_t allocated;
  124. size_t length;
  125. /* Allocate a small buffer that will hold a directive passed to
  126. sprintf or snprintf. */
  127. buf_neededlength =
  128. xsum4 (7, d.max_width_length, d.max_precision_length, 6);
  129. #if HAVE_ALLOCA
  130. if (buf_neededlength < 4000 / sizeof (CHAR_T))
  131. {
  132. buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
  133. buf_malloced = NULL;
  134. }
  135. else
  136. #endif
  137. {
  138. size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
  139. if (size_overflow_p (buf_memsize))
  140. goto out_of_memory_1;
  141. buf = (CHAR_T *) malloc (buf_memsize);
  142. if (buf == NULL)
  143. goto out_of_memory_1;
  144. buf_malloced = buf;
  145. }
  146. if (resultbuf != NULL)
  147. {
  148. result = resultbuf;
  149. allocated = *lengthp;
  150. }
  151. else
  152. {
  153. result = NULL;
  154. allocated = 0;
  155. }
  156. length = 0;
  157. /* Invariants:
  158. result is either == resultbuf or == NULL or malloc-allocated.
  159. If length > 0, then result != NULL. */
  160. /* Ensures that allocated >= needed. Aborts through a jump to
  161. out_of_memory if needed is SIZE_MAX or otherwise too big. */
  162. #define ENSURE_ALLOCATION(needed) \
  163. if ((needed) > allocated) \
  164. { \
  165. size_t memory_size; \
  166. CHAR_T *memory; \
  167. \
  168. allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
  169. if ((needed) > allocated) \
  170. allocated = (needed); \
  171. memory_size = xtimes (allocated, sizeof (CHAR_T)); \
  172. if (size_overflow_p (memory_size)) \
  173. goto out_of_memory; \
  174. if (result == resultbuf || result == NULL) \
  175. memory = (CHAR_T *) malloc (memory_size); \
  176. else \
  177. memory = (CHAR_T *) realloc (result, memory_size); \
  178. if (memory == NULL) \
  179. goto out_of_memory; \
  180. if (result == resultbuf && length > 0) \
  181. memcpy (memory, result, length * sizeof (CHAR_T)); \
  182. result = memory; \
  183. }
  184. for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
  185. {
  186. if (cp != dp->dir_start)
  187. {
  188. size_t n = dp->dir_start - cp;
  189. size_t augmented_length = xsum (length, n);
  190. ENSURE_ALLOCATION (augmented_length);
  191. memcpy (result + length, cp, n * sizeof (CHAR_T));
  192. length = augmented_length;
  193. }
  194. if (i == d.count)
  195. break;
  196. /* Execute a single directive. */
  197. if (dp->conversion == '%')
  198. {
  199. size_t augmented_length;
  200. if (!(dp->arg_index == ARG_NONE))
  201. abort ();
  202. augmented_length = xsum (length, 1);
  203. ENSURE_ALLOCATION (augmented_length);
  204. result[length] = '%';
  205. length = augmented_length;
  206. }
  207. else
  208. {
  209. if (!(dp->arg_index != ARG_NONE))
  210. abort ();
  211. if (dp->conversion == 'n')
  212. {
  213. switch (a.arg[dp->arg_index].type)
  214. {
  215. case TYPE_COUNT_SCHAR_POINTER:
  216. *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
  217. break;
  218. case TYPE_COUNT_SHORT_POINTER:
  219. *a.arg[dp->arg_index].a.a_count_short_pointer = length;
  220. break;
  221. case TYPE_COUNT_INT_POINTER:
  222. *a.arg[dp->arg_index].a.a_count_int_pointer = length;
  223. break;
  224. case TYPE_COUNT_LONGINT_POINTER:
  225. *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
  226. break;
  227. #ifdef HAVE_LONG_LONG_INT
  228. case TYPE_COUNT_LONGLONGINT_POINTER:
  229. *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
  230. break;
  231. #endif
  232. default:
  233. abort ();
  234. }
  235. }
  236. else
  237. {
  238. arg_type type = a.arg[dp->arg_index].type;
  239. CHAR_T *p;
  240. unsigned int prefix_count;
  241. int prefixes[2];
  242. #if !USE_SNPRINTF
  243. size_t tmp_length;
  244. CHAR_T tmpbuf[700];
  245. CHAR_T *tmp;
  246. /* Allocate a temporary buffer of sufficient size for calling
  247. sprintf. */
  248. {
  249. size_t width;
  250. size_t precision;
  251. width = 0;
  252. if (dp->width_start != dp->width_end)
  253. {
  254. if (dp->width_arg_index != ARG_NONE)
  255. {
  256. int arg;
  257. if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
  258. abort ();
  259. arg = a.arg[dp->width_arg_index].a.a_int;
  260. width = (arg < 0 ? (unsigned int) (-arg) : arg);
  261. }
  262. else
  263. {
  264. const CHAR_T *digitp = dp->width_start;
  265. do
  266. width = xsum (xtimes (width, 10), *digitp++ - '0');
  267. while (digitp != dp->width_end);
  268. }
  269. }
  270. precision = 6;
  271. if (dp->precision_start != dp->precision_end)
  272. {
  273. if (dp->precision_arg_index != ARG_NONE)
  274. {
  275. int arg;
  276. if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
  277. abort ();
  278. arg = a.arg[dp->precision_arg_index].a.a_int;
  279. precision = (arg < 0 ? 0 : arg);
  280. }
  281. else
  282. {
  283. const CHAR_T *digitp = dp->precision_start + 1;
  284. precision = 0;
  285. while (digitp != dp->precision_end)
  286. precision = xsum (xtimes (precision, 10), *digitp++ - '0');
  287. }
  288. }
  289. switch (dp->conversion)
  290. {
  291. case 'd': case 'i': case 'u':
  292. # ifdef HAVE_LONG_LONG_INT
  293. if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
  294. tmp_length =
  295. (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
  296. * 0.30103 /* binary -> decimal */
  297. )
  298. + 1; /* turn floor into ceil */
  299. else
  300. # endif
  301. if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
  302. tmp_length =
  303. (unsigned int) (sizeof (unsigned long) * CHAR_BIT
  304. * 0.30103 /* binary -> decimal */
  305. )
  306. + 1; /* turn floor into ceil */
  307. else
  308. tmp_length =
  309. (unsigned int) (sizeof (unsigned int) * CHAR_BIT
  310. * 0.30103 /* binary -> decimal */
  311. )
  312. + 1; /* turn floor into ceil */
  313. if (tmp_length < precision)
  314. tmp_length = precision;
  315. /* Multiply by 2, as an estimate for FLAG_GROUP. */
  316. tmp_length = xsum (tmp_length, tmp_length);
  317. /* Add 1, to account for a leading sign. */
  318. tmp_length = xsum (tmp_length, 1);
  319. break;
  320. case 'o':
  321. # ifdef HAVE_LONG_LONG_INT
  322. if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
  323. tmp_length =
  324. (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
  325. * 0.333334 /* binary -> octal */
  326. )
  327. + 1; /* turn floor into ceil */
  328. else
  329. # endif
  330. if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
  331. tmp_length =
  332. (unsigned int) (sizeof (unsigned long) * CHAR_BIT
  333. * 0.333334 /* binary -> octal */
  334. )
  335. + 1; /* turn floor into ceil */
  336. else
  337. tmp_length =
  338. (unsigned int) (sizeof (unsigned int) * CHAR_BIT
  339. * 0.333334 /* binary -> octal */
  340. )
  341. + 1; /* turn floor into ceil */
  342. if (tmp_length < precision)
  343. tmp_length = precision;
  344. /* Add 1, to account for a leading sign. */
  345. tmp_length = xsum (tmp_length, 1);
  346. break;
  347. case 'x': case 'X':
  348. # ifdef HAVE_LONG_LONG_INT
  349. if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
  350. tmp_length =
  351. (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
  352. * 0.25 /* binary -> hexadecimal */
  353. )
  354. + 1; /* turn floor into ceil */
  355. else
  356. # endif
  357. if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
  358. tmp_length =
  359. (unsigned int) (sizeof (unsigned long) * CHAR_BIT
  360. * 0.25 /* binary -> hexadecimal */
  361. )
  362. + 1; /* turn floor into ceil */
  363. else
  364. tmp_length =
  365. (unsigned int) (sizeof (unsigned int) * CHAR_BIT
  366. * 0.25 /* binary -> hexadecimal */
  367. )
  368. + 1; /* turn floor into ceil */
  369. if (tmp_length < precision)
  370. tmp_length = precision;
  371. /* Add 2, to account for a leading sign or alternate form. */
  372. tmp_length = xsum (tmp_length, 2);
  373. break;
  374. case 'f': case 'F':
  375. # ifdef HAVE_LONG_DOUBLE
  376. if (type == TYPE_LONGDOUBLE)
  377. tmp_length =
  378. (unsigned int) (LDBL_MAX_EXP
  379. * 0.30103 /* binary -> decimal */
  380. * 2 /* estimate for FLAG_GROUP */
  381. )
  382. + 1 /* turn floor into ceil */
  383. + 10; /* sign, decimal point etc. */
  384. else
  385. # endif
  386. tmp_length =
  387. (unsigned int) (DBL_MAX_EXP
  388. * 0.30103 /* binary -> decimal */
  389. * 2 /* estimate for FLAG_GROUP */
  390. )
  391. + 1 /* turn floor into ceil */
  392. + 10; /* sign, decimal point etc. */
  393. tmp_length = xsum (tmp_length, precision);
  394. break;
  395. case 'e': case 'E': case 'g': case 'G':
  396. case 'a': case 'A':
  397. tmp_length =
  398. 12; /* sign, decimal point, exponent etc. */
  399. tmp_length = xsum (tmp_length, precision);
  400. break;
  401. case 'c':
  402. # if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
  403. if (type == TYPE_WIDE_CHAR)
  404. tmp_length = MB_CUR_MAX;
  405. else
  406. # endif
  407. tmp_length = 1;
  408. break;
  409. case 's':
  410. # ifdef HAVE_WCHAR_T
  411. if (type == TYPE_WIDE_STRING)
  412. {
  413. tmp_length =
  414. local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
  415. # if !WIDE_CHAR_VERSION
  416. tmp_length = xtimes (tmp_length, MB_CUR_MAX);
  417. # endif
  418. }
  419. else
  420. # endif
  421. tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
  422. break;
  423. case 'p':
  424. tmp_length =
  425. (unsigned int) (sizeof (void *) * CHAR_BIT
  426. * 0.25 /* binary -> hexadecimal */
  427. )
  428. + 1 /* turn floor into ceil */
  429. + 2; /* account for leading 0x */
  430. break;
  431. default:
  432. abort ();
  433. }
  434. if (tmp_length < width)
  435. tmp_length = width;
  436. tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
  437. }
  438. if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
  439. tmp = tmpbuf;
  440. else
  441. {
  442. size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
  443. if (size_overflow_p (tmp_memsize))
  444. /* Overflow, would lead to out of memory. */
  445. goto out_of_memory;
  446. tmp = (CHAR_T *) malloc (tmp_memsize);
  447. if (tmp == NULL)
  448. /* Out of memory. */
  449. goto out_of_memory;
  450. }
  451. #endif
  452. /* Construct the format string for calling snprintf or
  453. sprintf. */
  454. p = buf;
  455. *p++ = '%';
  456. if (dp->flags & FLAG_GROUP)
  457. *p++ = '\'';
  458. if (dp->flags & FLAG_LEFT)
  459. *p++ = '-';
  460. if (dp->flags & FLAG_SHOWSIGN)
  461. *p++ = '+';
  462. if (dp->flags & FLAG_SPACE)
  463. *p++ = ' ';
  464. if (dp->flags & FLAG_ALT)
  465. *p++ = '#';
  466. if (dp->flags & FLAG_ZERO)
  467. *p++ = '0';
  468. if (dp->width_start != dp->width_end)
  469. {
  470. size_t n = dp->width_end - dp->width_start;
  471. memcpy (p, dp->width_start, n * sizeof (CHAR_T));
  472. p += n;
  473. }
  474. if (dp->precision_start != dp->precision_end)
  475. {
  476. size_t n = dp->precision_end - dp->precision_start;
  477. memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
  478. p += n;
  479. }
  480. switch (type)
  481. {
  482. #ifdef HAVE_LONG_LONG_INT
  483. case TYPE_LONGLONGINT:
  484. case TYPE_ULONGLONGINT:
  485. *p++ = 'l';
  486. /*FALLTHROUGH*/
  487. #endif
  488. case TYPE_LONGINT:
  489. case TYPE_ULONGINT:
  490. #ifdef HAVE_WINT_T
  491. case TYPE_WIDE_CHAR:
  492. #endif
  493. #ifdef HAVE_WCHAR_T
  494. case TYPE_WIDE_STRING:
  495. #endif
  496. *p++ = 'l';
  497. break;
  498. #ifdef HAVE_LONG_DOUBLE
  499. case TYPE_LONGDOUBLE:
  500. *p++ = 'L';
  501. break;
  502. #endif
  503. default:
  504. break;
  505. }
  506. *p = dp->conversion;
  507. #if USE_SNPRINTF
  508. p[1] = '%';
  509. p[2] = 'n';
  510. p[3] = '\0';
  511. #else
  512. p[1] = '\0';
  513. #endif
  514. /* Construct the arguments for calling snprintf or sprintf. */
  515. prefix_count = 0;
  516. if (dp->width_arg_index != ARG_NONE)
  517. {
  518. if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
  519. abort ();
  520. prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
  521. }
  522. if (dp->precision_arg_index != ARG_NONE)
  523. {
  524. if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
  525. abort ();
  526. prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
  527. }
  528. #if USE_SNPRINTF
  529. /* Prepare checking whether snprintf returns the count
  530. via %n. */
  531. ENSURE_ALLOCATION (xsum (length, 1));
  532. result[length] = '\0';
  533. #endif
  534. for (;;)
  535. {
  536. size_t maxlen;
  537. int count;
  538. int retcount;
  539. maxlen = allocated - length;
  540. count = -1;
  541. retcount = 0;
  542. #if USE_SNPRINTF
  543. # define SNPRINTF_BUF(arg) \
  544. switch (prefix_count) \
  545. { \
  546. case 0: \
  547. retcount = SNPRINTF (result + length, maxlen, buf, \
  548. arg, &count); \
  549. break; \
  550. case 1: \
  551. retcount = SNPRINTF (result + length, maxlen, buf, \
  552. prefixes[0], arg, &count); \
  553. break; \
  554. case 2: \
  555. retcount = SNPRINTF (result + length, maxlen, buf, \
  556. prefixes[0], prefixes[1], arg, \
  557. &count); \
  558. break; \
  559. default: \
  560. abort (); \
  561. }
  562. #else
  563. # define SNPRINTF_BUF(arg) \
  564. switch (prefix_count) \
  565. { \
  566. case 0: \
  567. count = sprintf (tmp, buf, arg); \
  568. break; \
  569. case 1: \
  570. count = sprintf (tmp, buf, prefixes[0], arg); \
  571. break; \
  572. case 2: \
  573. count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
  574. arg); \
  575. break; \
  576. default: \
  577. abort (); \
  578. }
  579. #endif
  580. switch (type)
  581. {
  582. case TYPE_SCHAR:
  583. {
  584. int arg = a.arg[dp->arg_index].a.a_schar;
  585. SNPRINTF_BUF (arg);
  586. }
  587. break;
  588. case TYPE_UCHAR:
  589. {
  590. unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
  591. SNPRINTF_BUF (arg);
  592. }
  593. break;
  594. case TYPE_SHORT:
  595. {
  596. int arg = a.arg[dp->arg_index].a.a_short;
  597. SNPRINTF_BUF (arg);
  598. }
  599. break;
  600. case TYPE_USHORT:
  601. {
  602. unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
  603. SNPRINTF_BUF (arg);
  604. }
  605. break;
  606. case TYPE_INT:
  607. {
  608. int arg = a.arg[dp->arg_index].a.a_int;
  609. SNPRINTF_BUF (arg);
  610. }
  611. break;
  612. case TYPE_UINT:
  613. {
  614. unsigned int arg = a.arg[dp->arg_index].a.a_uint;
  615. SNPRINTF_BUF (arg);
  616. }
  617. break;
  618. case TYPE_LONGINT:
  619. {
  620. long int arg = a.arg[dp->arg_index].a.a_longint;
  621. SNPRINTF_BUF (arg);
  622. }
  623. break;
  624. case TYPE_ULONGINT:
  625. {
  626. unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
  627. SNPRINTF_BUF (arg);
  628. }
  629. break;
  630. #ifdef HAVE_LONG_LONG_INT
  631. case TYPE_LONGLONGINT:
  632. {
  633. long long int arg = a.arg[dp->arg_index].a.a_longlongint;
  634. SNPRINTF_BUF (arg);
  635. }
  636. break;
  637. case TYPE_ULONGLONGINT:
  638. {
  639. unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
  640. SNPRINTF_BUF (arg);
  641. }
  642. break;
  643. #endif
  644. case TYPE_DOUBLE:
  645. {
  646. double arg = a.arg[dp->arg_index].a.a_double;
  647. SNPRINTF_BUF (arg);
  648. }
  649. break;
  650. #ifdef HAVE_LONG_DOUBLE
  651. case TYPE_LONGDOUBLE:
  652. {
  653. long double arg = a.arg[dp->arg_index].a.a_longdouble;
  654. SNPRINTF_BUF (arg);
  655. }
  656. break;
  657. #endif
  658. case TYPE_CHAR:
  659. {
  660. int arg = a.arg[dp->arg_index].a.a_char;
  661. SNPRINTF_BUF (arg);
  662. }
  663. break;
  664. #ifdef HAVE_WINT_T
  665. case TYPE_WIDE_CHAR:
  666. {
  667. wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
  668. SNPRINTF_BUF (arg);
  669. }
  670. break;
  671. #endif
  672. case TYPE_STRING:
  673. {
  674. const char *arg = a.arg[dp->arg_index].a.a_string;
  675. SNPRINTF_BUF (arg);
  676. }
  677. break;
  678. #ifdef HAVE_WCHAR_T
  679. case TYPE_WIDE_STRING:
  680. {
  681. const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
  682. SNPRINTF_BUF (arg);
  683. }
  684. break;
  685. #endif
  686. case TYPE_POINTER:
  687. {
  688. void *arg = a.arg[dp->arg_index].a.a_pointer;
  689. SNPRINTF_BUF (arg);
  690. }
  691. break;
  692. default:
  693. abort ();
  694. }
  695. #if USE_SNPRINTF
  696. /* Portability: Not all implementations of snprintf()
  697. are ISO C 99 compliant. Determine the number of
  698. bytes that snprintf() has produced or would have
  699. produced. */
  700. if (count >= 0)
  701. {
  702. /* Verify that snprintf() has NUL-terminated its
  703. result. */
  704. if (count < maxlen && result[length + count] != '\0')
  705. abort ();
  706. /* Portability hack. */
  707. if (retcount > count)
  708. count = retcount;
  709. }
  710. else
  711. {
  712. /* snprintf() doesn't understand the '%n'
  713. directive. */
  714. if (p[1] != '\0')
  715. {
  716. /* Don't use the '%n' directive; instead, look
  717. at the snprintf() return value. */
  718. p[1] = '\0';
  719. continue;
  720. }
  721. else
  722. {
  723. /* Look at the snprintf() return value. */
  724. if (retcount < 0)
  725. {
  726. /* HP-UX 10.20 snprintf() is doubly deficient:
  727. It doesn't understand the '%n' directive,
  728. *and* it returns -1 (rather than the length
  729. that would have been required) when the
  730. buffer is too small. */
  731. size_t bigger_need =
  732. xsum (xtimes (allocated, 2), 12);
  733. ENSURE_ALLOCATION (bigger_need);
  734. continue;
  735. }
  736. else
  737. count = retcount;
  738. }
  739. }
  740. #endif
  741. /* Attempt to handle failure. */
  742. if (count < 0)
  743. {
  744. if (!(result == resultbuf || result == NULL))
  745. free (result);
  746. if (buf_malloced != NULL)
  747. free (buf_malloced);
  748. CLEANUP ();
  749. errno = EINVAL;
  750. return NULL;
  751. }
  752. #if !USE_SNPRINTF
  753. if (count >= tmp_length)
  754. /* tmp_length was incorrectly calculated - fix the
  755. code above! */
  756. abort ();
  757. #endif
  758. /* Make room for the result. */
  759. if (count >= maxlen)
  760. {
  761. /* Need at least count bytes. But allocate
  762. proportionally, to avoid looping eternally if
  763. snprintf() reports a too small count. */
  764. size_t n =
  765. xmax (xsum (length, count), xtimes (allocated, 2));
  766. ENSURE_ALLOCATION (n);
  767. #if USE_SNPRINTF
  768. continue;
  769. #endif
  770. }
  771. #if USE_SNPRINTF
  772. /* The snprintf() result did fit. */
  773. #else
  774. /* Append the sprintf() result. */
  775. memcpy (result + length, tmp, count * sizeof (CHAR_T));
  776. if (tmp != tmpbuf)
  777. free (tmp);
  778. #endif
  779. length += count;
  780. break;
  781. }
  782. }
  783. }
  784. }
  785. /* Add the final NUL. */
  786. ENSURE_ALLOCATION (xsum (length, 1));
  787. result[length] = '\0';
  788. if (result != resultbuf && length + 1 < allocated)
  789. {
  790. /* Shrink the allocated memory if possible. */
  791. CHAR_T *memory;
  792. memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
  793. if (memory != NULL)
  794. result = memory;
  795. }
  796. if (buf_malloced != NULL)
  797. free (buf_malloced);
  798. CLEANUP ();
  799. *lengthp = length;
  800. /* Note that we can produce a big string of a length > INT_MAX. POSIX
  801. says that snprintf() fails with errno = EOVERFLOW in this case, but
  802. that's only because snprintf() returns an 'int'. This function does
  803. not have this limitation. */
  804. return result;
  805. out_of_memory:
  806. if (!(result == resultbuf || result == NULL))
  807. free (result);
  808. if (buf_malloced != NULL)
  809. free (buf_malloced);
  810. out_of_memory_1:
  811. CLEANUP ();
  812. errno = ENOMEM;
  813. return NULL;
  814. }
  815. }
  816. #undef SNPRINTF
  817. #undef USE_SNPRINTF
  818. #undef PRINTF_PARSE
  819. #undef DIRECTIVES
  820. #undef DIRECTIVE
  821. #undef CHAR_T
  822. #undef VASNPRINTF