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