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