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