You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vasnprintf.c 22KB

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