/src/glib/glib/gnulib/printf-args.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Decomposed printf argument list. |
2 | | Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2019 Free Software |
3 | | Foundation, Inc. |
4 | | |
5 | | This program is free software; you can redistribute it and/or modify |
6 | | it under the terms of the GNU Lesser General Public License as published by |
7 | | the Free Software Foundation; either version 2.1, or (at your option) |
8 | | any later version. |
9 | | |
10 | | This program 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 along |
16 | | 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 | | #include "g-gnulib.h" |
28 | | |
29 | | /* Specification. */ |
30 | | #ifndef PRINTF_FETCHARGS |
31 | | # include "printf-args.h" |
32 | | #endif |
33 | | |
34 | | #ifdef STATIC |
35 | | STATIC |
36 | | #endif |
37 | | int |
38 | | PRINTF_FETCHARGS (va_list args, arguments *a) |
39 | 72.2M | { |
40 | 72.2M | size_t i; |
41 | 72.2M | argument *ap; |
42 | | |
43 | 155M | for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) |
44 | 83.6M | switch (ap->type) |
45 | 83.6M | { |
46 | 0 | case TYPE_SCHAR: |
47 | 0 | ap->a.a_schar = va_arg (args, /*signed char*/ int); |
48 | 0 | break; |
49 | 0 | case TYPE_UCHAR: |
50 | 0 | ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); |
51 | 0 | break; |
52 | 0 | case TYPE_SHORT: |
53 | 0 | ap->a.a_short = va_arg (args, /*short*/ int); |
54 | 0 | break; |
55 | 0 | case TYPE_USHORT: |
56 | 0 | ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); |
57 | 0 | break; |
58 | 39.7k | case TYPE_INT: |
59 | 39.7k | ap->a.a_int = va_arg (args, int); |
60 | 39.7k | break; |
61 | 78.0M | case TYPE_UINT: |
62 | 78.0M | ap->a.a_uint = va_arg (args, unsigned int); |
63 | 78.0M | break; |
64 | 0 | case TYPE_LONGINT: |
65 | 0 | ap->a.a_longint = va_arg (args, long int); |
66 | 0 | break; |
67 | 34.8k | case TYPE_ULONGINT: |
68 | 34.8k | ap->a.a_ulongint = va_arg (args, unsigned long int); |
69 | 34.8k | break; |
70 | 0 | #if HAVE_LONG_LONG |
71 | 0 | case TYPE_LONGLONGINT: |
72 | 0 | ap->a.a_longlongint = va_arg (args, long long int); |
73 | 0 | break; |
74 | 0 | case TYPE_ULONGLONGINT: |
75 | 0 | ap->a.a_ulonglongint = va_arg (args, unsigned long long int); |
76 | 0 | break; |
77 | 0 | #endif |
78 | 1.84k | case TYPE_DOUBLE: |
79 | 1.84k | ap->a.a_double = va_arg (args, double); |
80 | 1.84k | break; |
81 | 0 | case TYPE_LONGDOUBLE: |
82 | 0 | ap->a.a_longdouble = va_arg (args, long double); |
83 | 0 | break; |
84 | 753 | case TYPE_CHAR: |
85 | 753 | ap->a.a_char = va_arg (args, int); |
86 | 753 | break; |
87 | 0 | #if HAVE_WINT_T |
88 | 0 | case TYPE_WIDE_CHAR: |
89 | | /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by |
90 | | default argument promotions", this is not the case in mingw32, |
91 | | where wint_t is 'unsigned short'. */ |
92 | 0 | ap->a.a_wide_char = |
93 | 0 | (sizeof (wint_t) < sizeof (int) |
94 | 0 | ? (wint_t) va_arg (args, int) |
95 | 0 | : va_arg (args, wint_t)); |
96 | 0 | break; |
97 | 0 | #endif |
98 | 5.54M | case TYPE_STRING: |
99 | 5.54M | ap->a.a_string = va_arg (args, const char *); |
100 | | /* A null pointer is an invalid argument for "%s", but in practice |
101 | | it occurs quite frequently in printf statements that produce |
102 | | debug output. Use a fallback in this case. */ |
103 | 5.54M | if (ap->a.a_string == NULL) |
104 | 38.2k | ap->a.a_string = "(NULL)"; |
105 | 5.54M | break; |
106 | 0 | #if HAVE_WCHAR_T |
107 | 0 | case TYPE_WIDE_STRING: |
108 | 0 | ap->a.a_wide_string = va_arg (args, const wchar_t *); |
109 | | /* A null pointer is an invalid argument for "%ls", but in practice |
110 | | it occurs quite frequently in printf statements that produce |
111 | | debug output. Use a fallback in this case. */ |
112 | 0 | if (ap->a.a_wide_string == NULL) |
113 | 0 | { |
114 | 0 | static const wchar_t wide_null_string[] = |
115 | 0 | { |
116 | 0 | (wchar_t)'(', |
117 | 0 | (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L', |
118 | 0 | (wchar_t)')', |
119 | 0 | (wchar_t)0 |
120 | 0 | }; |
121 | 0 | ap->a.a_wide_string = wide_null_string; |
122 | 0 | } |
123 | 0 | break; |
124 | 0 | #endif |
125 | 0 | case TYPE_POINTER: |
126 | 0 | ap->a.a_pointer = va_arg (args, void *); |
127 | 0 | break; |
128 | 0 | case TYPE_COUNT_SCHAR_POINTER: |
129 | 0 | ap->a.a_count_schar_pointer = va_arg (args, signed char *); |
130 | 0 | break; |
131 | 0 | case TYPE_COUNT_SHORT_POINTER: |
132 | 0 | ap->a.a_count_short_pointer = va_arg (args, short *); |
133 | 0 | break; |
134 | 0 | case TYPE_COUNT_INT_POINTER: |
135 | 0 | ap->a.a_count_int_pointer = va_arg (args, int *); |
136 | 0 | break; |
137 | 0 | case TYPE_COUNT_LONGINT_POINTER: |
138 | 0 | ap->a.a_count_longint_pointer = va_arg (args, long int *); |
139 | 0 | break; |
140 | 0 | #if HAVE_LONG_LONG |
141 | 0 | case TYPE_COUNT_LONGLONGINT_POINTER: |
142 | 0 | ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); |
143 | 0 | break; |
144 | 0 | #endif |
145 | | #if ENABLE_UNISTDIO |
146 | | /* The unistdio extensions. */ |
147 | | case TYPE_U8_STRING: |
148 | | ap->a.a_u8_string = va_arg (args, const uint8_t *); |
149 | | /* A null pointer is an invalid argument for "%U", but in practice |
150 | | it occurs quite frequently in printf statements that produce |
151 | | debug output. Use a fallback in this case. */ |
152 | | if (ap->a.a_u8_string == NULL) |
153 | | { |
154 | | static const uint8_t u8_null_string[] = |
155 | | { '(', 'N', 'U', 'L', 'L', ')', 0 }; |
156 | | ap->a.a_u8_string = u8_null_string; |
157 | | } |
158 | | break; |
159 | | case TYPE_U16_STRING: |
160 | | ap->a.a_u16_string = va_arg (args, const uint16_t *); |
161 | | /* A null pointer is an invalid argument for "%lU", but in practice |
162 | | it occurs quite frequently in printf statements that produce |
163 | | debug output. Use a fallback in this case. */ |
164 | | if (ap->a.a_u16_string == NULL) |
165 | | { |
166 | | static const uint16_t u16_null_string[] = |
167 | | { '(', 'N', 'U', 'L', 'L', ')', 0 }; |
168 | | ap->a.a_u16_string = u16_null_string; |
169 | | } |
170 | | break; |
171 | | case TYPE_U32_STRING: |
172 | | ap->a.a_u32_string = va_arg (args, const uint32_t *); |
173 | | /* A null pointer is an invalid argument for "%llU", but in practice |
174 | | it occurs quite frequently in printf statements that produce |
175 | | debug output. Use a fallback in this case. */ |
176 | | if (ap->a.a_u32_string == NULL) |
177 | | { |
178 | | static const uint32_t u32_null_string[] = |
179 | | { '(', 'N', 'U', 'L', 'L', ')', 0 }; |
180 | | ap->a.a_u32_string = u32_null_string; |
181 | | } |
182 | | break; |
183 | | #endif |
184 | 0 | default: |
185 | | /* Unknown type. */ |
186 | 0 | return -1; |
187 | 83.6M | } |
188 | 72.2M | return 0; |
189 | 72.2M | } |