1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (c) 2011 The FreeBSD Foundation 6 * All rights reserved. 7 * Portions of this software were developed by David Chisnall 8 * under sponsorship from the FreeBSD Foundation. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Chris Torek. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38#if defined(LIBC_SCCS) && !defined(lint) 39static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93"; 40#endif /* LIBC_SCCS and not lint */ 41#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (c) 2011 The FreeBSD Foundation 6 * All rights reserved. 7 * Portions of this software were developed by David Chisnall 8 * under sponsorship from the FreeBSD Foundation. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Chris Torek. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38#if defined(LIBC_SCCS) && !defined(lint) 39static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93"; 40#endif /* LIBC_SCCS and not lint */ 41#include <sys/cdefs.h>
|
42__FBSDID("$FreeBSD: head/lib/libc/stdio/vfscanf.c 234587 2012-04-22 21:28:14Z das $");
| 42__FBSDID("$FreeBSD: head/lib/libc/stdio/vfscanf.c 234799 2012-04-29 16:28:39Z das $");
|
43 44#include "namespace.h" 45#include <ctype.h> 46#include <inttypes.h> 47#include <stdio.h> 48#include <stdlib.h> 49#include <stddef.h> 50#include <stdarg.h> 51#include <string.h> 52#include <wchar.h> 53#include <wctype.h> 54#include "un-namespace.h" 55 56#include "collate.h" 57#include "libc_private.h" 58#include "local.h" 59#include "xlocale_private.h" 60 61#ifndef NO_FLOATING_POINT 62#include <locale.h> 63#endif 64 65#define BUF 513 /* Maximum length of numeric string. */ 66 67/* 68 * Flags used during conversion. 69 */ 70#define LONG 0x01 /* l: long or double */ 71#define LONGDBL 0x02 /* L: long double */ 72#define SHORT 0x04 /* h: short */ 73#define SUPPRESS 0x08 /* *: suppress assignment */ 74#define POINTER 0x10 /* p: void * (as hex) */ 75#define NOSKIP 0x20 /* [ or c: do not skip blanks */ 76#define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */ 77#define INTMAXT 0x800 /* j: intmax_t */ 78#define PTRDIFFT 0x1000 /* t: ptrdiff_t */ 79#define SIZET 0x2000 /* z: size_t */ 80#define SHORTSHORT 0x4000 /* hh: char */ 81#define UNSIGNED 0x8000 /* %[oupxX] conversions */ 82 83/* 84 * The following are used in integral conversions only: 85 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS 86 */ 87#define SIGNOK 0x40 /* +/- is (still) legal */ 88#define NDIGITS 0x80 /* no digits detected */ 89#define PFXOK 0x100 /* 0x prefix is (still) legal */ 90#define NZDIGITS 0x200 /* no zero digits detected */ 91#define HAVESIGN 0x10000 /* sign detected */ 92 93/* 94 * Conversion types. 95 */ 96#define CT_CHAR 0 /* %c conversion */ 97#define CT_CCL 1 /* %[...] conversion */ 98#define CT_STRING 2 /* %s conversion */ 99#define CT_INT 3 /* %[dioupxX] conversion */ 100#define CT_FLOAT 4 /* %[efgEFG] conversion */ 101 102static const u_char *__sccl(char *, const u_char *); 103#ifndef NO_FLOATING_POINT 104static int parsefloat(FILE *, char *, char *, locale_t); 105#endif 106 107__weak_reference(__vfscanf, vfscanf); 108 109/* 110 * Conversion functions are passed a pointer to this object instead of 111 * a real parameter to indicate that the assignment-suppression (*) 112 * flag was specified. We could use a NULL pointer to indicate this, 113 * but that would mask bugs in applications that call scanf() with a 114 * NULL pointer. 115 */ 116static const int suppress; 117#define SUPPRESS_PTR ((void *)&suppress) 118 119static const mbstate_t initial_mbs; 120 121/* 122 * The following conversion functions return the number of characters consumed, 123 * or -1 on input failure. Character class conversion returns 0 on match 124 * failure. 125 */ 126 127static __inline int 128convert_char(FILE *fp, char * __restrict p, int width) 129{
| 43 44#include "namespace.h" 45#include <ctype.h> 46#include <inttypes.h> 47#include <stdio.h> 48#include <stdlib.h> 49#include <stddef.h> 50#include <stdarg.h> 51#include <string.h> 52#include <wchar.h> 53#include <wctype.h> 54#include "un-namespace.h" 55 56#include "collate.h" 57#include "libc_private.h" 58#include "local.h" 59#include "xlocale_private.h" 60 61#ifndef NO_FLOATING_POINT 62#include <locale.h> 63#endif 64 65#define BUF 513 /* Maximum length of numeric string. */ 66 67/* 68 * Flags used during conversion. 69 */ 70#define LONG 0x01 /* l: long or double */ 71#define LONGDBL 0x02 /* L: long double */ 72#define SHORT 0x04 /* h: short */ 73#define SUPPRESS 0x08 /* *: suppress assignment */ 74#define POINTER 0x10 /* p: void * (as hex) */ 75#define NOSKIP 0x20 /* [ or c: do not skip blanks */ 76#define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */ 77#define INTMAXT 0x800 /* j: intmax_t */ 78#define PTRDIFFT 0x1000 /* t: ptrdiff_t */ 79#define SIZET 0x2000 /* z: size_t */ 80#define SHORTSHORT 0x4000 /* hh: char */ 81#define UNSIGNED 0x8000 /* %[oupxX] conversions */ 82 83/* 84 * The following are used in integral conversions only: 85 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS 86 */ 87#define SIGNOK 0x40 /* +/- is (still) legal */ 88#define NDIGITS 0x80 /* no digits detected */ 89#define PFXOK 0x100 /* 0x prefix is (still) legal */ 90#define NZDIGITS 0x200 /* no zero digits detected */ 91#define HAVESIGN 0x10000 /* sign detected */ 92 93/* 94 * Conversion types. 95 */ 96#define CT_CHAR 0 /* %c conversion */ 97#define CT_CCL 1 /* %[...] conversion */ 98#define CT_STRING 2 /* %s conversion */ 99#define CT_INT 3 /* %[dioupxX] conversion */ 100#define CT_FLOAT 4 /* %[efgEFG] conversion */ 101 102static const u_char *__sccl(char *, const u_char *); 103#ifndef NO_FLOATING_POINT 104static int parsefloat(FILE *, char *, char *, locale_t); 105#endif 106 107__weak_reference(__vfscanf, vfscanf); 108 109/* 110 * Conversion functions are passed a pointer to this object instead of 111 * a real parameter to indicate that the assignment-suppression (*) 112 * flag was specified. We could use a NULL pointer to indicate this, 113 * but that would mask bugs in applications that call scanf() with a 114 * NULL pointer. 115 */ 116static const int suppress; 117#define SUPPRESS_PTR ((void *)&suppress) 118 119static const mbstate_t initial_mbs; 120 121/* 122 * The following conversion functions return the number of characters consumed, 123 * or -1 on input failure. Character class conversion returns 0 on match 124 * failure. 125 */ 126 127static __inline int 128convert_char(FILE *fp, char * __restrict p, int width) 129{
|
130 int n, nread;
| 130 int n;
|
131
| 131
|
132 nread = 0;
| |
133 if (p == SUPPRESS_PTR) { 134 size_t sum = 0; 135 for (;;) { 136 if ((n = fp->_r) < width) { 137 sum += n; 138 width -= n; 139 fp->_p += n; 140 if (__srefill(fp)) { 141 if (sum == 0) 142 return (-1); 143 break; 144 } 145 } else { 146 sum += width; 147 fp->_r -= width; 148 fp->_p += width; 149 break; 150 } 151 }
| 132 if (p == SUPPRESS_PTR) { 133 size_t sum = 0; 134 for (;;) { 135 if ((n = fp->_r) < width) { 136 sum += n; 137 width -= n; 138 fp->_p += n; 139 if (__srefill(fp)) { 140 if (sum == 0) 141 return (-1); 142 break; 143 } 144 } else { 145 sum += width; 146 fp->_r -= width; 147 fp->_p += width; 148 break; 149 } 150 }
|
152 nread += sum;
| 151 return (sum);
|
153 } else { 154 size_t r = __fread(p, 1, width, fp); 155 156 if (r == 0) 157 return (-1);
| 152 } else { 153 size_t r = __fread(p, 1, width, fp); 154 155 if (r == 0) 156 return (-1);
|
158 nread += r;
| 157 return (r);
|
159 }
| 158 }
|
160 return (nread);
| |
161} 162 163static __inline int
| 159} 160 161static __inline int
|
164convert_wchar(FILE *fp, wchar_t *wcp, int width)
| 162convert_wchar(FILE *fp, wchar_t *wcp, int width, locale_t locale)
|
165{ 166 mbstate_t mbs;
| 163{ 164 mbstate_t mbs;
|
167 size_t nconv;
| |
168 int n, nread;
| 165 int n, nread;
|
169 char buf[MB_CUR_MAX];
| 166 wint_t wi;
|
170
| 167
|
171 nread = 0;
| 168 mbs = initial_mbs;
|
172 n = 0;
| 169 n = 0;
|
173 while (width != 0) { 174 if (n == MB_CUR_MAX) { 175 fp->_flags |= __SERR; 176 return (-1); 177 } 178 buf[n++] = *fp->_p; 179 fp->_p++; 180 fp->_r--; 181 mbs = initial_mbs; 182 nconv = mbrtowc(wcp, buf, n, &mbs); 183 if (nconv == (size_t)-1) { 184 fp->_flags |= __SERR; 185 return (-1); 186 } 187 if (nconv == 0 && wcp != SUPPRESS_PTR) 188 *wcp = L'\0'; 189 if (nconv != (size_t)-2) { 190 nread += n; 191 width--; 192 if (wcp != SUPPRESS_PTR) 193 wcp++; 194 n = 0; 195 } 196 if (fp->_r <= 0 && __srefill(fp)) { 197 if (n != 0) { 198 fp->_flags |= __SERR; 199 return (-1); 200 } 201 break; 202 }
| 170 while (width-- != 0 && 171 (wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF) { 172 if (wcp != SUPPRESS_PTR) 173 *wcp++ = (wchar_t)wi; 174 n += nread;
|
203 }
| 175 }
|
204 return (nread);
| 176 if (n == 0) 177 return (-1); 178 return (n);
|
205} 206 207static __inline int 208convert_ccl(FILE *fp, char * __restrict p, int width, const char *ccltab) 209{ 210 char *p0; 211 int n; 212 213 if (p == SUPPRESS_PTR) { 214 n = 0; 215 while (ccltab[*fp->_p]) { 216 n++, fp->_r--, fp->_p++; 217 if (--width == 0) 218 break; 219 if (fp->_r <= 0 && __srefill(fp)) { 220 if (n == 0) 221 return (-1); 222 break; 223 } 224 } 225 } else { 226 p0 = p; 227 while (ccltab[*fp->_p]) { 228 fp->_r--; 229 *p++ = *fp->_p++; 230 if (--width == 0) 231 break; 232 if (fp->_r <= 0 && __srefill(fp)) { 233 if (p == p0) 234 return (-1); 235 break; 236 } 237 } 238 n = p - p0; 239 if (n == 0) 240 return (0); 241 *p = 0; 242 } 243 return (n); 244} 245 246static __inline int
| 179} 180 181static __inline int 182convert_ccl(FILE *fp, char * __restrict p, int width, const char *ccltab) 183{ 184 char *p0; 185 int n; 186 187 if (p == SUPPRESS_PTR) { 188 n = 0; 189 while (ccltab[*fp->_p]) { 190 n++, fp->_r--, fp->_p++; 191 if (--width == 0) 192 break; 193 if (fp->_r <= 0 && __srefill(fp)) { 194 if (n == 0) 195 return (-1); 196 break; 197 } 198 } 199 } else { 200 p0 = p; 201 while (ccltab[*fp->_p]) { 202 fp->_r--; 203 *p++ = *fp->_p++; 204 if (--width == 0) 205 break; 206 if (fp->_r <= 0 && __srefill(fp)) { 207 if (p == p0) 208 return (-1); 209 break; 210 } 211 } 212 n = p - p0; 213 if (n == 0) 214 return (0); 215 *p = 0; 216 } 217 return (n); 218} 219 220static __inline int
|
247convert_wccl(FILE *fp, wchar_t *wcp, int width, const char *ccltab)
| 221convert_wccl(FILE *fp, wchar_t *wcp, int width, const char *ccltab, 222 locale_t locale)
|
248{ 249 mbstate_t mbs;
| 223{ 224 mbstate_t mbs;
|
250 wchar_t twc; 251 int n, nchars, nconv; 252 char buf[MB_CUR_MAX];
| 225 wint_t wi; 226 int n, nread;
|
253
| 227
|
254 if (wcp == SUPPRESS_PTR) 255 wcp = &twc;
| 228 mbs = initial_mbs;
|
256 n = 0;
| 229 n = 0;
|
257 nchars = 0; 258 while (width != 0) { 259 if (n == MB_CUR_MAX) { 260 fp->_flags |= __SERR; 261 return (-1);
| 230 if (wcp == SUPPRESS_PTR) { 231 while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF && 232 width-- != 0 && ccltab[wctob(wi)]) 233 n += nread; 234 if (wi != WEOF) 235 __ungetwc(wi, fp, __get_locale()); 236 } else { 237 while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF && 238 width-- != 0 && ccltab[wctob(wi)]) { 239 *wcp++ = (wchar_t)wi; 240 n += nread;
|
262 }
| 241 }
|
263 buf[n++] = *fp->_p; 264 fp->_p++; 265 fp->_r--; 266 mbs = initial_mbs; 267 nconv = mbrtowc(wcp, buf, n, &mbs); 268 if (nconv == (size_t)-1) { 269 fp->_flags |= __SERR; 270 return (-1); 271 } 272 if (nconv == 0) 273 *wcp = L'\0'; 274 if (nconv != (size_t)-2) { 275 if (wctob(*wcp) != EOF && !ccltab[wctob(*wcp)]) { 276 while (n != 0) { 277 n--; 278 __ungetc(buf[n], fp); 279 } 280 break; 281 } 282 width--; 283 if (wcp != &twc) 284 wcp++; 285 nchars++; 286 n = 0; 287 } 288 if (fp->_r <= 0 && __srefill(fp)) { 289 if (n != 0) { 290 fp->_flags |= __SERR; 291 return (-1); 292 } 293 break; 294 }
| 242 if (wi != WEOF) 243 __ungetwc(wi, fp, __get_locale()); 244 if (n == 0) 245 return (0); 246 *wcp = 0;
|
295 }
| 247 }
|
296 if (n != 0) { 297 fp->_flags |= __SERR; 298 return (-1); 299 } 300 if (nchars == 0) 301 return (0); 302 *wcp = L'\0'; 303 return (nchars);
| 248 return (n);
|
304} 305 306static __inline int 307convert_string(FILE *fp, char * __restrict p, int width) 308{ 309 char *p0; 310 int n; 311 312 if (p == SUPPRESS_PTR) { 313 n = 0; 314 while (!isspace(*fp->_p)) { 315 n++, fp->_r--, fp->_p++; 316 if (--width == 0) 317 break; 318 if (fp->_r <= 0 && __srefill(fp)) 319 break; 320 } 321 } else { 322 p0 = p; 323 while (!isspace(*fp->_p)) { 324 fp->_r--; 325 *p++ = *fp->_p++; 326 if (--width == 0) 327 break; 328 if (fp->_r <= 0 && __srefill(fp)) 329 break; 330 } 331 *p = 0; 332 n = p - p0; 333 } 334 return (n); 335} 336 337static __inline int
| 249} 250 251static __inline int 252convert_string(FILE *fp, char * __restrict p, int width) 253{ 254 char *p0; 255 int n; 256 257 if (p == SUPPRESS_PTR) { 258 n = 0; 259 while (!isspace(*fp->_p)) { 260 n++, fp->_r--, fp->_p++; 261 if (--width == 0) 262 break; 263 if (fp->_r <= 0 && __srefill(fp)) 264 break; 265 } 266 } else { 267 p0 = p; 268 while (!isspace(*fp->_p)) { 269 fp->_r--; 270 *p++ = *fp->_p++; 271 if (--width == 0) 272 break; 273 if (fp->_r <= 0 && __srefill(fp)) 274 break; 275 } 276 *p = 0; 277 n = p - p0; 278 } 279 return (n); 280} 281 282static __inline int
|
338convert_wstring(FILE *fp, wchar_t *wcp, int width)
| 283convert_wstring(FILE *fp, wchar_t *wcp, int width, locale_t locale)
|
339{ 340 mbstate_t mbs;
| 284{ 285 mbstate_t mbs;
|
341 wchar_t twc; 342 int n, nconv, nread; 343 char buf[MB_CUR_MAX];
| 286 wint_t wi; 287 int n, nread;
|
344
| 288
|
345 if (wcp == SUPPRESS_PTR) 346 wcp = &twc; 347 n = nread = 0; 348 while (!isspace(*fp->_p) && width != 0) { 349 if (n == MB_CUR_MAX) { 350 fp->_flags |= __SERR; 351 return (-1);
| 289 mbs = initial_mbs; 290 n = 0; 291 if (wcp == SUPPRESS_PTR) { 292 while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF && 293 width-- != 0 && !iswspace(wi)) 294 n += nread; 295 if (wi != WEOF) 296 __ungetwc(wi, fp, __get_locale()); 297 } else { 298 while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF && 299 width-- != 0 && !iswspace(wi)) { 300 *wcp++ = (wchar_t)wi; 301 n += nread;
|
352 }
| 302 }
|
353 buf[n++] = *fp->_p; 354 fp->_p++; 355 fp->_r--; 356 mbs = initial_mbs; 357 nconv = mbrtowc(wcp, buf, n, &mbs); 358 if (nconv == (size_t)-1) { 359 fp->_flags |= __SERR; 360 return (-1); 361 } 362 if (nconv == 0) 363 *wcp = L'\0'; 364 if (nconv != (size_t)-2) { 365 if (iswspace(*wcp)) { 366 while (n != 0) { 367 n--; 368 __ungetc(buf[n], fp); 369 } 370 break; 371 } 372 nread += n; 373 width--; 374 if (wcp != &twc) 375 wcp++; 376 n = 0; 377 } 378 if (fp->_r <= 0 && __srefill(fp)) { 379 if (n != 0) { 380 fp->_flags |= __SERR; 381 return (-1); 382 } 383 break; 384 }
| 303 if (wi != WEOF) 304 __ungetwc(wi, fp, __get_locale()); 305 *wcp = '\0';
|
385 }
| 306 }
|
386 *wcp = L'\0'; 387 return (nread);
| 307 return (n);
|
388} 389 390/* 391 * Read an integer, storing it in buf. The only relevant bit in the 392 * flags argument is PFXOK. 393 * 394 * Return 0 on a match failure, and the number of characters read 395 * otherwise. 396 */ 397static __inline int 398parseint(FILE *fp, char * __restrict buf, int width, int base, int flags) 399{ 400 /* `basefix' is used to avoid `if' tests */ 401 static const short basefix[17] = 402 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 403 char *p; 404 int c; 405 406 flags |= SIGNOK | NDIGITS | NZDIGITS; 407 for (p = buf; width; width--) { 408 c = *fp->_p; 409 /* 410 * Switch on the character; `goto ok' if we accept it 411 * as a part of number. 412 */ 413 switch (c) { 414 415 /* 416 * The digit 0 is always legal, but is special. For 417 * %i conversions, if no digits (zero or nonzero) have 418 * been scanned (only signs), we will have base==0. 419 * In that case, we should set it to 8 and enable 0x 420 * prefixing. Also, if we have not scanned zero 421 * digits before this, do not turn off prefixing 422 * (someone else will turn it off if we have scanned 423 * any nonzero digits). 424 */ 425 case '0': 426 if (base == 0) { 427 base = 8; 428 flags |= PFXOK; 429 } 430 if (flags & NZDIGITS) 431 flags &= ~(SIGNOK|NZDIGITS|NDIGITS); 432 else 433 flags &= ~(SIGNOK|PFXOK|NDIGITS); 434 goto ok; 435 436 /* 1 through 7 always legal */ 437 case '1': case '2': case '3': 438 case '4': case '5': case '6': case '7': 439 base = basefix[base]; 440 flags &= ~(SIGNOK | PFXOK | NDIGITS); 441 goto ok; 442 443 /* digits 8 and 9 ok iff decimal or hex */ 444 case '8': case '9': 445 base = basefix[base]; 446 if (base <= 8) 447 break; /* not legal here */ 448 flags &= ~(SIGNOK | PFXOK | NDIGITS); 449 goto ok; 450 451 /* letters ok iff hex */ 452 case 'A': case 'B': case 'C': 453 case 'D': case 'E': case 'F': 454 case 'a': case 'b': case 'c': 455 case 'd': case 'e': case 'f': 456 /* no need to fix base here */ 457 if (base <= 10) 458 break; /* not legal here */ 459 flags &= ~(SIGNOK | PFXOK | NDIGITS); 460 goto ok; 461 462 /* sign ok only as first character */ 463 case '+': case '-': 464 if (flags & SIGNOK) { 465 flags &= ~SIGNOK; 466 flags |= HAVESIGN; 467 goto ok; 468 } 469 break; 470 471 /* 472 * x ok iff flag still set & 2nd char (or 3rd char if 473 * we have a sign). 474 */ 475 case 'x': case 'X': 476 if (flags & PFXOK && p == 477 buf + 1 + !!(flags & HAVESIGN)) { 478 base = 16; /* if %i */ 479 flags &= ~PFXOK; 480 goto ok; 481 } 482 break; 483 } 484 485 /* 486 * If we got here, c is not a legal character for a 487 * number. Stop accumulating digits. 488 */ 489 break; 490 ok: 491 /* 492 * c is legal: store it and look at the next. 493 */ 494 *p++ = c; 495 if (--fp->_r > 0) 496 fp->_p++; 497 else if (__srefill(fp)) 498 break; /* EOF */ 499 } 500 /* 501 * If we had only a sign, it is no good; push back the sign. 502 * If the number ends in `x', it was [sign] '0' 'x', so push 503 * back the x and treat it as [sign] '0'. 504 */ 505 if (flags & NDIGITS) { 506 if (p > buf) 507 (void) __ungetc(*(u_char *)--p, fp); 508 return (0); 509 } 510 c = ((u_char *)p)[-1]; 511 if (c == 'x' || c == 'X') { 512 --p; 513 (void) __ungetc(c, fp); 514 } 515 return (p - buf); 516} 517 518/* 519 * __vfscanf - MT-safe version 520 */ 521int 522__vfscanf(FILE *fp, char const *fmt0, va_list ap) 523{ 524 int ret; 525 526 FLOCKFILE(fp); 527 ret = __svfscanf(fp, __get_locale(), fmt0, ap); 528 FUNLOCKFILE(fp); 529 return (ret); 530} 531int 532vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap) 533{ 534 int ret; 535 FIX_LOCALE(locale); 536 537 FLOCKFILE(fp); 538 ret = __svfscanf(fp, locale, fmt0, ap); 539 FUNLOCKFILE(fp); 540 return (ret); 541} 542 543/* 544 * __svfscanf - non-MT-safe version of __vfscanf 545 */ 546int 547__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) 548{ 549#define GETARG(type) ((flags & SUPPRESS) ? SUPPRESS_PTR : va_arg(ap, type)) 550 const u_char *fmt = (const u_char *)fmt0; 551 int c; /* character from format, or conversion */ 552 size_t width; /* field width, or 0 */ 553 int flags; /* flags as defined above */ 554 int nassigned; /* number of fields assigned */ 555 int nconversions; /* number of conversions */ 556 int nr; /* characters read by the current conversion */ 557 int nread; /* number of characters consumed from fp */ 558 int base; /* base argument to conversion function */ 559 char ccltab[256]; /* character class table for %[...] */ 560 char buf[BUF]; /* buffer for numeric conversions */ 561 562 ORIENT(fp, -1); 563 564 nassigned = 0; 565 nconversions = 0; 566 nread = 0; 567 for (;;) { 568 c = *fmt++; 569 if (c == 0) 570 return (nassigned); 571 if (isspace(c)) { 572 while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p)) 573 nread++, fp->_r--, fp->_p++; 574 continue; 575 } 576 if (c != '%') 577 goto literal; 578 width = 0; 579 flags = 0; 580 /* 581 * switch on the format. continue if done; 582 * break once format type is derived. 583 */ 584again: c = *fmt++; 585 switch (c) { 586 case '%': 587literal: 588 if (fp->_r <= 0 && __srefill(fp)) 589 goto input_failure; 590 if (*fp->_p != c) 591 goto match_failure; 592 fp->_r--, fp->_p++; 593 nread++; 594 continue; 595 596 case '*': 597 flags |= SUPPRESS; 598 goto again; 599 case 'j': 600 flags |= INTMAXT; 601 goto again; 602 case 'l': 603 if (flags & LONG) { 604 flags &= ~LONG; 605 flags |= LONGLONG; 606 } else 607 flags |= LONG; 608 goto again; 609 case 'q': 610 flags |= LONGLONG; /* not quite */ 611 goto again; 612 case 't': 613 flags |= PTRDIFFT; 614 goto again; 615 case 'z': 616 flags |= SIZET; 617 goto again; 618 case 'L': 619 flags |= LONGDBL; 620 goto again; 621 case 'h': 622 if (flags & SHORT) { 623 flags &= ~SHORT; 624 flags |= SHORTSHORT; 625 } else 626 flags |= SHORT; 627 goto again; 628 629 case '0': case '1': case '2': case '3': case '4': 630 case '5': case '6': case '7': case '8': case '9': 631 width = width * 10 + c - '0'; 632 goto again; 633 634 /* 635 * Conversions. 636 */ 637 case 'd': 638 c = CT_INT; 639 base = 10; 640 break; 641 642 case 'i': 643 c = CT_INT; 644 base = 0; 645 break; 646 647 case 'o': 648 c = CT_INT; 649 flags |= UNSIGNED; 650 base = 8; 651 break; 652 653 case 'u': 654 c = CT_INT; 655 flags |= UNSIGNED; 656 base = 10; 657 break; 658 659 case 'X': 660 case 'x': 661 flags |= PFXOK; /* enable 0x prefixing */ 662 c = CT_INT; 663 flags |= UNSIGNED; 664 base = 16; 665 break; 666 667#ifndef NO_FLOATING_POINT 668 case 'A': case 'E': case 'F': case 'G': 669 case 'a': case 'e': case 'f': case 'g': 670 c = CT_FLOAT; 671 break; 672#endif 673 674 case 'S': 675 flags |= LONG; 676 /* FALLTHROUGH */ 677 case 's': 678 c = CT_STRING; 679 break; 680 681 case '[': 682 fmt = __sccl(ccltab, fmt); 683 flags |= NOSKIP; 684 c = CT_CCL; 685 break; 686 687 case 'C': 688 flags |= LONG; 689 /* FALLTHROUGH */ 690 case 'c': 691 flags |= NOSKIP; 692 c = CT_CHAR; 693 break; 694 695 case 'p': /* pointer format is like hex */ 696 flags |= POINTER | PFXOK; 697 c = CT_INT; /* assumes sizeof(uintmax_t) */ 698 flags |= UNSIGNED; /* >= sizeof(uintptr_t) */ 699 base = 16; 700 break; 701 702 case 'n': 703 if (flags & SUPPRESS) /* ??? */ 704 continue; 705 if (flags & SHORTSHORT) 706 *va_arg(ap, char *) = nread; 707 else if (flags & SHORT) 708 *va_arg(ap, short *) = nread; 709 else if (flags & LONG) 710 *va_arg(ap, long *) = nread; 711 else if (flags & LONGLONG) 712 *va_arg(ap, long long *) = nread; 713 else if (flags & INTMAXT) 714 *va_arg(ap, intmax_t *) = nread; 715 else if (flags & SIZET) 716 *va_arg(ap, size_t *) = nread; 717 else if (flags & PTRDIFFT) 718 *va_arg(ap, ptrdiff_t *) = nread; 719 else 720 *va_arg(ap, int *) = nread; 721 continue; 722 723 default: 724 goto match_failure; 725 726 /* 727 * Disgusting backwards compatibility hack. XXX 728 */ 729 case '\0': /* compat */ 730 return (EOF); 731 } 732 733 /* 734 * We have a conversion that requires input. 735 */ 736 if (fp->_r <= 0 && __srefill(fp)) 737 goto input_failure; 738 739 /* 740 * Consume leading white space, except for formats 741 * that suppress this. 742 */ 743 if ((flags & NOSKIP) == 0) { 744 while (isspace(*fp->_p)) { 745 nread++; 746 if (--fp->_r > 0) 747 fp->_p++; 748 else if (__srefill(fp)) 749 goto input_failure; 750 } 751 /* 752 * Note that there is at least one character in 753 * the buffer, so conversions that do not set NOSKIP 754 * ca no longer result in an input failure. 755 */ 756 } 757 758 /* 759 * Do the conversion. 760 */ 761 switch (c) { 762 763 case CT_CHAR: 764 /* scan arbitrary characters (sets NOSKIP) */ 765 if (width == 0) 766 width = 1; 767 if (flags & LONG) { 768 nr = convert_wchar(fp, GETARG(wchar_t *),
| 308} 309 310/* 311 * Read an integer, storing it in buf. The only relevant bit in the 312 * flags argument is PFXOK. 313 * 314 * Return 0 on a match failure, and the number of characters read 315 * otherwise. 316 */ 317static __inline int 318parseint(FILE *fp, char * __restrict buf, int width, int base, int flags) 319{ 320 /* `basefix' is used to avoid `if' tests */ 321 static const short basefix[17] = 322 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 323 char *p; 324 int c; 325 326 flags |= SIGNOK | NDIGITS | NZDIGITS; 327 for (p = buf; width; width--) { 328 c = *fp->_p; 329 /* 330 * Switch on the character; `goto ok' if we accept it 331 * as a part of number. 332 */ 333 switch (c) { 334 335 /* 336 * The digit 0 is always legal, but is special. For 337 * %i conversions, if no digits (zero or nonzero) have 338 * been scanned (only signs), we will have base==0. 339 * In that case, we should set it to 8 and enable 0x 340 * prefixing. Also, if we have not scanned zero 341 * digits before this, do not turn off prefixing 342 * (someone else will turn it off if we have scanned 343 * any nonzero digits). 344 */ 345 case '0': 346 if (base == 0) { 347 base = 8; 348 flags |= PFXOK; 349 } 350 if (flags & NZDIGITS) 351 flags &= ~(SIGNOK|NZDIGITS|NDIGITS); 352 else 353 flags &= ~(SIGNOK|PFXOK|NDIGITS); 354 goto ok; 355 356 /* 1 through 7 always legal */ 357 case '1': case '2': case '3': 358 case '4': case '5': case '6': case '7': 359 base = basefix[base]; 360 flags &= ~(SIGNOK | PFXOK | NDIGITS); 361 goto ok; 362 363 /* digits 8 and 9 ok iff decimal or hex */ 364 case '8': case '9': 365 base = basefix[base]; 366 if (base <= 8) 367 break; /* not legal here */ 368 flags &= ~(SIGNOK | PFXOK | NDIGITS); 369 goto ok; 370 371 /* letters ok iff hex */ 372 case 'A': case 'B': case 'C': 373 case 'D': case 'E': case 'F': 374 case 'a': case 'b': case 'c': 375 case 'd': case 'e': case 'f': 376 /* no need to fix base here */ 377 if (base <= 10) 378 break; /* not legal here */ 379 flags &= ~(SIGNOK | PFXOK | NDIGITS); 380 goto ok; 381 382 /* sign ok only as first character */ 383 case '+': case '-': 384 if (flags & SIGNOK) { 385 flags &= ~SIGNOK; 386 flags |= HAVESIGN; 387 goto ok; 388 } 389 break; 390 391 /* 392 * x ok iff flag still set & 2nd char (or 3rd char if 393 * we have a sign). 394 */ 395 case 'x': case 'X': 396 if (flags & PFXOK && p == 397 buf + 1 + !!(flags & HAVESIGN)) { 398 base = 16; /* if %i */ 399 flags &= ~PFXOK; 400 goto ok; 401 } 402 break; 403 } 404 405 /* 406 * If we got here, c is not a legal character for a 407 * number. Stop accumulating digits. 408 */ 409 break; 410 ok: 411 /* 412 * c is legal: store it and look at the next. 413 */ 414 *p++ = c; 415 if (--fp->_r > 0) 416 fp->_p++; 417 else if (__srefill(fp)) 418 break; /* EOF */ 419 } 420 /* 421 * If we had only a sign, it is no good; push back the sign. 422 * If the number ends in `x', it was [sign] '0' 'x', so push 423 * back the x and treat it as [sign] '0'. 424 */ 425 if (flags & NDIGITS) { 426 if (p > buf) 427 (void) __ungetc(*(u_char *)--p, fp); 428 return (0); 429 } 430 c = ((u_char *)p)[-1]; 431 if (c == 'x' || c == 'X') { 432 --p; 433 (void) __ungetc(c, fp); 434 } 435 return (p - buf); 436} 437 438/* 439 * __vfscanf - MT-safe version 440 */ 441int 442__vfscanf(FILE *fp, char const *fmt0, va_list ap) 443{ 444 int ret; 445 446 FLOCKFILE(fp); 447 ret = __svfscanf(fp, __get_locale(), fmt0, ap); 448 FUNLOCKFILE(fp); 449 return (ret); 450} 451int 452vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap) 453{ 454 int ret; 455 FIX_LOCALE(locale); 456 457 FLOCKFILE(fp); 458 ret = __svfscanf(fp, locale, fmt0, ap); 459 FUNLOCKFILE(fp); 460 return (ret); 461} 462 463/* 464 * __svfscanf - non-MT-safe version of __vfscanf 465 */ 466int 467__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) 468{ 469#define GETARG(type) ((flags & SUPPRESS) ? SUPPRESS_PTR : va_arg(ap, type)) 470 const u_char *fmt = (const u_char *)fmt0; 471 int c; /* character from format, or conversion */ 472 size_t width; /* field width, or 0 */ 473 int flags; /* flags as defined above */ 474 int nassigned; /* number of fields assigned */ 475 int nconversions; /* number of conversions */ 476 int nr; /* characters read by the current conversion */ 477 int nread; /* number of characters consumed from fp */ 478 int base; /* base argument to conversion function */ 479 char ccltab[256]; /* character class table for %[...] */ 480 char buf[BUF]; /* buffer for numeric conversions */ 481 482 ORIENT(fp, -1); 483 484 nassigned = 0; 485 nconversions = 0; 486 nread = 0; 487 for (;;) { 488 c = *fmt++; 489 if (c == 0) 490 return (nassigned); 491 if (isspace(c)) { 492 while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p)) 493 nread++, fp->_r--, fp->_p++; 494 continue; 495 } 496 if (c != '%') 497 goto literal; 498 width = 0; 499 flags = 0; 500 /* 501 * switch on the format. continue if done; 502 * break once format type is derived. 503 */ 504again: c = *fmt++; 505 switch (c) { 506 case '%': 507literal: 508 if (fp->_r <= 0 && __srefill(fp)) 509 goto input_failure; 510 if (*fp->_p != c) 511 goto match_failure; 512 fp->_r--, fp->_p++; 513 nread++; 514 continue; 515 516 case '*': 517 flags |= SUPPRESS; 518 goto again; 519 case 'j': 520 flags |= INTMAXT; 521 goto again; 522 case 'l': 523 if (flags & LONG) { 524 flags &= ~LONG; 525 flags |= LONGLONG; 526 } else 527 flags |= LONG; 528 goto again; 529 case 'q': 530 flags |= LONGLONG; /* not quite */ 531 goto again; 532 case 't': 533 flags |= PTRDIFFT; 534 goto again; 535 case 'z': 536 flags |= SIZET; 537 goto again; 538 case 'L': 539 flags |= LONGDBL; 540 goto again; 541 case 'h': 542 if (flags & SHORT) { 543 flags &= ~SHORT; 544 flags |= SHORTSHORT; 545 } else 546 flags |= SHORT; 547 goto again; 548 549 case '0': case '1': case '2': case '3': case '4': 550 case '5': case '6': case '7': case '8': case '9': 551 width = width * 10 + c - '0'; 552 goto again; 553 554 /* 555 * Conversions. 556 */ 557 case 'd': 558 c = CT_INT; 559 base = 10; 560 break; 561 562 case 'i': 563 c = CT_INT; 564 base = 0; 565 break; 566 567 case 'o': 568 c = CT_INT; 569 flags |= UNSIGNED; 570 base = 8; 571 break; 572 573 case 'u': 574 c = CT_INT; 575 flags |= UNSIGNED; 576 base = 10; 577 break; 578 579 case 'X': 580 case 'x': 581 flags |= PFXOK; /* enable 0x prefixing */ 582 c = CT_INT; 583 flags |= UNSIGNED; 584 base = 16; 585 break; 586 587#ifndef NO_FLOATING_POINT 588 case 'A': case 'E': case 'F': case 'G': 589 case 'a': case 'e': case 'f': case 'g': 590 c = CT_FLOAT; 591 break; 592#endif 593 594 case 'S': 595 flags |= LONG; 596 /* FALLTHROUGH */ 597 case 's': 598 c = CT_STRING; 599 break; 600 601 case '[': 602 fmt = __sccl(ccltab, fmt); 603 flags |= NOSKIP; 604 c = CT_CCL; 605 break; 606 607 case 'C': 608 flags |= LONG; 609 /* FALLTHROUGH */ 610 case 'c': 611 flags |= NOSKIP; 612 c = CT_CHAR; 613 break; 614 615 case 'p': /* pointer format is like hex */ 616 flags |= POINTER | PFXOK; 617 c = CT_INT; /* assumes sizeof(uintmax_t) */ 618 flags |= UNSIGNED; /* >= sizeof(uintptr_t) */ 619 base = 16; 620 break; 621 622 case 'n': 623 if (flags & SUPPRESS) /* ??? */ 624 continue; 625 if (flags & SHORTSHORT) 626 *va_arg(ap, char *) = nread; 627 else if (flags & SHORT) 628 *va_arg(ap, short *) = nread; 629 else if (flags & LONG) 630 *va_arg(ap, long *) = nread; 631 else if (flags & LONGLONG) 632 *va_arg(ap, long long *) = nread; 633 else if (flags & INTMAXT) 634 *va_arg(ap, intmax_t *) = nread; 635 else if (flags & SIZET) 636 *va_arg(ap, size_t *) = nread; 637 else if (flags & PTRDIFFT) 638 *va_arg(ap, ptrdiff_t *) = nread; 639 else 640 *va_arg(ap, int *) = nread; 641 continue; 642 643 default: 644 goto match_failure; 645 646 /* 647 * Disgusting backwards compatibility hack. XXX 648 */ 649 case '\0': /* compat */ 650 return (EOF); 651 } 652 653 /* 654 * We have a conversion that requires input. 655 */ 656 if (fp->_r <= 0 && __srefill(fp)) 657 goto input_failure; 658 659 /* 660 * Consume leading white space, except for formats 661 * that suppress this. 662 */ 663 if ((flags & NOSKIP) == 0) { 664 while (isspace(*fp->_p)) { 665 nread++; 666 if (--fp->_r > 0) 667 fp->_p++; 668 else if (__srefill(fp)) 669 goto input_failure; 670 } 671 /* 672 * Note that there is at least one character in 673 * the buffer, so conversions that do not set NOSKIP 674 * ca no longer result in an input failure. 675 */ 676 } 677 678 /* 679 * Do the conversion. 680 */ 681 switch (c) { 682 683 case CT_CHAR: 684 /* scan arbitrary characters (sets NOSKIP) */ 685 if (width == 0) 686 width = 1; 687 if (flags & LONG) { 688 nr = convert_wchar(fp, GETARG(wchar_t *),
|
769 width);
| 689 width, locale);
|
770 } else { 771 nr = convert_char(fp, GETARG(char *), width); 772 } 773 if (nr < 0) 774 goto input_failure; 775 break; 776 777 case CT_CCL: 778 /* scan a (nonempty) character class (sets NOSKIP) */ 779 if (width == 0) 780 width = (size_t)~0; /* `infinity' */ 781 if (flags & LONG) { 782 nr = convert_wccl(fp, GETARG(wchar_t *), width,
| 690 } else { 691 nr = convert_char(fp, GETARG(char *), width); 692 } 693 if (nr < 0) 694 goto input_failure; 695 break; 696 697 case CT_CCL: 698 /* scan a (nonempty) character class (sets NOSKIP) */ 699 if (width == 0) 700 width = (size_t)~0; /* `infinity' */ 701 if (flags & LONG) { 702 nr = convert_wccl(fp, GETARG(wchar_t *), width,
|
783 ccltab);
| 703 ccltab, locale);
|
784 } else { 785 nr = convert_ccl(fp, GETARG(char *), width, 786 ccltab); 787 } 788 if (nr <= 0) { 789 if (nr < 0) 790 goto input_failure; 791 else /* nr == 0 */ 792 goto match_failure; 793 } 794 break; 795 796 case CT_STRING: 797 /* like CCL, but zero-length string OK, & no NOSKIP */ 798 if (width == 0) 799 width = (size_t)~0; 800 if (flags & LONG) { 801 nr = convert_wstring(fp, GETARG(wchar_t *),
| 704 } else { 705 nr = convert_ccl(fp, GETARG(char *), width, 706 ccltab); 707 } 708 if (nr <= 0) { 709 if (nr < 0) 710 goto input_failure; 711 else /* nr == 0 */ 712 goto match_failure; 713 } 714 break; 715 716 case CT_STRING: 717 /* like CCL, but zero-length string OK, & no NOSKIP */ 718 if (width == 0) 719 width = (size_t)~0; 720 if (flags & LONG) { 721 nr = convert_wstring(fp, GETARG(wchar_t *),
|
802 width);
| 722 width, locale);
|
803 } else { 804 nr = convert_string(fp, GETARG(char *), width); 805 } 806 if (nr < 0) 807 goto input_failure; 808 break; 809 810 case CT_INT: 811 /* scan an integer as if by the conversion function */ 812#ifdef hardway 813 if (width == 0 || width > sizeof(buf) - 1) 814 width = sizeof(buf) - 1; 815#else 816 /* size_t is unsigned, hence this optimisation */ 817 if (--width > sizeof(buf) - 2) 818 width = sizeof(buf) - 2; 819 width++; 820#endif 821 nr = parseint(fp, buf, width, base, flags); 822 if (nr == 0) 823 goto match_failure; 824 if ((flags & SUPPRESS) == 0) { 825 uintmax_t res; 826 827 buf[nr] = '\0'; 828 if ((flags & UNSIGNED) == 0) 829 res = strtoimax_l(buf, (char **)NULL, base, locale); 830 else 831 res = strtoumax_l(buf, (char **)NULL, base, locale); 832 if (flags & POINTER) 833 *va_arg(ap, void **) = 834 (void *)(uintptr_t)res; 835 else if (flags & SHORTSHORT) 836 *va_arg(ap, char *) = res; 837 else if (flags & SHORT) 838 *va_arg(ap, short *) = res; 839 else if (flags & LONG) 840 *va_arg(ap, long *) = res; 841 else if (flags & LONGLONG) 842 *va_arg(ap, long long *) = res; 843 else if (flags & INTMAXT) 844 *va_arg(ap, intmax_t *) = res; 845 else if (flags & PTRDIFFT) 846 *va_arg(ap, ptrdiff_t *) = res; 847 else if (flags & SIZET) 848 *va_arg(ap, size_t *) = res; 849 else 850 *va_arg(ap, int *) = res; 851 } 852 break; 853 854#ifndef NO_FLOATING_POINT 855 case CT_FLOAT: 856 /* scan a floating point number as if by strtod */ 857 if (width == 0 || width > sizeof(buf) - 1) 858 width = sizeof(buf) - 1; 859 nr = parsefloat(fp, buf, buf + width, locale); 860 if (nr == 0) 861 goto match_failure; 862 if ((flags & SUPPRESS) == 0) { 863 if (flags & LONGDBL) { 864 long double res = strtold_l(buf, NULL, 865 locale); 866 *va_arg(ap, long double *) = res; 867 } else if (flags & LONG) { 868 double res = strtod_l(buf, NULL, 869 locale); 870 *va_arg(ap, double *) = res; 871 } else { 872 float res = strtof_l(buf, NULL, locale); 873 *va_arg(ap, float *) = res; 874 } 875 } 876 break; 877#endif /* !NO_FLOATING_POINT */ 878 } 879 if (!(flags & SUPPRESS)) 880 nassigned++; 881 nread += nr; 882 nconversions++; 883 } 884input_failure: 885 return (nconversions != 0 ? nassigned : EOF); 886match_failure: 887 return (nassigned); 888} 889 890/* 891 * Fill in the given table from the scanset at the given format 892 * (just after `['). Return a pointer to the character past the 893 * closing `]'. The table has a 1 wherever characters should be 894 * considered part of the scanset. 895 */ 896static const u_char * 897__sccl(tab, fmt) 898 char *tab; 899 const u_char *fmt; 900{ 901 int c, n, v, i; 902 struct xlocale_collate *table = 903 (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; 904 905 /* first `clear' the whole table */ 906 c = *fmt++; /* first char hat => negated scanset */ 907 if (c == '^') { 908 v = 1; /* default => accept */ 909 c = *fmt++; /* get new first char */ 910 } else 911 v = 0; /* default => reject */ 912 913 /* XXX: Will not work if sizeof(tab*) > sizeof(char) */ 914 (void) memset(tab, v, 256); 915 916 if (c == 0) 917 return (fmt - 1);/* format ended before closing ] */ 918 919 /* 920 * Now set the entries corresponding to the actual scanset 921 * to the opposite of the above. 922 * 923 * The first character may be ']' (or '-') without being special; 924 * the last character may be '-'. 925 */ 926 v = 1 - v; 927 for (;;) { 928 tab[c] = v; /* take character c */ 929doswitch: 930 n = *fmt++; /* and examine the next */ 931 switch (n) { 932 933 case 0: /* format ended too soon */ 934 return (fmt - 1); 935 936 case '-': 937 /* 938 * A scanset of the form 939 * [01+-] 940 * is defined as `the digit 0, the digit 1, 941 * the character +, the character -', but 942 * the effect of a scanset such as 943 * [a-zA-Z0-9] 944 * is implementation defined. The V7 Unix 945 * scanf treats `a-z' as `the letters a through 946 * z', but treats `a-a' as `the letter a, the 947 * character -, and the letter a'. 948 * 949 * For compatibility, the `-' is not considerd 950 * to define a range if the character following 951 * it is either a close bracket (required by ANSI) 952 * or is not numerically greater than the character 953 * we just stored in the table (c). 954 */ 955 n = *fmt; 956 if (n == ']' 957 || (table->__collate_load_error ? n < c : 958 __collate_range_cmp (table, n, c) < 0 959 ) 960 ) { 961 c = '-'; 962 break; /* resume the for(;;) */ 963 } 964 fmt++; 965 /* fill in the range */ 966 if (table->__collate_load_error) { 967 do { 968 tab[++c] = v; 969 } while (c < n); 970 } else { 971 for (i = 0; i < 256; i ++) 972 if ( __collate_range_cmp (table, c, i) < 0 973 && __collate_range_cmp (table, i, n) <= 0 974 ) 975 tab[i] = v; 976 } 977#if 1 /* XXX another disgusting compatibility hack */ 978 c = n; 979 /* 980 * Alas, the V7 Unix scanf also treats formats 981 * such as [a-c-e] as `the letters a through e'. 982 * This too is permitted by the standard.... 983 */ 984 goto doswitch; 985#else 986 c = *fmt++; 987 if (c == 0) 988 return (fmt - 1); 989 if (c == ']') 990 return (fmt); 991#endif 992 break; 993 994 case ']': /* end of scanset */ 995 return (fmt); 996 997 default: /* just another character */ 998 c = n; 999 break; 1000 } 1001 } 1002 /* NOTREACHED */ 1003} 1004 1005#ifndef NO_FLOATING_POINT 1006static int 1007parsefloat(FILE *fp, char *buf, char *end, locale_t locale) 1008{ 1009 char *commit, *p; 1010 int infnanpos = 0, decptpos = 0; 1011 enum { 1012 S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX, 1013 S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS 1014 } state = S_START; 1015 unsigned char c; 1016 const char *decpt = localeconv_l(locale)->decimal_point; 1017 _Bool gotmantdig = 0, ishex = 0; 1018 1019 /* 1020 * We set commit = p whenever the string we have read so far 1021 * constitutes a valid representation of a floating point 1022 * number by itself. At some point, the parse will complete 1023 * or fail, and we will ungetc() back to the last commit point. 1024 * To ensure that the file offset gets updated properly, it is 1025 * always necessary to read at least one character that doesn't 1026 * match; thus, we can't short-circuit "infinity" or "nan(...)". 1027 */ 1028 commit = buf - 1; 1029 for (p = buf; p < end; ) { 1030 c = *fp->_p; 1031reswitch: 1032 switch (state) { 1033 case S_START: 1034 state = S_GOTSIGN; 1035 if (c == '-' || c == '+') 1036 break; 1037 else 1038 goto reswitch; 1039 case S_GOTSIGN: 1040 switch (c) { 1041 case '0': 1042 state = S_MAYBEHEX; 1043 commit = p; 1044 break; 1045 case 'I': 1046 case 'i': 1047 state = S_INF; 1048 break; 1049 case 'N': 1050 case 'n': 1051 state = S_NAN; 1052 break; 1053 default: 1054 state = S_DIGITS; 1055 goto reswitch; 1056 } 1057 break; 1058 case S_INF: 1059 if (infnanpos > 6 || 1060 (c != "nfinity"[infnanpos] && 1061 c != "NFINITY"[infnanpos])) 1062 goto parsedone; 1063 if (infnanpos == 1 || infnanpos == 6) 1064 commit = p; /* inf or infinity */ 1065 infnanpos++; 1066 break; 1067 case S_NAN: 1068 switch (infnanpos) { 1069 case 0: 1070 if (c != 'A' && c != 'a') 1071 goto parsedone; 1072 break; 1073 case 1: 1074 if (c != 'N' && c != 'n') 1075 goto parsedone; 1076 else 1077 commit = p; 1078 break; 1079 case 2: 1080 if (c != '(') 1081 goto parsedone; 1082 break; 1083 default: 1084 if (c == ')') { 1085 commit = p; 1086 state = S_DONE; 1087 } else if (!isalnum(c) && c != '_') 1088 goto parsedone; 1089 break; 1090 } 1091 infnanpos++; 1092 break; 1093 case S_DONE: 1094 goto parsedone; 1095 case S_MAYBEHEX: 1096 state = S_DIGITS; 1097 if (c == 'X' || c == 'x') { 1098 ishex = 1; 1099 break; 1100 } else { /* we saw a '0', but no 'x' */ 1101 gotmantdig = 1; 1102 goto reswitch; 1103 } 1104 case S_DIGITS: 1105 if ((ishex && isxdigit(c)) || isdigit(c)) { 1106 gotmantdig = 1; 1107 commit = p; 1108 break; 1109 } else { 1110 state = S_DECPT; 1111 goto reswitch; 1112 } 1113 case S_DECPT: 1114 if (c == decpt[decptpos]) { 1115 if (decpt[++decptpos] == '\0') { 1116 /* We read the complete decpt seq. */ 1117 state = S_FRAC; 1118 if (gotmantdig) 1119 commit = p; 1120 } 1121 break; 1122 } else if (!decptpos) { 1123 /* We didn't read any decpt characters. */ 1124 state = S_FRAC; 1125 goto reswitch; 1126 } else { 1127 /* 1128 * We read part of a multibyte decimal point, 1129 * but the rest is invalid, so bail. 1130 */ 1131 goto parsedone; 1132 } 1133 case S_FRAC: 1134 if (((c == 'E' || c == 'e') && !ishex) || 1135 ((c == 'P' || c == 'p') && ishex)) { 1136 if (!gotmantdig) 1137 goto parsedone; 1138 else 1139 state = S_EXP; 1140 } else if ((ishex && isxdigit(c)) || isdigit(c)) { 1141 commit = p; 1142 gotmantdig = 1; 1143 } else 1144 goto parsedone; 1145 break; 1146 case S_EXP: 1147 state = S_EXPDIGITS; 1148 if (c == '-' || c == '+') 1149 break; 1150 else 1151 goto reswitch; 1152 case S_EXPDIGITS: 1153 if (isdigit(c)) 1154 commit = p; 1155 else 1156 goto parsedone; 1157 break; 1158 default: 1159 abort(); 1160 } 1161 *p++ = c; 1162 if (--fp->_r > 0) 1163 fp->_p++; 1164 else if (__srefill(fp)) 1165 break; /* EOF */ 1166 } 1167 1168parsedone: 1169 while (commit < --p) 1170 __ungetc(*(u_char *)p, fp); 1171 *++commit = '\0'; 1172 return (commit - buf); 1173} 1174#endif
| 723 } else { 724 nr = convert_string(fp, GETARG(char *), width); 725 } 726 if (nr < 0) 727 goto input_failure; 728 break; 729 730 case CT_INT: 731 /* scan an integer as if by the conversion function */ 732#ifdef hardway 733 if (width == 0 || width > sizeof(buf) - 1) 734 width = sizeof(buf) - 1; 735#else 736 /* size_t is unsigned, hence this optimisation */ 737 if (--width > sizeof(buf) - 2) 738 width = sizeof(buf) - 2; 739 width++; 740#endif 741 nr = parseint(fp, buf, width, base, flags); 742 if (nr == 0) 743 goto match_failure; 744 if ((flags & SUPPRESS) == 0) { 745 uintmax_t res; 746 747 buf[nr] = '\0'; 748 if ((flags & UNSIGNED) == 0) 749 res = strtoimax_l(buf, (char **)NULL, base, locale); 750 else 751 res = strtoumax_l(buf, (char **)NULL, base, locale); 752 if (flags & POINTER) 753 *va_arg(ap, void **) = 754 (void *)(uintptr_t)res; 755 else if (flags & SHORTSHORT) 756 *va_arg(ap, char *) = res; 757 else if (flags & SHORT) 758 *va_arg(ap, short *) = res; 759 else if (flags & LONG) 760 *va_arg(ap, long *) = res; 761 else if (flags & LONGLONG) 762 *va_arg(ap, long long *) = res; 763 else if (flags & INTMAXT) 764 *va_arg(ap, intmax_t *) = res; 765 else if (flags & PTRDIFFT) 766 *va_arg(ap, ptrdiff_t *) = res; 767 else if (flags & SIZET) 768 *va_arg(ap, size_t *) = res; 769 else 770 *va_arg(ap, int *) = res; 771 } 772 break; 773 774#ifndef NO_FLOATING_POINT 775 case CT_FLOAT: 776 /* scan a floating point number as if by strtod */ 777 if (width == 0 || width > sizeof(buf) - 1) 778 width = sizeof(buf) - 1; 779 nr = parsefloat(fp, buf, buf + width, locale); 780 if (nr == 0) 781 goto match_failure; 782 if ((flags & SUPPRESS) == 0) { 783 if (flags & LONGDBL) { 784 long double res = strtold_l(buf, NULL, 785 locale); 786 *va_arg(ap, long double *) = res; 787 } else if (flags & LONG) { 788 double res = strtod_l(buf, NULL, 789 locale); 790 *va_arg(ap, double *) = res; 791 } else { 792 float res = strtof_l(buf, NULL, locale); 793 *va_arg(ap, float *) = res; 794 } 795 } 796 break; 797#endif /* !NO_FLOATING_POINT */ 798 } 799 if (!(flags & SUPPRESS)) 800 nassigned++; 801 nread += nr; 802 nconversions++; 803 } 804input_failure: 805 return (nconversions != 0 ? nassigned : EOF); 806match_failure: 807 return (nassigned); 808} 809 810/* 811 * Fill in the given table from the scanset at the given format 812 * (just after `['). Return a pointer to the character past the 813 * closing `]'. The table has a 1 wherever characters should be 814 * considered part of the scanset. 815 */ 816static const u_char * 817__sccl(tab, fmt) 818 char *tab; 819 const u_char *fmt; 820{ 821 int c, n, v, i; 822 struct xlocale_collate *table = 823 (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; 824 825 /* first `clear' the whole table */ 826 c = *fmt++; /* first char hat => negated scanset */ 827 if (c == '^') { 828 v = 1; /* default => accept */ 829 c = *fmt++; /* get new first char */ 830 } else 831 v = 0; /* default => reject */ 832 833 /* XXX: Will not work if sizeof(tab*) > sizeof(char) */ 834 (void) memset(tab, v, 256); 835 836 if (c == 0) 837 return (fmt - 1);/* format ended before closing ] */ 838 839 /* 840 * Now set the entries corresponding to the actual scanset 841 * to the opposite of the above. 842 * 843 * The first character may be ']' (or '-') without being special; 844 * the last character may be '-'. 845 */ 846 v = 1 - v; 847 for (;;) { 848 tab[c] = v; /* take character c */ 849doswitch: 850 n = *fmt++; /* and examine the next */ 851 switch (n) { 852 853 case 0: /* format ended too soon */ 854 return (fmt - 1); 855 856 case '-': 857 /* 858 * A scanset of the form 859 * [01+-] 860 * is defined as `the digit 0, the digit 1, 861 * the character +, the character -', but 862 * the effect of a scanset such as 863 * [a-zA-Z0-9] 864 * is implementation defined. The V7 Unix 865 * scanf treats `a-z' as `the letters a through 866 * z', but treats `a-a' as `the letter a, the 867 * character -, and the letter a'. 868 * 869 * For compatibility, the `-' is not considerd 870 * to define a range if the character following 871 * it is either a close bracket (required by ANSI) 872 * or is not numerically greater than the character 873 * we just stored in the table (c). 874 */ 875 n = *fmt; 876 if (n == ']' 877 || (table->__collate_load_error ? n < c : 878 __collate_range_cmp (table, n, c) < 0 879 ) 880 ) { 881 c = '-'; 882 break; /* resume the for(;;) */ 883 } 884 fmt++; 885 /* fill in the range */ 886 if (table->__collate_load_error) { 887 do { 888 tab[++c] = v; 889 } while (c < n); 890 } else { 891 for (i = 0; i < 256; i ++) 892 if ( __collate_range_cmp (table, c, i) < 0 893 && __collate_range_cmp (table, i, n) <= 0 894 ) 895 tab[i] = v; 896 } 897#if 1 /* XXX another disgusting compatibility hack */ 898 c = n; 899 /* 900 * Alas, the V7 Unix scanf also treats formats 901 * such as [a-c-e] as `the letters a through e'. 902 * This too is permitted by the standard.... 903 */ 904 goto doswitch; 905#else 906 c = *fmt++; 907 if (c == 0) 908 return (fmt - 1); 909 if (c == ']') 910 return (fmt); 911#endif 912 break; 913 914 case ']': /* end of scanset */ 915 return (fmt); 916 917 default: /* just another character */ 918 c = n; 919 break; 920 } 921 } 922 /* NOTREACHED */ 923} 924 925#ifndef NO_FLOATING_POINT 926static int 927parsefloat(FILE *fp, char *buf, char *end, locale_t locale) 928{ 929 char *commit, *p; 930 int infnanpos = 0, decptpos = 0; 931 enum { 932 S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX, 933 S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS 934 } state = S_START; 935 unsigned char c; 936 const char *decpt = localeconv_l(locale)->decimal_point; 937 _Bool gotmantdig = 0, ishex = 0; 938 939 /* 940 * We set commit = p whenever the string we have read so far 941 * constitutes a valid representation of a floating point 942 * number by itself. At some point, the parse will complete 943 * or fail, and we will ungetc() back to the last commit point. 944 * To ensure that the file offset gets updated properly, it is 945 * always necessary to read at least one character that doesn't 946 * match; thus, we can't short-circuit "infinity" or "nan(...)". 947 */ 948 commit = buf - 1; 949 for (p = buf; p < end; ) { 950 c = *fp->_p; 951reswitch: 952 switch (state) { 953 case S_START: 954 state = S_GOTSIGN; 955 if (c == '-' || c == '+') 956 break; 957 else 958 goto reswitch; 959 case S_GOTSIGN: 960 switch (c) { 961 case '0': 962 state = S_MAYBEHEX; 963 commit = p; 964 break; 965 case 'I': 966 case 'i': 967 state = S_INF; 968 break; 969 case 'N': 970 case 'n': 971 state = S_NAN; 972 break; 973 default: 974 state = S_DIGITS; 975 goto reswitch; 976 } 977 break; 978 case S_INF: 979 if (infnanpos > 6 || 980 (c != "nfinity"[infnanpos] && 981 c != "NFINITY"[infnanpos])) 982 goto parsedone; 983 if (infnanpos == 1 || infnanpos == 6) 984 commit = p; /* inf or infinity */ 985 infnanpos++; 986 break; 987 case S_NAN: 988 switch (infnanpos) { 989 case 0: 990 if (c != 'A' && c != 'a') 991 goto parsedone; 992 break; 993 case 1: 994 if (c != 'N' && c != 'n') 995 goto parsedone; 996 else 997 commit = p; 998 break; 999 case 2: 1000 if (c != '(') 1001 goto parsedone; 1002 break; 1003 default: 1004 if (c == ')') { 1005 commit = p; 1006 state = S_DONE; 1007 } else if (!isalnum(c) && c != '_') 1008 goto parsedone; 1009 break; 1010 } 1011 infnanpos++; 1012 break; 1013 case S_DONE: 1014 goto parsedone; 1015 case S_MAYBEHEX: 1016 state = S_DIGITS; 1017 if (c == 'X' || c == 'x') { 1018 ishex = 1; 1019 break; 1020 } else { /* we saw a '0', but no 'x' */ 1021 gotmantdig = 1; 1022 goto reswitch; 1023 } 1024 case S_DIGITS: 1025 if ((ishex && isxdigit(c)) || isdigit(c)) { 1026 gotmantdig = 1; 1027 commit = p; 1028 break; 1029 } else { 1030 state = S_DECPT; 1031 goto reswitch; 1032 } 1033 case S_DECPT: 1034 if (c == decpt[decptpos]) { 1035 if (decpt[++decptpos] == '\0') { 1036 /* We read the complete decpt seq. */ 1037 state = S_FRAC; 1038 if (gotmantdig) 1039 commit = p; 1040 } 1041 break; 1042 } else if (!decptpos) { 1043 /* We didn't read any decpt characters. */ 1044 state = S_FRAC; 1045 goto reswitch; 1046 } else { 1047 /* 1048 * We read part of a multibyte decimal point, 1049 * but the rest is invalid, so bail. 1050 */ 1051 goto parsedone; 1052 } 1053 case S_FRAC: 1054 if (((c == 'E' || c == 'e') && !ishex) || 1055 ((c == 'P' || c == 'p') && ishex)) { 1056 if (!gotmantdig) 1057 goto parsedone; 1058 else 1059 state = S_EXP; 1060 } else if ((ishex && isxdigit(c)) || isdigit(c)) { 1061 commit = p; 1062 gotmantdig = 1; 1063 } else 1064 goto parsedone; 1065 break; 1066 case S_EXP: 1067 state = S_EXPDIGITS; 1068 if (c == '-' || c == '+') 1069 break; 1070 else 1071 goto reswitch; 1072 case S_EXPDIGITS: 1073 if (isdigit(c)) 1074 commit = p; 1075 else 1076 goto parsedone; 1077 break; 1078 default: 1079 abort(); 1080 } 1081 *p++ = c; 1082 if (--fp->_r > 0) 1083 fp->_p++; 1084 else if (__srefill(fp)) 1085 break; /* EOF */ 1086 } 1087 1088parsedone: 1089 while (commit < --p) 1090 __ungetc(*(u_char *)p, fp); 1091 *++commit = '\0'; 1092 return (commit - buf); 1093} 1094#endif
|