printf-parse.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /* Formatted output to strings.
  2. Copyright (C) 1999-2000, 2002-2003, 2006-2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  14. USA. */
  15. /* This file can be parametrized with the following macros:
  16. CHAR_T The element type of the format string.
  17. CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
  18. in the format string are ASCII.
  19. DIRECTIVE Structure denoting a format directive.
  20. Depends on CHAR_T.
  21. DIRECTIVES Structure denoting the set of format directives of a
  22. format string. Depends on CHAR_T.
  23. PRINTF_PARSE Function that parses a format string.
  24. Depends on CHAR_T.
  25. STATIC Set to 'static' to declare the function static.
  26. ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */
  27. #ifndef PRINTF_PARSE
  28. # include <config.h>
  29. #endif
  30. /* Specification. */
  31. #ifndef PRINTF_PARSE
  32. # include "printf-parse.h"
  33. #endif
  34. /* Default parameters. */
  35. #ifndef PRINTF_PARSE
  36. # define PRINTF_PARSE printf_parse
  37. # define CHAR_T char
  38. # define DIRECTIVE char_directive
  39. # define DIRECTIVES char_directives
  40. #endif
  41. /* Get size_t, NULL. */
  42. #include <stddef.h>
  43. /* Get intmax_t. */
  44. #if defined IN_LIBINTL || defined IN_LIBASPRINTF
  45. # if HAVE_STDINT_H_WITH_UINTMAX
  46. # include <stdint.h>
  47. # endif
  48. # if HAVE_INTTYPES_H_WITH_UINTMAX
  49. # include <inttypes.h>
  50. # endif
  51. #else
  52. # include <stdint.h>
  53. #endif
  54. /* malloc(), realloc(), free(). */
  55. #include <stdlib.h>
  56. /* errno. */
  57. #include <errno.h>
  58. /* Checked size_t computations. */
  59. #include "xsize.h"
  60. #if CHAR_T_ONLY_ASCII
  61. /* c_isascii(). */
  62. # include "c-ctype.h"
  63. #endif
  64. #ifdef STATIC
  65. STATIC
  66. #endif
  67. int
  68. PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
  69. {
  70. const CHAR_T *cp = format; /* pointer into format */
  71. size_t arg_posn = 0; /* number of regular arguments consumed */
  72. size_t d_allocated; /* allocated elements of d->dir */
  73. size_t a_allocated; /* allocated elements of a->arg */
  74. size_t max_width_length = 0;
  75. size_t max_precision_length = 0;
  76. d->count = 0;
  77. d_allocated = 1;
  78. d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
  79. if (d->dir == NULL)
  80. /* Out of memory. */
  81. goto out_of_memory_1;
  82. a->count = 0;
  83. a_allocated = 0;
  84. a->arg = NULL;
  85. #define REGISTER_ARG(_index_,_type_) \
  86. { \
  87. size_t n = (_index_); \
  88. if (n >= a_allocated) \
  89. { \
  90. size_t memory_size; \
  91. argument *memory; \
  92. \
  93. a_allocated = xtimes (a_allocated, 2); \
  94. if (a_allocated <= n) \
  95. a_allocated = xsum (n, 1); \
  96. memory_size = xtimes (a_allocated, sizeof (argument)); \
  97. if (size_overflow_p (memory_size)) \
  98. /* Overflow, would lead to out of memory. */ \
  99. goto out_of_memory; \
  100. memory = (argument *) (a->arg \
  101. ? realloc (a->arg, memory_size) \
  102. : malloc (memory_size)); \
  103. if (memory == NULL) \
  104. /* Out of memory. */ \
  105. goto out_of_memory; \
  106. a->arg = memory; \
  107. } \
  108. while (a->count <= n) \
  109. a->arg[a->count++].type = TYPE_NONE; \
  110. if (a->arg[n].type == TYPE_NONE) \
  111. a->arg[n].type = (_type_); \
  112. else if (a->arg[n].type != (_type_)) \
  113. /* Ambiguous type for positional argument. */ \
  114. goto error; \
  115. }
  116. while (*cp != '\0')
  117. {
  118. CHAR_T c = *cp++;
  119. if (c == '%')
  120. {
  121. size_t arg_index = ARG_NONE;
  122. DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
  123. /* Initialize the next directive. */
  124. dp->dir_start = cp - 1;
  125. dp->flags = 0;
  126. dp->width_start = NULL;
  127. dp->width_end = NULL;
  128. dp->width_arg_index = ARG_NONE;
  129. dp->precision_start = NULL;
  130. dp->precision_end = NULL;
  131. dp->precision_arg_index = ARG_NONE;
  132. dp->arg_index = ARG_NONE;
  133. /* Test for positional argument. */
  134. if (*cp >= '0' && *cp <= '9')
  135. {
  136. const CHAR_T *np;
  137. for (np = cp; *np >= '0' && *np <= '9'; np++)
  138. ;
  139. if (*np == '$')
  140. {
  141. size_t n = 0;
  142. for (np = cp; *np >= '0' && *np <= '9'; np++)
  143. n = xsum (xtimes (n, 10), *np - '0');
  144. if (n == 0)
  145. /* Positional argument 0. */
  146. goto error;
  147. if (size_overflow_p (n))
  148. /* n too large, would lead to out of memory later. */
  149. goto error;
  150. arg_index = n - 1;
  151. cp = np + 1;
  152. }
  153. }
  154. /* Read the flags. */
  155. for (;;)
  156. {
  157. if (*cp == '\'')
  158. {
  159. dp->flags |= FLAG_GROUP;
  160. cp++;
  161. }
  162. else if (*cp == '-')
  163. {
  164. dp->flags |= FLAG_LEFT;
  165. cp++;
  166. }
  167. else if (*cp == '+')
  168. {
  169. dp->flags |= FLAG_SHOWSIGN;
  170. cp++;
  171. }
  172. else if (*cp == ' ')
  173. {
  174. dp->flags |= FLAG_SPACE;
  175. cp++;
  176. }
  177. else if (*cp == '#')
  178. {
  179. dp->flags |= FLAG_ALT;
  180. cp++;
  181. }
  182. else if (*cp == '0')
  183. {
  184. dp->flags |= FLAG_ZERO;
  185. cp++;
  186. }
  187. else
  188. break;
  189. }
  190. /* Parse the field width. */
  191. if (*cp == '*')
  192. {
  193. dp->width_start = cp;
  194. cp++;
  195. dp->width_end = cp;
  196. if (max_width_length < 1)
  197. max_width_length = 1;
  198. /* Test for positional argument. */
  199. if (*cp >= '0' && *cp <= '9')
  200. {
  201. const CHAR_T *np;
  202. for (np = cp; *np >= '0' && *np <= '9'; np++)
  203. ;
  204. if (*np == '$')
  205. {
  206. size_t n = 0;
  207. for (np = cp; *np >= '0' && *np <= '9'; np++)
  208. n = xsum (xtimes (n, 10), *np - '0');
  209. if (n == 0)
  210. /* Positional argument 0. */
  211. goto error;
  212. if (size_overflow_p (n))
  213. /* n too large, would lead to out of memory later. */
  214. goto error;
  215. dp->width_arg_index = n - 1;
  216. cp = np + 1;
  217. }
  218. }
  219. if (dp->width_arg_index == ARG_NONE)
  220. {
  221. dp->width_arg_index = arg_posn++;
  222. if (dp->width_arg_index == ARG_NONE)
  223. /* arg_posn wrapped around. */
  224. goto error;
  225. }
  226. REGISTER_ARG (dp->width_arg_index, TYPE_INT);
  227. }
  228. else if (*cp >= '0' && *cp <= '9')
  229. {
  230. size_t width_length;
  231. dp->width_start = cp;
  232. for (; *cp >= '0' && *cp <= '9'; cp++)
  233. ;
  234. dp->width_end = cp;
  235. width_length = dp->width_end - dp->width_start;
  236. if (max_width_length < width_length)
  237. max_width_length = width_length;
  238. }
  239. /* Parse the precision. */
  240. if (*cp == '.')
  241. {
  242. cp++;
  243. if (*cp == '*')
  244. {
  245. dp->precision_start = cp - 1;
  246. cp++;
  247. dp->precision_end = cp;
  248. if (max_precision_length < 2)
  249. max_precision_length = 2;
  250. /* Test for positional argument. */
  251. if (*cp >= '0' && *cp <= '9')
  252. {
  253. const CHAR_T *np;
  254. for (np = cp; *np >= '0' && *np <= '9'; np++)
  255. ;
  256. if (*np == '$')
  257. {
  258. size_t n = 0;
  259. for (np = cp; *np >= '0' && *np <= '9'; np++)
  260. n = xsum (xtimes (n, 10), *np - '0');
  261. if (n == 0)
  262. /* Positional argument 0. */
  263. goto error;
  264. if (size_overflow_p (n))
  265. /* n too large, would lead to out of memory
  266. later. */
  267. goto error;
  268. dp->precision_arg_index = n - 1;
  269. cp = np + 1;
  270. }
  271. }
  272. if (dp->precision_arg_index == ARG_NONE)
  273. {
  274. dp->precision_arg_index = arg_posn++;
  275. if (dp->precision_arg_index == ARG_NONE)
  276. /* arg_posn wrapped around. */
  277. goto error;
  278. }
  279. REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
  280. }
  281. else
  282. {
  283. size_t precision_length;
  284. dp->precision_start = cp - 1;
  285. for (; *cp >= '0' && *cp <= '9'; cp++)
  286. ;
  287. dp->precision_end = cp;
  288. precision_length = dp->precision_end - dp->precision_start;
  289. if (max_precision_length < precision_length)
  290. max_precision_length = precision_length;
  291. }
  292. }
  293. {
  294. arg_type type;
  295. /* Parse argument type/size specifiers. */
  296. {
  297. int flags = 0;
  298. for (;;)
  299. {
  300. if (*cp == 'h')
  301. {
  302. flags |= (1 << (flags & 1));
  303. cp++;
  304. }
  305. else if (*cp == 'L')
  306. {
  307. flags |= 4;
  308. cp++;
  309. }
  310. else if (*cp == 'l')
  311. {
  312. flags += 8;
  313. cp++;
  314. }
  315. else if (*cp == 'j')
  316. {
  317. if (sizeof (intmax_t) > sizeof (long))
  318. {
  319. /* intmax_t = long long */
  320. flags += 16;
  321. }
  322. else if (sizeof (intmax_t) > sizeof (int))
  323. {
  324. /* intmax_t = long */
  325. flags += 8;
  326. }
  327. cp++;
  328. }
  329. else if (*cp == 'z' || *cp == 'Z')
  330. {
  331. /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
  332. because the warning facility in gcc-2.95.2 understands
  333. only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
  334. if (sizeof (size_t) > sizeof (long))
  335. {
  336. /* size_t = long long */
  337. flags += 16;
  338. }
  339. else if (sizeof (size_t) > sizeof (int))
  340. {
  341. /* size_t = long */
  342. flags += 8;
  343. }
  344. cp++;
  345. }
  346. else if (*cp == 't')
  347. {
  348. if (sizeof (ptrdiff_t) > sizeof (long))
  349. {
  350. /* ptrdiff_t = long long */
  351. flags += 16;
  352. }
  353. else if (sizeof (ptrdiff_t) > sizeof (int))
  354. {
  355. /* ptrdiff_t = long */
  356. flags += 8;
  357. }
  358. cp++;
  359. }
  360. else
  361. break;
  362. }
  363. /* Read the conversion character. */
  364. c = *cp++;
  365. switch (c)
  366. {
  367. case 'd': case 'i':
  368. #if HAVE_LONG_LONG_INT
  369. /* If 'long long' exists and is larger than 'long': */
  370. if (flags >= 16 || (flags & 4))
  371. type = TYPE_LONGLONGINT;
  372. else
  373. #endif
  374. /* If 'long long' exists and is the same as 'long', we parse
  375. "lld" into TYPE_LONGINT. */
  376. if (flags >= 8)
  377. type = TYPE_LONGINT;
  378. else if (flags & 2)
  379. type = TYPE_SCHAR;
  380. else if (flags & 1)
  381. type = TYPE_SHORT;
  382. else
  383. type = TYPE_INT;
  384. break;
  385. case 'o': case 'u': case 'x': case 'X':
  386. #if HAVE_LONG_LONG_INT
  387. /* If 'long long' exists and is larger than 'long': */
  388. if (flags >= 16 || (flags & 4))
  389. type = TYPE_ULONGLONGINT;
  390. else
  391. #endif
  392. /* If 'unsigned long long' exists and is the same as
  393. 'unsigned long', we parse "llu" into TYPE_ULONGINT. */
  394. if (flags >= 8)
  395. type = TYPE_ULONGINT;
  396. else if (flags & 2)
  397. type = TYPE_UCHAR;
  398. else if (flags & 1)
  399. type = TYPE_USHORT;
  400. else
  401. type = TYPE_UINT;
  402. break;
  403. case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
  404. case 'a': case 'A':
  405. if (flags >= 16 || (flags & 4))
  406. type = TYPE_LONGDOUBLE;
  407. else
  408. type = TYPE_DOUBLE;
  409. break;
  410. case 'c':
  411. if (flags >= 8)
  412. #if HAVE_WINT_T
  413. type = TYPE_WIDE_CHAR;
  414. #else
  415. goto error;
  416. #endif
  417. else
  418. type = TYPE_CHAR;
  419. break;
  420. #if HAVE_WINT_T
  421. case 'C':
  422. type = TYPE_WIDE_CHAR;
  423. c = 'c';
  424. break;
  425. #endif
  426. case 's':
  427. if (flags >= 8)
  428. #if HAVE_WCHAR_T
  429. type = TYPE_WIDE_STRING;
  430. #else
  431. goto error;
  432. #endif
  433. else
  434. type = TYPE_STRING;
  435. break;
  436. #if HAVE_WCHAR_T
  437. case 'S':
  438. type = TYPE_WIDE_STRING;
  439. c = 's';
  440. break;
  441. #endif
  442. case 'p':
  443. type = TYPE_POINTER;
  444. break;
  445. case 'n':
  446. #if HAVE_LONG_LONG_INT
  447. /* If 'long long' exists and is larger than 'long': */
  448. if (flags >= 16 || (flags & 4))
  449. type = TYPE_COUNT_LONGLONGINT_POINTER;
  450. else
  451. #endif
  452. /* If 'long long' exists and is the same as 'long', we parse
  453. "lln" into TYPE_COUNT_LONGINT_POINTER. */
  454. if (flags >= 8)
  455. type = TYPE_COUNT_LONGINT_POINTER;
  456. else if (flags & 2)
  457. type = TYPE_COUNT_SCHAR_POINTER;
  458. else if (flags & 1)
  459. type = TYPE_COUNT_SHORT_POINTER;
  460. else
  461. type = TYPE_COUNT_INT_POINTER;
  462. break;
  463. #if ENABLE_UNISTDIO
  464. /* The unistdio extensions. */
  465. case 'U':
  466. if (flags >= 16)
  467. type = TYPE_U32_STRING;
  468. else if (flags >= 8)
  469. type = TYPE_U16_STRING;
  470. else
  471. type = TYPE_U8_STRING;
  472. break;
  473. #endif
  474. case '%':
  475. type = TYPE_NONE;
  476. break;
  477. default:
  478. /* Unknown conversion character. */
  479. goto error;
  480. }
  481. }
  482. if (type != TYPE_NONE)
  483. {
  484. dp->arg_index = arg_index;
  485. if (dp->arg_index == ARG_NONE)
  486. {
  487. dp->arg_index = arg_posn++;
  488. if (dp->arg_index == ARG_NONE)
  489. /* arg_posn wrapped around. */
  490. goto error;
  491. }
  492. REGISTER_ARG (dp->arg_index, type);
  493. }
  494. dp->conversion = c;
  495. dp->dir_end = cp;
  496. }
  497. d->count++;
  498. if (d->count >= d_allocated)
  499. {
  500. size_t memory_size;
  501. DIRECTIVE *memory;
  502. d_allocated = xtimes (d_allocated, 2);
  503. memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
  504. if (size_overflow_p (memory_size))
  505. /* Overflow, would lead to out of memory. */
  506. goto out_of_memory;
  507. memory = (DIRECTIVE *) realloc (d->dir, memory_size);
  508. if (memory == NULL)
  509. /* Out of memory. */
  510. goto out_of_memory;
  511. d->dir = memory;
  512. }
  513. }
  514. #if CHAR_T_ONLY_ASCII
  515. else if (!c_isascii (c))
  516. {
  517. /* Non-ASCII character. Not supported. */
  518. goto error;
  519. }
  520. #endif
  521. }
  522. d->dir[d->count].dir_start = cp;
  523. d->max_width_length = max_width_length;
  524. d->max_precision_length = max_precision_length;
  525. return 0;
  526. error:
  527. if (a->arg)
  528. free (a->arg);
  529. if (d->dir)
  530. free (d->dir);
  531. errno = EINVAL;
  532. return -1;
  533. out_of_memory:
  534. if (a->arg)
  535. free (a->arg);
  536. if (d->dir)
  537. free (d->dir);
  538. out_of_memory_1:
  539. errno = ENOMEM;
  540. return -1;
  541. }
  542. #undef PRINTF_PARSE
  543. #undef DIRECTIVES
  544. #undef DIRECTIVE
  545. #undef CHAR_T_ONLY_ASCII
  546. #undef CHAR_T