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