1*946379e7Schristos /* Decomposed printf argument list.
2*946379e7Schristos Copyright (C) 1999, 2002-2003, 2005-2006 Free Software Foundation, Inc.
3*946379e7Schristos
4*946379e7Schristos This program is free software; you can redistribute it and/or modify it
5*946379e7Schristos under the terms of the GNU Library General Public License as published
6*946379e7Schristos by the Free Software Foundation; either version 2, or (at your option)
7*946379e7Schristos any later version.
8*946379e7Schristos
9*946379e7Schristos This program is distributed in the hope that it will be useful,
10*946379e7Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
11*946379e7Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12*946379e7Schristos Library General Public License for more details.
13*946379e7Schristos
14*946379e7Schristos You should have received a copy of the GNU Library General Public
15*946379e7Schristos License along with this program; if not, write to the Free Software
16*946379e7Schristos Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17*946379e7Schristos USA. */
18*946379e7Schristos
19*946379e7Schristos #include <config.h>
20*946379e7Schristos
21*946379e7Schristos /* Specification. */
22*946379e7Schristos #include "printf-args.h"
23*946379e7Schristos
24*946379e7Schristos #ifdef STATIC
25*946379e7Schristos STATIC
26*946379e7Schristos #endif
27*946379e7Schristos int
printf_fetchargs(va_list args,arguments * a)28*946379e7Schristos printf_fetchargs (va_list args, arguments *a)
29*946379e7Schristos {
30*946379e7Schristos size_t i;
31*946379e7Schristos argument *ap;
32*946379e7Schristos
33*946379e7Schristos for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
34*946379e7Schristos switch (ap->type)
35*946379e7Schristos {
36*946379e7Schristos case TYPE_SCHAR:
37*946379e7Schristos ap->a.a_schar = va_arg (args, /*signed char*/ int);
38*946379e7Schristos break;
39*946379e7Schristos case TYPE_UCHAR:
40*946379e7Schristos ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
41*946379e7Schristos break;
42*946379e7Schristos case TYPE_SHORT:
43*946379e7Schristos ap->a.a_short = va_arg (args, /*short*/ int);
44*946379e7Schristos break;
45*946379e7Schristos case TYPE_USHORT:
46*946379e7Schristos ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
47*946379e7Schristos break;
48*946379e7Schristos case TYPE_INT:
49*946379e7Schristos ap->a.a_int = va_arg (args, int);
50*946379e7Schristos break;
51*946379e7Schristos case TYPE_UINT:
52*946379e7Schristos ap->a.a_uint = va_arg (args, unsigned int);
53*946379e7Schristos break;
54*946379e7Schristos case TYPE_LONGINT:
55*946379e7Schristos ap->a.a_longint = va_arg (args, long int);
56*946379e7Schristos break;
57*946379e7Schristos case TYPE_ULONGINT:
58*946379e7Schristos ap->a.a_ulongint = va_arg (args, unsigned long int);
59*946379e7Schristos break;
60*946379e7Schristos #ifdef HAVE_LONG_LONG_INT
61*946379e7Schristos case TYPE_LONGLONGINT:
62*946379e7Schristos ap->a.a_longlongint = va_arg (args, long long int);
63*946379e7Schristos break;
64*946379e7Schristos case TYPE_ULONGLONGINT:
65*946379e7Schristos ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
66*946379e7Schristos break;
67*946379e7Schristos #endif
68*946379e7Schristos case TYPE_DOUBLE:
69*946379e7Schristos ap->a.a_double = va_arg (args, double);
70*946379e7Schristos break;
71*946379e7Schristos #ifdef HAVE_LONG_DOUBLE
72*946379e7Schristos case TYPE_LONGDOUBLE:
73*946379e7Schristos ap->a.a_longdouble = va_arg (args, long double);
74*946379e7Schristos break;
75*946379e7Schristos #endif
76*946379e7Schristos case TYPE_CHAR:
77*946379e7Schristos ap->a.a_char = va_arg (args, int);
78*946379e7Schristos break;
79*946379e7Schristos #ifdef HAVE_WINT_T
80*946379e7Schristos case TYPE_WIDE_CHAR:
81*946379e7Schristos /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
82*946379e7Schristos default argument promotions", this is not the case in mingw32,
83*946379e7Schristos where wint_t is 'unsigned short'. */
84*946379e7Schristos ap->a.a_wide_char =
85*946379e7Schristos (sizeof (wint_t) < sizeof (int)
86*946379e7Schristos ? va_arg (args, int)
87*946379e7Schristos : va_arg (args, wint_t));
88*946379e7Schristos break;
89*946379e7Schristos #endif
90*946379e7Schristos case TYPE_STRING:
91*946379e7Schristos ap->a.a_string = va_arg (args, const char *);
92*946379e7Schristos /* A null pointer is an invalid argument for "%s", but in practice
93*946379e7Schristos it occurs quite frequently in printf statements that produce
94*946379e7Schristos debug output. Use a fallback in this case. */
95*946379e7Schristos if (ap->a.a_string == NULL)
96*946379e7Schristos ap->a.a_string = "(NULL)";
97*946379e7Schristos break;
98*946379e7Schristos #ifdef HAVE_WCHAR_T
99*946379e7Schristos case TYPE_WIDE_STRING:
100*946379e7Schristos ap->a.a_wide_string = va_arg (args, const wchar_t *);
101*946379e7Schristos /* A null pointer is an invalid argument for "%ls", but in practice
102*946379e7Schristos it occurs quite frequently in printf statements that produce
103*946379e7Schristos debug output. Use a fallback in this case. */
104*946379e7Schristos if (ap->a.a_wide_string == NULL)
105*946379e7Schristos {
106*946379e7Schristos static const wchar_t wide_null_string[] =
107*946379e7Schristos {
108*946379e7Schristos (wchar_t)'(',
109*946379e7Schristos (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
110*946379e7Schristos (wchar_t)')',
111*946379e7Schristos (wchar_t)0
112*946379e7Schristos };
113*946379e7Schristos ap->a.a_wide_string = wide_null_string;
114*946379e7Schristos }
115*946379e7Schristos break;
116*946379e7Schristos #endif
117*946379e7Schristos case TYPE_POINTER:
118*946379e7Schristos ap->a.a_pointer = va_arg (args, void *);
119*946379e7Schristos break;
120*946379e7Schristos case TYPE_COUNT_SCHAR_POINTER:
121*946379e7Schristos ap->a.a_count_schar_pointer = va_arg (args, signed char *);
122*946379e7Schristos break;
123*946379e7Schristos case TYPE_COUNT_SHORT_POINTER:
124*946379e7Schristos ap->a.a_count_short_pointer = va_arg (args, short *);
125*946379e7Schristos break;
126*946379e7Schristos case TYPE_COUNT_INT_POINTER:
127*946379e7Schristos ap->a.a_count_int_pointer = va_arg (args, int *);
128*946379e7Schristos break;
129*946379e7Schristos case TYPE_COUNT_LONGINT_POINTER:
130*946379e7Schristos ap->a.a_count_longint_pointer = va_arg (args, long int *);
131*946379e7Schristos break;
132*946379e7Schristos #ifdef HAVE_LONG_LONG_INT
133*946379e7Schristos case TYPE_COUNT_LONGLONGINT_POINTER:
134*946379e7Schristos ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
135*946379e7Schristos break;
136*946379e7Schristos #endif
137*946379e7Schristos default:
138*946379e7Schristos /* Unknown type. */
139*946379e7Schristos return -1;
140*946379e7Schristos }
141*946379e7Schristos return 0;
142*946379e7Schristos }
143