xref: /openbsd-src/gnu/usr.bin/texinfo/intl/printf-parse.c (revision a1acfa9b69ad64eb720639240c8438f11107dc85)
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