Blame gl/printf-parse.c

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