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