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