Bug Summary

File:src/lib/libc/stdio/vfwscanf.c
Warning:line 487, column 5
Value stored to 'p0' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name vfwscanf.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libc/obj -resource-dir /usr/local/lib/clang/13.0.0 -include namespace.h -I /usr/src/lib/libc/include -I /usr/src/lib/libc/hidden -D __LIBC__ -D APIWARN -D YP -I /usr/src/lib/libc/yp -I /usr/src/lib/libc -I /usr/src/lib/libc/gdtoa -I /usr/src/lib/libc/arch/amd64/gdtoa -D INFNAN_CHECK -D MULTIPLE_THREADS -D NO_FENV_H -D USE_LOCALE -I /usr/src/lib/libc -I /usr/src/lib/libc/citrus -D RESOLVSORT -D FLOATING_POINT -D PRINTF_WIDE_CHAR -D SCANF_WIDE_CHAR -D FUTEX -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libc/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libc/stdio/vfwscanf.c
1/* $OpenBSD: vfwscanf.c,v 1.7 2017/12/08 01:03:51 kevlo Exp $ */
2/*-
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <inttypes.h>
35#include <limits.h>
36#include <locale.h>
37#include <stdarg.h>
38#include <stddef.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <wctype.h>
43#include "local.h"
44
45#ifdef FLOATING_POINT1
46#include <float.h>
47#include "floatio.h"
48#endif
49
50#define BUF513 513 /* Maximum length of numeric string. */
51
52/*
53 * Flags used during conversion.
54 */
55#define LONG0x00001 0x00001 /* l: long or double */
56#define LONGDBL0x00002 0x00002 /* L: long double */
57#define SHORT0x00004 0x00004 /* h: short */
58#define SHORTSHORT0x00008 0x00008 /* hh: 8 bit integer */
59#define LLONG0x00010 0x00010 /* ll: long long (+ deprecated q: quad) */
60#define POINTER0x00020 0x00020 /* p: void * (as hex) */
61#define SIZEINT0x00040 0x00040 /* z: (signed) size_t */
62#define MAXINT0x00080 0x00080 /* j: intmax_t */
63#define PTRINT0x00100 0x00100 /* t: ptrdiff_t */
64#define NOSKIP0x00200 0x00200 /* [ or c: do not skip blanks */
65#define SUPPRESS0x00400 0x00400 /* *: suppress assignment */
66#define UNSIGNED0x00800 0x00800 /* %[oupxX] conversions */
67
68/*
69 * The following are used in numeric conversions only:
70 * SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point;
71 * SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral.
72 */
73#define SIGNOK0x01000 0x01000 /* +/- is (still) legal */
74#define HAVESIGN0x02000 0x02000 /* sign detected */
75#define NDIGITS0x04000 0x04000 /* no digits detected */
76
77#define DPTOK0x08000 0x08000 /* (float) decimal point is still legal */
78#define EXPOK0x10000 0x10000 /* (float) exponent (e+3, etc) still legal */
79
80#define PFXOK0x08000 0x08000 /* 0x prefix is (still) legal */
81#define NZDIGITS0x10000 0x10000 /* no zero digits detected */
82
83/*
84 * Conversion types.
85 */
86#define CT_CHAR0 0 /* %c conversion */
87#define CT_CCL1 1 /* %[...] conversion */
88#define CT_STRING2 2 /* %s conversion */
89#define CT_INT3 3 /* integer, i.e., strtoimax or strtoumax */
90#define CT_FLOAT4 4 /* floating, i.e., strtod */
91
92#define u_charunsigned char unsigned char
93#define u_longunsigned long unsigned long
94
95#define INCCL(_c)(cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == ((void*)0)) :
(wmemchr(ccls, (_c), ccle - ccls) != ((void*)0)))
\
96 (cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL((void*)0)) : \
97 (wmemchr(ccls, (_c), ccle - ccls) != NULL((void*)0)))
98
99/*
100 * vfwscanf
101 */
102int
103__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, __va_list ap)
104{
105 wint_t c; /* character from format, or conversion */
106 size_t width; /* field width, or 0 */
107 wchar_t *p; /* points into all kinds of strings */
108 int n; /* handy integer */
109 int flags; /* flags as defined above */
110 wchar_t *p0; /* saves original value of p when necessary */
111 int nassigned; /* number of fields assigned */
112 int nconversions; /* number of conversions */
113 int nread; /* number of characters consumed from fp */
114 int base; /* base argument to strtoimax/strtouimax */
115 wchar_t buf[BUF513]; /* buffer for numeric conversions */
116 const wchar_t *ccls; /* character class start */
117 const wchar_t *ccle; /* character class end */
118 int cclcompl; /* ccl is complemented? */
119 wint_t wi; /* handy wint_t */
120 char *mbp; /* multibyte string pointer for %c %s %[ */
121 size_t nconv; /* number of bytes in mb. conversion */
122 char mbbuf[MB_LEN_MAX4]; /* temporary mb. character buffer */
123 mbstate_t mbs;
124#ifdef FLOATING_POINT1
125 wchar_t decimal_point = 0;
126#endif
127
128 /* `basefix' is used to avoid `if' tests in the integer scanner */
129 static short basefix[17] =
130 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
131
132 _SET_ORIENTATION(fp, 1)do { struct wchar_io_data *_wcio = (((struct __sfileext *)((fp
)->_ext._base)) ? &(((struct __sfileext *)((fp)->_ext
._base))->_wcio) : (struct wchar_io_data *)0); if (_wcio &&
_wcio->wcio_mode == 0) _wcio->wcio_mode = (1);} while (
0)
;
133
134 nassigned = 0;
135 nconversions = 0;
136 nread = 0;
137 base = 0; /* XXX just to keep gcc happy */
138 ccls = ccle = NULL((void*)0);
139 for (;;) {
140 c = *fmt++;
141 if (c == 0) {
142 return (nassigned);
143 }
144 if (iswspace(c)) {
145 while ((c = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
146 iswspace(c))
147 ;
148 if (c != WEOF((wint_t)-1))
149 __ungetwc(c, fp);
150 continue;
151 }
152 if (c != '%')
153 goto literal;
154 width = 0;
155 flags = 0;
156 /*
157 * switch on the format. continue if done;
158 * break once format type is derived.
159 */
160again: c = *fmt++;
161 switch (c) {
162 case '%':
163literal:
164 if ((wi = __fgetwc_unlock(fp)) == WEOF((wint_t)-1))
165 goto input_failure;
166 if (wi != c) {
167 __ungetwc(wi, fp);
168 goto match_failure;
169 }
170 nread++;
171 continue;
172
173 case '*':
174 flags |= SUPPRESS0x00400;
175 goto again;
176 case 'j':
177 flags |= MAXINT0x00080;
178 goto again;
179 case 'L':
180 flags |= LONGDBL0x00002;
181 goto again;
182 case 'h':
183 if (*fmt == 'h') {
184 fmt++;
185 flags |= SHORTSHORT0x00008;
186 } else {
187 flags |= SHORT0x00004;
188 }
189 goto again;
190 case 'l':
191 if (*fmt == 'l') {
192 fmt++;
193 flags |= LLONG0x00010;
194 } else {
195 flags |= LONG0x00001;
196 }
197 goto again;
198 case 'q':
199 flags |= LLONG0x00010; /* deprecated */
200 goto again;
201 case 't':
202 flags |= PTRINT0x00100;
203 goto again;
204 case 'z':
205 flags |= SIZEINT0x00040;
206 goto again;
207
208 case '0': case '1': case '2': case '3': case '4':
209 case '5': case '6': case '7': case '8': case '9':
210 width = width * 10 + c - '0';
211 goto again;
212
213 /*
214 * Conversions.
215 * Those marked `compat' are for 4.[123]BSD compatibility.
216 *
217 * (According to ANSI, E and X formats are supposed
218 * to the same as e and x. Sorry about that.)
219 */
220 case 'D': /* compat */
221 flags |= LONG0x00001;
222 /* FALLTHROUGH */
223 case 'd':
224 c = CT_INT3;
225 base = 10;
226 break;
227
228 case 'i':
229 c = CT_INT3;
230 base = 0;
231 break;
232
233 case 'O': /* compat */
234 flags |= LONG0x00001;
235 /* FALLTHROUGH */
236 case 'o':
237 c = CT_INT3;
238 flags |= UNSIGNED0x00800;
239 base = 8;
240 break;
241
242 case 'u':
243 c = CT_INT3;
244 flags |= UNSIGNED0x00800;
245 base = 10;
246 break;
247
248 case 'X':
249 case 'x':
250 flags |= PFXOK0x08000; /* enable 0x prefixing */
251 c = CT_INT3;
252 flags |= UNSIGNED0x00800;
253 base = 16;
254 break;
255
256#ifdef FLOATING_POINT1
257 case 'e': case 'E':
258 case 'f': case 'F':
259 case 'g': case 'G':
260 case 'a': case 'A':
261 c = CT_FLOAT4;
262 break;
263#endif
264
265 case 's':
266 c = CT_STRING2;
267 break;
268
269 case '[':
270 ccls = fmt;
271 if (*fmt == '^') {
272 cclcompl = 1;
273 fmt++;
274 } else
275 cclcompl = 0;
276 if (*fmt == ']')
277 fmt++;
278 while (*fmt != '\0' && *fmt != ']')
279 fmt++;
280 ccle = fmt;
281 fmt++;
282 flags |= NOSKIP0x00200;
283 c = CT_CCL1;
284 break;
285
286 case 'c':
287 flags |= NOSKIP0x00200;
288 c = CT_CHAR0;
289 break;
290
291 case 'p': /* pointer format is like hex */
292 flags |= POINTER0x00020 | PFXOK0x08000;
293 c = CT_INT3;
294 flags |= UNSIGNED0x00800;
295 base = 16;
296 break;
297
298 case 'n':
299 nconversions++;
300 if (flags & SUPPRESS0x00400)
301 continue;
302 if (flags & SHORTSHORT0x00008)
303 *va_arg(ap, signed char *)__builtin_va_arg(ap, signed char *) = nread;
304 else if (flags & SHORT0x00004)
305 *va_arg(ap, short *)__builtin_va_arg(ap, short *) = nread;
306 else if (flags & LONG0x00001)
307 *va_arg(ap, long *)__builtin_va_arg(ap, long *) = nread;
308 else if (flags & SIZEINT0x00040)
309 *va_arg(ap, ssize_t *)__builtin_va_arg(ap, ssize_t *) = nread;
310 else if (flags & PTRINT0x00100)
311 *va_arg(ap, ptrdiff_t *)__builtin_va_arg(ap, ptrdiff_t *) = nread;
312 else if (flags & LLONG0x00010)
313 *va_arg(ap, long long *)__builtin_va_arg(ap, long long *) = nread;
314 else if (flags & MAXINT0x00080)
315 *va_arg(ap, intmax_t *)__builtin_va_arg(ap, intmax_t *) = nread;
316 else
317 *va_arg(ap, int *)__builtin_va_arg(ap, int *) = nread;
318 continue;
319
320 /*
321 * Disgusting backwards compatibility hacks. XXX
322 */
323 case '\0': /* compat */
324 return (EOF(-1));
325
326 default: /* compat */
327 if (iswupper(c))
328 flags |= LONG0x00001;
329 c = CT_INT3;
330 base = 10;
331 break;
332 }
333
334 /*
335 * Consume leading white space, except for formats
336 * that suppress this.
337 */
338 if ((flags & NOSKIP0x00200) == 0) {
339 while ((wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
340 iswspace(wi))
341 nread++;
342 if (wi == WEOF((wint_t)-1))
343 goto input_failure;
344 __ungetwc(wi, fp);
345 }
346
347 /*
348 * Do the conversion.
349 */
350 switch (c) {
351
352 case CT_CHAR0:
353 /* scan arbitrary characters (sets NOSKIP) */
354 if (width == 0)
355 width = 1;
356 if (flags & LONG0x00001) {
357 if (!(flags & SUPPRESS0x00400))
358 p = va_arg(ap, wchar_t *)__builtin_va_arg(ap, wchar_t *);
359 n = 0;
360 while (width-- != 0 &&
361 (wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1)) {
362 if (!(flags & SUPPRESS0x00400))
363 *p++ = (wchar_t)wi;
364 n++;
365 }
366 if (n == 0)
367 goto input_failure;
368 nread += n;
369 if (!(flags & SUPPRESS0x00400))
370 nassigned++;
371 } else {
372 if (!(flags & SUPPRESS0x00400))
373 mbp = va_arg(ap, char *)__builtin_va_arg(ap, char *);
374 n = 0;
375 bzero(&mbs, sizeof(mbs));
376 while (width != 0 &&
377 (wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1)) {
378 if (width >= MB_CUR_MAX__mb_cur_max() &&
379 !(flags & SUPPRESS0x00400)) {
380 nconv = wcrtomb(mbp, wi, &mbs);
381 if (nconv == (size_t)-1)
382 goto input_failure;
383 } else {
384 nconv = wcrtomb(mbbuf, wi,
385 &mbs);
386 if (nconv == (size_t)-1)
387 goto input_failure;
388 if (nconv > width) {
389 __ungetwc(wi, fp);
390 break;
391 }
392 if (!(flags & SUPPRESS0x00400))
393 memcpy(mbp, mbbuf,
394 nconv);
395 }
396 if (!(flags & SUPPRESS0x00400))
397 mbp += nconv;
398 width -= nconv;
399 n++;
400 }
401 if (n == 0)
402 goto input_failure;
403 nread += n;
404 if (!(flags & SUPPRESS0x00400))
405 nassigned++;
406 }
407 nconversions++;
408 break;
409
410 case CT_CCL1:
411 /* scan a (nonempty) character class (sets NOSKIP) */
412 if (width == 0)
413 width = (size_t)~0; /* `infinity' */
414 /* take only those things in the class */
415 if ((flags & SUPPRESS0x00400) && (flags & LONG0x00001)) {
416 n = 0;
417 while ((wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
418 width-- != 0 && INCCL(wi)(cclcompl ? (wmemchr(ccls, (wi), ccle - ccls) == ((void*)0)) :
(wmemchr(ccls, (wi), ccle - ccls) != ((void*)0)))
)
419 n++;
420 if (wi != WEOF((wint_t)-1))
421 __ungetwc(wi, fp);
422 if (n == 0)
423 goto match_failure;
424 } else if (flags & LONG0x00001) {
425 p0 = p = va_arg(ap, wchar_t *)__builtin_va_arg(ap, wchar_t *);
426 while ((wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
427 width-- != 0 && INCCL(wi)(cclcompl ? (wmemchr(ccls, (wi), ccle - ccls) == ((void*)0)) :
(wmemchr(ccls, (wi), ccle - ccls) != ((void*)0)))
)
428 *p++ = (wchar_t)wi;
429 if (wi != WEOF((wint_t)-1))
430 __ungetwc(wi, fp);
431 n = p - p0;
432 if (n == 0)
433 goto match_failure;
434 *p = 0;
435 nassigned++;
436 } else {
437 if (!(flags & SUPPRESS0x00400))
438 mbp = va_arg(ap, char *)__builtin_va_arg(ap, char *);
439 n = 0;
440 bzero(&mbs, sizeof(mbs));
441 while ((wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
442 width != 0 && INCCL(wi)(cclcompl ? (wmemchr(ccls, (wi), ccle - ccls) == ((void*)0)) :
(wmemchr(ccls, (wi), ccle - ccls) != ((void*)0)))
) {
443 if (width >= MB_CUR_MAX__mb_cur_max() &&
444 !(flags & SUPPRESS0x00400)) {
445 nconv = wcrtomb(mbp, wi, &mbs);
446 if (nconv == (size_t)-1)
447 goto input_failure;
448 } else {
449 nconv = wcrtomb(mbbuf, wi,
450 &mbs);
451 if (nconv == (size_t)-1)
452 goto input_failure;
453 if (nconv > width)
454 break;
455 if (!(flags & SUPPRESS0x00400))
456 memcpy(mbp, mbbuf,
457 nconv);
458 }
459 if (!(flags & SUPPRESS0x00400))
460 mbp += nconv;
461 width -= nconv;
462 n++;
463 }
464 if (wi != WEOF((wint_t)-1))
465 __ungetwc(wi, fp);
466 if (!(flags & SUPPRESS0x00400)) {
467 *mbp = 0;
468 nassigned++;
469 }
470 }
471 nread += n;
472 nconversions++;
473 break;
474
475 case CT_STRING2:
476 /* like CCL, but zero-length string OK, & no NOSKIP */
477 if (width == 0)
478 width = (size_t)~0;
479 if ((flags & SUPPRESS0x00400) && (flags & LONG0x00001)) {
480 while ((wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
481 width-- != 0 &&
482 !iswspace(wi))
483 nread++;
484 if (wi != WEOF((wint_t)-1))
485 __ungetwc(wi, fp);
486 } else if (flags & LONG0x00001) {
487 p0 = p = va_arg(ap, wchar_t *)__builtin_va_arg(ap, wchar_t *);
Value stored to 'p0' is never read
488 while ((wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
489 width-- != 0 &&
490 !iswspace(wi)) {
491 *p++ = (wchar_t)wi;
492 nread++;
493 }
494 if (wi != WEOF((wint_t)-1))
495 __ungetwc(wi, fp);
496 *p = 0;
497 nassigned++;
498 } else {
499 if (!(flags & SUPPRESS0x00400))
500 mbp = va_arg(ap, char *)__builtin_va_arg(ap, char *);
501 bzero(&mbs, sizeof(mbs));
502 while ((wi = __fgetwc_unlock(fp)) != WEOF((wint_t)-1) &&
503 width != 0 &&
504 !iswspace(wi)) {
505 if (width >= MB_CUR_MAX__mb_cur_max() &&
506 !(flags & SUPPRESS0x00400)) {
507 nconv = wcrtomb(mbp, wi, &mbs);
508 if (nconv == (size_t)-1)
509 goto input_failure;
510 } else {
511 nconv = wcrtomb(mbbuf, wi,
512 &mbs);
513 if (nconv == (size_t)-1)
514 goto input_failure;
515 if (nconv > width)
516 break;
517 if (!(flags & SUPPRESS0x00400))
518 memcpy(mbp, mbbuf,
519 nconv);
520 }
521 if (!(flags & SUPPRESS0x00400))
522 mbp += nconv;
523 width -= nconv;
524 nread++;
525 }
526 if (wi != WEOF((wint_t)-1))
527 __ungetwc(wi, fp);
528 if (!(flags & SUPPRESS0x00400)) {
529 *mbp = 0;
530 nassigned++;
531 }
532 }
533 nconversions++;
534 continue;
535
536 case CT_INT3:
537 /* scan an integer as if by strtoimax/strtoumax */
538 if (width == 0 || width > sizeof(buf) /
539 sizeof(*buf) - 1)
540 width = sizeof(buf) / sizeof(*buf) - 1;
541 flags |= SIGNOK0x01000 | NDIGITS0x04000 | NZDIGITS0x10000;
542 for (p = buf; width; width--) {
543 c = __fgetwc_unlock(fp);
544 /*
545 * Switch on the character; `goto ok'
546 * if we accept it as a part of number.
547 */
548 switch (c) {
549
550 /*
551 * The digit 0 is always legal, but is
552 * special. For %i conversions, if no
553 * digits (zero or nonzero) have been
554 * scanned (only signs), we will have
555 * base==0. In that case, we should set
556 * it to 8 and enable 0x prefixing.
557 * Also, if we have not scanned zero digits
558 * before this, do not turn off prefixing
559 * (someone else will turn it off if we
560 * have scanned any nonzero digits).
561 */
562 case '0':
563 if (base == 0) {
564 base = 8;
565 flags |= PFXOK0x08000;
566 }
567 if (flags & NZDIGITS0x10000)
568 flags &= ~(SIGNOK0x01000|NZDIGITS0x10000|NDIGITS0x04000);
569 else
570 flags &= ~(SIGNOK0x01000|PFXOK0x08000|NDIGITS0x04000);
571 goto ok;
572
573 /* 1 through 7 always legal */
574 case '1': case '2': case '3':
575 case '4': case '5': case '6': case '7':
576 base = basefix[base];
577 flags &= ~(SIGNOK0x01000 | PFXOK0x08000 | NDIGITS0x04000);
578 goto ok;
579
580 /* digits 8 and 9 ok iff decimal or hex */
581 case '8': case '9':
582 base = basefix[base];
583 if (base <= 8)
584 break; /* not legal here */
585 flags &= ~(SIGNOK0x01000 | PFXOK0x08000 | NDIGITS0x04000);
586 goto ok;
587
588 /* letters ok iff hex */
589 case 'A': case 'B': case 'C':
590 case 'D': case 'E': case 'F':
591 case 'a': case 'b': case 'c':
592 case 'd': case 'e': case 'f':
593 /* no need to fix base here */
594 if (base <= 10)
595 break; /* not legal here */
596 flags &= ~(SIGNOK0x01000 | PFXOK0x08000 | NDIGITS0x04000);
597 goto ok;
598
599 /* sign ok only as first character */
600 case '+': case '-':
601 if (flags & SIGNOK0x01000) {
602 flags &= ~SIGNOK0x01000;
603 flags |= HAVESIGN0x02000;
604 goto ok;
605 }
606 break;
607
608 /*
609 * x ok iff flag still set and 2nd char (or
610 * 3rd char if we have a sign).
611 */
612 case 'x': case 'X':
613 if ((flags & PFXOK0x08000) && p ==
614 buf + 1 + !!(flags & HAVESIGN0x02000)) {
615 base = 16; /* if %i */
616 flags &= ~PFXOK0x08000;
617 goto ok;
618 }
619 break;
620 }
621
622 /*
623 * If we got here, c is not a legal character
624 * for a number. Stop accumulating digits.
625 */
626 if (c != WEOF((wint_t)-1))
627 __ungetwc(c, fp);
628 break;
629 ok:
630 /*
631 * c is legal: store it and look at the next.
632 */
633 *p++ = (wchar_t)c;
634 }
635 /*
636 * If we had only a sign, it is no good; push
637 * back the sign. If the number ends in `x',
638 * it was [sign] '0' 'x', so push back the x
639 * and treat it as [sign] '0'.
640 */
641 if (flags & NDIGITS0x04000) {
642 if (p > buf)
643 __ungetwc(*--p, fp);
644 goto match_failure;
645 }
646 c = p[-1];
647 if (c == 'x' || c == 'X') {
648 --p;
649 __ungetwc(c, fp);
650 }
651 if ((flags & SUPPRESS0x00400) == 0) {
652 uintmax_t res;
653
654 *p = '\0';
655 if (flags & UNSIGNED0x00800)
656 res = wcstoimax(buf, NULL((void*)0), base);
657 else
658 res = wcstoumax(buf, NULL((void*)0), base);
659 if (flags & POINTER0x00020)
660 *va_arg(ap, void **)__builtin_va_arg(ap, void **) =
661 (void *)(uintptr_t)res;
662 else if (flags & MAXINT0x00080)
663 *va_arg(ap, intmax_t *)__builtin_va_arg(ap, intmax_t *) = res;
664 else if (flags & LLONG0x00010)
665 *va_arg(ap, long long *)__builtin_va_arg(ap, long long *) = res;
666 else if (flags & SIZEINT0x00040)
667 *va_arg(ap, ssize_t *)__builtin_va_arg(ap, ssize_t *) = res;
668 else if (flags & PTRINT0x00100)
669 *va_arg(ap, ptrdiff_t *)__builtin_va_arg(ap, ptrdiff_t *) = res;
670 else if (flags & LONG0x00001)
671 *va_arg(ap, long *)__builtin_va_arg(ap, long *) = res;
672 else if (flags & SHORT0x00004)
673 *va_arg(ap, short *)__builtin_va_arg(ap, short *) = res;
674 else if (flags & SHORTSHORT0x00008)
675 *va_arg(ap, signed char *)__builtin_va_arg(ap, signed char *) = res;
676 else
677 *va_arg(ap, int *)__builtin_va_arg(ap, int *) = res;
678 nassigned++;
679 }
680 nread += p - buf;
681 nconversions++;
682 break;
683
684#ifdef FLOATING_POINT1
685 case CT_FLOAT4:
686 /* scan a floating point number as if by strtod */
687 if (width == 0 || width > sizeof(buf) /
688 sizeof(*buf) - 1)
689 width = sizeof(buf) / sizeof(*buf) - 1;
690 flags |= SIGNOK0x01000 | NDIGITS0x04000 | DPTOK0x08000 | EXPOK0x10000;
691 for (p = buf; width; width--) {
692 c = __fgetwc_unlock(fp);
693 /*
694 * This code mimicks the integer conversion
695 * code, but is much simpler.
696 */
697 switch (c) {
698
699 case '0': case '1': case '2': case '3':
700 case '4': case '5': case '6': case '7':
701 case '8': case '9':
702 flags &= ~(SIGNOK0x01000 | NDIGITS0x04000);
703 goto fok;
704
705 case '+': case '-':
706 if (flags & SIGNOK0x01000) {
707 flags &= ~SIGNOK0x01000;
708 goto fok;
709 }
710 break;
711 case 'e': case 'E':
712 /* no exponent without some digits */
713 if ((flags&(NDIGITS0x04000|EXPOK0x10000)) == EXPOK0x10000) {
714 flags =
715 (flags & ~(EXPOK0x10000|DPTOK0x08000)) |
716 SIGNOK0x01000 | NDIGITS0x04000;
717 goto fok;
718 }
719 break;
720 default:
721 if (decimal_point == 0) {
722 bzero(&mbs, sizeof(mbs));
723 nconv = mbrtowc(&decimal_point,
724 localeconv()->decimal_point,
725 MB_CUR_MAX__mb_cur_max(), &mbs);
726 if (nconv == 0 ||
727 nconv == (size_t)-1 ||
728 nconv == (size_t)-2)
729 decimal_point = '.';
730 }
731 if (c == decimal_point &&
732 (flags & DPTOK0x08000)) {
733 flags &= ~(SIGNOK0x01000 | DPTOK0x08000);
734 goto fok;
735 }
736 break;
737 }
738 if (c != WEOF((wint_t)-1))
739 __ungetwc(c, fp);
740 break;
741 fok:
742 *p++ = c;
743 }
744 /*
745 * If no digits, might be missing exponent digits
746 * (just give back the exponent) or might be missing
747 * regular digits, but had sign and/or decimal point.
748 */
749 if (flags & NDIGITS0x04000) {
750 if (flags & EXPOK0x10000) {
751 /* no digits at all */
752 while (p > buf)
753 __ungetwc(*--p, fp);
754 goto match_failure;
755 }
756 /* just a bad exponent (e and maybe sign) */
757 c = *--p;
758 if (c != 'e' && c != 'E') {
759 __ungetwc(c, fp);/* sign */
760 c = *--p;
761 }
762 __ungetwc(c, fp);
763 }
764 if ((flags & SUPPRESS0x00400) == 0) {
765 *p = 0;
766 if (flags & LONGDBL0x00002) {
767 long double res = wcstold(buf, NULL((void*)0));
768 *va_arg(ap, long double *)__builtin_va_arg(ap, long double *) = res;
769 } else if (flags & LONG0x00001) {
770 double res = wcstod(buf, NULL((void*)0));
771 *va_arg(ap, double *)__builtin_va_arg(ap, double *) = res;
772 } else {
773 float res = wcstof(buf, NULL((void*)0));
774 *va_arg(ap, float *)__builtin_va_arg(ap, float *) = res;
775 }
776 nassigned++;
777 }
778 nread += p - buf;
779 nconversions++;
780 break;
781#endif /* FLOATING_POINT */
782 }
783 }
784input_failure:
785 return (nconversions != 0 ? nassigned : EOF(-1));
786match_failure:
787 return (nassigned);
788}
789
790int
791vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, __va_list ap)
792{
793 int r;
794
795 FLOCKFILE(fp)do { if (_thread_cb.tc_flockfile != ((void*)0)) _thread_cb.tc_flockfile
(fp); } while (0)
;
796 r = __vfwscanf(fp, fmt, ap);
797 FUNLOCKFILE(fp)do { if (_thread_cb.tc_funlockfile != ((void*)0)) _thread_cb.
tc_funlockfile(fp); } while (0)
;
798 return (r);
799}
800DEF_STRONG(vfwscanf)__asm__(".global " "vfwscanf" " ; " "vfwscanf" " = " "_libc_vfwscanf"
)
;