12aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/** @file 22aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm Implementation of scanf internals for <stdio.h>. 32aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 49792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR> 52aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm This program and the accompanying materials are licensed and made available 62aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm under the terms and conditions of the BSD License that accompanies this 72aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm distribution. The full text of the license may be found at 853e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm http://opensource.org/licenses/bsd-license. 92aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm Copyright (c) 1990, 1993 142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm The Regents of the University of California. All rights reserved. 152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm This code is derived from software contributed to Berkeley by 172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm Chris Torek. 182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm Redistribution and use in source and binary forms, with or without 202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm modification, are permitted provided that the following conditions 212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm are met: 222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm - Redistributions of source code must retain the above copyright 232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm notice, this list of conditions and the following disclaimer. 242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm - Redistributions in binary form must reproduce the above copyright 252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm notice, this list of conditions and the following disclaimer in the 262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm documentation and/or other materials provided with the distribution. 272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm - Neither the name of the University nor the names of its contributors 282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm may be used to endorse or promote products derived from this software 292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm without specific prior written permission. 302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm POSSIBILITY OF SUCH DAMAGE. 422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm NetBSD: vfscanf.c,v 1.37.4.1 2007/05/07 19:49:08 pavel Exp 442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.41 2007/01/09 00:28:07 imp Exp 452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm vfscanf.c 8.1 (Berkeley) 6/4/93 462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm**/ 472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <LibConfig.h> 482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include "namespace.h" 502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <assert.h> 512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <ctype.h> 5253e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm#include <errno.h> 532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <inttypes.h> 542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <stdio.h> 552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <stdlib.h> 562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <stddef.h> 572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <stdarg.h> 582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <string.h> 592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <sys/types.h> 602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <wchar.h> 612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <wctype.h> 622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include "reentrant.h" 642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include "local.h" 652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef NO_FLOATING_POINT 672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#include <locale.h> 682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif 692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* 71f45df7a607b8f875228e3fe4480f99bed8dad2b4darylm * Provide an external name for vfscanf. Note, EFI uses the normal 722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * namespace.h method; stdio routines explicitly use the internal name 732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * __svfscanf. 742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef __weak_alias 762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__weak_alias(vfscanf,__svfscanf) 772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif 782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define BUF 513 /* Maximum length of numeric string. */ 802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* 822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Flags used during conversion. 832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define LONG 0x0001 /* l: long or double */ 852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define LONGDBL 0x0002 /* L: long double */ 862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define SHORT 0x0004 /* h: short */ 872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define SUPPRESS 0x0008 /* *: suppress assignment */ 882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define POINTER 0x0010 /* p: void * (as hex) */ 892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define NOSKIP 0x0020 /* [ or c: do not skip blanks */ 902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define LONGLONG 0x0400 /* ll: long long (+ deprecated q: quad) */ 912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define INTMAXT 0x0800 /* j: intmax_t */ 922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define PTRDIFFT 0x1000 /* t: ptrdiff_t */ 932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define SIZET 0x2000 /* z: size_t */ 942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define SHORTSHORT 0x4000 /* hh: char */ 952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define UNSIGNED 0x8000 /* %[oupxX] conversions */ 962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* 982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * The following are used in integral conversions only: 992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * SIGNOK, NDIGITS, PFXOK, and NZDIGITS 1002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 1012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define SIGNOK 0x00040 /* +/- is (still) legal */ 1022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define NDIGITS 0x00080 /* no digits detected */ 1032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define PFXOK 0x00100 /* 0x prefix is (still) legal */ 1042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define NZDIGITS 0x00200 /* no zero digits detected */ 1052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define HAVESIGN 0x10000 /* sign detected */ 1062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* 1082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Conversion types. 1092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 1102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define CT_CHAR 0 /* %c conversion */ 1112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define CT_CCL 1 /* %[...] conversion */ 1122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define CT_STRING 2 /* %s conversion */ 1132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define CT_INT 3 /* %[dioupxX] conversion */ 1142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define CT_FLOAT 4 /* %[efgEFG] conversion */ 1152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic const u_char *__sccl(char *, const u_char *); 1172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef NO_FLOATING_POINT 1182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm static int parsefloat(FILE *, char *, char *); 1192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif 1202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmint __scanfdebug = 0; 1222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#define __collate_load_error /*CONSTCOND*/0 1242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int 1252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__collate_range_cmp(int c1, int c2) 1262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{ 1270e398dc7392bcf5f855ab76192f226051b05a309Olivier Martin static char s1[2] = { 0 }; 1280e398dc7392bcf5f855ab76192f226051b05a309Olivier Martin static char s2[2] = { 0 }; 1292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm s1[0] = (char)c1; 1312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm s2[0] = (char)c2; 1322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return strcoll(s1, s2); 1332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm} 1342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* 1372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * __svfscanf - MT-safe version 1382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 1392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmint 1402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__svfscanf(FILE *fp, char const *fmt0, va_list ap) 1412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{ 1422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm int ret; 1432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 14453e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm if(fp == NULL) { 14553e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm errno = EINVAL; 14653e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm return (EOF); 14753e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm } 1482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm FLOCKFILE(fp); 1492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm ret = __svfscanf_unlocked(fp, fmt0, ap); 1502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm FUNLOCKFILE(fp); 1512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (ret); 1522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm} 1532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* 1552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * __svfscanf_unlocked - non-MT-safe version of __svfscanf 1562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 1572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmint 1582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__svfscanf_unlocked(FILE *fp, const char *fmt0, va_list ap) 1592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{ 1609792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin const u_char *fmt = (const u_char *)fmt0; 1619792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin int c; /* character from format, or conversion */ 1629792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin size_t width; /* field width, or 0 */ 1639792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin char *p; /* points into all kinds of strings */ 1649792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin size_t n; /* handy size_t */ 1659792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin int flags; /* flags as defined above */ 1669792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin char *p0; /* saves original value of p when necessary */ 1679792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin int nassigned; /* number of fields assigned */ 1689792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin int nconversions; /* number of conversions */ 1699792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin int nread; /* number of characters consumed from fp */ 1709792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin int base; /* base argument to conversion function */ 1719792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin char ccltab[256]; /* character class table for %[...] */ 1729792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin char buf[BUF]; /* buffer for numeric and mb conversions */ 1739792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin wchar_t *wcp; /* handy wide character pointer */ 1749792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin size_t nconv; /* length of multibyte sequence converted */ 1759792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin static const mbstate_t initial = { 0 }; 1769792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin mbstate_t mbs; 1772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* `basefix' is used to avoid `if' tests in the integer scanner */ 1792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm static const short basefix[17] = 1802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 1812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm _DIAGASSERT(fp != NULL); 1832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm _DIAGASSERT(fmt0 != NULL); 18453e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm if(fp == NULL) { 18553e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm errno = EINVAL; 18653e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm return (EOF); 18753e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm } 1882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm _SET_ORIENTATION(fp, -1); 1902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 1912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a( %d, \"%a\", ...)\n", __func__, fp->_file, fmt0); 1922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned = 0; 1932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconversions = 0; 1942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread = 0; 1952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 0; 1962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm for (;;) { 1972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = (unsigned char)*fmt++; 1982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == 0) 1992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (nassigned); 2002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (isspace(c)) { 2012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while ((fp->_r > 0 || __srefill(fp) == 0) && 2022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm isspace(*fp->_p)) 2032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread++, fp->_r--, fp->_p++; 2042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm continue; 2052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 2062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 2072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c != '%') 2082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto literal; 2092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = 0; 2102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags = 0; 2112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 2122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * switch on the format. continue if done; 2132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * break once format type is derived. 2142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 2152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmagain: c = *fmt++; 2162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 2172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm switch (c) { 2182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '%': 2192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmliteral: 2202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 2212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) 2222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 2232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (*fp->_p != c) 2242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto match_failure; 2252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_r--, fp->_p++; 2262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread++; 2272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm continue; 2282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 2292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '*': 2302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= SUPPRESS; 2312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'j': 2332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= INTMAXT; 2342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'l': 2362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & LONG) { 2372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~LONG; 2382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= LONGLONG; 2392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else 2402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= LONG; 2412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'q': 2432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= LONGLONG; /* not quite */ 2442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 't': 2462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= PTRDIFFT; 2472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'z': 2492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= SIZET; 2502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'L': 2522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= LONGDBL; 2532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'h': 2552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & SHORT) { 2562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~SHORT; 2572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= SHORTSHORT; 2582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else 2592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= SHORT; 2602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 2622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '0': case '1': case '2': case '3': case '4': 2632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '5': case '6': case '7': case '8': case '9': 2642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = width * 10 + c - '0'; 2652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto again; 2662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 2672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 2682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Conversions. 2692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 2702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'd': 2712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_INT; 2722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 10; 2732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 2742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 2752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'i': 2762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_INT; 2772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 0; 2782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 2792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 2802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'o': 2812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_INT; 2822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= UNSIGNED; 2832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 8; 2842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 2852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 2862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'u': 2872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_INT; 2882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= UNSIGNED; 2892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 10; 2902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 2912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 2922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'X': 2932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'x': 2942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= PFXOK; /* enable 0x prefixing */ 2952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_INT; 2962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= UNSIGNED; 2972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 16; 2982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 2992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef NO_FLOATING_POINT 3012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'A': case 'E': case 'F': case 'G': 3022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'a': case 'e': case 'f': case 'g': 3032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_FLOAT; 3042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 3052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif 3062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'S': 3082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= LONG; 3092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* FALLTHROUGH */ 3102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 's': 3112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_STRING; 3122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 3132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '[': 3152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fmt = __sccl(ccltab, fmt); 3162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= NOSKIP; 3172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_CCL; 3182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 3192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'C': 3212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= LONG; 3222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* FALLTHROUGH */ 3232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'c': 3242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= NOSKIP; 3252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_CHAR; 3262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 3272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'p': /* pointer format is like hex */ 3292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= POINTER | PFXOK; 3302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = CT_INT; /* assumes sizeof(uintmax_t) */ 3312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= UNSIGNED; /* >= sizeof(uintptr_t) */ 3322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 16; 3332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 3342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'n': 3362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconversions++; 3372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & SUPPRESS) /* ??? */ 3382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm continue; 3392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & SHORTSHORT) 3402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, char *) = (char)nread; 3412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & SHORT) 3422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, short *) = (short)nread; 3432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & LONG) 3442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, long *) = nread; 3452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & LONGLONG) 3462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, long long *) = nread; 3472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & INTMAXT) 3482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, intmax_t *) = nread; 3492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & SIZET) 3502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, size_t *) = nread; 3512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & PTRDIFFT) 3522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, ptrdiff_t *) = nread; 3532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 3542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, int *) = nread; 3552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm continue; 3562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm default: 3582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto match_failure; 3592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 3612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Disgusting backwards compatibility hack. XXX 3622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 3632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '\0': /* compat */ 3642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (EOF); 3652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 3662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 3672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 3692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * We have a conversion that requires input. 3702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 3712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) 3722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm { 3732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 3742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 3752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 3762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 3782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Consume leading white space, except for formats 3792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * that suppress this. 3802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 3812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((flags & NOSKIP) == 0) { 3822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (isspace(*fp->_p)) { 3832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread++; 3842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--fp->_r > 0) 3852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p++; 3862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (__srefill(fp)) 3872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm { 3882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 3892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 3902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 3912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 3922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 3932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Note that there is at least one character in 3942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * the buffer, so conversions that do not set NOSKIP 3952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * ca no longer result in an input failure. 3962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 3972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 3982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 3992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 4002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Do the conversion. 4012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 4022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 4032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm switch (c) { 4042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 4052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case CT_CHAR: 4062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* scan arbitrary characters (sets NOSKIP) */ 4072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (width == 0) 4082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = 1; 4092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & LONG) { 4102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((flags & SUPPRESS) == 0) 4112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp = va_arg(ap, wchar_t *); 4122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 4132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp = NULL; 4142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 4152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (width != 0) { 4162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == MB_CUR_MAX) { 4172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 4182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 4192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm buf[n++] = *fp->_p; 4212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p++; 4222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_r--; 4232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm mbs = initial; 4242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconv = mbrtowc(wcp, buf, n, &mbs); 4252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv == (size_t)-1) { 4262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 4272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 4282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv == 0 && !(flags & SUPPRESS)) 4302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *wcp = L'\0'; 4312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv != (size_t)-2) { 4322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)n; 4332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width--; 4342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (!(flags & SUPPRESS)) 4352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp++; 4362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 4372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) { 4392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n != 0) { 4402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 4412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 4422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 4442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (!(flags & SUPPRESS)) 4472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 4482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else if (flags & SUPPRESS) { 4492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm size_t sum = 0; 4502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm for (;;) { 4512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((n = fp->_r) < width) { 4522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm sum += n; 4532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width -= n; 4542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p += n; 4552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (__srefill(fp)) { 4562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (sum == 0) 4572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 4582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 4592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else { 4612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm sum += width; 4622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_r -= (int)width; 4632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p += width; 4642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 4652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)sum; 4682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else { 4692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm size_t r = fread(va_arg(ap, char *), 1, 4702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width, fp); 4712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 4722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (r == 0) 4732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 4742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)r; 4752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 4762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 4772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconversions++; 4782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 4792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 4802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case CT_CCL: 4812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* scan a (nonempty) character class (sets NOSKIP) */ 4822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (width == 0) 4832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = (size_t)~0; /* `infinity' */ 4842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* take only those things in the class */ 4852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & LONG) { 4862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wchar_t twc; 4872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm int nchars; 4882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 4892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((flags & SUPPRESS) == 0) 4902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp = va_arg(ap, wchar_t *); 4912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 4922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp = &twc; 4932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 4942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nchars = 0; 4952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (width != 0) { 4962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == MB_CUR_MAX) { 4972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 4982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 4992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm buf[n++] = *fp->_p; 5012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p++; 5022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_r--; 5032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm mbs = initial; 5042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconv = mbrtowc(wcp, buf, n, &mbs); 5052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv == (size_t)-1) { 5062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 5072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 5082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv == 0) 5102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *wcp = L'\0'; 5112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv != (size_t)-2) { 5122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (wctob(*wcp) != EOF && 5132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm !ccltab[wctob(*wcp)]) { 5142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (n != 0) { 5152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n--; 5162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm (void)ungetc(buf[n], 5172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp); 5182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 5202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)n; 5222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width--; 5232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (!(flags & SUPPRESS)) 5242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp++; 5252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nchars++; 5262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 5272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) { 5292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n != 0) { 5302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 5312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 5322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 5342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n != 0) { 5372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 5382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 5392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = nchars; 5412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == 0) 5422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto match_failure; 5432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (!(flags & SUPPRESS)) { 5442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *wcp = L'\0'; 5452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 5462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else if (flags & SUPPRESS) { 5482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 5492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (ccltab[*fp->_p]) { 5502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n++, fp->_r--, fp->_p++; 5512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--width == 0) 5522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 5532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) { 5542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == 0) 5552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 5562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 5572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == 0) 5602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto match_failure; 5612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else { 5622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm p0 = p = va_arg(ap, char *); 5632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (ccltab[*fp->_p]) { 5642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_r--; 5652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *p++ = *fp->_p++; 5662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--width == 0) 5672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 5682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) { 5692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (p == p0) 5702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 5712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 5722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = p - p0; 5752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == 0) 5762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto match_failure; 5772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *p = 0; 5782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 5792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 5802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)n; 5812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconversions++; 5822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 5832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 5842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case CT_STRING: 5852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* like CCL, but zero-length string OK, & no NOSKIP */ 5862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (width == 0) 5872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = (size_t)~0; 5882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & LONG) { 5892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wchar_t twc; 5902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 5912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((flags & SUPPRESS) == 0) 5922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp = va_arg(ap, wchar_t *); 5932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 5942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp = &twc; 5952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 5962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (!isspace(*fp->_p) && width != 0) { 5972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == MB_CUR_MAX) { 5982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 5992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 6002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm buf[n++] = *fp->_p; 6022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p++; 6032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_r--; 6042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm mbs = initial; 6052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconv = mbrtowc(wcp, buf, n, &mbs); 6062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv == (size_t)-1) { 6072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 6082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 6092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv == 0) 6112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *wcp = L'\0'; 6122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (nconv != (size_t)-2) { 6132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (iswspace(*wcp)) { 6142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (n != 0) { 6152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n--; 6162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm (void)ungetc(buf[n], 6172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp); 6182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 6202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)n; 6222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width--; 6232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (!(flags & SUPPRESS)) 6242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm wcp++; 6252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 6262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) { 6282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n != 0) { 6292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_flags |= __SERR; 6302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto input_failure; 6312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 6332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (!(flags & SUPPRESS)) { 6362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *wcp = L'\0'; 6372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 6382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else if (flags & SUPPRESS) { 6402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = 0; 6412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (!isspace(*fp->_p)) { 6422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n++, fp->_r--, fp->_p++; 6432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--width == 0) 6442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 6452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) 6462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 6472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)n; 6492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else { 6502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm p0 = p = va_arg(ap, char *); 6512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (!isspace(*fp->_p)) { 6522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_r--; 6532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *p++ = *fp->_p++; 6542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--width == 0) 6552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 6562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (fp->_r <= 0 && __srefill(fp)) 6572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 6582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *p = 0; 6602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)(p - p0); 6612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 6622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 6632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconversions++; 6642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm continue; 6652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 6662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case CT_INT: 6672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 6682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* scan an integer as if by the conversion function */ 6692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifdef hardway 6702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (width == 0 || width > sizeof(buf) - 1) 6712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = sizeof(buf) - 1; 6722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#else 6732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* size_t is unsigned, hence this optimisation */ 6742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--width > sizeof(buf) - 2) 6752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = sizeof(buf) - 2; 6762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width++; 6772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif 6782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= SIGNOK | NDIGITS | NZDIGITS; 6792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm for (p = buf; width; width--) { 6802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = *fp->_p; 6812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 6822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Switch on the character; `goto ok' 6832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * if we accept it as a part of number. 6842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 6852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm switch (c) { 6862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 6872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 6882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * The digit 0 is always legal, but is 6892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * special. For %i conversions, if no 6902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * digits (zero or nonzero) have been 6912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * scanned (only signs), we will have 6922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * base==0. In that case, we should set 6932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * it to 8 and enable 0x prefixing. 6942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Also, if we have not scanned zero digits 6952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * before this, do not turn off prefixing 6962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * (someone else will turn it off if we 6972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * have scanned any nonzero digits). 6982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 6992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '0': 7002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (base == 0) { 7012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 8; 7022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= PFXOK; 7032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 7042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & NZDIGITS) 7052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~(SIGNOK|NZDIGITS|NDIGITS); 7062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 7072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~(SIGNOK|PFXOK|NDIGITS); 7082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto ok; 7092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 7102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 1 through 7 always legal */ 7112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '1': case '2': case '3': 7122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '4': case '5': case '6': case '7': 7132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = basefix[base]; 7142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~(SIGNOK | PFXOK | NDIGITS); 7152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto ok; 7162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 7172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* digits 8 and 9 ok iff decimal or hex */ 7182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '8': case '9': 7192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = basefix[base]; 7202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (base <= 8) 7212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; /* not legal here */ 7222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~(SIGNOK | PFXOK | NDIGITS); 7232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto ok; 7242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 7252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* letters ok iff hex */ 7262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'A': case 'B': case 'C': 7272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'D': case 'E': case 'F': 7282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'a': case 'b': case 'c': 7292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'd': case 'e': case 'f': 7302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* no need to fix base here */ 7312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (base <= 10) 7322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; /* not legal here */ 7332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~(SIGNOK | PFXOK | NDIGITS); 7342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto ok; 7352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 7362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* sign ok only as first character */ 7372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '+': case '-': 7382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & SIGNOK) { 7392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~SIGNOK; 7402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags |= HAVESIGN; 7412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto ok; 7422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 7432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 7442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 7452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 7462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * x ok iff flag still set & 2nd char (or 7472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * 3rd char if we have a sign). 7482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 7492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'x': case 'X': 7502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & PFXOK && p == 7512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm buf + 1 + !!(flags & HAVESIGN)) { 7522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm base = 16; /* if %i */ 7532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm flags &= ~PFXOK; 7542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto ok; 7552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 7562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 7572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 7582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 7592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 7602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * If we got here, c is not a legal character 7612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * for a number. Stop accumulating digits. 7622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 7632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 7642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm ok: 7652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 7662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * c is legal: store it and look at the next. 7672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 7682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *p++ = (char)c; 7692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--fp->_r > 0) 7702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p++; 7712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (__srefill(fp)) 7722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; /* EOF */ 7732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 7742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 7752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * If we had only a sign, it is no good; push 7762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * back the sign. If the number ends in `x', 7772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * it was [sign] '0' 'x', so push back the x 7782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * and treat it as [sign] '0'. 7792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 7802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & NDIGITS) { 7812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (p > buf) 7822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm (void)ungetc(*(u_char *)--p, fp); 7832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto match_failure; 7842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 7852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = ((u_char *)p)[-1]; 7862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == 'x' || c == 'X') { 7872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm --p; 7882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm (void)ungetc(c, fp); 7892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 7902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((flags & SUPPRESS) == 0) { 7912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm //uintmax_t res; 7922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm // Use a union to get around the truncation warnings. 7932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm union { 7942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm uintmax_t umax; 7952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm intmax_t imax; 7962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm void *vp; 7972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm ptrdiff_t pdt; 7982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm size_t sz; 7992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm long long ll; 8002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm long lo; 8012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm int in; 8022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm short hw; 8032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm char ch; 8042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } res; 8052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 8062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *p = 0; 8072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((flags & UNSIGNED) == 0) 8082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm res.imax = strtoimax(buf, (char **)NULL, base); 8092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 8102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm res.umax = strtoumax(buf, (char **)NULL, base); 8112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & POINTER) 8122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, void **) = res.vp; 8132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm //(void *)((uintptr_t)res); 8142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & SHORTSHORT) 8152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, char *) = res.ch; 8162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & SHORT) 8172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, short *) = res.hw; 8182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & LONG) 8192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, long *) = res.lo; 8202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & LONGLONG) 8212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, long long *) = res.ll; 8222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & INTMAXT) 8232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, intmax_t *) = res.imax; 8242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & PTRDIFFT) 8252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, ptrdiff_t *) = res.pdt; 8262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm //(ptrdiff_t)res; 8272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (flags & SIZET) 8282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, size_t *) = res.sz; 8292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 8302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, int *) = res.in; 8312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 8322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 8332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)(p - buf); 8342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconversions++; 8352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 8362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 8372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 8382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef NO_FLOATING_POINT 8392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case CT_FLOAT: 8402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* scan a floating point number as if by strtod */ 8412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (width == 0 || width > sizeof(buf) - 1) 8422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm width = sizeof(buf) - 1; 8432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((width = parsefloat(fp, buf, buf + width)) == 0) 8442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto match_failure; 8452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((flags & SUPPRESS) == 0) { 8462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (flags & LONGDBL) { 8472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm long double res = strtold(buf, &p); 8489792ff7c5d0d35b5fff06453a623dce80a2754e8Olivier Martin *va_arg(ap, long double *) = res; 8492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else if (flags & LONG) { 8502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm double res = strtod(buf, &p); 8512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, double *) = res; 8522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else { 8532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm float res = strtof(buf, &p); 8542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *va_arg(ap, float *) = res; 8552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 8562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (__scanfdebug && p - buf != (ptrdiff_t)width) 8572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm abort(); 8582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nassigned++; 8592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 8602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nread += (int)width; 8612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm nconversions++; 8622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 8632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif /* !NO_FLOATING_POINT */ 8642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 8652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 8662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylminput_failure: 8672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm//Print(L"%a: %d\n", __func__, __LINE__); 8682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (nconversions != 0 ? nassigned : EOF); 8692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmmatch_failure: 8702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (nassigned); 8712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm} 8722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 8732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm/* 8742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Fill in the given table from the scanset at the given format 8752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * (just after `['). Return a pointer to the character past the 8762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * closing `]'. The table has a 1 wherever characters should be 8772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * considered part of the scanset. 8782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 8792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic const u_char * 8802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm__sccl(char *tab, const u_char *fmt) 8812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{ 8822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm int c, n, v, i; 8832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 8842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm _DIAGASSERT(tab != NULL); 8852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm _DIAGASSERT(fmt != NULL); 8862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* first `clear' the whole table */ 8872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = *fmt++; /* first char hat => negated scanset */ 8882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == '^') { 8892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm v = 1; /* default => accept */ 8902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = *fmt++; /* get new first char */ 8912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else 8922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm v = 0; /* default => reject */ 8932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 8942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* XXX: Will not work if sizeof(tab*) > sizeof(char) */ 8952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm (void)memset(tab, v, 256); 8962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 8972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == 0) 8982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (fmt - 1);/* format ended before closing ] */ 8992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 9002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 9012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Now set the entries corresponding to the actual scanset 9022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * to the opposite of the above. 9032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * 9042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * The first character may be ']' (or '-') without being special; 9052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * the last character may be '-'. 9062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 9072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm v = 1 - v; 9082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm for (;;) { 9092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm tab[c] = (char)v; /* take character c */ 9102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmdoswitch: 9112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = *fmt++; /* and examine the next */ 9122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm switch (n) { 9132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 9142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 0: /* format ended too soon */ 9152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (fmt - 1); 9162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 9172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '-': 9182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 9192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * A scanset of the form 9202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * [01+-] 9212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * is defined as `the digit 0, the digit 1, 9222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * the character +, the character -', but 9232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * the effect of a scanset such as 9242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * [a-zA-Z0-9] 9252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * is implementation defined. The V7 Unix 9262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * scanf treats `a-z' as `the letters a through 9272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * z', but treats `a-a' as `the letter a, the 9282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * character -, and the letter a'. 9292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * 9302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * For compatibility, the `-' is not considerd 9312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * to define a range if the character following 9322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * it is either a close bracket (required by ANSI) 9332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * or is not numerically greater than the character 9342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * we just stored in the table (c). 9352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 9362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm n = *fmt; 9372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (n == ']' || (__collate_load_error ? n < c : 9382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm __collate_range_cmp(n, c) < 0)) { 9392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = '-'; 9402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; /* resume the for(;;) */ 9412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 9422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fmt++; 9432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* fill in the range */ 9442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (__collate_load_error) { 9452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm do 9462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm tab[++c] = (char)v; 9472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (c < n); 9482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else { 9492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm for (i = 0; i < 256; i ++) 9502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (__collate_range_cmp(c, i) < 0 && 9512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm __collate_range_cmp(i, n) <= 0) 9522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm tab[i] = (char)v; 9532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 9542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#if 1 /* XXX another disgusting compatibility hack */ 9552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = n; 9562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 9572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * Alas, the V7 Unix scanf also treats formats 9582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * such as [a-c-e] as `the letters a through e'. 9592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * This too is permitted by the standard.... 9602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 9612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto doswitch; 9622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#else 9632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = *fmt++; 9642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == 0) 9652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (fmt - 1); 9662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == ']') 9672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (fmt); 9682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif 9692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 9702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case ']': /* end of scanset */ 9712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (fmt); 9722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 9732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm default: /* just another character */ 9742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = n; 9752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 9762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 9772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 9782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* NOTREACHED */ 9792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm} 9802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 9812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#ifndef NO_FLOATING_POINT 9822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmstatic int 9832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmparsefloat(FILE *fp, char *buf, char *end) 9842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm{ 9852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm char *commit, *p; 9862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm int infnanpos = 0; 9872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm enum { 9882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX, 9892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS 9902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } state = S_START; 9912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm unsigned char c; 9922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm char decpt = *localeconv()->decimal_point; 9932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm _Bool gotmantdig = 0, ishex = 0; 9942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 99553e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm if(fp == NULL) { 99653e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm errno = EINVAL; 99753e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm return (EOF); 99853e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm } 99953e1e5c647b73e45569ed6e8b8a0a5b276aa685edarylm 10002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm /* 10012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * We set commit = p whenever the string we have read so far 10022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * constitutes a valid representation of a floating point 10032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * number by itself. At some point, the parse will complete 10042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * or fail, and we will ungetc() back to the last commit point. 10052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * To ensure that the file offset gets updated properly, it is 10062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * always necessary to read at least one character that doesn't 10072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm * match; thus, we can't short-circuit "infinity" or "nan(...)". 10082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm */ 10092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = buf - 1; 10102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm for (p = buf; p < end; ) { 10112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c = *fp->_p; 10122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmreswitch: 10132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm switch (state) { 10142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_START: 10152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_GOTSIGN; 10162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == '-' || c == '+') 10172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 10192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto reswitch; 10202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_GOTSIGN: 10212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm switch (c) { 10222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case '0': 10232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_MAYBEHEX; 10242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = p; 10252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'I': 10272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'i': 10282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_INF; 10292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'N': 10312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 'n': 10322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_NAN; 10332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm default: 10352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_DIGITS; 10362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto reswitch; 10372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 10382aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10392aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_INF: 10402aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (infnanpos > 6 || 10412aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm (c != "nfinity"[infnanpos] && 10422aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm c != "NFINITY"[infnanpos])) 10432aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 10442aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (infnanpos == 1 || infnanpos == 6) 10452aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = p; /* inf or infinity */ 10462aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm infnanpos++; 10472aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10482aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_NAN: 10492aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm switch (infnanpos) { 10502aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case -1: /* XXX kludge to deal with nan(...) */ 10512aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 10522aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 0: 10532aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c != 'A' && c != 'a') 10542aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 10552aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10562aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 1: 10572aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c != 'N' && c != 'n') 10582aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 10592aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 10602aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = p; 10612aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10622aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case 2: 10632aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c != '(') 10642aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 10652aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10662aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm default: 10672aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == ')') { 10682aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = p; 10692aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm infnanpos = -2; 10702aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else if (!isalnum(c) && c != '_') 10712aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 10722aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10732aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 10742aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm infnanpos++; 10752aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10762aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_MAYBEHEX: 10772aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_DIGITS; 10782aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == 'X' || c == 'x') { 10792aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm ishex = 1; 10802aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10812aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else { /* we saw a '0', but no 'x' */ 10822aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm gotmantdig = 1; 10832aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto reswitch; 10842aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 10852aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_DIGITS: 10862aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if ((ishex && isxdigit(c)) || isdigit(c)) 10872aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm gotmantdig = 1; 10882aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else { 10892aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_FRAC; 10902aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c != decpt) 10912aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto reswitch; 10922aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 10932aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (gotmantdig) 10942aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = p; 10952aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 10962aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_FRAC: 10972aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (((c == 'E' || c == 'e') && !ishex) || 10982aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm ((c == 'P' || c == 'p') && ishex)) { 10992aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (!gotmantdig) 11002aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 11012aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 11022aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_EXP; 11032aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else if ((ishex && isxdigit(c)) || isdigit(c)) { 11042aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = p; 11052aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm gotmantdig = 1; 11062aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } else 11072aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 11082aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 11092aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_EXP: 11102aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm state = S_EXPDIGITS; 11112aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (c == '-' || c == '+') 11122aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 11132aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 11142aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto reswitch; 11152aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm case S_EXPDIGITS: 11162aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (isdigit(c)) 11172aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm commit = p; 11182aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else 11192aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm goto parsedone; 11202aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; 11212aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm default: 11222aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm abort(); 11232aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 11242aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *p++ = c; 11252aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm if (--fp->_r > 0) 11262aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm fp->_p++; 11272aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm else if (__srefill(fp)) 11282aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm break; /* EOF */ 11292aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm } 11302aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm 11312aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylmparsedone: 11322aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm while (commit < --p) 11332aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm (void)ungetc(*(u_char *)p, fp); 11342aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm *++commit = '\0'; 11352aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm return (int)(commit - buf); 11362aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm} 11372aa62f2bc9a9654687b377d9ca8a8c2c860a3852darylm#endif 1138