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