Blame gnulib-tests/printf-parse.c

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