Line data Source code
1 : /* Formatted output to strings.
2 : Copyright (C) 1999-2000, 2002-2003, 2006-2025 Free Software Foundation, Inc.
3 :
4 : This file is free software: you can redistribute it and/or modify
5 : it under the terms of the GNU Lesser General Public License as
6 : published by the Free Software Foundation; either version 2.1 of the
7 : License, or (at your option) any later version.
8 :
9 : This file 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 Lesser General Public License for more details.
13 :
14 : You should have received a copy of the GNU Lesser General Public License
15 : along with this program. If not, see <https://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 : #include <stdint.h>
52 :
53 : /* malloc(), realloc(), free(). */
54 : #include <stdlib.h>
55 :
56 : /* memcpy(). */
57 : #include <string.h>
58 :
59 : /* errno. */
60 : #include <errno.h>
61 :
62 : /* Checked size_t computations. */
63 : #include "xsize.h"
64 :
65 : #if CHAR_T_ONLY_ASCII
66 : /* c_isascii(). */
67 : # include "c-ctype.h"
68 : #endif
69 :
70 : #ifdef STATIC
71 : STATIC
72 : #endif
73 : int
74 14391 : PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
75 : {
76 14391 : const CHAR_T *cp = format; /* pointer into format */
77 14391 : size_t arg_posn = 0; /* number of regular arguments consumed */
78 : size_t d_allocated; /* allocated elements of d->dir */
79 : size_t a_allocated; /* allocated elements of a->arg */
80 14391 : size_t max_width_length = 0;
81 14391 : size_t max_precision_length = 0;
82 :
83 14391 : d->count = 0;
84 14391 : d_allocated = N_DIRECT_ALLOC_DIRECTIVES;
85 14391 : d->dir = d->direct_alloc_dir;
86 :
87 14391 : a->count = 0;
88 14391 : a_allocated = N_DIRECT_ALLOC_ARGUMENTS;
89 14391 : a->arg = a->direct_alloc_arg;
90 :
91 : #define REGISTER_ARG(_index_,_type_) \
92 : { \
93 : size_t n = (_index_); \
94 : if (n >= a_allocated) \
95 : { \
96 : size_t memory_size; \
97 : argument *memory; \
98 : \
99 : a_allocated = xtimes (a_allocated, 2); \
100 : if (a_allocated <= n) \
101 : a_allocated = xsum (n, 1); \
102 : memory_size = xtimes (a_allocated, sizeof (argument)); \
103 : if (size_overflow_p (memory_size)) \
104 : /* Overflow, would lead to out of memory. */ \
105 : goto out_of_memory; \
106 : memory = (argument *) (a->arg != a->direct_alloc_arg \
107 : ? realloc (a->arg, memory_size) \
108 : : malloc (memory_size)); \
109 : if (memory == NULL) \
110 : /* Out of memory. */ \
111 : goto out_of_memory; \
112 : if (a->arg == a->direct_alloc_arg) \
113 : memcpy (memory, a->arg, a->count * sizeof (argument)); \
114 : a->arg = memory; \
115 : } \
116 : while (a->count <= n) \
117 : a->arg[a->count++].type = TYPE_NONE; \
118 : if (a->arg[n].type == TYPE_NONE) \
119 : a->arg[n].type = (_type_); \
120 : else if (a->arg[n].type != (_type_)) \
121 : /* Ambiguous type for positional argument. */ \
122 : goto error; \
123 : }
124 :
125 40944 : while (*cp != '\0')
126 : {
127 26553 : CHAR_T c = *cp++;
128 26553 : if (c == '%')
129 : {
130 15407 : size_t arg_index = ARG_NONE;
131 15407 : DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
132 :
133 : /* Initialize the next directive. */
134 15407 : dp->dir_start = cp - 1;
135 15407 : dp->flags = 0;
136 15407 : dp->width_start = NULL;
137 15407 : dp->width_end = NULL;
138 15407 : dp->width_arg_index = ARG_NONE;
139 15407 : dp->precision_start = NULL;
140 15407 : dp->precision_end = NULL;
141 15407 : dp->precision_arg_index = ARG_NONE;
142 15407 : dp->arg_index = ARG_NONE;
143 :
144 : /* Test for positional argument. */
145 15407 : if (*cp >= '0' && *cp <= '9')
146 : {
147 : const CHAR_T *np;
148 :
149 40875 : for (np = cp; *np >= '0' && *np <= '9'; np++)
150 : ;
151 13625 : if (*np == '$')
152 : {
153 0 : size_t n = 0;
154 :
155 0 : for (np = cp; *np >= '0' && *np <= '9'; np++)
156 0 : n = xsum (xtimes (n, 10), *np - '0');
157 0 : if (n == 0)
158 : /* Positional argument 0. */
159 0 : goto error;
160 0 : if (size_overflow_p (n))
161 : /* n too large, would lead to out of memory later. */
162 0 : goto error;
163 0 : arg_index = n - 1;
164 0 : cp = np + 1;
165 : }
166 : }
167 :
168 : /* Read the flags. */
169 : for (;;)
170 : {
171 29032 : if (*cp == '\'')
172 : {
173 0 : dp->flags |= FLAG_GROUP;
174 0 : cp++;
175 : }
176 29032 : else if (*cp == '-')
177 : {
178 0 : dp->flags |= FLAG_LEFT;
179 0 : cp++;
180 : }
181 29032 : else if (*cp == '+')
182 : {
183 0 : dp->flags |= FLAG_SHOWSIGN;
184 0 : cp++;
185 : }
186 29032 : else if (*cp == ' ')
187 : {
188 0 : dp->flags |= FLAG_SPACE;
189 0 : cp++;
190 : }
191 29032 : else if (*cp == '#')
192 : {
193 0 : dp->flags |= FLAG_ALT;
194 0 : cp++;
195 : }
196 29032 : else if (*cp == '0')
197 : {
198 13625 : dp->flags |= FLAG_ZERO;
199 13625 : cp++;
200 : }
201 : #if __GLIBC__ >= 2 && !defined __UCLIBC__
202 15407 : else if (*cp == 'I')
203 : {
204 0 : dp->flags |= FLAG_LOCALIZED;
205 0 : cp++;
206 : }
207 : #endif
208 : else
209 15407 : break;
210 : }
211 :
212 : /* Parse the field width. */
213 15407 : if (*cp == '*')
214 : {
215 0 : dp->width_start = cp;
216 0 : cp++;
217 0 : dp->width_end = cp;
218 0 : if (max_width_length < 1)
219 0 : max_width_length = 1;
220 :
221 : /* Test for positional argument. */
222 0 : if (*cp >= '0' && *cp <= '9')
223 : {
224 : const CHAR_T *np;
225 :
226 0 : for (np = cp; *np >= '0' && *np <= '9'; np++)
227 : ;
228 0 : if (*np == '$')
229 : {
230 0 : size_t n = 0;
231 :
232 0 : for (np = cp; *np >= '0' && *np <= '9'; np++)
233 0 : n = xsum (xtimes (n, 10), *np - '0');
234 0 : if (n == 0)
235 : /* Positional argument 0. */
236 0 : goto error;
237 0 : if (size_overflow_p (n))
238 : /* n too large, would lead to out of memory later. */
239 0 : goto error;
240 0 : dp->width_arg_index = n - 1;
241 0 : cp = np + 1;
242 : }
243 : }
244 0 : if (dp->width_arg_index == ARG_NONE)
245 : {
246 0 : dp->width_arg_index = arg_posn++;
247 0 : if (dp->width_arg_index == ARG_NONE)
248 : /* arg_posn wrapped around. */
249 0 : goto error;
250 : }
251 0 : REGISTER_ARG (dp->width_arg_index, TYPE_INT);
252 : }
253 15407 : else if (*cp >= '0' && *cp <= '9')
254 : {
255 : size_t width_length;
256 :
257 13625 : dp->width_start = cp;
258 27250 : for (; *cp >= '0' && *cp <= '9'; cp++)
259 : ;
260 13625 : dp->width_end = cp;
261 13625 : width_length = dp->width_end - dp->width_start;
262 13625 : if (max_width_length < width_length)
263 13625 : max_width_length = width_length;
264 : }
265 :
266 : /* Parse the precision. */
267 15407 : if (*cp == '.')
268 : {
269 10 : cp++;
270 10 : if (*cp == '*')
271 : {
272 0 : dp->precision_start = cp - 1;
273 0 : cp++;
274 0 : dp->precision_end = cp;
275 0 : if (max_precision_length < 2)
276 0 : max_precision_length = 2;
277 :
278 : /* Test for positional argument. */
279 0 : if (*cp >= '0' && *cp <= '9')
280 : {
281 : const CHAR_T *np;
282 :
283 0 : for (np = cp; *np >= '0' && *np <= '9'; np++)
284 : ;
285 0 : if (*np == '$')
286 : {
287 0 : size_t n = 0;
288 :
289 0 : for (np = cp; *np >= '0' && *np <= '9'; np++)
290 0 : n = xsum (xtimes (n, 10), *np - '0');
291 0 : if (n == 0)
292 : /* Positional argument 0. */
293 0 : goto error;
294 0 : if (size_overflow_p (n))
295 : /* n too large, would lead to out of memory
296 : later. */
297 0 : goto error;
298 0 : dp->precision_arg_index = n - 1;
299 0 : cp = np + 1;
300 : }
301 : }
302 0 : if (dp->precision_arg_index == ARG_NONE)
303 : {
304 0 : dp->precision_arg_index = arg_posn++;
305 0 : if (dp->precision_arg_index == ARG_NONE)
306 : /* arg_posn wrapped around. */
307 0 : goto error;
308 : }
309 0 : REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
310 : }
311 : else
312 : {
313 : size_t precision_length;
314 :
315 10 : dp->precision_start = cp - 1;
316 20 : for (; *cp >= '0' && *cp <= '9'; cp++)
317 : ;
318 10 : dp->precision_end = cp;
319 10 : precision_length = dp->precision_end - dp->precision_start;
320 10 : if (max_precision_length < precision_length)
321 10 : max_precision_length = precision_length;
322 : }
323 : }
324 :
325 : {
326 : arg_type type;
327 :
328 : /* Parse argument type/size specifiers. */
329 : /* Relevant for the conversion characters d, i. */
330 15407 : arg_type signed_type = TYPE_INT;
331 : /* Relevant for the conversion characters b, o, u, x, X. */
332 15407 : arg_type unsigned_type = TYPE_UINT;
333 : /* Relevant for the conversion characters n. */
334 15407 : arg_type pointer_type = TYPE_COUNT_INT_POINTER;
335 : /* Relevant for the conversion characters a, A, e, E, f, F, g, G. */
336 15407 : arg_type floatingpoint_type = TYPE_DOUBLE;
337 :
338 15407 : if (*cp == 'h')
339 : {
340 0 : if (cp[1] == 'h')
341 : {
342 0 : signed_type = TYPE_SCHAR;
343 0 : unsigned_type = TYPE_UCHAR;
344 0 : pointer_type = TYPE_COUNT_SCHAR_POINTER;
345 0 : cp += 2;
346 : }
347 : else
348 : {
349 0 : signed_type = TYPE_SHORT;
350 0 : unsigned_type = TYPE_USHORT;
351 0 : pointer_type = TYPE_COUNT_SHORT_POINTER;
352 0 : cp++;
353 : }
354 : }
355 15407 : else if (*cp == 'l')
356 : {
357 0 : if (cp[1] == 'l')
358 : {
359 0 : signed_type = TYPE_LONGLONGINT;
360 0 : unsigned_type = TYPE_ULONGLONGINT;
361 0 : pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
362 : /* For backward compatibility only. */
363 0 : floatingpoint_type = TYPE_LONGDOUBLE;
364 0 : cp += 2;
365 : }
366 : else
367 : {
368 0 : signed_type = TYPE_LONGINT;
369 0 : unsigned_type = TYPE_ULONGINT;
370 0 : pointer_type = TYPE_COUNT_LONGINT_POINTER;
371 0 : cp++;
372 : }
373 : }
374 15407 : else if (*cp == 'j')
375 : {
376 : if (sizeof (intmax_t) > sizeof (long))
377 : {
378 : /* intmax_t = long long */
379 : signed_type = TYPE_LONGLONGINT;
380 : unsigned_type = TYPE_ULONGLONGINT;
381 : pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
382 : /* For backward compatibility only. */
383 : floatingpoint_type = TYPE_LONGDOUBLE;
384 : }
385 : else if (sizeof (intmax_t) > sizeof (int))
386 : {
387 : /* intmax_t = long */
388 0 : signed_type = TYPE_LONGINT;
389 0 : unsigned_type = TYPE_ULONGINT;
390 0 : pointer_type = TYPE_COUNT_LONGINT_POINTER;
391 : }
392 0 : cp++;
393 : }
394 15407 : else if (*cp == 'z' || *cp == 'Z')
395 : {
396 : /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
397 : because the warning facility in gcc-2.95.2 understands
398 : only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
399 : if (sizeof (size_t) > sizeof (long))
400 : {
401 : /* size_t = unsigned long long */
402 : signed_type = TYPE_LONGLONGINT;
403 : unsigned_type = TYPE_ULONGLONGINT;
404 : pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
405 : /* For backward compatibility only. */
406 : floatingpoint_type = TYPE_LONGDOUBLE;
407 : }
408 : else if (sizeof (size_t) > sizeof (int))
409 : {
410 : /* size_t = unsigned long */
411 0 : signed_type = TYPE_LONGINT;
412 0 : unsigned_type = TYPE_ULONGINT;
413 0 : pointer_type = TYPE_COUNT_LONGINT_POINTER;
414 : }
415 0 : cp++;
416 : }
417 15407 : else if (*cp == 't')
418 : {
419 : if (sizeof (ptrdiff_t) > sizeof (long))
420 : {
421 : /* ptrdiff_t = long long */
422 : signed_type = TYPE_LONGLONGINT;
423 : unsigned_type = TYPE_ULONGLONGINT;
424 : pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
425 : /* For backward compatibility only. */
426 : floatingpoint_type = TYPE_LONGDOUBLE;
427 : }
428 : else if (sizeof (ptrdiff_t) > sizeof (int))
429 : {
430 : /* ptrdiff_t = long */
431 0 : signed_type = TYPE_LONGINT;
432 0 : unsigned_type = TYPE_ULONGINT;
433 0 : pointer_type = TYPE_COUNT_LONGINT_POINTER;
434 : }
435 0 : cp++;
436 : }
437 15407 : else if (*cp == 'w')
438 : {
439 : /* wN and wfN are standardized in ISO C 23. */
440 0 : if (cp[1] == 'f')
441 : {
442 0 : if (cp[2] == '8')
443 : {
444 0 : signed_type = TYPE_INT_FAST8_T;
445 0 : unsigned_type = TYPE_UINT_FAST8_T;
446 0 : pointer_type = TYPE_COUNT_INT_FAST8_T_POINTER;
447 0 : cp += 3;
448 : }
449 0 : else if (cp[2] == '1' && cp[3] == '6')
450 : {
451 0 : signed_type = TYPE_INT_FAST16_T;
452 0 : unsigned_type = TYPE_UINT_FAST16_T;
453 0 : pointer_type = TYPE_COUNT_INT_FAST16_T_POINTER;
454 0 : cp += 4;
455 : }
456 0 : else if (cp[2] == '3' && cp[3] == '2')
457 : {
458 0 : signed_type = TYPE_INT_FAST32_T;
459 0 : unsigned_type = TYPE_UINT_FAST32_T;
460 0 : pointer_type = TYPE_COUNT_INT_FAST32_T_POINTER;
461 0 : cp += 4;
462 : }
463 0 : else if (cp[2] == '6' && cp[3] == '4')
464 : {
465 0 : signed_type = TYPE_INT_FAST64_T;
466 0 : unsigned_type = TYPE_UINT_FAST64_T;
467 0 : pointer_type = TYPE_COUNT_INT_FAST64_T_POINTER;
468 0 : cp += 4;
469 : }
470 : }
471 : else
472 : {
473 0 : if (cp[1] == '8')
474 : {
475 0 : signed_type = TYPE_INT8_T;
476 0 : unsigned_type = TYPE_UINT8_T;
477 0 : pointer_type = TYPE_COUNT_INT8_T_POINTER;
478 0 : cp += 2;
479 : }
480 0 : else if (cp[1] == '1' && cp[2] == '6')
481 : {
482 0 : signed_type = TYPE_INT16_T;
483 0 : unsigned_type = TYPE_UINT16_T;
484 0 : pointer_type = TYPE_COUNT_INT16_T_POINTER;
485 0 : cp += 3;
486 : }
487 0 : else if (cp[1] == '3' && cp[2] == '2')
488 : {
489 0 : signed_type = TYPE_INT32_T;
490 0 : unsigned_type = TYPE_UINT32_T;
491 0 : pointer_type = TYPE_COUNT_INT32_T_POINTER;
492 0 : cp += 3;
493 : }
494 0 : else if (cp[1] == '6' && cp[2] == '4')
495 : {
496 0 : signed_type = TYPE_INT64_T;
497 0 : unsigned_type = TYPE_UINT64_T;
498 0 : pointer_type = TYPE_COUNT_INT64_T_POINTER;
499 0 : cp += 3;
500 : }
501 : }
502 : }
503 15407 : else if (*cp == 'L')
504 : {
505 0 : signed_type = TYPE_LONGLONGINT;
506 0 : unsigned_type = TYPE_ULONGLONGINT;
507 0 : pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
508 0 : floatingpoint_type = TYPE_LONGDOUBLE;
509 0 : cp++;
510 : }
511 : #if defined __APPLE__ && defined __MACH__
512 : /* On Mac OS X 10.3, PRIdMAX is defined as "qd".
513 : We cannot change it to "lld" because PRIdMAX must also
514 : be understood by the system's printf routines. */
515 : else if (*cp == 'q')
516 : {
517 : if (64 / 8 > sizeof (long))
518 : {
519 : /* int64_t = long long */
520 : signed_type = TYPE_LONGLONGINT;
521 : unsigned_type = TYPE_ULONGLONGINT;
522 : pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
523 : /* For backward compatibility only. */
524 : floatingpoint_type = TYPE_LONGDOUBLE;
525 : }
526 : else
527 : {
528 : /* int64_t = long */
529 : signed_type = TYPE_LONGINT;
530 : unsigned_type = TYPE_ULONGINT;
531 : pointer_type = TYPE_COUNT_LONGINT_POINTER;
532 : }
533 : cp++;
534 : }
535 : #endif
536 : #if defined _WIN32 && ! defined __CYGWIN__
537 : /* On native Windows, PRIdMAX is defined as "I64d".
538 : We cannot change it to "lld" because PRIdMAX must also
539 : be understood by the system's printf routines. */
540 : else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
541 : {
542 : if (64 / 8 > sizeof (long))
543 : {
544 : /* __int64_t = long long */
545 : signed_type = TYPE_LONGLONGINT;
546 : unsigned_type = TYPE_ULONGLONGINT;
547 : pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
548 : /* For backward compatibility only. */
549 : floatingpoint_type = TYPE_LONGDOUBLE;
550 : }
551 : else
552 : {
553 : /* __int64_t = long */
554 : signed_type = TYPE_LONGINT;
555 : unsigned_type = TYPE_ULONGINT;
556 : pointer_type = TYPE_COUNT_LONGINT_POINTER;
557 : }
558 : cp += 3;
559 : }
560 : #endif
561 : (void) pointer_type;
562 :
563 : /* Read the conversion character. */
564 15407 : c = *cp++;
565 15407 : switch (c)
566 : {
567 755 : case 'd': case 'i':
568 755 : type = signed_type;
569 755 : break;
570 13705 : case 'b': case 'o': case 'u': case 'x': case 'X':
571 : #if SUPPORT_GNU_PRINTF_DIRECTIVES \
572 : || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
573 : case 'B':
574 : #endif
575 13705 : type = unsigned_type;
576 13705 : break;
577 43 : case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
578 : case 'a': case 'A':
579 43 : type = floatingpoint_type;
580 43 : break;
581 31 : case 'c':
582 31 : if (signed_type == TYPE_LONGINT
583 : /* For backward compatibility only. */
584 31 : || signed_type == TYPE_LONGLONGINT)
585 : #if HAVE_WINT_T
586 0 : type = TYPE_WIDE_CHAR;
587 : #else
588 : goto error;
589 : #endif
590 : else
591 31 : type = TYPE_CHAR;
592 31 : break;
593 : #if HAVE_WINT_T
594 0 : case 'C':
595 0 : type = TYPE_WIDE_CHAR;
596 0 : c = 'c';
597 0 : break;
598 : #endif
599 713 : case 's':
600 713 : if (signed_type == TYPE_LONGINT
601 : /* For backward compatibility only. */
602 713 : || signed_type == TYPE_LONGLONGINT)
603 0 : type = TYPE_WIDE_STRING;
604 : else
605 713 : type = TYPE_STRING;
606 713 : break;
607 0 : case 'S':
608 0 : type = TYPE_WIDE_STRING;
609 0 : c = 's';
610 0 : break;
611 0 : case 'p':
612 0 : type = TYPE_POINTER;
613 0 : break;
614 : #if NEED_PRINTF_WITH_N_DIRECTIVE
615 : case 'n':
616 : type = pointer_type;
617 : break;
618 : #endif
619 : #if ENABLE_UNISTDIO
620 : /* The unistdio extensions. */
621 : case 'U':
622 : if (signed_type == TYPE_LONGLONGINT)
623 : type = TYPE_U32_STRING;
624 : else if (signed_type == TYPE_LONGINT)
625 : type = TYPE_U16_STRING;
626 : else
627 : type = TYPE_U8_STRING;
628 : break;
629 : #endif
630 160 : case '%':
631 160 : type = TYPE_NONE;
632 160 : break;
633 0 : default:
634 : /* Unknown conversion character. */
635 0 : goto error;
636 : }
637 :
638 15407 : if (type != TYPE_NONE)
639 : {
640 15247 : dp->arg_index = arg_index;
641 15247 : if (dp->arg_index == ARG_NONE)
642 : {
643 15247 : dp->arg_index = arg_posn++;
644 15247 : if (dp->arg_index == ARG_NONE)
645 : /* arg_posn wrapped around. */
646 0 : goto error;
647 : }
648 30494 : REGISTER_ARG (dp->arg_index, type);
649 : }
650 15407 : dp->conversion = c;
651 15407 : dp->dir_end = cp;
652 : }
653 :
654 15407 : d->count++;
655 15407 : if (d->count >= d_allocated)
656 : {
657 : size_t memory_size;
658 : DIRECTIVE *memory;
659 :
660 99 : d_allocated = xtimes (d_allocated, 2);
661 99 : memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
662 99 : if (size_overflow_p (memory_size))
663 : /* Overflow, would lead to out of memory. */
664 0 : goto out_of_memory;
665 99 : memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir
666 0 : ? realloc (d->dir, memory_size)
667 99 : : malloc (memory_size));
668 99 : if (memory == NULL)
669 : /* Out of memory. */
670 0 : goto out_of_memory;
671 99 : if (d->dir == d->direct_alloc_dir)
672 99 : memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE));
673 99 : d->dir = memory;
674 : }
675 : }
676 : #if CHAR_T_ONLY_ASCII
677 : else if (!c_isascii (c))
678 : {
679 : /* Non-ASCII character. Not supported. */
680 : goto error;
681 : }
682 : #endif
683 : }
684 14391 : d->dir[d->count].dir_start = cp;
685 :
686 14391 : d->max_width_length = max_width_length;
687 14391 : d->max_precision_length = max_precision_length;
688 14391 : return 0;
689 :
690 0 : error:
691 0 : if (a->arg != a->direct_alloc_arg)
692 0 : free (a->arg);
693 0 : if (d->dir != d->direct_alloc_dir)
694 0 : free (d->dir);
695 0 : errno = EINVAL;
696 0 : return -1;
697 :
698 0 : out_of_memory:
699 0 : if (a->arg != a->direct_alloc_arg)
700 0 : free (a->arg);
701 0 : if (d->dir != d->direct_alloc_dir)
702 0 : free (d->dir);
703 0 : errno = ENOMEM;
704 0 : return -1;
705 : }
706 :
707 : #undef PRINTF_PARSE
708 : #undef DIRECTIVES
709 : #undef DIRECTIVE
710 : #undef CHAR_T_ONLY_ASCII
711 : #undef CHAR_T
|