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