105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Decomposed printf argument list.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2012 Free Software
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Foundation, Inc.
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software; you can redistribute it and/or modify
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation; either version 3, or (at your option)
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   any later version.
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License along
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   with this program; if not, see <http://www.gnu.org/licenses/>.  */
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* This file can be parametrized with the following macros:
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang     ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang     PRINTF_FETCHARGS   Name of the function to be defined.
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     STATIC             Set to 'static' to declare the function static.  */
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef PRINTF_FETCHARGS
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <config.h>
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification.  */
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef PRINTF_FETCHARGS
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "printf-args.h"
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef STATIC
3305436638acc7c010349a69c3395f1a57c642dc62Ying WangSTATIC
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wangint
3605436638acc7c010349a69c3395f1a57c642dc62Ying WangPRINTF_FETCHARGS (va_list args, arguments *a)
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t i;
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  argument *ap;
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    switch (ap->type)
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_SCHAR:
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_schar = va_arg (args, /*signed char*/ int);
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_UCHAR:
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_SHORT:
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_short = va_arg (args, /*short*/ int);
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_USHORT:
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_INT:
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_int = va_arg (args, int);
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_UINT:
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_uint = va_arg (args, unsigned int);
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_LONGINT:
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_longint = va_arg (args, long int);
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_ULONGINT:
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_ulongint = va_arg (args, unsigned long int);
6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_LONGLONGINT:
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_longlongint = va_arg (args, long long int);
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_ULONGLONGINT:
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_DOUBLE:
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_double = va_arg (args, double);
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_LONGDOUBLE:
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_longdouble = va_arg (args, long double);
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_CHAR:
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_char = va_arg (args, int);
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WINT_T
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_WIDE_CHAR:
8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang           default argument promotions", this is not the case in mingw32,
8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang           where wint_t is 'unsigned short'.  */
9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_wide_char =
9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          (sizeof (wint_t) < sizeof (int)
9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang           ? (wint_t) va_arg (args, int)
9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang           : va_arg (args, wint_t));
9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_STRING:
9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_string = va_arg (args, const char *);
9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* A null pointer is an invalid argument for "%s", but in practice
9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang           it occurs quite frequently in printf statements that produce
10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang           debug output.  Use a fallback in this case.  */
10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (ap->a.a_string == NULL)
10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          ap->a.a_string = "(NULL)";
10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WCHAR_T
10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_WIDE_STRING:
10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_wide_string = va_arg (args, const wchar_t *);
10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* A null pointer is an invalid argument for "%ls", but in practice
10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang           it occurs quite frequently in printf statements that produce
10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang           debug output.  Use a fallback in this case.  */
11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (ap->a.a_wide_string == NULL)
11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            static const wchar_t wide_null_string[] =
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                (wchar_t)'(',
11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                (wchar_t)')',
11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                (wchar_t)0
11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              };
11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            ap->a.a_wide_string = wide_null_string;
12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_POINTER:
12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_pointer = va_arg (args, void *);
12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_COUNT_SCHAR_POINTER:
12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_count_schar_pointer = va_arg (args, signed char *);
12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_COUNT_SHORT_POINTER:
13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_count_short_pointer = va_arg (args, short *);
13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_COUNT_INT_POINTER:
13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_count_int_pointer = va_arg (args, int *);
13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_COUNT_LONGINT_POINTER:
13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_count_longint_pointer = va_arg (args, long int *);
13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT
13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_COUNT_LONGLONGINT_POINTER:
14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if ENABLE_UNISTDIO
14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* The unistdio extensions.  */
14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_U8_STRING:
14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_u8_string = va_arg (args, const uint8_t *);
14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* A null pointer is an invalid argument for "%U", but in practice
14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang           it occurs quite frequently in printf statements that produce
14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang           debug output.  Use a fallback in this case.  */
15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (ap->a.a_u8_string == NULL)
15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            static const uint8_t u8_null_string[] =
15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang              { '(', 'N', 'U', 'L', 'L', ')', 0 };
15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            ap->a.a_u8_string = u8_null_string;
15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_U16_STRING:
15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_u16_string = va_arg (args, const uint16_t *);
15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* A null pointer is an invalid argument for "%lU", but in practice
16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang           it occurs quite frequently in printf statements that produce
16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang           debug output.  Use a fallback in this case.  */
16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (ap->a.a_u16_string == NULL)
16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang            static const uint16_t u16_null_string[] =
16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang              { '(', 'N', 'U', 'L', 'L', ')', 0 };
16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            ap->a.a_u16_string = u16_null_string;
16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      case TYPE_U32_STRING:
17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ap->a.a_u32_string = va_arg (args, const uint32_t *);
17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* A null pointer is an invalid argument for "%llU", but in practice
17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang           it occurs quite frequently in printf statements that produce
17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang           debug output.  Use a fallback in this case.  */
17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (ap->a.a_u32_string == NULL)
17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang            static const uint32_t u32_null_string[] =
17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              { '(', 'N', 'U', 'L', 'L', ')', 0 };
17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang            ap->a.a_u32_string = u32_null_string;
17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      default:
18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        /* Unknown type.  */
18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return -1;
18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return 0;
18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
188