diff lib/printf-parse.c @ 434:b8bf63962a99 3.0

Added various generated files for release
author lost@l-w.ca
date Fri, 29 Oct 2010 19:20:39 -0600
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/printf-parse.c	Fri Oct 29 19:20:39 2010 -0600
@@ -0,0 +1,627 @@
+/* Formatted output to strings.
+   Copyright (C) 1999-2000, 2002-2003, 2006-2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, 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 General Public License for more details.
+
+   You should have received a copy of the GNU 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++;
+                    }
+#if defined __APPLE__ && defined __MACH__
+                  /* On MacOS X 10.3, PRIdMAX is defined as "qd".
+                     We cannot change it to "lld" because PRIdMAX must also
+                     be understood by the system's printf routines.  */
+                  else if (*cp == 'q')
+                    {
+                      if (64 / 8 > sizeof (long))
+                        {
+                          /* int64_t = long long */
+                          flags += 16;
+                        }
+                      else
+                        {
+                          /* int64_t = long */
+                          flags += 8;
+                        }
+                      cp++;
+                    }
+#endif
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                  /* On native Win32, PRIdMAX is defined as "I64d".
+                     We cannot change it to "lld" because PRIdMAX must also
+                     be understood by the system's printf routines.  */
+                  else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
+                    {
+                      if (64 / 8 > sizeof (long))
+                        {
+                          /* __int64 = long long */
+                          flags += 16;
+                        }
+                      else
+                        {
+                          /* __int64 = long */
+                          flags += 8;
+                        }
+                      cp += 3;
+                    }
+#endif
+                  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