xref: /netbsd-src/external/gpl2/texinfo/dist/intl/printf-parse.c (revision 29619d2afe564e54d657b83e5a3ae89584f83720)
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