Blame gettext-runtime/intl/printf-args.c

Packit 5b56b6
/* Decomposed printf argument list.
Packit 5b56b6
   Copyright (C) 1999, 2002-2003, 2005-2007, 2015 Free Software
Packit 5b56b6
   Foundation, Inc.
Packit 5b56b6
Packit 5b56b6
   This program is free software: you can redistribute it and/or modify
Packit 5b56b6
   it under the terms of the GNU Lesser General Public License as published by
Packit 5b56b6
   the Free Software Foundation; either version 2.1 of the License, or
Packit 5b56b6
   (at your option) any later version.
Packit 5b56b6
Packit 5b56b6
   This program is distributed in the hope that it will be useful,
Packit 5b56b6
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5b56b6
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 5b56b6
   GNU Lesser General Public License for more details.
Packit 5b56b6
Packit 5b56b6
   You should have received a copy of the GNU Lesser General Public License
Packit 5b56b6
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 5b56b6
Packit 5b56b6
/* This file can be parametrized with the following macros:
Packit 5b56b6
     ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.
Packit 5b56b6
     PRINTF_FETCHARGS   Name of the function to be defined.
Packit 5b56b6
     STATIC             Set to 'static' to declare the function static.  */
Packit 5b56b6
Packit 5b56b6
#ifndef PRINTF_FETCHARGS
Packit 5b56b6
# include <config.h>
Packit 5b56b6
#endif
Packit 5b56b6
Packit 5b56b6
/* Specification.  */
Packit 5b56b6
#ifndef PRINTF_FETCHARGS
Packit 5b56b6
# include "printf-args.h"
Packit 5b56b6
#endif
Packit 5b56b6
Packit 5b56b6
#ifdef STATIC
Packit 5b56b6
STATIC
Packit 5b56b6
#endif
Packit 5b56b6
int
Packit 5b56b6
PRINTF_FETCHARGS (va_list args, arguments *a)
Packit 5b56b6
{
Packit 5b56b6
  size_t i;
Packit 5b56b6
  argument *ap;
Packit 5b56b6
Packit 5b56b6
  for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
Packit 5b56b6
    switch (ap->type)
Packit 5b56b6
      {
Packit 5b56b6
      case TYPE_SCHAR:
Packit 5b56b6
        ap->a.a_schar = va_arg (args, /*signed char*/ int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_UCHAR:
Packit 5b56b6
        ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_SHORT:
Packit 5b56b6
        ap->a.a_short = va_arg (args, /*short*/ int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_USHORT:
Packit 5b56b6
        ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_INT:
Packit 5b56b6
        ap->a.a_int = va_arg (args, int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_UINT:
Packit 5b56b6
        ap->a.a_uint = va_arg (args, unsigned int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_LONGINT:
Packit 5b56b6
        ap->a.a_longint = va_arg (args, long int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_ULONGINT:
Packit 5b56b6
        ap->a.a_ulongint = va_arg (args, unsigned long int);
Packit 5b56b6
        break;
Packit 5b56b6
#if HAVE_LONG_LONG_INT
Packit 5b56b6
      case TYPE_LONGLONGINT:
Packit 5b56b6
        ap->a.a_longlongint = va_arg (args, long long int);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_ULONGLONGINT:
Packit 5b56b6
        ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
Packit 5b56b6
        break;
Packit 5b56b6
#endif
Packit 5b56b6
      case TYPE_DOUBLE:
Packit 5b56b6
        ap->a.a_double = va_arg (args, double);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_LONGDOUBLE:
Packit 5b56b6
        ap->a.a_longdouble = va_arg (args, long double);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_CHAR:
Packit 5b56b6
        ap->a.a_char = va_arg (args, int);
Packit 5b56b6
        break;
Packit 5b56b6
#if HAVE_WINT_T
Packit 5b56b6
      case TYPE_WIDE_CHAR:
Packit 5b56b6
        /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
Packit 5b56b6
           default argument promotions", this is not the case in mingw32,
Packit 5b56b6
           where wint_t is 'unsigned short'.  */
Packit 5b56b6
        ap->a.a_wide_char =
Packit 5b56b6
          (sizeof (wint_t) < sizeof (int)
Packit 5b56b6
           ? va_arg (args, int)
Packit 5b56b6
           : va_arg (args, wint_t));
Packit 5b56b6
        break;
Packit 5b56b6
#endif
Packit 5b56b6
      case TYPE_STRING:
Packit 5b56b6
        ap->a.a_string = va_arg (args, const char *);
Packit 5b56b6
        /* A null pointer is an invalid argument for "%s", but in practice
Packit 5b56b6
           it occurs quite frequently in printf statements that produce
Packit 5b56b6
           debug output.  Use a fallback in this case.  */
Packit 5b56b6
        if (ap->a.a_string == NULL)
Packit 5b56b6
          ap->a.a_string = "(NULL)";
Packit 5b56b6
        break;
Packit 5b56b6
#if HAVE_WCHAR_T
Packit 5b56b6
      case TYPE_WIDE_STRING:
Packit 5b56b6
        ap->a.a_wide_string = va_arg (args, const wchar_t *);
Packit 5b56b6
        /* A null pointer is an invalid argument for "%ls", but in practice
Packit 5b56b6
           it occurs quite frequently in printf statements that produce
Packit 5b56b6
           debug output.  Use a fallback in this case.  */
Packit 5b56b6
        if (ap->a.a_wide_string == NULL)
Packit 5b56b6
          {
Packit 5b56b6
            static const wchar_t wide_null_string[] =
Packit 5b56b6
              {
Packit 5b56b6
                (wchar_t)'(',
Packit 5b56b6
                (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
Packit 5b56b6
                (wchar_t)')',
Packit 5b56b6
                (wchar_t)0
Packit 5b56b6
              };
Packit 5b56b6
            ap->a.a_wide_string = wide_null_string;
Packit 5b56b6
          }
Packit 5b56b6
        break;
Packit 5b56b6
#endif
Packit 5b56b6
      case TYPE_POINTER:
Packit 5b56b6
        ap->a.a_pointer = va_arg (args, void *);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_COUNT_SCHAR_POINTER:
Packit 5b56b6
        ap->a.a_count_schar_pointer = va_arg (args, signed char *);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_COUNT_SHORT_POINTER:
Packit 5b56b6
        ap->a.a_count_short_pointer = va_arg (args, short *);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_COUNT_INT_POINTER:
Packit 5b56b6
        ap->a.a_count_int_pointer = va_arg (args, int *);
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_COUNT_LONGINT_POINTER:
Packit 5b56b6
        ap->a.a_count_longint_pointer = va_arg (args, long int *);
Packit 5b56b6
        break;
Packit 5b56b6
#if HAVE_LONG_LONG_INT
Packit 5b56b6
      case TYPE_COUNT_LONGLONGINT_POINTER:
Packit 5b56b6
        ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
Packit 5b56b6
        break;
Packit 5b56b6
#endif
Packit 5b56b6
#if ENABLE_UNISTDIO
Packit 5b56b6
      /* The unistdio extensions.  */
Packit 5b56b6
      case TYPE_U8_STRING:
Packit 5b56b6
        ap->a.a_u8_string = va_arg (args, const uint8_t *);
Packit 5b56b6
        /* A null pointer is an invalid argument for "%U", but in practice
Packit 5b56b6
           it occurs quite frequently in printf statements that produce
Packit 5b56b6
           debug output.  Use a fallback in this case.  */
Packit 5b56b6
        if (ap->a.a_u8_string == NULL)
Packit 5b56b6
          {
Packit 5b56b6
            static const uint8_t u8_null_string[] =
Packit 5b56b6
              { '(', 'N', 'U', 'L', 'L', ')', 0 };
Packit 5b56b6
            ap->a.a_u8_string = u8_null_string;
Packit 5b56b6
          }
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_U16_STRING:
Packit 5b56b6
        ap->a.a_u16_string = va_arg (args, const uint16_t *);
Packit 5b56b6
        /* A null pointer is an invalid argument for "%lU", but in practice
Packit 5b56b6
           it occurs quite frequently in printf statements that produce
Packit 5b56b6
           debug output.  Use a fallback in this case.  */
Packit 5b56b6
        if (ap->a.a_u16_string == NULL)
Packit 5b56b6
          {
Packit 5b56b6
            static const uint16_t u16_null_string[] =
Packit 5b56b6
              { '(', 'N', 'U', 'L', 'L', ')', 0 };
Packit 5b56b6
            ap->a.a_u16_string = u16_null_string;
Packit 5b56b6
          }
Packit 5b56b6
        break;
Packit 5b56b6
      case TYPE_U32_STRING:
Packit 5b56b6
        ap->a.a_u32_string = va_arg (args, const uint32_t *);
Packit 5b56b6
        /* A null pointer is an invalid argument for "%llU", but in practice
Packit 5b56b6
           it occurs quite frequently in printf statements that produce
Packit 5b56b6
           debug output.  Use a fallback in this case.  */
Packit 5b56b6
        if (ap->a.a_u32_string == NULL)
Packit 5b56b6
          {
Packit 5b56b6
            static const uint32_t u32_null_string[] =
Packit 5b56b6
              { '(', 'N', 'U', 'L', 'L', ')', 0 };
Packit 5b56b6
            ap->a.a_u32_string = u32_null_string;
Packit 5b56b6
          }
Packit 5b56b6
        break;
Packit 5b56b6
#endif
Packit 5b56b6
      default:
Packit 5b56b6
        /* Unknown type.  */
Packit 5b56b6
        return -1;
Packit 5b56b6
      }
Packit 5b56b6
  return 0;
Packit 5b56b6
}