Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gettext-0.26/gettext-tools/libgettextpo/printf-args.c
Line
Count
Source
1
/* Decomposed printf argument list.
2
   Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2025 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
/* Get abort().  */
36
#include <stdlib.h>
37
38
#ifdef STATIC
39
STATIC
40
#endif
41
int
42
PRINTF_FETCHARGS (va_list args, arguments *a)
43
11.0k
{
44
11.0k
  size_t i;
45
11.0k
  argument *ap;
46
47
22.0k
  for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
48
11.0k
    switch (ap->type)
49
11.0k
      {
50
0
      case TYPE_SCHAR:
51
0
        ap->a.a_schar = va_arg (args, /*signed char*/ int);
52
0
        break;
53
0
      case TYPE_UCHAR:
54
0
        ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
55
0
        break;
56
0
      case TYPE_SHORT:
57
0
        ap->a.a_short = va_arg (args, /*short*/ int);
58
0
        break;
59
0
      case TYPE_USHORT:
60
0
        ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
61
0
        break;
62
0
      case TYPE_INT:
63
0
        ap->a.a_int = va_arg (args, int);
64
0
        break;
65
0
      case TYPE_UINT:
66
0
        ap->a.a_uint = va_arg (args, unsigned int);
67
0
        break;
68
0
      case TYPE_LONGINT:
69
0
        ap->a.a_longint = va_arg (args, long int);
70
0
        break;
71
0
      case TYPE_ULONGINT:
72
0
        ap->a.a_ulongint = va_arg (args, unsigned long int);
73
0
        break;
74
0
      case TYPE_LONGLONGINT:
75
0
        ap->a.a_longlongint = va_arg (args, long long int);
76
0
        break;
77
0
      case TYPE_ULONGLONGINT:
78
0
        ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
79
0
        break;
80
0
      case TYPE_INT8_T:
81
0
        #if INT8_WIDTH < INT_WIDTH
82
0
        ap->a.a_int8_t = va_arg (args, /* int8_t */ int);
83
        #else
84
        ap->a.a_int8_t = va_arg (args, int8_t);
85
        #endif
86
0
        break;
87
0
      case TYPE_UINT8_T:
88
0
        #if UINT8_WIDTH < INT_WIDTH
89
0
        ap->a.a_uint8_t = va_arg (args, /* uint8_t */ int);
90
        #else
91
        ap->a.a_uint8_t = va_arg (args, uint8_t);
92
        #endif
93
0
        break;
94
0
      case TYPE_INT16_T:
95
0
        #if INT16_WIDTH < INT_WIDTH
96
0
        ap->a.a_int16_t = va_arg (args, /* int16_t */ int);
97
        #else
98
        ap->a.a_int16_t = va_arg (args, int16_t);
99
        #endif
100
0
        break;
101
0
      case TYPE_UINT16_T:
102
0
        #if UINT16_WIDTH < INT_WIDTH
103
0
        ap->a.a_uint16_t = va_arg (args, /* uint16_t */ int);
104
        #else
105
        ap->a.a_uint16_t = va_arg (args, uint16_t);
106
        #endif
107
0
        break;
108
0
      case TYPE_INT32_T:
109
        #if INT32_WIDTH < INT_WIDTH
110
        ap->a.a_int32_t = va_arg (args, /* int32_t */ int);
111
        #else
112
0
        ap->a.a_int32_t = va_arg (args, int32_t);
113
0
        #endif
114
0
        break;
115
0
      case TYPE_UINT32_T:
116
        #if UINT32_WIDTH < INT_WIDTH
117
        ap->a.a_uint32_t = va_arg (args, /* uint32_t */ int);
118
        #else
119
0
        ap->a.a_uint32_t = va_arg (args, uint32_t);
120
0
        #endif
121
0
        break;
122
0
      case TYPE_INT64_T:
123
0
        ap->a.a_int64_t = va_arg (args, int64_t);
124
0
        break;
125
0
      case TYPE_UINT64_T:
126
0
        ap->a.a_uint64_t = va_arg (args, uint64_t);
127
0
        break;
128
0
      case TYPE_INT_FAST8_T:
129
0
        #if INT_FAST8_WIDTH < INT_WIDTH
130
0
        ap->a.a_int_fast8_t = va_arg (args, /* int_fast8_t */ int);
131
        #else
132
        ap->a.a_int_fast8_t = va_arg (args, int_fast8_t);
133
        #endif
134
0
        break;
135
0
      case TYPE_UINT_FAST8_T:
136
0
        #if UINT_FAST8_WIDTH < INT_WIDTH
137
0
        ap->a.a_uint_fast8_t = va_arg (args, /* uint_fast8_t */ int);
138
        #else
139
        ap->a.a_uint_fast8_t = va_arg (args, uint_fast8_t);
140
        #endif
141
0
        break;
142
0
      case TYPE_INT_FAST16_T:
143
        #if INT_FAST16_WIDTH < INT_WIDTH
144
        ap->a.a_int_fast16_t = va_arg (args, /* int_fast16_t */ int);
145
        #else
146
0
        ap->a.a_int_fast16_t = va_arg (args, int_fast16_t);
147
0
        #endif
148
0
        break;
149
0
      case TYPE_UINT_FAST16_T:
150
        #if UINT_FAST16_WIDTH < INT_WIDTH
151
        ap->a.a_uint_fast16_t = va_arg (args, /* uint_fast16_t */ int);
152
        #else
153
0
        ap->a.a_uint_fast16_t = va_arg (args, uint_fast16_t);
154
0
        #endif
155
0
        break;
156
0
      case TYPE_INT_FAST32_T:
157
        #if INT_FAST32_WIDTH < INT_WIDTH
158
        ap->a.a_int_fast32_t = va_arg (args, /* int_fast32_t */ int);
159
        #else
160
0
        ap->a.a_int_fast32_t = va_arg (args, int_fast32_t);
161
0
        #endif
162
0
        break;
163
0
      case TYPE_UINT_FAST32_T:
164
        #if UINT_FAST32_WIDTH < INT_WIDTH
165
        ap->a.a_uint_fast32_t = va_arg (args, /* uint_fast32_t */ int);
166
        #else
167
0
        ap->a.a_uint_fast32_t = va_arg (args, uint_fast32_t);
168
0
        #endif
169
0
        break;
170
0
      case TYPE_INT_FAST64_T:
171
0
        ap->a.a_int_fast64_t = va_arg (args, int_fast64_t);
172
0
        break;
173
0
      case TYPE_UINT_FAST64_T:
174
0
        ap->a.a_uint_fast64_t = va_arg (args, uint_fast64_t);
175
0
        break;
176
0
      case TYPE_DOUBLE:
177
0
        ap->a.a_double = va_arg (args, double);
178
0
        break;
179
0
      case TYPE_LONGDOUBLE:
180
0
        ap->a.a_longdouble = va_arg (args, long double);
181
0
        break;
182
0
      case TYPE_CHAR:
183
0
        ap->a.a_char = va_arg (args, int);
184
0
        break;
185
0
#if HAVE_WINT_T
186
0
      case TYPE_WIDE_CHAR:
187
        /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
188
           default argument promotions", this is not the case in mingw32,
189
           where wint_t is 'unsigned short'.  */
190
0
        ap->a.a_wide_char =
191
0
          (sizeof (wint_t) < sizeof (int)
192
0
           ? (wint_t) va_arg (args, int)
193
0
           : va_arg (args, wint_t));
194
0
        break;
195
0
#endif
196
11.0k
      case TYPE_STRING:
197
11.0k
        ap->a.a_string = va_arg (args, const char *);
198
        /* A null pointer is an invalid argument for "%s", but in practice
199
           it occurs quite frequently in printf statements that produce
200
           debug output.  Use a fallback in this case.  */
201
11.0k
        if (ap->a.a_string == NULL)
202
0
          ap->a.a_string = "(NULL)";
203
11.0k
        break;
204
0
      case TYPE_WIDE_STRING:
205
0
        ap->a.a_wide_string = va_arg (args, const wchar_t *);
206
        /* A null pointer is an invalid argument for "%ls", but in practice
207
           it occurs quite frequently in printf statements that produce
208
           debug output.  Use a fallback in this case.  */
209
0
        if (ap->a.a_wide_string == NULL)
210
0
          {
211
0
            static const wchar_t wide_null_string[] =
212
0
              {
213
0
                (wchar_t)'(',
214
0
                (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
215
0
                (wchar_t)')',
216
0
                (wchar_t)0
217
0
              };
218
0
            ap->a.a_wide_string = wide_null_string;
219
0
          }
220
0
        break;
221
0
      case TYPE_POINTER:
222
0
        ap->a.a_pointer = va_arg (args, void *);
223
0
        break;
224
0
      case TYPE_COUNT_SCHAR_POINTER:
225
0
        ap->a.a_count_schar_pointer = va_arg (args, signed char *);
226
0
        break;
227
0
      case TYPE_COUNT_SHORT_POINTER:
228
0
        ap->a.a_count_short_pointer = va_arg (args, short *);
229
0
        break;
230
0
      case TYPE_COUNT_INT_POINTER:
231
0
        ap->a.a_count_int_pointer = va_arg (args, int *);
232
0
        break;
233
0
      case TYPE_COUNT_LONGINT_POINTER:
234
0
        ap->a.a_count_longint_pointer = va_arg (args, long int *);
235
0
        break;
236
0
      case TYPE_COUNT_LONGLONGINT_POINTER:
237
0
        ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
238
0
        break;
239
0
      case TYPE_COUNT_INT8_T_POINTER:
240
0
        ap->a.a_count_int8_t_pointer = va_arg (args, int8_t *);
241
0
        break;
242
0
      case TYPE_COUNT_INT16_T_POINTER:
243
0
        ap->a.a_count_int16_t_pointer = va_arg (args, int16_t *);
244
0
        break;
245
0
      case TYPE_COUNT_INT32_T_POINTER:
246
0
        ap->a.a_count_int32_t_pointer = va_arg (args, int32_t *);
247
0
        break;
248
0
      case TYPE_COUNT_INT64_T_POINTER:
249
0
        ap->a.a_count_int64_t_pointer = va_arg (args, int64_t *);
250
0
        break;
251
0
      case TYPE_COUNT_INT_FAST8_T_POINTER:
252
0
        ap->a.a_count_int_fast8_t_pointer = va_arg (args, int_fast8_t *);
253
0
        break;
254
0
      case TYPE_COUNT_INT_FAST16_T_POINTER:
255
0
        ap->a.a_count_int_fast16_t_pointer = va_arg (args, int_fast16_t *);
256
0
        break;
257
0
      case TYPE_COUNT_INT_FAST32_T_POINTER:
258
0
        ap->a.a_count_int_fast32_t_pointer = va_arg (args, int_fast32_t *);
259
0
        break;
260
0
      case TYPE_COUNT_INT_FAST64_T_POINTER:
261
0
        ap->a.a_count_int_fast64_t_pointer = va_arg (args, int_fast64_t *);
262
0
        break;
263
#if ENABLE_UNISTDIO
264
      /* The unistdio extensions.  */
265
      case TYPE_U8_STRING:
266
        ap->a.a_u8_string = va_arg (args, const uint8_t *);
267
        /* A null pointer is an invalid argument for "%U", but in practice
268
           it occurs quite frequently in printf statements that produce
269
           debug output.  Use a fallback in this case.  */
270
        if (ap->a.a_u8_string == NULL)
271
          {
272
            static const uint8_t u8_null_string[] =
273
              { '(', 'N', 'U', 'L', 'L', ')', 0 };
274
            ap->a.a_u8_string = u8_null_string;
275
          }
276
        break;
277
      case TYPE_U16_STRING:
278
        ap->a.a_u16_string = va_arg (args, const uint16_t *);
279
        /* A null pointer is an invalid argument for "%lU", but in practice
280
           it occurs quite frequently in printf statements that produce
281
           debug output.  Use a fallback in this case.  */
282
        if (ap->a.a_u16_string == NULL)
283
          {
284
            static const uint16_t u16_null_string[] =
285
              { '(', 'N', 'U', 'L', 'L', ')', 0 };
286
            ap->a.a_u16_string = u16_null_string;
287
          }
288
        break;
289
      case TYPE_U32_STRING:
290
        ap->a.a_u32_string = va_arg (args, const uint32_t *);
291
        /* A null pointer is an invalid argument for "%llU", but in practice
292
           it occurs quite frequently in printf statements that produce
293
           debug output.  Use a fallback in this case.  */
294
        if (ap->a.a_u32_string == NULL)
295
          {
296
            static const uint32_t u32_null_string[] =
297
              { '(', 'N', 'U', 'L', 'L', ')', 0 };
298
            ap->a.a_u32_string = u32_null_string;
299
          }
300
        break;
301
#endif
302
0
      case TYPE_NONE:
303
        /* Argument i is not used by any directive, but some argument with
304
           number > i is used by a format directive.  POSIX says that this
305
           is invalid:
306
             "When numbered argument specifications are used, specifying the
307
              Nth argument requires that all the leading arguments, from the
308
              first to the (N-1)th, are specified in the format string."
309
           The reason is that we cannot know how many bytes to skip in the
310
           va_arg sequence.  */
311
0
        return -1;
312
0
      default:
313
        /* Unknown type.  Should not happen.  */
314
0
        abort ();
315
11.0k
      }
316
11.0k
  return 0;
317
11.0k
}