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