| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590 | 
							- /* Formatted output to strings.
 
-    Copyright (C) 1999-2000, 2002-2003, 2006-2007 Free Software Foundation, Inc.
 
-    This program is free software; you can redistribute it and/or modify it
 
-    under the terms of the GNU Library General Public License as published
 
-    by the Free Software Foundation; either version 2, or (at your option)
 
-    any later version.
 
-    This program is distributed in the hope that it will be useful,
 
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
-    Library General Public License for more details.
 
-    You should have received a copy of the GNU Library General Public
 
-    License along with this program; if not, write to the Free Software
 
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
-    USA.  */
 
- /* This file can be parametrized with the following macros:
 
-      CHAR_T             The element type of the format string.
 
-      CHAR_T_ONLY_ASCII  Set to 1 to enable verification that all characters
 
-                         in the format string are ASCII.
 
-      DIRECTIVE          Structure denoting a format directive.
 
-                         Depends on CHAR_T.
 
-      DIRECTIVES         Structure denoting the set of format directives of a
 
-                         format string.  Depends on CHAR_T.
 
-      PRINTF_PARSE       Function that parses a format string.
 
-                         Depends on CHAR_T.
 
-      STATIC             Set to 'static' to declare the function static.
 
-      ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.  */
 
- #ifndef PRINTF_PARSE
 
- # include <config.h>
 
- #endif
 
- /* Specification.  */
 
- #ifndef PRINTF_PARSE
 
- # include "printf-parse.h"
 
- #endif
 
- /* Default parameters.  */
 
- #ifndef PRINTF_PARSE
 
- # define PRINTF_PARSE printf_parse
 
- # define CHAR_T char
 
- # define DIRECTIVE char_directive
 
- # define DIRECTIVES char_directives
 
- #endif
 
- /* Get size_t, NULL.  */
 
- #include <stddef.h>
 
- /* Get intmax_t.  */
 
- #if defined IN_LIBINTL || defined IN_LIBASPRINTF
 
- # if HAVE_STDINT_H_WITH_UINTMAX
 
- #  include <stdint.h>
 
- # endif
 
- # if HAVE_INTTYPES_H_WITH_UINTMAX
 
- #  include <inttypes.h>
 
- # endif
 
- #else
 
- # include <stdint.h>
 
- #endif
 
- /* malloc(), realloc(), free().  */
 
- #include <stdlib.h>
 
- /* errno.  */
 
- #include <errno.h>
 
- /* Checked size_t computations.  */
 
- #include "xsize.h"
 
- #if CHAR_T_ONLY_ASCII
 
- /* c_isascii().  */
 
- # include "c-ctype.h"
 
- #endif
 
- #ifdef STATIC
 
- STATIC
 
- #endif
 
- int
 
- PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
 
- {
 
-   const CHAR_T *cp = format;		/* pointer into format */
 
-   size_t arg_posn = 0;		/* number of regular arguments consumed */
 
-   size_t d_allocated;			/* allocated elements of d->dir */
 
-   size_t a_allocated;			/* allocated elements of a->arg */
 
-   size_t max_width_length = 0;
 
-   size_t max_precision_length = 0;
 
-   d->count = 0;
 
-   d_allocated = 1;
 
-   d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
 
-   if (d->dir == NULL)
 
-     /* Out of memory.  */
 
-     goto out_of_memory_1;
 
-   a->count = 0;
 
-   a_allocated = 0;
 
-   a->arg = NULL;
 
- #define REGISTER_ARG(_index_,_type_) \
 
-   {									\
 
-     size_t n = (_index_);						\
 
-     if (n >= a_allocated)						\
 
-       {									\
 
- 	size_t memory_size;						\
 
- 	argument *memory;						\
 
- 									\
 
- 	a_allocated = xtimes (a_allocated, 2);				\
 
- 	if (a_allocated <= n)						\
 
- 	  a_allocated = xsum (n, 1);					\
 
- 	memory_size = xtimes (a_allocated, sizeof (argument));		\
 
- 	if (size_overflow_p (memory_size))				\
 
- 	  /* Overflow, would lead to out of memory.  */			\
 
- 	  goto out_of_memory;						\
 
- 	memory = (argument *) (a->arg					\
 
- 			       ? realloc (a->arg, memory_size)		\
 
- 			       : malloc (memory_size));			\
 
- 	if (memory == NULL)						\
 
- 	  /* Out of memory.  */						\
 
- 	  goto out_of_memory;						\
 
- 	a->arg = memory;						\
 
-       }									\
 
-     while (a->count <= n)						\
 
-       a->arg[a->count++].type = TYPE_NONE;				\
 
-     if (a->arg[n].type == TYPE_NONE)					\
 
-       a->arg[n].type = (_type_);					\
 
-     else if (a->arg[n].type != (_type_))				\
 
-       /* Ambiguous type for positional argument.  */			\
 
-       goto error;							\
 
-   }
 
-   while (*cp != '\0')
 
-     {
 
-       CHAR_T c = *cp++;
 
-       if (c == '%')
 
- 	{
 
- 	  size_t arg_index = ARG_NONE;
 
- 	  DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
 
- 	  /* Initialize the next directive.  */
 
- 	  dp->dir_start = cp - 1;
 
- 	  dp->flags = 0;
 
- 	  dp->width_start = NULL;
 
- 	  dp->width_end = NULL;
 
- 	  dp->width_arg_index = ARG_NONE;
 
- 	  dp->precision_start = NULL;
 
- 	  dp->precision_end = NULL;
 
- 	  dp->precision_arg_index = ARG_NONE;
 
- 	  dp->arg_index = ARG_NONE;
 
- 	  /* Test for positional argument.  */
 
- 	  if (*cp >= '0' && *cp <= '9')
 
- 	    {
 
- 	      const CHAR_T *np;
 
- 	      for (np = cp; *np >= '0' && *np <= '9'; np++)
 
- 		;
 
- 	      if (*np == '$')
 
- 		{
 
- 		  size_t n = 0;
 
- 		  for (np = cp; *np >= '0' && *np <= '9'; np++)
 
- 		    n = xsum (xtimes (n, 10), *np - '0');
 
- 		  if (n == 0)
 
- 		    /* Positional argument 0.  */
 
- 		    goto error;
 
- 		  if (size_overflow_p (n))
 
- 		    /* n too large, would lead to out of memory later.  */
 
- 		    goto error;
 
- 		  arg_index = n - 1;
 
- 		  cp = np + 1;
 
- 		}
 
- 	    }
 
- 	  /* Read the flags.  */
 
- 	  for (;;)
 
- 	    {
 
- 	      if (*cp == '\'')
 
- 		{
 
- 		  dp->flags |= FLAG_GROUP;
 
- 		  cp++;
 
- 		}
 
- 	      else if (*cp == '-')
 
- 		{
 
- 		  dp->flags |= FLAG_LEFT;
 
- 		  cp++;
 
- 		}
 
- 	      else if (*cp == '+')
 
- 		{
 
- 		  dp->flags |= FLAG_SHOWSIGN;
 
- 		  cp++;
 
- 		}
 
- 	      else if (*cp == ' ')
 
- 		{
 
- 		  dp->flags |= FLAG_SPACE;
 
- 		  cp++;
 
- 		}
 
- 	      else if (*cp == '#')
 
- 		{
 
- 		  dp->flags |= FLAG_ALT;
 
- 		  cp++;
 
- 		}
 
- 	      else if (*cp == '0')
 
- 		{
 
- 		  dp->flags |= FLAG_ZERO;
 
- 		  cp++;
 
- 		}
 
- 	      else
 
- 		break;
 
- 	    }
 
- 	  /* Parse the field width.  */
 
- 	  if (*cp == '*')
 
- 	    {
 
- 	      dp->width_start = cp;
 
- 	      cp++;
 
- 	      dp->width_end = cp;
 
- 	      if (max_width_length < 1)
 
- 		max_width_length = 1;
 
- 	      /* Test for positional argument.  */
 
- 	      if (*cp >= '0' && *cp <= '9')
 
- 		{
 
- 		  const CHAR_T *np;
 
- 		  for (np = cp; *np >= '0' && *np <= '9'; np++)
 
- 		    ;
 
- 		  if (*np == '$')
 
- 		    {
 
- 		      size_t n = 0;
 
- 		      for (np = cp; *np >= '0' && *np <= '9'; np++)
 
- 			n = xsum (xtimes (n, 10), *np - '0');
 
- 		      if (n == 0)
 
- 			/* Positional argument 0.  */
 
- 			goto error;
 
- 		      if (size_overflow_p (n))
 
- 			/* n too large, would lead to out of memory later.  */
 
- 			goto error;
 
- 		      dp->width_arg_index = n - 1;
 
- 		      cp = np + 1;
 
- 		    }
 
- 		}
 
- 	      if (dp->width_arg_index == ARG_NONE)
 
- 		{
 
- 		  dp->width_arg_index = arg_posn++;
 
- 		  if (dp->width_arg_index == ARG_NONE)
 
- 		    /* arg_posn wrapped around.  */
 
- 		    goto error;
 
- 		}
 
- 	      REGISTER_ARG (dp->width_arg_index, TYPE_INT);
 
- 	    }
 
- 	  else if (*cp >= '0' && *cp <= '9')
 
- 	    {
 
- 	      size_t width_length;
 
- 	      dp->width_start = cp;
 
- 	      for (; *cp >= '0' && *cp <= '9'; cp++)
 
- 		;
 
- 	      dp->width_end = cp;
 
- 	      width_length = dp->width_end - dp->width_start;
 
- 	      if (max_width_length < width_length)
 
- 		max_width_length = width_length;
 
- 	    }
 
- 	  /* Parse the precision.  */
 
- 	  if (*cp == '.')
 
- 	    {
 
- 	      cp++;
 
- 	      if (*cp == '*')
 
- 		{
 
- 		  dp->precision_start = cp - 1;
 
- 		  cp++;
 
- 		  dp->precision_end = cp;
 
- 		  if (max_precision_length < 2)
 
- 		    max_precision_length = 2;
 
- 		  /* Test for positional argument.  */
 
- 		  if (*cp >= '0' && *cp <= '9')
 
- 		    {
 
- 		      const CHAR_T *np;
 
- 		      for (np = cp; *np >= '0' && *np <= '9'; np++)
 
- 			;
 
- 		      if (*np == '$')
 
- 			{
 
- 			  size_t n = 0;
 
- 			  for (np = cp; *np >= '0' && *np <= '9'; np++)
 
- 			    n = xsum (xtimes (n, 10), *np - '0');
 
- 			  if (n == 0)
 
- 			    /* Positional argument 0.  */
 
- 			    goto error;
 
- 			  if (size_overflow_p (n))
 
- 			    /* n too large, would lead to out of memory
 
- 			       later.  */
 
- 			    goto error;
 
- 			  dp->precision_arg_index = n - 1;
 
- 			  cp = np + 1;
 
- 			}
 
- 		    }
 
- 		  if (dp->precision_arg_index == ARG_NONE)
 
- 		    {
 
- 		      dp->precision_arg_index = arg_posn++;
 
- 		      if (dp->precision_arg_index == ARG_NONE)
 
- 			/* arg_posn wrapped around.  */
 
- 			goto error;
 
- 		    }
 
- 		  REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
 
- 		}
 
- 	      else
 
- 		{
 
- 		  size_t precision_length;
 
- 		  dp->precision_start = cp - 1;
 
- 		  for (; *cp >= '0' && *cp <= '9'; cp++)
 
- 		    ;
 
- 		  dp->precision_end = cp;
 
- 		  precision_length = dp->precision_end - dp->precision_start;
 
- 		  if (max_precision_length < precision_length)
 
- 		    max_precision_length = precision_length;
 
- 		}
 
- 	    }
 
- 	  {
 
- 	    arg_type type;
 
- 	    /* Parse argument type/size specifiers.  */
 
- 	    {
 
- 	      int flags = 0;
 
- 	      for (;;)
 
- 		{
 
- 		  if (*cp == 'h')
 
- 		    {
 
- 		      flags |= (1 << (flags & 1));
 
- 		      cp++;
 
- 		    }
 
- 		  else if (*cp == 'L')
 
- 		    {
 
- 		      flags |= 4;
 
- 		      cp++;
 
- 		    }
 
- 		  else if (*cp == 'l')
 
- 		    {
 
- 		      flags += 8;
 
- 		      cp++;
 
- 		    }
 
- 		  else if (*cp == 'j')
 
- 		    {
 
- 		      if (sizeof (intmax_t) > sizeof (long))
 
- 			{
 
- 			  /* intmax_t = long long */
 
- 			  flags += 16;
 
- 			}
 
- 		      else if (sizeof (intmax_t) > sizeof (int))
 
- 			{
 
- 			  /* intmax_t = long */
 
- 			  flags += 8;
 
- 			}
 
- 		      cp++;
 
- 		    }
 
- 		  else if (*cp == 'z' || *cp == 'Z')
 
- 		    {
 
- 		      /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
 
- 			 because the warning facility in gcc-2.95.2 understands
 
- 			 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
 
- 		      if (sizeof (size_t) > sizeof (long))
 
- 			{
 
- 			  /* size_t = long long */
 
- 			  flags += 16;
 
- 			}
 
- 		      else if (sizeof (size_t) > sizeof (int))
 
- 			{
 
- 			  /* size_t = long */
 
- 			  flags += 8;
 
- 			}
 
- 		      cp++;
 
- 		    }
 
- 		  else if (*cp == 't')
 
- 		    {
 
- 		      if (sizeof (ptrdiff_t) > sizeof (long))
 
- 			{
 
- 			  /* ptrdiff_t = long long */
 
- 			  flags += 16;
 
- 			}
 
- 		      else if (sizeof (ptrdiff_t) > sizeof (int))
 
- 			{
 
- 			  /* ptrdiff_t = long */
 
- 			  flags += 8;
 
- 			}
 
- 		      cp++;
 
- 		    }
 
- 		  else
 
- 		    break;
 
- 		}
 
- 	      /* Read the conversion character.  */
 
- 	      c = *cp++;
 
- 	      switch (c)
 
- 		{
 
- 		case 'd': case 'i':
 
- #if HAVE_LONG_LONG_INT
 
- 		  /* If 'long long' exists and is larger than 'long':  */
 
- 		  if (flags >= 16 || (flags & 4))
 
- 		    type = TYPE_LONGLONGINT;
 
- 		  else
 
- #endif
 
- 		  /* If 'long long' exists and is the same as 'long', we parse
 
- 		     "lld" into TYPE_LONGINT.  */
 
- 		  if (flags >= 8)
 
- 		    type = TYPE_LONGINT;
 
- 		  else if (flags & 2)
 
- 		    type = TYPE_SCHAR;
 
- 		  else if (flags & 1)
 
- 		    type = TYPE_SHORT;
 
- 		  else
 
- 		    type = TYPE_INT;
 
- 		  break;
 
- 		case 'o': case 'u': case 'x': case 'X':
 
- #if HAVE_LONG_LONG_INT
 
- 		  /* If 'long long' exists and is larger than 'long':  */
 
- 		  if (flags >= 16 || (flags & 4))
 
- 		    type = TYPE_ULONGLONGINT;
 
- 		  else
 
- #endif
 
- 		  /* If 'unsigned long long' exists and is the same as
 
- 		     'unsigned long', we parse "llu" into TYPE_ULONGINT.  */
 
- 		  if (flags >= 8)
 
- 		    type = TYPE_ULONGINT;
 
- 		  else if (flags & 2)
 
- 		    type = TYPE_UCHAR;
 
- 		  else if (flags & 1)
 
- 		    type = TYPE_USHORT;
 
- 		  else
 
- 		    type = TYPE_UINT;
 
- 		  break;
 
- 		case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
 
- 		case 'a': case 'A':
 
- 		  if (flags >= 16 || (flags & 4))
 
- 		    type = TYPE_LONGDOUBLE;
 
- 		  else
 
- 		    type = TYPE_DOUBLE;
 
- 		  break;
 
- 		case 'c':
 
- 		  if (flags >= 8)
 
- #if HAVE_WINT_T
 
- 		    type = TYPE_WIDE_CHAR;
 
- #else
 
- 		    goto error;
 
- #endif
 
- 		  else
 
- 		    type = TYPE_CHAR;
 
- 		  break;
 
- #if HAVE_WINT_T
 
- 		case 'C':
 
- 		  type = TYPE_WIDE_CHAR;
 
- 		  c = 'c';
 
- 		  break;
 
- #endif
 
- 		case 's':
 
- 		  if (flags >= 8)
 
- #if HAVE_WCHAR_T
 
- 		    type = TYPE_WIDE_STRING;
 
- #else
 
- 		    goto error;
 
- #endif
 
- 		  else
 
- 		    type = TYPE_STRING;
 
- 		  break;
 
- #if HAVE_WCHAR_T
 
- 		case 'S':
 
- 		  type = TYPE_WIDE_STRING;
 
- 		  c = 's';
 
- 		  break;
 
- #endif
 
- 		case 'p':
 
- 		  type = TYPE_POINTER;
 
- 		  break;
 
- 		case 'n':
 
- #if HAVE_LONG_LONG_INT
 
- 		  /* If 'long long' exists and is larger than 'long':  */
 
- 		  if (flags >= 16 || (flags & 4))
 
- 		    type = TYPE_COUNT_LONGLONGINT_POINTER;
 
- 		  else
 
- #endif
 
- 		  /* If 'long long' exists and is the same as 'long', we parse
 
- 		     "lln" into TYPE_COUNT_LONGINT_POINTER.  */
 
- 		  if (flags >= 8)
 
- 		    type = TYPE_COUNT_LONGINT_POINTER;
 
- 		  else if (flags & 2)
 
- 		    type = TYPE_COUNT_SCHAR_POINTER;
 
- 		  else if (flags & 1)
 
- 		    type = TYPE_COUNT_SHORT_POINTER;
 
- 		  else
 
- 		    type = TYPE_COUNT_INT_POINTER;
 
- 		  break;
 
- #if ENABLE_UNISTDIO
 
- 		/* The unistdio extensions.  */
 
- 		case 'U':
 
- 		  if (flags >= 16)
 
- 		    type = TYPE_U32_STRING;
 
- 		  else if (flags >= 8)
 
- 		    type = TYPE_U16_STRING;
 
- 		  else
 
- 		    type = TYPE_U8_STRING;
 
- 		  break;
 
- #endif
 
- 		case '%':
 
- 		  type = TYPE_NONE;
 
- 		  break;
 
- 		default:
 
- 		  /* Unknown conversion character.  */
 
- 		  goto error;
 
- 		}
 
- 	    }
 
- 	    if (type != TYPE_NONE)
 
- 	      {
 
- 		dp->arg_index = arg_index;
 
- 		if (dp->arg_index == ARG_NONE)
 
- 		  {
 
- 		    dp->arg_index = arg_posn++;
 
- 		    if (dp->arg_index == ARG_NONE)
 
- 		      /* arg_posn wrapped around.  */
 
- 		      goto error;
 
- 		  }
 
- 		REGISTER_ARG (dp->arg_index, type);
 
- 	      }
 
- 	    dp->conversion = c;
 
- 	    dp->dir_end = cp;
 
- 	  }
 
- 	  d->count++;
 
- 	  if (d->count >= d_allocated)
 
- 	    {
 
- 	      size_t memory_size;
 
- 	      DIRECTIVE *memory;
 
- 	      d_allocated = xtimes (d_allocated, 2);
 
- 	      memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
 
- 	      if (size_overflow_p (memory_size))
 
- 		/* Overflow, would lead to out of memory.  */
 
- 		goto out_of_memory;
 
- 	      memory = (DIRECTIVE *) realloc (d->dir, memory_size);
 
- 	      if (memory == NULL)
 
- 		/* Out of memory.  */
 
- 		goto out_of_memory;
 
- 	      d->dir = memory;
 
- 	    }
 
- 	}
 
- #if CHAR_T_ONLY_ASCII
 
-       else if (!c_isascii (c))
 
- 	{
 
- 	  /* Non-ASCII character.  Not supported.  */
 
- 	  goto error;
 
- 	}
 
- #endif
 
-     }
 
-   d->dir[d->count].dir_start = cp;
 
-   d->max_width_length = max_width_length;
 
-   d->max_precision_length = max_precision_length;
 
-   return 0;
 
- error:
 
-   if (a->arg)
 
-     free (a->arg);
 
-   if (d->dir)
 
-     free (d->dir);
 
-   errno = EINVAL;
 
-   return -1;
 
- out_of_memory:
 
-   if (a->arg)
 
-     free (a->arg);
 
-   if (d->dir)
 
-     free (d->dir);
 
- out_of_memory_1:
 
-   errno = ENOMEM;
 
-   return -1;
 
- }
 
- #undef PRINTF_PARSE
 
- #undef DIRECTIVES
 
- #undef DIRECTIVE
 
- #undef CHAR_T_ONLY_ASCII
 
- #undef CHAR_T
 
 
  |