(root)/
tar-1.35/
gnu/
printf-args.c
       1  /* Decomposed printf argument list.
       2     Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2023 Free Software
       3     Foundation, Inc.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  /* This file can be parametrized with the following macros:
      19       ENABLE_UNISTDIO    Set to 1 to enable the unistdio extensions.
      20       PRINTF_FETCHARGS   Name of the function to be defined.
      21       STATIC             Set to 'static' to declare the function static.  */
      22  
      23  #ifndef PRINTF_FETCHARGS
      24  # include <config.h>
      25  #endif
      26  
      27  /* Specification.  */
      28  #ifndef PRINTF_FETCHARGS
      29  # include "printf-args.h"
      30  #endif
      31  
      32  /* Get INT_WIDTH.  */
      33  #include <limits.h>
      34  
      35  #ifdef STATIC
      36  STATIC
      37  #endif
      38  int
      39  PRINTF_FETCHARGS (va_list args, arguments *a)
      40  {
      41    size_t i;
      42    argument *ap;
      43  
      44    for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
      45      switch (ap->type)
      46        {
      47        case TYPE_SCHAR:
      48          ap->a.a_schar = va_arg (args, /*signed char*/ int);
      49          break;
      50        case TYPE_UCHAR:
      51          ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
      52          break;
      53        case TYPE_SHORT:
      54          ap->a.a_short = va_arg (args, /*short*/ int);
      55          break;
      56        case TYPE_USHORT:
      57          ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
      58          break;
      59        case TYPE_INT:
      60          ap->a.a_int = va_arg (args, int);
      61          break;
      62        case TYPE_UINT:
      63          ap->a.a_uint = va_arg (args, unsigned int);
      64          break;
      65        case TYPE_LONGINT:
      66          ap->a.a_longint = va_arg (args, long int);
      67          break;
      68        case TYPE_ULONGINT:
      69          ap->a.a_ulongint = va_arg (args, unsigned long int);
      70          break;
      71        case TYPE_LONGLONGINT:
      72          ap->a.a_longlongint = va_arg (args, long long int);
      73          break;
      74        case TYPE_ULONGLONGINT:
      75          ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
      76          break;
      77        case TYPE_INT8_T:
      78          #if INT8_WIDTH < INT_WIDTH
      79          ap->a.a_int8_t = va_arg (args, /* int8_t */ int);
      80          #else
      81          ap->a.a_int8_t = va_arg (args, int8_t);
      82          #endif
      83          break;
      84        case TYPE_UINT8_T:
      85          #if UINT8_WIDTH < INT_WIDTH
      86          ap->a.a_uint8_t = va_arg (args, /* uint8_t */ int);
      87          #else
      88          ap->a.a_uint8_t = va_arg (args, uint8_t);
      89          #endif
      90          break;
      91        case TYPE_INT16_T:
      92          #if INT16_WIDTH < INT_WIDTH
      93          ap->a.a_int16_t = va_arg (args, /* int16_t */ int);
      94          #else
      95          ap->a.a_int16_t = va_arg (args, int16_t);
      96          #endif
      97          break;
      98        case TYPE_UINT16_T:
      99          #if UINT16_WIDTH < INT_WIDTH
     100          ap->a.a_uint16_t = va_arg (args, /* uint16_t */ int);
     101          #else
     102          ap->a.a_uint16_t = va_arg (args, uint16_t);
     103          #endif
     104          break;
     105        case TYPE_INT32_T:
     106          #if INT32_WIDTH < INT_WIDTH
     107          ap->a.a_int32_t = va_arg (args, /* int32_t */ int);
     108          #else
     109          ap->a.a_int32_t = va_arg (args, int32_t);
     110          #endif
     111          break;
     112        case TYPE_UINT32_T:
     113          #if UINT32_WIDTH < INT_WIDTH
     114          ap->a.a_uint32_t = va_arg (args, /* uint32_t */ int);
     115          #else
     116          ap->a.a_uint32_t = va_arg (args, uint32_t);
     117          #endif
     118          break;
     119        case TYPE_INT64_T:
     120          ap->a.a_int64_t = va_arg (args, int64_t);
     121          break;
     122        case TYPE_UINT64_T:
     123          ap->a.a_uint64_t = va_arg (args, uint64_t);
     124          break;
     125        case TYPE_INT_FAST8_T:
     126          #if INT_FAST8_WIDTH < INT_WIDTH
     127          ap->a.a_int_fast8_t = va_arg (args, /* int_fast8_t */ int);
     128          #else
     129          ap->a.a_int_fast8_t = va_arg (args, int_fast8_t);
     130          #endif
     131          break;
     132        case TYPE_UINT_FAST8_T:
     133          #if UINT_FAST8_WIDTH < INT_WIDTH
     134          ap->a.a_uint_fast8_t = va_arg (args, /* uint_fast8_t */ int);
     135          #else
     136          ap->a.a_uint_fast8_t = va_arg (args, uint_fast8_t);
     137          #endif
     138          break;
     139        case TYPE_INT_FAST16_T:
     140          #if INT_FAST16_WIDTH < INT_WIDTH
     141          ap->a.a_int_fast16_t = va_arg (args, /* int_fast16_t */ int);
     142          #else
     143          ap->a.a_int_fast16_t = va_arg (args, int_fast16_t);
     144          #endif
     145          break;
     146        case TYPE_UINT_FAST16_T:
     147          #if UINT_FAST16_WIDTH < INT_WIDTH
     148          ap->a.a_uint_fast16_t = va_arg (args, /* uint_fast16_t */ int);
     149          #else
     150          ap->a.a_uint_fast16_t = va_arg (args, uint_fast16_t);
     151          #endif
     152          break;
     153        case TYPE_INT_FAST32_T:
     154          #if INT_FAST32_WIDTH < INT_WIDTH
     155          ap->a.a_int_fast32_t = va_arg (args, /* int_fast32_t */ int);
     156          #else
     157          ap->a.a_int_fast32_t = va_arg (args, int_fast32_t);
     158          #endif
     159          break;
     160        case TYPE_UINT_FAST32_T:
     161          #if UINT_FAST32_WIDTH < INT_WIDTH
     162          ap->a.a_uint_fast32_t = va_arg (args, /* uint_fast32_t */ int);
     163          #else
     164          ap->a.a_uint_fast32_t = va_arg (args, uint_fast32_t);
     165          #endif
     166          break;
     167        case TYPE_INT_FAST64_T:
     168          ap->a.a_int_fast64_t = va_arg (args, int_fast64_t);
     169          break;
     170        case TYPE_UINT_FAST64_T:
     171          ap->a.a_uint_fast64_t = va_arg (args, uint_fast64_t);
     172          break;
     173        case TYPE_DOUBLE:
     174          ap->a.a_double = va_arg (args, double);
     175          break;
     176        case TYPE_LONGDOUBLE:
     177          ap->a.a_longdouble = va_arg (args, long double);
     178          break;
     179        case TYPE_CHAR:
     180          ap->a.a_char = va_arg (args, int);
     181          break;
     182  #if HAVE_WINT_T
     183        case TYPE_WIDE_CHAR:
     184          /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
     185             default argument promotions", this is not the case in mingw32,
     186             where wint_t is 'unsigned short'.  */
     187          ap->a.a_wide_char =
     188            (sizeof (wint_t) < sizeof (int)
     189             ? (wint_t) va_arg (args, int)
     190             : va_arg (args, wint_t));
     191          break;
     192  #endif
     193        case TYPE_STRING:
     194          ap->a.a_string = va_arg (args, const char *);
     195          /* A null pointer is an invalid argument for "%s", but in practice
     196             it occurs quite frequently in printf statements that produce
     197             debug output.  Use a fallback in this case.  */
     198          if (ap->a.a_string == NULL)
     199            ap->a.a_string = "(NULL)";
     200          break;
     201  #if HAVE_WCHAR_T
     202        case TYPE_WIDE_STRING:
     203          ap->a.a_wide_string = va_arg (args, const wchar_t *);
     204          /* A null pointer is an invalid argument for "%ls", but in practice
     205             it occurs quite frequently in printf statements that produce
     206             debug output.  Use a fallback in this case.  */
     207          if (ap->a.a_wide_string == NULL)
     208            {
     209              static const wchar_t wide_null_string[] =
     210                {
     211                  (wchar_t)'(',
     212                  (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
     213                  (wchar_t)')',
     214                  (wchar_t)0
     215                };
     216              ap->a.a_wide_string = wide_null_string;
     217            }
     218          break;
     219  #endif
     220        case TYPE_POINTER:
     221          ap->a.a_pointer = va_arg (args, void *);
     222          break;
     223        case TYPE_COUNT_SCHAR_POINTER:
     224          ap->a.a_count_schar_pointer = va_arg (args, signed char *);
     225          break;
     226        case TYPE_COUNT_SHORT_POINTER:
     227          ap->a.a_count_short_pointer = va_arg (args, short *);
     228          break;
     229        case TYPE_COUNT_INT_POINTER:
     230          ap->a.a_count_int_pointer = va_arg (args, int *);
     231          break;
     232        case TYPE_COUNT_LONGINT_POINTER:
     233          ap->a.a_count_longint_pointer = va_arg (args, long int *);
     234          break;
     235        case TYPE_COUNT_LONGLONGINT_POINTER:
     236          ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
     237          break;
     238        case TYPE_COUNT_INT8_T_POINTER:
     239          ap->a.a_count_int8_t_pointer = va_arg (args, int8_t *);
     240          break;
     241        case TYPE_COUNT_INT16_T_POINTER:
     242          ap->a.a_count_int16_t_pointer = va_arg (args, int16_t *);
     243          break;
     244        case TYPE_COUNT_INT32_T_POINTER:
     245          ap->a.a_count_int32_t_pointer = va_arg (args, int32_t *);
     246          break;
     247        case TYPE_COUNT_INT64_T_POINTER:
     248          ap->a.a_count_int64_t_pointer = va_arg (args, int64_t *);
     249          break;
     250        case TYPE_COUNT_INT_FAST8_T_POINTER:
     251          ap->a.a_count_int_fast8_t_pointer = va_arg (args, int_fast8_t *);
     252          break;
     253        case TYPE_COUNT_INT_FAST16_T_POINTER:
     254          ap->a.a_count_int_fast16_t_pointer = va_arg (args, int_fast16_t *);
     255          break;
     256        case TYPE_COUNT_INT_FAST32_T_POINTER:
     257          ap->a.a_count_int_fast32_t_pointer = va_arg (args, int_fast32_t *);
     258          break;
     259        case TYPE_COUNT_INT_FAST64_T_POINTER:
     260          ap->a.a_count_int_fast64_t_pointer = va_arg (args, int_fast64_t *);
     261          break;
     262  #if ENABLE_UNISTDIO
     263        /* The unistdio extensions.  */
     264        case TYPE_U8_STRING:
     265          ap->a.a_u8_string = va_arg (args, const uint8_t *);
     266          /* A null pointer is an invalid argument for "%U", but in practice
     267             it occurs quite frequently in printf statements that produce
     268             debug output.  Use a fallback in this case.  */
     269          if (ap->a.a_u8_string == NULL)
     270            {
     271              static const uint8_t u8_null_string[] =
     272                { '(', 'N', 'U', 'L', 'L', ')', 0 };
     273              ap->a.a_u8_string = u8_null_string;
     274            }
     275          break;
     276        case TYPE_U16_STRING:
     277          ap->a.a_u16_string = va_arg (args, const uint16_t *);
     278          /* A null pointer is an invalid argument for "%lU", but in practice
     279             it occurs quite frequently in printf statements that produce
     280             debug output.  Use a fallback in this case.  */
     281          if (ap->a.a_u16_string == NULL)
     282            {
     283              static const uint16_t u16_null_string[] =
     284                { '(', 'N', 'U', 'L', 'L', ')', 0 };
     285              ap->a.a_u16_string = u16_null_string;
     286            }
     287          break;
     288        case TYPE_U32_STRING:
     289          ap->a.a_u32_string = va_arg (args, const uint32_t *);
     290          /* A null pointer is an invalid argument for "%llU", but in practice
     291             it occurs quite frequently in printf statements that produce
     292             debug output.  Use a fallback in this case.  */
     293          if (ap->a.a_u32_string == NULL)
     294            {
     295              static const uint32_t u32_null_string[] =
     296                { '(', 'N', 'U', 'L', 'L', ')', 0 };
     297              ap->a.a_u32_string = u32_null_string;
     298            }
     299          break;
     300  #endif
     301        default:
     302          /* Unknown type.  */
     303          return -1;
     304        }
     305    return 0;
     306  }