Branch data Line data Source code
1 : : /* Formatted output to strings.
2 : : Copyright (C) 1999-2000, 2002-2003, 2006-2012 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 <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 : 36 : PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
84 : : {
85 : 36 : const CHAR_T *cp = format; /* pointer into format */
86 : 36 : 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 : 36 : size_t max_width_length = 0;
90 : 36 : size_t max_precision_length = 0;
91 : :
92 : 36 : d->count = 0;
93 : 36 : d_allocated = N_DIRECT_ALLOC_DIRECTIVES;
94 : 36 : d->dir = d->direct_alloc_dir;
95 : :
96 : 36 : a->count = 0;
97 : 36 : a_allocated = N_DIRECT_ALLOC_ARGUMENTS;
98 : 36 : 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 [ + + ]: 72 : while (*cp != '\0')
135 : : {
136 : 36 : CHAR_T c = *cp++;
137 [ + - ]: 36 : if (c == '%')
138 : : {
139 : 36 : size_t arg_index = ARG_NONE;
140 : 36 : DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
141 : :
142 : : /* Initialize the next directive. */
143 : 36 : dp->dir_start = cp - 1;
144 : 36 : dp->flags = 0;
145 : 36 : dp->width_start = NULL;
146 : 36 : dp->width_end = NULL;
147 : 36 : dp->width_arg_index = ARG_NONE;
148 : 36 : dp->precision_start = NULL;
149 : 36 : dp->precision_end = NULL;
150 : 36 : dp->precision_arg_index = ARG_NONE;
151 : 36 : dp->arg_index = ARG_NONE;
152 : :
153 : : /* Test for positional argument. */
154 [ + - ][ - + ]: 36 : 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 [ - + ]: 36 : if (*cp == '\'')
181 : : {
182 : 0 : dp->flags |= FLAG_GROUP;
183 : 0 : cp++;
184 : : }
185 [ - + ]: 36 : else if (*cp == '-')
186 : : {
187 : 0 : dp->flags |= FLAG_LEFT;
188 : 0 : cp++;
189 : : }
190 [ - + ]: 36 : else if (*cp == '+')
191 : : {
192 : 0 : dp->flags |= FLAG_SHOWSIGN;
193 : 0 : cp++;
194 : : }
195 [ - + ]: 36 : else if (*cp == ' ')
196 : : {
197 : 0 : dp->flags |= FLAG_SPACE;
198 : 0 : cp++;
199 : : }
200 [ - + ]: 36 : else if (*cp == '#')
201 : : {
202 : 0 : dp->flags |= FLAG_ALT;
203 : 0 : cp++;
204 : : }
205 [ - + ]: 36 : else if (*cp == '0')
206 : : {
207 : 0 : dp->flags |= FLAG_ZERO;
208 : 0 : cp++;
209 : : }
210 : : #if __GLIBC__ >= 2 && !defined __UCLIBC__
211 [ - + ]: 36 : else if (*cp == 'I')
212 : : {
213 : 0 : dp->flags |= FLAG_LOCALIZED;
214 : 0 : cp++;
215 : : }
216 : : #endif
217 : : else
218 : 36 : break;
219 : 0 : }
220 : :
221 : : /* Parse the field width. */
222 [ - + ]: 36 : 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 [ + - ][ - + ]: 36 : 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 [ - + ]: 36 : 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 : 36 : int flags = 0;
340 : :
341 : : for (;;)
342 : : {
343 [ - + ]: 36 : if (*cp == 'h')
344 : : {
345 : 0 : flags |= (1 << (flags & 1));
346 : 0 : cp++;
347 : : }
348 [ - + ]: 36 : else if (*cp == 'L')
349 : : {
350 : 0 : flags |= 4;
351 : 0 : cp++;
352 : : }
353 [ - + ]: 36 : else if (*cp == 'l')
354 : : {
355 : 0 : flags += 8;
356 : 0 : cp++;
357 : : }
358 [ - + ]: 36 : 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 [ + - ][ - + ]: 36 : 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 [ - + ]: 36 : 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 MacOS 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 : 36 : break;
443 : 0 : }
444 : :
445 : : /* Read the conversion character. */
446 : 36 : c = *cp++;
447 [ + - - - : 36 : 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 [ + - ][ - + ]: 36 : 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 [ - + ]: 36 : if (flags >= 8)
459 : 0 : type = TYPE_LONGINT;
460 [ - + ]: 36 : else if (flags & 2)
461 : 0 : type = TYPE_SCHAR;
462 [ - + ]: 36 : else if (flags & 1)
463 : 0 : type = TYPE_SHORT;
464 : : else
465 : 36 : type = TYPE_INT;
466 : 36 : 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 [ + - ]: 36 : if (type != TYPE_NONE)
566 : : {
567 : 36 : dp->arg_index = arg_index;
568 [ + - ]: 36 : if (dp->arg_index == ARG_NONE)
569 : : {
570 : 36 : dp->arg_index = arg_posn++;
571 [ - + ]: 36 : if (dp->arg_index == ARG_NONE)
572 : : /* arg_posn wrapped around. */
573 : 0 : goto error;
574 : : }
575 [ - + ][ # # ]: 72 : REGISTER_ARG (dp->arg_index, type);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + + ][ + - ]
[ # # ]
576 : : }
577 : 36 : dp->conversion = c;
578 : 36 : dp->dir_end = cp;
579 : : }
580 : :
581 : 36 : d->count++;
582 [ - + ]: 36 : 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 : 36 : d->dir[d->count].dir_start = cp;
612 : :
613 : 36 : d->max_width_length = max_width_length;
614 : 36 : d->max_precision_length = max_precision_length;
615 : 36 : 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 : 36 : return -1;
632 : : }
633 : :
634 : : #undef PRINTF_PARSE
635 : : #undef DIRECTIVES
636 : : #undef DIRECTIVE
637 : : #undef CHAR_T_ONLY_ASCII
638 : : #undef CHAR_T
|