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