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