xref: /aosp_15_r20/bionic/libc/stdio/vfwscanf.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*	$OpenBSD: vfwscanf.c,v 1.4 2014/03/19 05:17:01 guenther Exp $ */
2*8d67ca89SAndroid Build Coastguard Worker /*-
3*8d67ca89SAndroid Build Coastguard Worker  * Copyright (c) 1990, 1993
4*8d67ca89SAndroid Build Coastguard Worker  *	The Regents of the University of California.  All rights reserved.
5*8d67ca89SAndroid Build Coastguard Worker  *
6*8d67ca89SAndroid Build Coastguard Worker  * This code is derived from software contributed to Berkeley by
7*8d67ca89SAndroid Build Coastguard Worker  * Chris Torek.
8*8d67ca89SAndroid Build Coastguard Worker  *
9*8d67ca89SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
10*8d67ca89SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
11*8d67ca89SAndroid Build Coastguard Worker  * are met:
12*8d67ca89SAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
13*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
14*8d67ca89SAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
15*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
16*8d67ca89SAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
17*8d67ca89SAndroid Build Coastguard Worker  * 3. Neither the name of the University nor the names of its contributors
18*8d67ca89SAndroid Build Coastguard Worker  *    may be used to endorse or promote products derived from this software
19*8d67ca89SAndroid Build Coastguard Worker  *    without specific prior written permission.
20*8d67ca89SAndroid Build Coastguard Worker  *
21*8d67ca89SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22*8d67ca89SAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*8d67ca89SAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*8d67ca89SAndroid Build Coastguard Worker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25*8d67ca89SAndroid Build Coastguard Worker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*8d67ca89SAndroid Build Coastguard Worker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*8d67ca89SAndroid Build Coastguard Worker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*8d67ca89SAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*8d67ca89SAndroid Build Coastguard Worker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*8d67ca89SAndroid Build Coastguard Worker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*8d67ca89SAndroid Build Coastguard Worker  * SUCH DAMAGE.
32*8d67ca89SAndroid Build Coastguard Worker  */
33*8d67ca89SAndroid Build Coastguard Worker 
34*8d67ca89SAndroid Build Coastguard Worker #include "scanf_common.h"
35*8d67ca89SAndroid Build Coastguard Worker 
36*8d67ca89SAndroid Build Coastguard Worker // An interpretive version of __sccl from vfscanf.c --- a table of all wchar_t values would
37*8d67ca89SAndroid Build Coastguard Worker // be a little too expensive, and some kind of compressed version isn't worth the trouble.
in_ccl(wchar_t wc,const wchar_t * ccl)38*8d67ca89SAndroid Build Coastguard Worker static inline bool in_ccl(wchar_t wc, const wchar_t* ccl) {
39*8d67ca89SAndroid Build Coastguard Worker   // Is this a negated set?
40*8d67ca89SAndroid Build Coastguard Worker   bool member_result = true;
41*8d67ca89SAndroid Build Coastguard Worker   if (*ccl == '^') {
42*8d67ca89SAndroid Build Coastguard Worker     member_result = false;
43*8d67ca89SAndroid Build Coastguard Worker     ++ccl;
44*8d67ca89SAndroid Build Coastguard Worker   }
45*8d67ca89SAndroid Build Coastguard Worker 
46*8d67ca89SAndroid Build Coastguard Worker   // The first character may be ']' or '-' without being special.
47*8d67ca89SAndroid Build Coastguard Worker   if (*ccl == '-' || *ccl == ']') {
48*8d67ca89SAndroid Build Coastguard Worker     // A literal match?
49*8d67ca89SAndroid Build Coastguard Worker     if (*ccl == wc) return member_result;
50*8d67ca89SAndroid Build Coastguard Worker     ++ccl;
51*8d67ca89SAndroid Build Coastguard Worker   }
52*8d67ca89SAndroid Build Coastguard Worker 
53*8d67ca89SAndroid Build Coastguard Worker   while (*ccl && *ccl != ']') {
54*8d67ca89SAndroid Build Coastguard Worker     // The last character may be '-' without being special.
55*8d67ca89SAndroid Build Coastguard Worker     if (*ccl == '-' && ccl[1] != '\0' && ccl[1] != ']') {
56*8d67ca89SAndroid Build Coastguard Worker       wchar_t first = *(ccl - 1);
57*8d67ca89SAndroid Build Coastguard Worker       wchar_t last = *(ccl + 1);
58*8d67ca89SAndroid Build Coastguard Worker       if (first <= last) {
59*8d67ca89SAndroid Build Coastguard Worker         // In the range?
60*8d67ca89SAndroid Build Coastguard Worker         if (wc >= first && wc <= last) return member_result;
61*8d67ca89SAndroid Build Coastguard Worker         ccl += 2;
62*8d67ca89SAndroid Build Coastguard Worker         continue;
63*8d67ca89SAndroid Build Coastguard Worker       }
64*8d67ca89SAndroid Build Coastguard Worker       // A '-' is not considered to be part of a range if the character after
65*8d67ca89SAndroid Build Coastguard Worker       // is not greater than the character before, so fall through...
66*8d67ca89SAndroid Build Coastguard Worker     }
67*8d67ca89SAndroid Build Coastguard Worker     // A literal match?
68*8d67ca89SAndroid Build Coastguard Worker     if (*ccl == wc) return member_result;
69*8d67ca89SAndroid Build Coastguard Worker     ++ccl;
70*8d67ca89SAndroid Build Coastguard Worker   }
71*8d67ca89SAndroid Build Coastguard Worker   return !member_result;
72*8d67ca89SAndroid Build Coastguard Worker }
73*8d67ca89SAndroid Build Coastguard Worker 
74*8d67ca89SAndroid Build Coastguard Worker #pragma GCC diagnostic push
75*8d67ca89SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wframe-larger-than="
76*8d67ca89SAndroid Build Coastguard Worker 
77*8d67ca89SAndroid Build Coastguard Worker /*
78*8d67ca89SAndroid Build Coastguard Worker  * vfwscanf
79*8d67ca89SAndroid Build Coastguard Worker  */
__vfwscanf(FILE * __restrict fp,const wchar_t * __restrict fmt,__va_list ap)80*8d67ca89SAndroid Build Coastguard Worker int __vfwscanf(FILE* __restrict fp, const wchar_t* __restrict fmt, __va_list ap) {
81*8d67ca89SAndroid Build Coastguard Worker   wint_t c;               /* character from format, or conversion */
82*8d67ca89SAndroid Build Coastguard Worker   size_t width;           /* field width, or 0 */
83*8d67ca89SAndroid Build Coastguard Worker   wchar_t* p;             /* points into all kinds of strings */
84*8d67ca89SAndroid Build Coastguard Worker   int n;                  /* handy integer */
85*8d67ca89SAndroid Build Coastguard Worker   int flags;              /* flags as defined above */
86*8d67ca89SAndroid Build Coastguard Worker   wchar_t* p0;            /* saves original value of p when necessary */
87*8d67ca89SAndroid Build Coastguard Worker   int nassigned;          /* number of fields assigned */
88*8d67ca89SAndroid Build Coastguard Worker   int nconversions;       /* number of conversions */
89*8d67ca89SAndroid Build Coastguard Worker   int nread;              /* number of characters consumed from fp */
90*8d67ca89SAndroid Build Coastguard Worker   int base;               /* base argument to strtoimax/strtouimax */
91*8d67ca89SAndroid Build Coastguard Worker   wchar_t buf[BUF];       /* buffer for numeric conversions */
92*8d67ca89SAndroid Build Coastguard Worker   const wchar_t* ccl;
93*8d67ca89SAndroid Build Coastguard Worker   wint_t wi;              /* handy wint_t */
94*8d67ca89SAndroid Build Coastguard Worker   char* mbp;              /* multibyte string pointer for %c %s %[ */
95*8d67ca89SAndroid Build Coastguard Worker   size_t nconv;           /* number of bytes in mb. conversion */
96*8d67ca89SAndroid Build Coastguard Worker   char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
97*8d67ca89SAndroid Build Coastguard Worker   mbstate_t mbs;
98*8d67ca89SAndroid Build Coastguard Worker 
99*8d67ca89SAndroid Build Coastguard Worker   _SET_ORIENTATION(fp, ORIENT_CHARS);
100*8d67ca89SAndroid Build Coastguard Worker 
101*8d67ca89SAndroid Build Coastguard Worker   nassigned = 0;
102*8d67ca89SAndroid Build Coastguard Worker   nconversions = 0;
103*8d67ca89SAndroid Build Coastguard Worker   nread = 0;
104*8d67ca89SAndroid Build Coastguard Worker   base = 0; /* XXX just to keep gcc happy */
105*8d67ca89SAndroid Build Coastguard Worker   for (;;) {
106*8d67ca89SAndroid Build Coastguard Worker     c = *fmt++;
107*8d67ca89SAndroid Build Coastguard Worker     if (c == 0) {
108*8d67ca89SAndroid Build Coastguard Worker       return (nassigned);
109*8d67ca89SAndroid Build Coastguard Worker     }
110*8d67ca89SAndroid Build Coastguard Worker     if (iswspace(c)) {
111*8d67ca89SAndroid Build Coastguard Worker       while ((c = __fgetwc_unlock(fp)) != WEOF && iswspace(c))
112*8d67ca89SAndroid Build Coastguard Worker         ;
113*8d67ca89SAndroid Build Coastguard Worker       if (c != WEOF) __ungetwc(c, fp);
114*8d67ca89SAndroid Build Coastguard Worker       continue;
115*8d67ca89SAndroid Build Coastguard Worker     }
116*8d67ca89SAndroid Build Coastguard Worker     if (c != '%') goto literal;
117*8d67ca89SAndroid Build Coastguard Worker     width = 0;
118*8d67ca89SAndroid Build Coastguard Worker     flags = 0;
119*8d67ca89SAndroid Build Coastguard Worker     /*
120*8d67ca89SAndroid Build Coastguard Worker      * switch on the format.  continue if done;
121*8d67ca89SAndroid Build Coastguard Worker      * break once format type is derived.
122*8d67ca89SAndroid Build Coastguard Worker      */
123*8d67ca89SAndroid Build Coastguard Worker   again:
124*8d67ca89SAndroid Build Coastguard Worker     c = *fmt++;
125*8d67ca89SAndroid Build Coastguard Worker   reswitch:
126*8d67ca89SAndroid Build Coastguard Worker     switch (c) {
127*8d67ca89SAndroid Build Coastguard Worker       case '%':
128*8d67ca89SAndroid Build Coastguard Worker       literal:
129*8d67ca89SAndroid Build Coastguard Worker         if ((wi = __fgetwc_unlock(fp)) == WEOF) goto input_failure;
130*8d67ca89SAndroid Build Coastguard Worker         if (wi != c) {
131*8d67ca89SAndroid Build Coastguard Worker           __ungetwc(wi, fp);
132*8d67ca89SAndroid Build Coastguard Worker           goto match_failure;
133*8d67ca89SAndroid Build Coastguard Worker         }
134*8d67ca89SAndroid Build Coastguard Worker         nread++;
135*8d67ca89SAndroid Build Coastguard Worker         continue;
136*8d67ca89SAndroid Build Coastguard Worker 
137*8d67ca89SAndroid Build Coastguard Worker       case '*':
138*8d67ca89SAndroid Build Coastguard Worker         flags |= SUPPRESS;
139*8d67ca89SAndroid Build Coastguard Worker         goto again;
140*8d67ca89SAndroid Build Coastguard Worker       case 'j':
141*8d67ca89SAndroid Build Coastguard Worker         flags |= MAXINT;
142*8d67ca89SAndroid Build Coastguard Worker         goto again;
143*8d67ca89SAndroid Build Coastguard Worker       case 'L':
144*8d67ca89SAndroid Build Coastguard Worker         flags |= LONGDBL;
145*8d67ca89SAndroid Build Coastguard Worker         goto again;
146*8d67ca89SAndroid Build Coastguard Worker       case 'h':
147*8d67ca89SAndroid Build Coastguard Worker         if (*fmt == 'h') {
148*8d67ca89SAndroid Build Coastguard Worker           fmt++;
149*8d67ca89SAndroid Build Coastguard Worker           flags |= SHORTSHORT;
150*8d67ca89SAndroid Build Coastguard Worker         } else {
151*8d67ca89SAndroid Build Coastguard Worker           flags |= SHORT;
152*8d67ca89SAndroid Build Coastguard Worker         }
153*8d67ca89SAndroid Build Coastguard Worker         goto again;
154*8d67ca89SAndroid Build Coastguard Worker       case 'l':
155*8d67ca89SAndroid Build Coastguard Worker         if (*fmt == 'l') {
156*8d67ca89SAndroid Build Coastguard Worker           fmt++;
157*8d67ca89SAndroid Build Coastguard Worker           flags |= LLONG;
158*8d67ca89SAndroid Build Coastguard Worker         } else {
159*8d67ca89SAndroid Build Coastguard Worker           flags |= LONG;
160*8d67ca89SAndroid Build Coastguard Worker         }
161*8d67ca89SAndroid Build Coastguard Worker         goto again;
162*8d67ca89SAndroid Build Coastguard Worker       case 'q':
163*8d67ca89SAndroid Build Coastguard Worker         flags |= LLONG; /* deprecated */
164*8d67ca89SAndroid Build Coastguard Worker         goto again;
165*8d67ca89SAndroid Build Coastguard Worker       case 't':
166*8d67ca89SAndroid Build Coastguard Worker         flags |= PTRINT;
167*8d67ca89SAndroid Build Coastguard Worker         goto again;
168*8d67ca89SAndroid Build Coastguard Worker       case 'z':
169*8d67ca89SAndroid Build Coastguard Worker         flags |= SIZEINT;
170*8d67ca89SAndroid Build Coastguard Worker         goto again;
171*8d67ca89SAndroid Build Coastguard Worker 
172*8d67ca89SAndroid Build Coastguard Worker       case '0':
173*8d67ca89SAndroid Build Coastguard Worker       case '1':
174*8d67ca89SAndroid Build Coastguard Worker       case '2':
175*8d67ca89SAndroid Build Coastguard Worker       case '3':
176*8d67ca89SAndroid Build Coastguard Worker       case '4':
177*8d67ca89SAndroid Build Coastguard Worker       case '5':
178*8d67ca89SAndroid Build Coastguard Worker       case '6':
179*8d67ca89SAndroid Build Coastguard Worker       case '7':
180*8d67ca89SAndroid Build Coastguard Worker       case '8':
181*8d67ca89SAndroid Build Coastguard Worker       case '9':
182*8d67ca89SAndroid Build Coastguard Worker         width = width * 10 + c - '0';
183*8d67ca89SAndroid Build Coastguard Worker         goto again;
184*8d67ca89SAndroid Build Coastguard Worker 
185*8d67ca89SAndroid Build Coastguard Worker       /*
186*8d67ca89SAndroid Build Coastguard Worker        * Conversions.
187*8d67ca89SAndroid Build Coastguard Worker        * Those marked `compat' are for 4.[123]BSD compatibility.
188*8d67ca89SAndroid Build Coastguard Worker        */
189*8d67ca89SAndroid Build Coastguard Worker       case 'b':
190*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
191*8d67ca89SAndroid Build Coastguard Worker         base = 2;
192*8d67ca89SAndroid Build Coastguard Worker         flags |= PFBOK; /* enable 0b prefixing */
193*8d67ca89SAndroid Build Coastguard Worker         break;
194*8d67ca89SAndroid Build Coastguard Worker 
195*8d67ca89SAndroid Build Coastguard Worker       case 'D': /* compat */
196*8d67ca89SAndroid Build Coastguard Worker         flags |= LONG;
197*8d67ca89SAndroid Build Coastguard Worker         __BIONIC_FALLTHROUGH;
198*8d67ca89SAndroid Build Coastguard Worker       case 'd':
199*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
200*8d67ca89SAndroid Build Coastguard Worker         base = 10;
201*8d67ca89SAndroid Build Coastguard Worker         break;
202*8d67ca89SAndroid Build Coastguard Worker 
203*8d67ca89SAndroid Build Coastguard Worker       case 'i':
204*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
205*8d67ca89SAndroid Build Coastguard Worker         base = 0;
206*8d67ca89SAndroid Build Coastguard Worker         break;
207*8d67ca89SAndroid Build Coastguard Worker 
208*8d67ca89SAndroid Build Coastguard Worker       case 'O': /* compat */
209*8d67ca89SAndroid Build Coastguard Worker         flags |= LONG;
210*8d67ca89SAndroid Build Coastguard Worker         __BIONIC_FALLTHROUGH;
211*8d67ca89SAndroid Build Coastguard Worker       case 'o':
212*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
213*8d67ca89SAndroid Build Coastguard Worker         flags |= UNSIGNED;
214*8d67ca89SAndroid Build Coastguard Worker         base = 8;
215*8d67ca89SAndroid Build Coastguard Worker         break;
216*8d67ca89SAndroid Build Coastguard Worker 
217*8d67ca89SAndroid Build Coastguard Worker       case 'u':
218*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
219*8d67ca89SAndroid Build Coastguard Worker         flags |= UNSIGNED;
220*8d67ca89SAndroid Build Coastguard Worker         base = 10;
221*8d67ca89SAndroid Build Coastguard Worker         break;
222*8d67ca89SAndroid Build Coastguard Worker 
223*8d67ca89SAndroid Build Coastguard Worker       case 'w': {
224*8d67ca89SAndroid Build Coastguard Worker         int size = 0;
225*8d67ca89SAndroid Build Coastguard Worker         bool fast = false;
226*8d67ca89SAndroid Build Coastguard Worker         c = *fmt++;
227*8d67ca89SAndroid Build Coastguard Worker         if (c == 'f') {
228*8d67ca89SAndroid Build Coastguard Worker           fast = true;
229*8d67ca89SAndroid Build Coastguard Worker           c = *fmt++;
230*8d67ca89SAndroid Build Coastguard Worker         }
231*8d67ca89SAndroid Build Coastguard Worker         while (is_digit(c)) {
232*8d67ca89SAndroid Build Coastguard Worker           APPEND_DIGIT(size, c);
233*8d67ca89SAndroid Build Coastguard Worker           c = *fmt++;
234*8d67ca89SAndroid Build Coastguard Worker         }
235*8d67ca89SAndroid Build Coastguard Worker         flags |= w_to_flag(size, fast);
236*8d67ca89SAndroid Build Coastguard Worker         goto reswitch;
237*8d67ca89SAndroid Build Coastguard Worker       }
238*8d67ca89SAndroid Build Coastguard Worker 
239*8d67ca89SAndroid Build Coastguard Worker       case 'X':
240*8d67ca89SAndroid Build Coastguard Worker       case 'x':
241*8d67ca89SAndroid Build Coastguard Worker         flags |= PFXOK; /* enable 0x prefixing */
242*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
243*8d67ca89SAndroid Build Coastguard Worker         flags |= UNSIGNED;
244*8d67ca89SAndroid Build Coastguard Worker         base = 16;
245*8d67ca89SAndroid Build Coastguard Worker         break;
246*8d67ca89SAndroid Build Coastguard Worker 
247*8d67ca89SAndroid Build Coastguard Worker       case 'e':
248*8d67ca89SAndroid Build Coastguard Worker       case 'E':
249*8d67ca89SAndroid Build Coastguard Worker       case 'f':
250*8d67ca89SAndroid Build Coastguard Worker       case 'F':
251*8d67ca89SAndroid Build Coastguard Worker       case 'g':
252*8d67ca89SAndroid Build Coastguard Worker       case 'G':
253*8d67ca89SAndroid Build Coastguard Worker       case 'a':
254*8d67ca89SAndroid Build Coastguard Worker       case 'A':
255*8d67ca89SAndroid Build Coastguard Worker         c = CT_FLOAT;
256*8d67ca89SAndroid Build Coastguard Worker         break;
257*8d67ca89SAndroid Build Coastguard Worker 
258*8d67ca89SAndroid Build Coastguard Worker       case 's':
259*8d67ca89SAndroid Build Coastguard Worker         c = CT_STRING;
260*8d67ca89SAndroid Build Coastguard Worker         break;
261*8d67ca89SAndroid Build Coastguard Worker 
262*8d67ca89SAndroid Build Coastguard Worker       case '[':
263*8d67ca89SAndroid Build Coastguard Worker         ccl = fmt;
264*8d67ca89SAndroid Build Coastguard Worker         if (*fmt == '^') fmt++;
265*8d67ca89SAndroid Build Coastguard Worker         if (*fmt == ']') fmt++;
266*8d67ca89SAndroid Build Coastguard Worker         while (*fmt != '\0' && *fmt != ']') fmt++;
267*8d67ca89SAndroid Build Coastguard Worker         fmt++;
268*8d67ca89SAndroid Build Coastguard Worker         flags |= NOSKIP;
269*8d67ca89SAndroid Build Coastguard Worker         c = CT_CCL;
270*8d67ca89SAndroid Build Coastguard Worker         break;
271*8d67ca89SAndroid Build Coastguard Worker 
272*8d67ca89SAndroid Build Coastguard Worker       case 'c':
273*8d67ca89SAndroid Build Coastguard Worker         flags |= NOSKIP;
274*8d67ca89SAndroid Build Coastguard Worker         c = CT_CHAR;
275*8d67ca89SAndroid Build Coastguard Worker         break;
276*8d67ca89SAndroid Build Coastguard Worker 
277*8d67ca89SAndroid Build Coastguard Worker       case 'p': /* pointer format is like hex */
278*8d67ca89SAndroid Build Coastguard Worker         flags |= POINTER | PFXOK;
279*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
280*8d67ca89SAndroid Build Coastguard Worker         flags |= UNSIGNED;
281*8d67ca89SAndroid Build Coastguard Worker         base = 16;
282*8d67ca89SAndroid Build Coastguard Worker         break;
283*8d67ca89SAndroid Build Coastguard Worker 
284*8d67ca89SAndroid Build Coastguard Worker       case 'n':
285*8d67ca89SAndroid Build Coastguard Worker         nconversions++;
286*8d67ca89SAndroid Build Coastguard Worker         if (flags & SUPPRESS) continue;
287*8d67ca89SAndroid Build Coastguard Worker         if (flags & SHORTSHORT)
288*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, signed char*) = nread;
289*8d67ca89SAndroid Build Coastguard Worker         else if (flags & SHORT)
290*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, short*) = nread;
291*8d67ca89SAndroid Build Coastguard Worker         else if (flags & LONG)
292*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, long*) = nread;
293*8d67ca89SAndroid Build Coastguard Worker         else if (flags & SIZEINT)
294*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, ssize_t*) = nread;
295*8d67ca89SAndroid Build Coastguard Worker         else if (flags & PTRINT)
296*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, ptrdiff_t*) = nread;
297*8d67ca89SAndroid Build Coastguard Worker         else if (flags & LLONG)
298*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, long long*) = nread;
299*8d67ca89SAndroid Build Coastguard Worker         else if (flags & MAXINT)
300*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, intmax_t*) = nread;
301*8d67ca89SAndroid Build Coastguard Worker         else
302*8d67ca89SAndroid Build Coastguard Worker           *va_arg(ap, int*) = nread;
303*8d67ca89SAndroid Build Coastguard Worker         continue;
304*8d67ca89SAndroid Build Coastguard Worker 
305*8d67ca89SAndroid Build Coastguard Worker       /*
306*8d67ca89SAndroid Build Coastguard Worker        * Disgusting backwards compatibility hacks.	XXX
307*8d67ca89SAndroid Build Coastguard Worker        */
308*8d67ca89SAndroid Build Coastguard Worker       case '\0': /* compat */
309*8d67ca89SAndroid Build Coastguard Worker         return (EOF);
310*8d67ca89SAndroid Build Coastguard Worker 
311*8d67ca89SAndroid Build Coastguard Worker       default: /* compat */
312*8d67ca89SAndroid Build Coastguard Worker         if (iswupper(c)) flags |= LONG;
313*8d67ca89SAndroid Build Coastguard Worker         c = CT_INT;
314*8d67ca89SAndroid Build Coastguard Worker         base = 10;
315*8d67ca89SAndroid Build Coastguard Worker         break;
316*8d67ca89SAndroid Build Coastguard Worker     }
317*8d67ca89SAndroid Build Coastguard Worker 
318*8d67ca89SAndroid Build Coastguard Worker     /*
319*8d67ca89SAndroid Build Coastguard Worker      * Consume leading white space, except for formats
320*8d67ca89SAndroid Build Coastguard Worker      * that suppress this.
321*8d67ca89SAndroid Build Coastguard Worker      */
322*8d67ca89SAndroid Build Coastguard Worker     if ((flags & NOSKIP) == 0) {
323*8d67ca89SAndroid Build Coastguard Worker       while ((wi = __fgetwc_unlock(fp)) != WEOF && iswspace(wi)) nread++;
324*8d67ca89SAndroid Build Coastguard Worker       if (wi == WEOF) goto input_failure;
325*8d67ca89SAndroid Build Coastguard Worker       __ungetwc(wi, fp);
326*8d67ca89SAndroid Build Coastguard Worker     }
327*8d67ca89SAndroid Build Coastguard Worker 
328*8d67ca89SAndroid Build Coastguard Worker     /*
329*8d67ca89SAndroid Build Coastguard Worker      * Do the conversion.
330*8d67ca89SAndroid Build Coastguard Worker      */
331*8d67ca89SAndroid Build Coastguard Worker     switch (c) {
332*8d67ca89SAndroid Build Coastguard Worker       case CT_CHAR:
333*8d67ca89SAndroid Build Coastguard Worker         /* scan arbitrary characters (sets NOSKIP) */
334*8d67ca89SAndroid Build Coastguard Worker         if (width == 0) width = 1;
335*8d67ca89SAndroid Build Coastguard Worker         if (flags & LONG) {
336*8d67ca89SAndroid Build Coastguard Worker           if (!(flags & SUPPRESS)) p = va_arg(ap, wchar_t*);
337*8d67ca89SAndroid Build Coastguard Worker           n = 0;
338*8d67ca89SAndroid Build Coastguard Worker           while (width-- != 0 && (wi = __fgetwc_unlock(fp)) != WEOF) {
339*8d67ca89SAndroid Build Coastguard Worker             if (!(flags & SUPPRESS)) *p++ = static_cast<wchar_t>(wi);
340*8d67ca89SAndroid Build Coastguard Worker             n++;
341*8d67ca89SAndroid Build Coastguard Worker           }
342*8d67ca89SAndroid Build Coastguard Worker           if (n == 0) goto input_failure;
343*8d67ca89SAndroid Build Coastguard Worker           nread += n;
344*8d67ca89SAndroid Build Coastguard Worker           if (!(flags & SUPPRESS)) nassigned++;
345*8d67ca89SAndroid Build Coastguard Worker         } else {
346*8d67ca89SAndroid Build Coastguard Worker           if (!(flags & SUPPRESS)) mbp = va_arg(ap, char*);
347*8d67ca89SAndroid Build Coastguard Worker           n = 0;
348*8d67ca89SAndroid Build Coastguard Worker           memset(&mbs, 0, sizeof(mbs));
349*8d67ca89SAndroid Build Coastguard Worker           while (width != 0 && (wi = __fgetwc_unlock(fp)) != WEOF) {
350*8d67ca89SAndroid Build Coastguard Worker             if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) {
351*8d67ca89SAndroid Build Coastguard Worker               nconv = wcrtomb(mbp, wi, &mbs);
352*8d67ca89SAndroid Build Coastguard Worker               if (nconv == static_cast<size_t>(-1)) goto input_failure;
353*8d67ca89SAndroid Build Coastguard Worker             } else {
354*8d67ca89SAndroid Build Coastguard Worker               nconv = wcrtomb(mbbuf, wi, &mbs);
355*8d67ca89SAndroid Build Coastguard Worker               if (nconv == static_cast<size_t>(-1)) goto input_failure;
356*8d67ca89SAndroid Build Coastguard Worker               if (nconv > width) {
357*8d67ca89SAndroid Build Coastguard Worker                 __ungetwc(wi, fp);
358*8d67ca89SAndroid Build Coastguard Worker                 break;
359*8d67ca89SAndroid Build Coastguard Worker               }
360*8d67ca89SAndroid Build Coastguard Worker               if (!(flags & SUPPRESS)) memcpy(mbp, mbbuf, nconv);
361*8d67ca89SAndroid Build Coastguard Worker             }
362*8d67ca89SAndroid Build Coastguard Worker             if (!(flags & SUPPRESS)) mbp += nconv;
363*8d67ca89SAndroid Build Coastguard Worker             width -= nconv;
364*8d67ca89SAndroid Build Coastguard Worker             n++;
365*8d67ca89SAndroid Build Coastguard Worker           }
366*8d67ca89SAndroid Build Coastguard Worker           if (n == 0) goto input_failure;
367*8d67ca89SAndroid Build Coastguard Worker           nread += n;
368*8d67ca89SAndroid Build Coastguard Worker           if (!(flags & SUPPRESS)) nassigned++;
369*8d67ca89SAndroid Build Coastguard Worker         }
370*8d67ca89SAndroid Build Coastguard Worker         nconversions++;
371*8d67ca89SAndroid Build Coastguard Worker         break;
372*8d67ca89SAndroid Build Coastguard Worker 
373*8d67ca89SAndroid Build Coastguard Worker       case CT_CCL:
374*8d67ca89SAndroid Build Coastguard Worker       case CT_STRING:
375*8d67ca89SAndroid Build Coastguard Worker         // CT_CCL: scan a (nonempty) character class (sets NOSKIP).
376*8d67ca89SAndroid Build Coastguard Worker         // CT_STRING: like CCL, but zero-length string OK, & no NOSKIP.
377*8d67ca89SAndroid Build Coastguard Worker         if (width == 0) width = SIZE_MAX; // 'infinity'.
378*8d67ca89SAndroid Build Coastguard Worker         if ((flags & SUPPRESS) && (flags & LONG)) {
379*8d67ca89SAndroid Build Coastguard Worker           n = 0;
380*8d67ca89SAndroid Build Coastguard Worker           while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && ((c == CT_CCL && in_ccl(wi, ccl)) || (c == CT_STRING && !iswspace(wi)))) n++;
381*8d67ca89SAndroid Build Coastguard Worker           if (wi != WEOF) __ungetwc(wi, fp);
382*8d67ca89SAndroid Build Coastguard Worker         } else if (flags & LONG) {
383*8d67ca89SAndroid Build Coastguard Worker           p0 = p = va_arg(ap, wchar_t*);
384*8d67ca89SAndroid Build Coastguard Worker           while ((wi = __fgetwc_unlock(fp)) != WEOF && width-- != 0 && ((c == CT_CCL && in_ccl(wi, ccl)) || (c == CT_STRING && !iswspace(wi)))) {
385*8d67ca89SAndroid Build Coastguard Worker             *p++ = static_cast<wchar_t>(wi);
386*8d67ca89SAndroid Build Coastguard Worker           }
387*8d67ca89SAndroid Build Coastguard Worker           if (wi != WEOF) __ungetwc(wi, fp);
388*8d67ca89SAndroid Build Coastguard Worker           n = p - p0;
389*8d67ca89SAndroid Build Coastguard Worker         } else {
390*8d67ca89SAndroid Build Coastguard Worker           if (!(flags & SUPPRESS)) mbp = va_arg(ap, char*);
391*8d67ca89SAndroid Build Coastguard Worker           n = 0;
392*8d67ca89SAndroid Build Coastguard Worker           memset(&mbs, 0, sizeof(mbs));
393*8d67ca89SAndroid Build Coastguard Worker           while ((wi = __fgetwc_unlock(fp)) != WEOF && width != 0 && ((c == CT_CCL && in_ccl(wi, ccl)) || (c == CT_STRING && !iswspace(wi)))) {
394*8d67ca89SAndroid Build Coastguard Worker             if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) {
395*8d67ca89SAndroid Build Coastguard Worker               nconv = wcrtomb(mbp, wi, &mbs);
396*8d67ca89SAndroid Build Coastguard Worker               if (nconv == static_cast<size_t>(-1)) goto input_failure;
397*8d67ca89SAndroid Build Coastguard Worker             } else {
398*8d67ca89SAndroid Build Coastguard Worker               nconv = wcrtomb(mbbuf, wi, &mbs);
399*8d67ca89SAndroid Build Coastguard Worker               if (nconv == static_cast<size_t>(-1)) goto input_failure;
400*8d67ca89SAndroid Build Coastguard Worker               if (nconv > width) break;
401*8d67ca89SAndroid Build Coastguard Worker               if (!(flags & SUPPRESS)) memcpy(mbp, mbbuf, nconv);
402*8d67ca89SAndroid Build Coastguard Worker             }
403*8d67ca89SAndroid Build Coastguard Worker             if (!(flags & SUPPRESS)) mbp += nconv;
404*8d67ca89SAndroid Build Coastguard Worker             width -= nconv;
405*8d67ca89SAndroid Build Coastguard Worker             n++;
406*8d67ca89SAndroid Build Coastguard Worker           }
407*8d67ca89SAndroid Build Coastguard Worker           if (wi != WEOF) __ungetwc(wi, fp);
408*8d67ca89SAndroid Build Coastguard Worker         }
409*8d67ca89SAndroid Build Coastguard Worker         if (c == CT_CCL && n == 0) goto match_failure;
410*8d67ca89SAndroid Build Coastguard Worker         if (!(flags & SUPPRESS)) {
411*8d67ca89SAndroid Build Coastguard Worker           if (flags & LONG) {
412*8d67ca89SAndroid Build Coastguard Worker             *p = L'\0';
413*8d67ca89SAndroid Build Coastguard Worker           } else {
414*8d67ca89SAndroid Build Coastguard Worker             *mbp = '\0';
415*8d67ca89SAndroid Build Coastguard Worker           }
416*8d67ca89SAndroid Build Coastguard Worker           ++nassigned;
417*8d67ca89SAndroid Build Coastguard Worker         }
418*8d67ca89SAndroid Build Coastguard Worker         nread += n;
419*8d67ca89SAndroid Build Coastguard Worker         nconversions++;
420*8d67ca89SAndroid Build Coastguard Worker         break;
421*8d67ca89SAndroid Build Coastguard Worker 
422*8d67ca89SAndroid Build Coastguard Worker       case CT_INT:
423*8d67ca89SAndroid Build Coastguard Worker         /* scan an integer as if by strtoimax/strtoumax */
424*8d67ca89SAndroid Build Coastguard Worker         if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1)
425*8d67ca89SAndroid Build Coastguard Worker           width = sizeof(buf) / sizeof(*buf) - 1;
426*8d67ca89SAndroid Build Coastguard Worker         flags |= SIGNOK | NDIGITS | NZDIGITS;
427*8d67ca89SAndroid Build Coastguard Worker         for (p = buf; width; width--) {
428*8d67ca89SAndroid Build Coastguard Worker           c = __fgetwc_unlock(fp);
429*8d67ca89SAndroid Build Coastguard Worker           /*
430*8d67ca89SAndroid Build Coastguard Worker            * Switch on the character; `goto ok'
431*8d67ca89SAndroid Build Coastguard Worker            * if we accept it as a part of number.
432*8d67ca89SAndroid Build Coastguard Worker            */
433*8d67ca89SAndroid Build Coastguard Worker           switch (c) {
434*8d67ca89SAndroid Build Coastguard Worker             /*
435*8d67ca89SAndroid Build Coastguard Worker              * The digit 0 is always legal, but is
436*8d67ca89SAndroid Build Coastguard Worker              * special.  For %i conversions, if no
437*8d67ca89SAndroid Build Coastguard Worker              * digits (zero or nonzero) have been
438*8d67ca89SAndroid Build Coastguard Worker              * scanned (only signs), we will have
439*8d67ca89SAndroid Build Coastguard Worker              * base==0.  In that case, we should set
440*8d67ca89SAndroid Build Coastguard Worker              * it to 8 and enable 0b/0x prefixing.
441*8d67ca89SAndroid Build Coastguard Worker              * Also, if we have not scanned zero digits
442*8d67ca89SAndroid Build Coastguard Worker              * before this, do not turn off prefixing
443*8d67ca89SAndroid Build Coastguard Worker              * (someone else will turn it off if we
444*8d67ca89SAndroid Build Coastguard Worker              * have scanned any nonzero digits).
445*8d67ca89SAndroid Build Coastguard Worker              */
446*8d67ca89SAndroid Build Coastguard Worker             case '0':
447*8d67ca89SAndroid Build Coastguard Worker               if (base == 0) {
448*8d67ca89SAndroid Build Coastguard Worker                 base = 8;
449*8d67ca89SAndroid Build Coastguard Worker                 flags |= PFBOK | PFXOK;
450*8d67ca89SAndroid Build Coastguard Worker               }
451*8d67ca89SAndroid Build Coastguard Worker               if (flags & NZDIGITS) {
452*8d67ca89SAndroid Build Coastguard Worker                 flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
453*8d67ca89SAndroid Build Coastguard Worker               } else {
454*8d67ca89SAndroid Build Coastguard Worker                 flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
455*8d67ca89SAndroid Build Coastguard Worker               }
456*8d67ca89SAndroid Build Coastguard Worker               goto ok;
457*8d67ca89SAndroid Build Coastguard Worker 
458*8d67ca89SAndroid Build Coastguard Worker             /* 1 through 7 always legal */
459*8d67ca89SAndroid Build Coastguard Worker             case 'B':
460*8d67ca89SAndroid Build Coastguard Worker             case 'b':
461*8d67ca89SAndroid Build Coastguard Worker               // Is this 'b' potentially part of an "0b" prefix?
462*8d67ca89SAndroid Build Coastguard Worker               if ((flags & PFBOK) && p == buf + 1 + !!(flags & HAVESIGN)) {
463*8d67ca89SAndroid Build Coastguard Worker                 base = 2;
464*8d67ca89SAndroid Build Coastguard Worker                 flags &= ~PFBOK;
465*8d67ca89SAndroid Build Coastguard Worker                 goto ok;
466*8d67ca89SAndroid Build Coastguard Worker               }
467*8d67ca89SAndroid Build Coastguard Worker               // No? Fall through and see if it's a hex digit instead then...
468*8d67ca89SAndroid Build Coastguard Worker               __BIONIC_FALLTHROUGH;
469*8d67ca89SAndroid Build Coastguard Worker             case '1':
470*8d67ca89SAndroid Build Coastguard Worker             case '2':
471*8d67ca89SAndroid Build Coastguard Worker             case '3':
472*8d67ca89SAndroid Build Coastguard Worker             case '4':
473*8d67ca89SAndroid Build Coastguard Worker             case '5':
474*8d67ca89SAndroid Build Coastguard Worker             case '6':
475*8d67ca89SAndroid Build Coastguard Worker             case '7':
476*8d67ca89SAndroid Build Coastguard Worker             case '8':
477*8d67ca89SAndroid Build Coastguard Worker             case '9':
478*8d67ca89SAndroid Build Coastguard Worker             case 'A':
479*8d67ca89SAndroid Build Coastguard Worker             case 'C':
480*8d67ca89SAndroid Build Coastguard Worker             case 'D':
481*8d67ca89SAndroid Build Coastguard Worker             case 'E':
482*8d67ca89SAndroid Build Coastguard Worker             case 'F':
483*8d67ca89SAndroid Build Coastguard Worker             case 'a':
484*8d67ca89SAndroid Build Coastguard Worker             case 'c':
485*8d67ca89SAndroid Build Coastguard Worker             case 'd':
486*8d67ca89SAndroid Build Coastguard Worker             case 'e':
487*8d67ca89SAndroid Build Coastguard Worker             case 'f':
488*8d67ca89SAndroid Build Coastguard Worker               if (base == 0) base = 10;
489*8d67ca89SAndroid Build Coastguard Worker               if (base != 16 && static_cast<int>(c - '0') >= base) break; /* not legal here */
490*8d67ca89SAndroid Build Coastguard Worker               flags &= ~(SIGNOK | PFBOK | PFXOK | NDIGITS);
491*8d67ca89SAndroid Build Coastguard Worker               goto ok;
492*8d67ca89SAndroid Build Coastguard Worker 
493*8d67ca89SAndroid Build Coastguard Worker             /* sign ok only as first character */
494*8d67ca89SAndroid Build Coastguard Worker             case '+':
495*8d67ca89SAndroid Build Coastguard Worker             case '-':
496*8d67ca89SAndroid Build Coastguard Worker               if (flags & SIGNOK) {
497*8d67ca89SAndroid Build Coastguard Worker                 flags &= ~SIGNOK;
498*8d67ca89SAndroid Build Coastguard Worker                 flags |= HAVESIGN;
499*8d67ca89SAndroid Build Coastguard Worker                 goto ok;
500*8d67ca89SAndroid Build Coastguard Worker               }
501*8d67ca89SAndroid Build Coastguard Worker               break;
502*8d67ca89SAndroid Build Coastguard Worker 
503*8d67ca89SAndroid Build Coastguard Worker             /*
504*8d67ca89SAndroid Build Coastguard Worker              * x ok iff flag still set and 2nd char (or
505*8d67ca89SAndroid Build Coastguard Worker              * 3rd char if we have a sign).
506*8d67ca89SAndroid Build Coastguard Worker              */
507*8d67ca89SAndroid Build Coastguard Worker             case 'x':
508*8d67ca89SAndroid Build Coastguard Worker             case 'X':
509*8d67ca89SAndroid Build Coastguard Worker               if ((flags & PFXOK) && p == buf + 1 + !!(flags & HAVESIGN)) {
510*8d67ca89SAndroid Build Coastguard Worker                 base = 16; /* if %i */
511*8d67ca89SAndroid Build Coastguard Worker                 flags &= ~PFXOK;
512*8d67ca89SAndroid Build Coastguard Worker                 goto ok;
513*8d67ca89SAndroid Build Coastguard Worker               }
514*8d67ca89SAndroid Build Coastguard Worker               break;
515*8d67ca89SAndroid Build Coastguard Worker           }
516*8d67ca89SAndroid Build Coastguard Worker 
517*8d67ca89SAndroid Build Coastguard Worker           /*
518*8d67ca89SAndroid Build Coastguard Worker            * If we got here, c is not a legal character
519*8d67ca89SAndroid Build Coastguard Worker            * for a number.  Stop accumulating digits.
520*8d67ca89SAndroid Build Coastguard Worker            */
521*8d67ca89SAndroid Build Coastguard Worker           if (c != WEOF) __ungetwc(c, fp);
522*8d67ca89SAndroid Build Coastguard Worker           break;
523*8d67ca89SAndroid Build Coastguard Worker         ok:
524*8d67ca89SAndroid Build Coastguard Worker           /*
525*8d67ca89SAndroid Build Coastguard Worker            * c is legal: store it and look at the next.
526*8d67ca89SAndroid Build Coastguard Worker            */
527*8d67ca89SAndroid Build Coastguard Worker           *p++ = static_cast<wchar_t>(c);
528*8d67ca89SAndroid Build Coastguard Worker         }
529*8d67ca89SAndroid Build Coastguard Worker         /*
530*8d67ca89SAndroid Build Coastguard Worker          * If we had only a sign, it is no good; push back the sign.
531*8d67ca89SAndroid Build Coastguard Worker          * If the number was `[-+]0[BbXx]`, push back and treat it
532*8d67ca89SAndroid Build Coastguard Worker          * as `[-+]0`.
533*8d67ca89SAndroid Build Coastguard Worker          */
534*8d67ca89SAndroid Build Coastguard Worker         if (flags & NDIGITS) {
535*8d67ca89SAndroid Build Coastguard Worker           if (p > buf) __ungetwc(*--p, fp);
536*8d67ca89SAndroid Build Coastguard Worker           goto match_failure;
537*8d67ca89SAndroid Build Coastguard Worker         }
538*8d67ca89SAndroid Build Coastguard Worker         c = p[-1];
539*8d67ca89SAndroid Build Coastguard Worker         if ((base == 2 && (c == 'b' || c == 'B')) || c == 'x' || c == 'X') {
540*8d67ca89SAndroid Build Coastguard Worker           --p;
541*8d67ca89SAndroid Build Coastguard Worker           __ungetwc(c, fp);
542*8d67ca89SAndroid Build Coastguard Worker         }
543*8d67ca89SAndroid Build Coastguard Worker         if ((flags & SUPPRESS) == 0) {
544*8d67ca89SAndroid Build Coastguard Worker           uintmax_t res;
545*8d67ca89SAndroid Build Coastguard Worker 
546*8d67ca89SAndroid Build Coastguard Worker           *p = '\0';
547*8d67ca89SAndroid Build Coastguard Worker           if (flags & UNSIGNED)
548*8d67ca89SAndroid Build Coastguard Worker             res = wcstoimax(buf, NULL, base);
549*8d67ca89SAndroid Build Coastguard Worker           else
550*8d67ca89SAndroid Build Coastguard Worker             res = wcstoumax(buf, NULL, base);
551*8d67ca89SAndroid Build Coastguard Worker           if (flags & POINTER)
552*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, void**) = reinterpret_cast<void*>(res);
553*8d67ca89SAndroid Build Coastguard Worker           else if (flags & MAXINT)
554*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, intmax_t*) = res;
555*8d67ca89SAndroid Build Coastguard Worker           else if (flags & LLONG)
556*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, long long*) = res;
557*8d67ca89SAndroid Build Coastguard Worker           else if (flags & SIZEINT)
558*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, ssize_t*) = res;
559*8d67ca89SAndroid Build Coastguard Worker           else if (flags & PTRINT)
560*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, ptrdiff_t*) = res;
561*8d67ca89SAndroid Build Coastguard Worker           else if (flags & LONG)
562*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, long*) = res;
563*8d67ca89SAndroid Build Coastguard Worker           else if (flags & SHORT)
564*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, short*) = res;
565*8d67ca89SAndroid Build Coastguard Worker           else if (flags & SHORTSHORT)
566*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, signed char*) = res;
567*8d67ca89SAndroid Build Coastguard Worker           else
568*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, int*) = res;
569*8d67ca89SAndroid Build Coastguard Worker           nassigned++;
570*8d67ca89SAndroid Build Coastguard Worker         }
571*8d67ca89SAndroid Build Coastguard Worker         nread += p - buf;
572*8d67ca89SAndroid Build Coastguard Worker         nconversions++;
573*8d67ca89SAndroid Build Coastguard Worker         break;
574*8d67ca89SAndroid Build Coastguard Worker 
575*8d67ca89SAndroid Build Coastguard Worker       case CT_FLOAT:
576*8d67ca89SAndroid Build Coastguard Worker         /* scan a floating point number as if by strtod */
577*8d67ca89SAndroid Build Coastguard Worker         if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1)
578*8d67ca89SAndroid Build Coastguard Worker           width = sizeof(buf) / sizeof(*buf) - 1;
579*8d67ca89SAndroid Build Coastguard Worker         if ((width = wparsefloat(fp, buf, buf + width)) == 0) goto match_failure;
580*8d67ca89SAndroid Build Coastguard Worker         if ((flags & SUPPRESS) == 0) {
581*8d67ca89SAndroid Build Coastguard Worker           if (flags & LONGDBL) {
582*8d67ca89SAndroid Build Coastguard Worker             long double res = wcstold(buf, &p);
583*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, long double*) = res;
584*8d67ca89SAndroid Build Coastguard Worker           } else if (flags & LONG) {
585*8d67ca89SAndroid Build Coastguard Worker             double res = wcstod(buf, &p);
586*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, double*) = res;
587*8d67ca89SAndroid Build Coastguard Worker           } else {
588*8d67ca89SAndroid Build Coastguard Worker             float res = wcstof(buf, &p);
589*8d67ca89SAndroid Build Coastguard Worker             *va_arg(ap, float*) = res;
590*8d67ca89SAndroid Build Coastguard Worker           }
591*8d67ca89SAndroid Build Coastguard Worker           if (static_cast<size_t>(p - buf) != width) abort();
592*8d67ca89SAndroid Build Coastguard Worker           nassigned++;
593*8d67ca89SAndroid Build Coastguard Worker         }
594*8d67ca89SAndroid Build Coastguard Worker         nread += width;
595*8d67ca89SAndroid Build Coastguard Worker         nconversions++;
596*8d67ca89SAndroid Build Coastguard Worker         break;
597*8d67ca89SAndroid Build Coastguard Worker     }
598*8d67ca89SAndroid Build Coastguard Worker   }
599*8d67ca89SAndroid Build Coastguard Worker input_failure:
600*8d67ca89SAndroid Build Coastguard Worker   return (nconversions != 0 ? nassigned : EOF);
601*8d67ca89SAndroid Build Coastguard Worker match_failure:
602*8d67ca89SAndroid Build Coastguard Worker   return (nassigned);
603*8d67ca89SAndroid Build Coastguard Worker }
604*8d67ca89SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
605