Blame lib/printf-parse.c

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