Blame lib/printf-parse.c

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