1/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8
9   The GNU C Library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with the GNU C Library; if not, write to the Free
16   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17   02111-1307 USA.  */
18
19#include <assert.h>
20#include <errno.h>
21#include <limits.h>
22#include <ctype.h>
23#include <stdarg.h>
24#include <stdio.h>
25#include <stdint.h>
26#include <stdlib.h>
27#include <string.h>
28#include <wchar.h>
29#include <wctype.h>
30#include <bits/libc-lock.h>
31#include <locale/localeinfo.h>
32
33#ifdef	__GNUC__
34# define HAVE_LONGLONG
35# define LONGLONG	long long
36#else
37# define LONGLONG	long
38#endif
39
40/* Determine whether we have to handle `long long' at all.  */
41#if LONG_MAX == LONG_LONG_MAX
42# define need_longlong	0
43#else
44# define need_longlong	1
45#endif
46
47/* Determine whether we have to handle `long'.  */
48#if INT_MAX == LONG_MAX
49# define need_long	0
50#else
51# define need_long 	1
52#endif
53
54/* Those are flags in the conversion format. */
55#define LONG		0x001	/* l: long or double */
56#define LONGDBL		0x002	/* L: long long or long double */
57#define SHORT		0x004	/* h: short */
58#define SUPPRESS	0x008	/* *: suppress assignment */
59#define POINTER		0x010	/* weird %p pointer (`fake hex') */
60#define NOSKIP		0x020	/* do not skip blanks */
61#define WIDTH		0x040	/* width was given */
62#define GROUP		0x080	/* ': group numbers */
63#define MALLOC		0x100	/* a: malloc strings */
64#define CHAR		0x200	/* hh: char */
65#define I18N		0x400	/* I: use locale's digits */
66
67
68#ifdef USE_IN_LIBIO
69# include <libioP.h>
70# include <libio.h>
71
72# undef va_list
73# define va_list	_IO_va_list
74
75# ifdef COMPILE_WSCANF
76#  define ungetc(c, s)	((void) (c == WEOF				      \
77				 || (--read_in,				      \
78				     _IO_sputbackwc (s, c))))
79#  define ungetc_not_eof(c, s)	((void) (--read_in,			      \
80					 _IO_sputbackwc (s, c)))
81#  define inchar()	(c == WEOF ? WEOF				      \
82			 : ((c = _IO_getwc_unlocked (s)),		      \
83			    (void) (c != WEOF && ++read_in), c))
84
85#  define MEMCPY(d, s, n) __wmemcpy (d, s, n)
86#  define ISSPACE(Ch)	  iswspace (Ch)
87#  define ISDIGIT(Ch)	  iswdigit (Ch)
88#  define ISXDIGIT(Ch)	  iswxdigit (Ch)
89#  define TOLOWER(Ch)	  towlower (Ch)
90#  define ORIENT	  if (_IO_fwide (s, 1) != 1) return WEOF
91#  define __strtoll_internal	__wcstoll_internal
92#  define __strtoull_internal	__wcstoull_internal
93#  define __strtol_internal	__wcstol_internal
94#  define __strtoul_internal	__wcstoul_internal
95#  define __strtold_internal	__wcstold_internal
96#  define __strtod_internal	__wcstod_internal
97#  define __strtof_internal	__wcstof_internal
98
99#  define L_(Str)	  L##Str
100#  define CHAR_T	  wchar_t
101#  define UCHAR_T	  unsigned int
102#  define WINT_T	  wint_t
103#  undef EOF
104#  define EOF		  WEOF
105# else
106#  define ungetc(c, s)	((void) ((int) c == EOF				      \
107				 || (--read_in,				      \
108				     _IO_sputbackc (s, (unsigned char) c))))
109#  define ungetc_not_eof(c, s)	((void) (--read_in,			      \
110					 _IO_sputbackc (s, (unsigned char) c)))
111#  define inchar()	(c == EOF ? EOF					      \
112			 : ((c = _IO_getc_unlocked (s)),		      \
113			    (void) (c != EOF && ++read_in), c))
114#  define MEMCPY(d, s, n) memcpy (d, s, n)
115#  define ISSPACE(Ch)	  isspace (Ch)
116#  define ISDIGIT(Ch)	  isdigit (Ch)
117#  define ISXDIGIT(Ch)	  isxdigit (Ch)
118#  define TOLOWER(Ch)	  tolower (Ch)
119#  define ORIENT	  if (s->_vtable_offset == 0			      \
120			      && _IO_fwide (s, -1) != -1)		      \
121			    return EOF
122
123#  define L_(Str)	  Str
124#  define CHAR_T	  char
125#  define UCHAR_T	  unsigned char
126#  define WINT_T	  int
127# endif
128
129# define encode_error() do {						      \
130			  if (errp != NULL) *errp |= 4;			      \
131			  _IO_funlockfile (s);				      \
132			  __libc_cleanup_end (0);			      \
133			  __set_errno (EILSEQ);				      \
134			  return done;					      \
135			} while (0)
136# define conv_error()	do {						      \
137			  if (errp != NULL) *errp |= 2;			      \
138			  _IO_funlockfile (s);				      \
139			  __libc_cleanup_end (0);			      \
140			  return done;					      \
141			} while (0)
142# define input_error()	do {						      \
143			  _IO_funlockfile (s);				      \
144			  if (errp != NULL) *errp |= 1;			      \
145			  __libc_cleanup_end (0);			      \
146			  return done ?: EOF;				      \
147			} while (0)
148# define memory_error() do {						      \
149			  _IO_funlockfile (s);				      \
150			  __set_errno (ENOMEM);				      \
151			  __libc_cleanup_end (0);			      \
152			  return EOF;					      \
153			} while (0)
154# define ARGCHECK(s, format)						      \
155  do									      \
156    {									      \
157      /* Check file argument for consistence.  */			      \
158      CHECK_FILE (s, EOF);						      \
159      if (s->_flags & _IO_NO_READS)					      \
160	{								      \
161	  __set_errno (EBADF);						      \
162	  return EOF;							      \
163	}								      \
164      else if (format == NULL)						      \
165	{								      \
166	  MAYBE_SET_EINVAL;						      \
167	  return EOF;							      \
168	}								      \
169    } while (0)
170# define LOCK_STREAM(S)							      \
171  __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, (S)); \
172  _IO_flockfile (S)
173# define UNLOCK_STREAM(S)						      \
174  _IO_funlockfile (S);							      \
175  __libc_cleanup_region_end (0)
176#else
177# define ungetc(c, s)	((void) (c != EOF && --read_in), ungetc (c, s))
178# define ungetc_not_eof(c, s)	(--read_in, (ungetc) (c, s))
179# define inchar()	(c == EOF ? EOF					      \
180			 : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
181# define MEMCPY(d, s, n)  memcpy (d, s, n)
182# define ISSPACE(Ch)      isspace (Ch)
183# define ISDIGIT(Ch)      isdigit (Ch)
184# define ISXDIGIT(Ch)     isxdigit (Ch)
185# define TOLOWER(Ch)      tolower (Ch)
186
187# define L_(Str)          Str
188# define CHAR_T           char
189# define UCHAR_T          unsigned char
190# define WINT_T           int
191
192# define encode_error()	do {						      \
193			  funlockfile (s);				      \
194			  __set_errno (EILSEQ);				      \
195			  return done;					      \
196			} while (0)
197# define conv_error()	do {						      \
198			  funlockfile (s);				      \
199			  return done;					      \
200			} while (0)
201# define input_error()	do {						      \
202			  funlockfile (s);				      \
203			  return done ?: EOF;				      \
204			} while (0)
205# define memory_error()	do {						      \
206			  funlockfile (s);				      \
207			  __set_errno (ENOMEM);				      \
208			  return EOF;					      \
209			} while (0)
210# define ARGCHECK(s, format)						      \
211  do									      \
212    {									      \
213      /* Check file argument for consistence.  */			      \
214      if (!__validfp (s) || !s->__mode.__read)				      \
215	{								      \
216	  __set_errno (EBADF);						      \
217	  return EOF;							      \
218	}								      \
219      else if (format == NULL)						      \
220	{								      \
221	  __set_errno (EINVAL);						      \
222	  return EOF;							      \
223	}								      \
224    } while (0)
225#if 1
226      /* XXX For now !!! */
227# define flockfile(S) /* nothing */
228# define funlockfile(S) /* nothing */
229# define LOCK_STREAM(S)
230# define UNLOCK_STREAM(S)
231#else
232# define LOCK_STREAM(S)							      \
233  __libc_cleanup_region_start (&__funlockfile, (S));			      \
234  __flockfile (S)
235# define UNLOCK_STREAM(S)						      \
236  __funlockfile (S);							      \
237  __libc_cleanup_region_end (0)
238#endif
239#endif
240
241
242/* Read formatted input from S according to the format string
243   FORMAT, using the argument list in ARG.
244   Return the number of assignments made, or -1 for an input error.  */
245#ifdef USE_IN_LIBIO
246# ifdef COMPILE_WSCANF
247int
248_IO_vfwscanf (s, format, argptr, errp)
249     _IO_FILE *s;
250     const wchar_t *format;
251     _IO_va_list argptr;
252     int *errp;
253# else
254int
255_IO_vfscanf (s, format, argptr, errp)
256     _IO_FILE *s;
257     const char *format;
258     _IO_va_list argptr;
259     int *errp;
260# endif
261#else
262int
263__vfscanf (FILE *s, const char *format, va_list argptr)
264#endif
265{
266  va_list arg;
267  register const CHAR_T *f = format;
268  register UCHAR_T fc;	/* Current character of the format.  */
269  register WINT_T done = 0;	/* Assignments done.  */
270  register size_t read_in = 0;	/* Chars read in.  */
271  register WINT_T c = 0;	/* Last char read.  */
272  register int width;		/* Maximum field width.  */
273  register int flags;		/* Modifiers for current format element.  */
274
275  /* Status for reading F-P nums.  */
276  char got_dot, got_e, negative;
277  /* If a [...] is a [^...].  */
278  CHAR_T not_in;
279#define exp_char not_in
280  /* Base for integral numbers.  */
281  int base;
282  /* Signedness for integral numbers.  */
283  int number_signed;
284#define is_hexa number_signed
285  /* Decimal point character.  */
286#ifdef COMPILE_WSCANF
287  wchar_t decimal;
288#else
289  const char *decimal;
290#endif
291  /* The thousands character of the current locale.  */
292#ifdef COMPILE_WSCANF
293  wchar_t thousands;
294#else
295  const char *thousands;
296#endif
297  /* State for the conversions.  */
298  mbstate_t state;
299  /* Integral holding variables.  */
300  union
301    {
302      long long int q;
303      unsigned long long int uq;
304      long int l;
305      unsigned long int ul;
306    } num;
307  /* Character-buffer pointer.  */
308  char *str = NULL;
309  wchar_t *wstr = NULL;
310  char **strptr = NULL;
311  ssize_t strsize = 0;
312  /* We must not react on white spaces immediately because they can
313     possibly be matched even if in the input stream no character is
314     available anymore.  */
315  int skip_space = 0;
316  /* Nonzero if we are reading a pointer.  */
317  int read_pointer;
318  /* Workspace.  */
319  CHAR_T *tw;			/* Temporary pointer.  */
320  CHAR_T *wp = NULL;		/* Workspace.  */
321  size_t wpmax = 0;		/* Maximal size of workspace.  */
322  size_t wpsize;		/* Currently used bytes in workspace.  */
323#define ADDW(Ch)							    \
324  do									    \
325    {									    \
326      if (wpsize == wpmax)						    \
327	{								    \
328	  CHAR_T *old = wp;						    \
329	  wpmax = (UCHAR_MAX + 1 > 2 * wpmax ? UCHAR_MAX + 1 : 2 * wpmax);  \
330	  wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t));		    \
331	  if (old != NULL)						    \
332	    MEMCPY (wp, old, wpsize);					    \
333	}								    \
334      wp[wpsize++] = (Ch);						    \
335    }									    \
336  while (0)
337
338#ifdef __va_copy
339  __va_copy (arg, argptr);
340#else
341  arg = (va_list) argptr;
342#endif
343
344#ifdef ORIENT
345  ORIENT;
346#endif
347
348  ARGCHECK (s, format);
349
350  /* Figure out the decimal point character.  */
351#ifdef COMPILE_WSCANF
352  decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
353#else
354  decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
355#endif
356  /* Figure out the thousands separator character.  */
357#ifdef COMPILE_WSCANF
358  thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
359#else
360  thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
361  if (*thousands == '\0')
362    thousands = NULL;
363#endif
364
365  /* Lock the stream.  */
366  LOCK_STREAM (s);
367
368
369#ifndef COMPILE_WSCANF
370  /* From now on we use `state' to convert the format string.  */
371  memset (&state, '\0', sizeof (state));
372#endif
373
374  /* Run through the format string.  */
375  while (*f != '\0')
376    {
377      unsigned int argpos;
378      /* Extract the next argument, which is of type TYPE.
379	 For a %N$... spec, this is the Nth argument from the beginning;
380	 otherwise it is the next argument after the state now in ARG.  */
381#ifdef __va_copy
382# define ARG(type)	(argpos == 0 ? va_arg (arg, type) :		      \
383			 ({ unsigned int pos = argpos;			      \
384			    va_list arg;				      \
385			    __va_copy (arg, argptr);			      \
386			    while (--pos > 0)				      \
387			      (void) va_arg (arg, void *);		      \
388			    va_arg (arg, type);				      \
389			  }))
390#else
391# if 0
392      /* XXX Possible optimization.  */
393#  define ARG(type)	(argpos == 0 ? va_arg (arg, type) :		      \
394			 ({ va_list arg = (va_list) argptr;		      \
395			    arg = (va_list) ((char *) arg		      \
396					     + (argpos - 1)		      \
397					     * __va_rounded_size (void *));   \
398			    va_arg (arg, type);				      \
399			 }))
400# else
401#  define ARG(type)	(argpos == 0 ? va_arg (arg, type) :		      \
402			 ({ unsigned int pos = argpos;			      \
403			    va_list arg = (va_list) argptr;		      \
404			    while (--pos > 0)				      \
405			      (void) va_arg (arg, void *);		      \
406			    va_arg (arg, type);				      \
407			  }))
408# endif
409#endif
410
411#ifndef COMPILE_WSCANF
412      if (!isascii ((unsigned char) *f))
413	{
414	  /* Non-ASCII, may be a multibyte.  */
415	  int len = __mbrlen (f, strlen (f), &state);
416	  if (len > 0)
417	    {
418	      do
419		{
420		  c = inchar ();
421		  if (c == EOF)
422		    input_error ();
423		  else if (c != (unsigned char) *f++)
424		    {
425		      ungetc_not_eof (c, s);
426		      conv_error ();
427		    }
428		}
429	      while (--len > 0);
430	      continue;
431	    }
432	}
433#endif
434
435      fc = *f++;
436      if (fc != '%')
437	{
438	  /* Remember to skip spaces.  */
439	  if (ISSPACE (fc))
440	    {
441	      skip_space = 1;
442	      continue;
443	    }
444
445	  /* Read a character.  */
446	  c = inchar ();
447
448	  /* Characters other than format specs must just match.  */
449	  if (c == EOF)
450	    input_error ();
451
452	  /* We saw white space char as the last character in the format
453	     string.  Now it's time to skip all leading white space.  */
454	  if (skip_space)
455	    {
456	      while (ISSPACE (c))
457		if (inchar () == EOF && errno == EINTR)
458		  conv_error ();
459	      skip_space = 0;
460	    }
461
462	  if (c != fc)
463	    {
464	      ungetc (c, s);
465	      conv_error ();
466	    }
467
468	  continue;
469	}
470
471      /* This is the start of the conversion string. */
472      flags = 0;
473
474      /* Not yet decided whether we read a pointer or not.  */
475      read_pointer = 0;
476
477      /* Initialize state of modifiers.  */
478      argpos = 0;
479
480      /* Prepare temporary buffer.  */
481      wpsize = 0;
482
483      /* Check for a positional parameter specification.  */
484      if (ISDIGIT ((UCHAR_T) *f))
485	{
486	  argpos = (UCHAR_T) *f++ - L_('0');
487	  while (ISDIGIT ((UCHAR_T) *f))
488	    argpos = argpos * 10 + ((UCHAR_T) *f++ - L_('0'));
489	  if (*f == L_('$'))
490	    ++f;
491	  else
492	    {
493	      /* Oops; that was actually the field width.  */
494	      width = argpos;
495	      flags |= WIDTH;
496	      argpos = 0;
497	      goto got_width;
498	    }
499	}
500
501      /* Check for the assignment-suppressing, the number grouping flag,
502	 and the signal to use the locale's digit representation.  */
503      while (*f == L_('*') || *f == L_('\'') || *f == L_('I'))
504	switch (*f++)
505	  {
506	  case L_('*'):
507	    flags |= SUPPRESS;
508	    break;
509	  case L_('\''):
510	    flags |= GROUP;
511	    break;
512	  case L_('I'):
513	    flags |= I18N;
514	    break;
515	  }
516
517      /* We have seen width. */
518      if (ISDIGIT ((UCHAR_T) *f))
519	flags |= WIDTH;
520
521      /* Find the maximum field width.  */
522      width = 0;
523      while (ISDIGIT ((UCHAR_T) *f))
524	{
525	  width *= 10;
526	  width += (UCHAR_T) *f++ - L_('0');
527	}
528    got_width:
529      if (width == 0)
530	width = -1;
531
532      /* Check for type modifiers.  */
533      switch (*f++)
534	{
535	case L_('h'):
536	  /* ints are short ints or chars.  */
537	  if (*f == L_('h'))
538	    {
539	      ++f;
540	      flags |= CHAR;
541	    }
542	  else
543	    flags |= SHORT;
544	  break;
545	case L_('l'):
546	  if (*f == L_('l'))
547	    {
548	      /* A double `l' is equivalent to an `L'.  */
549	      ++f;
550	      flags |= LONGDBL | LONG;
551	    }
552	  else
553	    /* ints are long ints.  */
554	    flags |= LONG;
555	  break;
556	case L_('q'):
557	case L_('L'):
558	  /* doubles are long doubles, and ints are long long ints.  */
559	  flags |= LONGDBL | LONG;
560	  break;
561	case L_('a'):
562	  /* The `a' is used as a flag only if followed by `s', `S' or
563	     `['.  */
564	  if (*f != L_('s') && *f != L_('S') && *f != L_('['))
565	    {
566	      --f;
567	      break;
568	    }
569	  /* String conversions (%s, %[) take a `char **'
570	     arg and fill it in with a malloc'd pointer.  */
571	  flags |= MALLOC;
572	  break;
573	case L_('z'):
574	  if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
575	    flags |= LONGDBL;
576	  else if (sizeof (size_t) > sizeof (unsigned int))
577	    flags |= LONG;
578	  break;
579	case L_('j'):
580	  if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
581	    flags |= LONGDBL;
582	  else if (sizeof (uintmax_t) > sizeof (unsigned int))
583	    flags |= LONG;
584	  break;
585	case L_('t'):
586	  if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
587	    flags |= LONGDBL;
588	  else if (sizeof (ptrdiff_t) > sizeof (int))
589	    flags |= LONG;
590	  break;
591	default:
592	  /* Not a recognized modifier.  Backup.  */
593	  --f;
594	  break;
595	}
596
597      /* End of the format string?  */
598      if (*f == L_('\0'))
599	conv_error ();
600
601      /* Find the conversion specifier.  */
602      fc = *f++;
603      if (skip_space || (fc != L_('[') && fc != L_('c')
604			 && fc != L_('C') && fc != L_('n')))
605	{
606	  /* Eat whitespace.  */
607	  int save_errno = errno;
608	  __set_errno(0);
609	  do
610	    if (inchar () == EOF && errno == EINTR)
611	      input_error ();
612	  while (ISSPACE (c));
613	  __set_errno(save_errno);
614	  ungetc (c, s);
615	  skip_space = 0;
616	}
617
618      switch (fc)
619	{
620	case L_('%'):	/* Must match a literal '%'.  */
621	  c = inchar ();
622	  if (c == EOF)
623	    input_error ();
624	  if (c != fc)
625	    {
626	      ungetc_not_eof (c, s);
627	      conv_error ();
628	    }
629	  break;
630
631	case L_('n'):	/* Answer number of assignments done.  */
632	  /* Corrigendum 1 to ISO C 1990 describes the allowed flags
633	     with the 'n' conversion specifier.  */
634	  if (!(flags & SUPPRESS))
635	    {
636	      /* Don't count the read-ahead.  */
637	      if (need_longlong && (flags & LONGDBL))
638		*ARG (long long int *) = read_in;
639	      else if (need_long && (flags & LONG))
640		*ARG (long int *) = read_in;
641	      else if (flags & SHORT)
642		*ARG (short int *) = read_in;
643	      else if (!(flags & CHAR))
644		*ARG (int *) = read_in;
645	      else
646		*ARG (char *) = read_in;
647
648#ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
649	      /* We have a severe problem here.  The ISO C standard
650		 contradicts itself in explaining the effect of the %n
651		 format in `scanf'.  While in ISO C:1990 and the ISO C
652		 Amendement 1:1995 the result is described as
653
654		   Execution of a %n directive does not effect the
655		   assignment count returned at the completion of
656		   execution of the f(w)scanf function.
657
658		 in ISO C Corrigendum 1:1994 the following was added:
659
660		   Subclause 7.9.6.2
661		   Add the following fourth example:
662		     In:
663		       #include <stdio.h>
664		       int d1, d2, n1, n2, i;
665		       i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
666		     the value 123 is assigned to d1 and the value3 to n1.
667		     Because %n can never get an input failure the value
668		     of 3 is also assigned to n2.  The value of d2 is not
669		     affected.  The value 3 is assigned to i.
670
671		 We go for now with the historically correct code from ISO C,
672		 i.e., we don't count the %n assignments.  When it ever
673		 should proof to be wrong just remove the #ifdef above.  */
674	      ++done;
675#endif
676	    }
677	  break;
678
679	case L_('c'):	/* Match characters.  */
680	  if ((flags & LONG) == 0)
681	    {
682	      if (!(flags & SUPPRESS))
683		{
684		  str = ARG (char *);
685		  if (str == NULL)
686		    conv_error ();
687		}
688
689	      c = inchar ();
690	      if (c == EOF)
691		input_error ();
692
693	      if (width == -1)
694		width = 1;
695
696#ifdef COMPILE_WSCANF
697	      /* We have to convert the wide character(s) into multibyte
698		 characters and store the result.  */
699	      memset (&state, '\0', sizeof (state));
700
701	      do
702		{
703		  size_t n;
704
705		  n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
706		  if (n == (size_t) -1)
707		    /* No valid wide character.  */
708		    input_error ();
709
710		  /* Increment the output pointer.  Even if we don't
711		     write anything.  */
712		  str += n;
713		}
714	      while (--width > 0 && inchar () != EOF);
715#else
716	      if (!(flags & SUPPRESS))
717		{
718		  do
719		    *str++ = c;
720		  while (--width > 0 && inchar () != EOF);
721		}
722	      else
723		while (--width > 0 && inchar () != EOF);
724#endif
725
726	      if (!(flags & SUPPRESS))
727		++done;
728
729	      break;
730	    }
731	  /* FALLTHROUGH */
732	case L_('C'):
733	  if (!(flags & SUPPRESS))
734	    {
735	      wstr = ARG (wchar_t *);
736	      if (wstr == NULL)
737		conv_error ();
738	    }
739
740	  c = inchar ();
741	  if (c == EOF)
742	    input_error ();
743
744#ifdef COMPILE_WSCANF
745	  /* Just store the incoming wide characters.  */
746	  if (!(flags & SUPPRESS))
747	    {
748	      do
749		*wstr++ = c;
750	      while (--width > 0 && inchar () != EOF);
751	    }
752	  else
753	    while (--width > 0 && inchar () != EOF);
754#else
755	  {
756	    /* We have to convert the multibyte input sequence to wide
757	       characters.  */
758	    char buf[1];
759	    mbstate_t cstate;
760
761	    memset (&cstate, '\0', sizeof (cstate));
762
763	    do
764	      {
765		/* This is what we present the mbrtowc function first.  */
766		buf[0] = c;
767
768		while (1)
769		  {
770		    size_t n;
771
772		    n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
773				   buf, 1, &cstate);
774
775		    if (n == (size_t) -2)
776		      {
777			/* Possibly correct character, just not enough
778			   input.  */
779			if (inchar () == EOF)
780			  encode_error ();
781
782			buf[0] = c;
783			continue;
784		      }
785
786		    if (n != 1)
787		      encode_error ();
788
789		    /* We have a match.  */
790		    break;
791		  }
792
793		/* Advance the result pointer.  */
794		++wstr;
795	      }
796	    while (--width > 0 && inchar () != EOF);
797	  }
798#endif
799
800	  if (!(flags & SUPPRESS))
801	    ++done;
802
803	  break;
804
805	case L_('s'):		/* Read a string.  */
806	  if (!(flags & LONG))
807	    {
808#define STRING_ARG(Str, Type)						      \
809	      do if (!(flags & SUPPRESS))				      \
810		{							      \
811		  if (flags & MALLOC)					      \
812		    {							      \
813		      /* The string is to be stored in a malloc'd buffer.  */ \
814		      strptr = ARG (char **);				      \
815		      if (strptr == NULL)				      \
816			conv_error ();					      \
817		      /* Allocate an initial buffer.  */		      \
818		      strsize = 100;					      \
819		      *strptr = (char *) malloc (strsize * sizeof (Type));    \
820		      Str = (Type *) *strptr;				      \
821		    }							      \
822		  else							      \
823		    Str = ARG (Type *);					      \
824		  if (Str == NULL)					      \
825		    conv_error ();					      \
826		} while (0)
827	      STRING_ARG (str, char);
828
829	      c = inchar ();
830	      if (c == EOF)
831		input_error ();
832
833#ifdef COMPILE_WSCANF
834	      memset (&state, '\0', sizeof (state));
835#endif
836
837	      do
838		{
839		  if (ISSPACE (c))
840		    {
841		      ungetc_not_eof (c, s);
842		      break;
843		    }
844
845#ifdef COMPILE_WSCANF
846		  /* This is quite complicated.  We have to convert the
847		     wide characters into multibyte characters and then
848		     store them.  */
849		  {
850		    size_t n;
851
852		    if (!(flags & SUPPRESS) && (flags & MALLOC)
853			&& str + MB_CUR_MAX >= *strptr + strsize)
854		      {
855			/* We have to enlarge the buffer if the `a' flag
856			   was given.  */
857			size_t strleng = str - *strptr;
858			char *newstr;
859
860			newstr = (char *) realloc (*strptr, strsize * 2);
861			if (newstr == NULL)
862			  {
863			    /* Can't allocate that much.  Last-ditch
864			       effort.  */
865			    newstr = (char *) realloc (*strptr,
866						       strleng + MB_CUR_MAX);
867			    if (newstr == NULL)
868			      {
869				/* We lose.  Oh well.  Terminate the
870				   string and stop converting,
871				   so at least we don't skip any input.  */
872				((char *) (*strptr))[strleng] = '\0';
873				++done;
874				conv_error ();
875			      }
876			    else
877			      {
878				*strptr = newstr;
879				str = newstr + strleng;
880				strsize = strleng + MB_CUR_MAX;
881			      }
882			  }
883			else
884			  {
885			    *strptr = newstr;
886			    str = newstr + strleng;
887			    strsize *= 2;
888			  }
889		      }
890
891		    n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c,
892				   &state);
893		    if (n == (size_t) -1)
894		      encode_error ();
895
896		    assert (n <= MB_CUR_MAX);
897		    str += n;
898		  }
899#else
900		  /* This is easy.  */
901		  if (!(flags & SUPPRESS))
902		    {
903		      *str++ = c;
904		      if ((flags & MALLOC)
905			  && (char *) str == *strptr + strsize)
906			{
907			  /* Enlarge the buffer.  */
908			  str = (char *) realloc (*strptr, 2 * strsize);
909			  if (str == NULL)
910			    {
911			      /* Can't allocate that much.  Last-ditch
912				 effort.  */
913			      str = (char *) realloc (*strptr, strsize + 1);
914			      if (str == NULL)
915				{
916				  /* We lose.  Oh well.  Terminate the
917				     string and stop converting,
918				     so at least we don't skip any input.  */
919				  ((char *) (*strptr))[strsize - 1] = '\0';
920				  ++done;
921				  conv_error ();
922				}
923			      else
924				{
925				  *strptr = (char *) str;
926				  str += strsize;
927				  ++strsize;
928				}
929			    }
930			  else
931			    {
932			      *strptr = (char *) str;
933			      str += strsize;
934			      strsize *= 2;
935			    }
936			}
937		    }
938#endif
939		}
940	      while ((width <= 0 || --width > 0) && inchar () != EOF);
941
942	      if (!(flags & SUPPRESS))
943		{
944#ifdef COMPILE_WSCANF
945		  /* We have to emit the code to get into the initial
946		     state.  */
947		  char buf[MB_LEN_MAX];
948		  size_t n = __wcrtomb (buf, L'\0', &state);
949		  if (n > 0 && (flags & MALLOC)
950		      && str + n >= *strptr + strsize)
951		    {
952		      /* Enlarge the buffer.  */
953		      size_t strleng = str - *strptr;
954		      char *newstr;
955
956		      newstr = (char *) realloc (*strptr, strleng + n + 1);
957		      if (newstr == NULL)
958			{
959			  /* We lose.  Oh well.  Terminate the string
960			     and stop converting, so at least we don't
961			     skip any input.  */
962			  ((char *) (*strptr))[strleng] = '\0';
963			  ++done;
964			  conv_error ();
965			}
966		      else
967			{
968			  *strptr = newstr;
969			  str = newstr + strleng;
970			  strsize = strleng + n + 1;
971			}
972		    }
973
974		  str = __mempcpy (str, buf, n);
975#endif
976		  *str++ = '\0';
977
978		  if ((flags & MALLOC) && str - *strptr != strsize)
979		    {
980		      char *cp = (char *) realloc (*strptr, str - *strptr);
981		      if (cp != NULL)
982			*strptr = cp;
983		    }
984
985		  ++done;
986		}
987	      break;
988	    }
989	  /* FALLTHROUGH */
990
991	case L_('S'):
992	  {
993#ifndef COMPILE_WSCANF
994	    mbstate_t cstate;
995#endif
996
997	    /* Wide character string.  */
998	    STRING_ARG (wstr, wchar_t);
999
1000	    c = inchar ();
1001	    if (c == EOF)
1002	      input_error ();
1003
1004#ifndef COMPILE_WSCANF
1005	    memset (&cstate, '\0', sizeof (cstate));
1006#endif
1007
1008	    do
1009	      {
1010		if (ISSPACE (c))
1011		  {
1012		    ungetc_not_eof (c, s);
1013		    break;
1014		  }
1015
1016#ifdef COMPILE_WSCANF
1017		/* This is easy.  */
1018		if (!(flags & SUPPRESS))
1019		  {
1020		    *wstr++ = c;
1021		    if ((flags & MALLOC)
1022			&& wstr == (wchar_t *) *strptr + strsize)
1023		      {
1024			/* Enlarge the buffer.  */
1025			wstr = (wchar_t *) realloc (*strptr,
1026						    (2 * strsize)
1027						    * sizeof (wchar_t));
1028			if (wstr == NULL)
1029			  {
1030			    /* Can't allocate that much.  Last-ditch
1031                               effort.  */
1032			    wstr = (wchar_t *) realloc (*strptr,
1033							(strsize + 1)
1034							* sizeof (wchar_t));
1035			    if (wstr == NULL)
1036			      {
1037				/* We lose.  Oh well.  Terminate the string
1038				   and stop converting, so at least we don't
1039				   skip any input.  */
1040				((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1041				++done;
1042				conv_error ();
1043			      }
1044			    else
1045			      {
1046				*strptr = (char *) wstr;
1047				wstr += strsize;
1048				++strsize;
1049			      }
1050			  }
1051			else
1052			  {
1053			    *strptr = (char *) wstr;
1054			    wstr += strsize;
1055			    strsize *= 2;
1056			  }
1057		      }
1058		  }
1059#else
1060		{
1061		  char buf[1];
1062
1063		  buf[0] = c;
1064
1065		  while (1)
1066		    {
1067		      size_t n;
1068
1069		      n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
1070				     buf, 1, &cstate);
1071
1072		      if (n == (size_t) -2)
1073			{
1074			  /* Possibly correct character, just not enough
1075			     input.  */
1076			  if (inchar () == EOF)
1077			    encode_error ();
1078
1079			  buf[0] = c;
1080			  continue;
1081			}
1082
1083		      if (n != 1)
1084			encode_error ();
1085
1086		      /* We have a match.  */
1087		      ++wstr;
1088		      break;
1089		    }
1090
1091		  if (!(flags & SUPPRESS) && (flags & MALLOC)
1092		      && wstr == (wchar_t *) *strptr + strsize)
1093		    {
1094		      /* Enlarge the buffer.  */
1095		      wstr = (wchar_t *) realloc (*strptr,
1096						  (2 * strsize
1097						   * sizeof (wchar_t)));
1098		      if (wstr == NULL)
1099			{
1100			  /* Can't allocate that much.  Last-ditch effort.  */
1101			  wstr = (wchar_t *) realloc (*strptr,
1102						      ((strsize + 1)
1103						       * sizeof (wchar_t)));
1104			  if (wstr == NULL)
1105			    {
1106			      /* We lose.  Oh well.  Terminate the
1107				 string and stop converting, so at
1108				 least we don't skip any input.  */
1109			      ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1110			      ++done;
1111			      conv_error ();
1112			    }
1113			  else
1114			    {
1115			      *strptr = (char *) wstr;
1116			      wstr += strsize;
1117			      ++strsize;
1118			    }
1119			}
1120		      else
1121			{
1122			  *strptr = (char *) wstr;
1123			  wstr += strsize;
1124			  strsize *= 2;
1125			}
1126		    }
1127		}
1128#endif
1129	      }
1130	    while ((width <= 0 || --width > 0) && inchar () != EOF);
1131
1132	    if (!(flags & SUPPRESS))
1133	      {
1134		*wstr++ = L'\0';
1135
1136		if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
1137		  {
1138		    wchar_t *cp = (wchar_t *) realloc (*strptr,
1139						       ((wstr
1140							 - (wchar_t *) *strptr)
1141							* sizeof(wchar_t)));
1142		    if (cp != NULL)
1143		      *strptr = (char *) cp;
1144		  }
1145
1146		++done;
1147	      }
1148	  }
1149	  break;
1150
1151	case L_('x'):	/* Hexadecimal integer.  */
1152	case L_('X'):	/* Ditto.  */
1153	  base = 16;
1154	  number_signed = 0;
1155	  goto number;
1156
1157	case L_('o'):	/* Octal integer.  */
1158	  base = 8;
1159	  number_signed = 0;
1160	  goto number;
1161
1162	case L_('u'):	/* Unsigned decimal integer.  */
1163	  base = 10;
1164	  number_signed = 0;
1165	  goto number;
1166
1167	case L_('d'):	/* Signed decimal integer.  */
1168	  base = 10;
1169	  number_signed = 1;
1170	  goto number;
1171
1172	case L_('i'):	/* Generic number.  */
1173	  base = 0;
1174	  number_signed = 1;
1175
1176	number:
1177	  c = inchar ();
1178	  if (c == EOF)
1179	    input_error ();
1180
1181	  /* Check for a sign.  */
1182	  if (c == L_('-') || c == L_('+'))
1183	    {
1184	      ADDW (c);
1185	      if (width > 0)
1186		--width;
1187	      c = inchar ();
1188	    }
1189
1190	  /* Look for a leading indication of base.  */
1191	  if (width != 0 && c == L_('0'))
1192	    {
1193	      if (width > 0)
1194		--width;
1195
1196	      ADDW (c);
1197	      c = inchar ();
1198
1199	      if (width != 0 && TOLOWER (c) == L_('x'))
1200		{
1201		  if (base == 0)
1202		    base = 16;
1203		  if (base == 16)
1204		    {
1205		      if (width > 0)
1206			--width;
1207		      c = inchar ();
1208		    }
1209		}
1210	      else if (base == 0)
1211		base = 8;
1212	    }
1213
1214	  if (base == 0)
1215	    base = 10;
1216
1217	  if (base == 10 && (flags & I18N) != 0)
1218	    {
1219	      int from_level;
1220	      int to_level;
1221	      int level;
1222#ifdef COMPILE_WSCANF
1223	      const wchar_t *wcdigits[10];
1224#else
1225	      const char *mbdigits[10];
1226#endif
1227	      int n;
1228
1229	      from_level = 0;
1230#ifdef COMPILE_WSCANF
1231	      to_level = _NL_CURRENT_WORD (LC_CTYPE,
1232					   _NL_CTYPE_INDIGITS_WC_LEN) - 1;
1233#else
1234	      to_level = _NL_CURRENT_WORD (LC_CTYPE,
1235					   _NL_CTYPE_INDIGITS_MB_LEN) - 1;
1236#endif
1237
1238	      /* Read the number into workspace.  */
1239	      while (c != EOF && width != 0)
1240		{
1241		  /* In this round we get the pointer to the digit strings
1242		     and also perform the first round of comparisons.  */
1243		  for (n = 0; n < 10; ++n)
1244		    {
1245		      /* Get the string for the digits with value N.  */
1246#ifdef COMPILE_WSCANF
1247		      wcdigits[n] = (const wchar_t *)
1248			_NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
1249		      wcdigits[n] += from_level;
1250
1251		      if (c == *wcdigits[n])
1252			{
1253			  to_level = from_level;
1254			  break;
1255			}
1256
1257		      /* Advance the pointer to the next string.  */
1258		      ++wcdigits[n];
1259#else
1260		      const char *cmpp;
1261		      int avail = width > 0 ? width : INT_MAX;
1262
1263		      mbdigits[n] = _NL_CURRENT (LC_CTYPE,
1264						 _NL_CTYPE_INDIGITS0_MB + n);
1265
1266		      for (level = 0; level < from_level; level++)
1267			mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1268
1269		      cmpp = mbdigits[n];
1270		      while ((unsigned char) *cmpp == c && avail > 0)
1271			{
1272			  if (*++cmpp == '\0')
1273			    break;
1274			  else
1275			    {
1276			      if ((c = inchar ()) == EOF)
1277				break;
1278			      --avail;
1279			    }
1280			}
1281
1282		      if (*cmpp == '\0')
1283			{
1284			  if (width > 0)
1285			    width = avail;
1286			  to_level = from_level;
1287			  break;
1288			}
1289
1290		      /* We are pushing all read characters back.  */
1291		      if (cmpp > mbdigits[n])
1292			{
1293			  ungetc (c, s);
1294			  while (--cmpp > mbdigits[n])
1295			    ungetc_not_eof ((unsigned char) *cmpp, s);
1296			  c = (unsigned char) *cmpp;
1297			}
1298
1299		      /* Advance the pointer to the next string.  */
1300		      mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1301#endif
1302		    }
1303
1304		  if (n == 10)
1305		    {
1306		      /* Have not yet found the digit.  */
1307		      for (level = from_level + 1; level <= to_level; ++level)
1308			{
1309			  /* Search all ten digits of this level.  */
1310			  for (n = 0; n < 10; ++n)
1311			    {
1312#ifdef COMPILE_WSCANF
1313			      if (c == *wcdigits[n])
1314				break;
1315
1316			      /* Advance the pointer to the next string.  */
1317			      ++wcdigits[n];
1318#else
1319			      const char *cmpp;
1320			      int avail = width > 0 ? width : INT_MAX;
1321
1322			      cmpp = mbdigits[n];
1323			      while ((unsigned char) *cmpp == c && avail > 0)
1324				{
1325				  if (*++cmpp == '\0')
1326				    break;
1327				  else
1328				    {
1329				      if ((c = inchar ()) == EOF)
1330					break;
1331				      --avail;
1332				    }
1333				}
1334
1335			      if (*cmpp == '\0')
1336				{
1337				  if (width > 0)
1338				    width = avail;
1339				  break;
1340				}
1341
1342			      /* We are pushing all read characters back.  */
1343			      if (cmpp > mbdigits[n])
1344				{
1345				  ungetc (c, s);
1346				  while (--cmpp > mbdigits[n])
1347				    ungetc_not_eof ((unsigned char) *cmpp, s);
1348				  c = (unsigned char) *cmpp;
1349				}
1350
1351			      /* Advance the pointer to the next string.  */
1352			      mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1353#endif
1354			    }
1355
1356			  if (n < 10)
1357			    {
1358			      /* Found it.  */
1359			      from_level = level;
1360			      to_level = level;
1361			      break;
1362			    }
1363			}
1364		    }
1365
1366		  if (n < 10)
1367		    c = L_('0') + n;
1368		  else if ((flags & GROUP)
1369#ifdef COMPILE_WSCANF
1370			   && thousands != L'\0'
1371#else
1372			   && thousands != NULL
1373#endif
1374			   )
1375		    {
1376		      /* Try matching against the thousands separator.  */
1377#ifdef COMPILE_WSCANF
1378		      if (c != thousands)
1379			  break;
1380#else
1381		      const char *cmpp = thousands;
1382		      int avail = width > 0 ? width : INT_MAX;
1383
1384		      while ((unsigned char) *cmpp == c && avail > 0)
1385			{
1386			  ADDW (c);
1387			  if (*++cmpp == '\0')
1388			    break;
1389			  else
1390			    {
1391			      if ((c = inchar ()) == EOF)
1392				break;
1393			      --avail;
1394			    }
1395			}
1396
1397		      if (*cmpp != '\0')
1398			{
1399			  /* We are pushing all read characters back.  */
1400			  if (cmpp > thousands)
1401			    {
1402			      wpsize -= cmpp - thousands;
1403			      ungetc (c, s);
1404			      while (--cmpp > thousands)
1405				ungetc_not_eof ((unsigned char) *cmpp, s);
1406			      c = (unsigned char) *cmpp;
1407			    }
1408			  break;
1409			}
1410
1411		      if (width > 0)
1412			width = avail;
1413
1414		      /* The last thousands character will be added back by
1415			 the ADDW below.  */
1416			--wpsize;
1417#endif
1418		    }
1419		  else
1420		    break;
1421
1422		  ADDW (c);
1423		  if (width > 0)
1424		    --width;
1425
1426		  c = inchar ();
1427		}
1428	    }
1429	  else
1430	    /* Read the number into workspace.  */
1431	    while (c != EOF && width != 0)
1432	      {
1433		if (base == 16)
1434		  {
1435		    if (!ISXDIGIT (c))
1436		      break;
1437		  }
1438		else if (!ISDIGIT (c) || c - L_('0') >= base)
1439		  {
1440		    if (base == 10 && (flags & GROUP)
1441#ifdef COMPILE_WSCANF
1442			&& thousands != L'\0'
1443#else
1444			&& thousands != NULL
1445#endif
1446			)
1447		      {
1448			/* Try matching against the thousands separator.  */
1449#ifdef COMPILE_WSCANF
1450			if (c != thousands)
1451			  break;
1452#else
1453			const char *cmpp = thousands;
1454			int avail = width > 0 ? width : INT_MAX;
1455
1456			while ((unsigned char) *cmpp == c && avail > 0)
1457			  {
1458			    ADDW (c);
1459			    if (*++cmpp == '\0')
1460			      break;
1461			    else
1462			      {
1463				if ((c = inchar ()) == EOF)
1464				  break;
1465				--avail;
1466			      }
1467			  }
1468
1469			if (*cmpp != '\0')
1470			  {
1471			    /* We are pushing all read characters back.  */
1472			    if (cmpp > thousands)
1473			      {
1474				wpsize -= cmpp - thousands;
1475				ungetc (c, s);
1476				while (--cmpp > thousands)
1477				  ungetc_not_eof ((unsigned char) *cmpp, s);
1478				c = (unsigned char) *cmpp;
1479			      }
1480			    break;
1481			  }
1482
1483			if (width > 0)
1484			  width = avail;
1485
1486			/* The last thousands character will be added back by
1487			   the ADDW below.  */
1488			--wpsize;
1489#endif
1490		      }
1491		    else
1492		      break;
1493		  }
1494		ADDW (c);
1495		if (width > 0)
1496		  --width;
1497
1498		c = inchar ();
1499	      }
1500
1501	  if (wpsize == 0
1502	      || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
1503	    {
1504	      /* There was no number.  If we are supposed to read a pointer
1505		 we must recognize "(nil)" as well.  */
1506	      if (wpsize == 0 && read_pointer && (width < 0 || width >= 0)
1507		  && c == '('
1508		  && TOLOWER (inchar ()) == L_('n')
1509		  && TOLOWER (inchar ()) == L_('i')
1510		  && TOLOWER (inchar ()) == L_('l')
1511		  && inchar () == L_(')'))
1512		/* We must produce the value of a NULL pointer.  A single
1513		   '0' digit is enough.  */
1514		ADDW (L_('0'));
1515	      else
1516		{
1517		  /* The last read character is not part of the number
1518		     anymore.  */
1519		  ungetc (c, s);
1520
1521		  conv_error ();
1522		}
1523	    }
1524	  else
1525	    /* The just read character is not part of the number anymore.  */
1526	    ungetc (c, s);
1527
1528	  /* Convert the number.  */
1529	  ADDW (L_('\0'));
1530	  if (need_longlong && (flags & LONGDBL))
1531	    {
1532	      if (number_signed)
1533		num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
1534	      else
1535		num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
1536	    }
1537	  else
1538	    {
1539	      if (number_signed)
1540		num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
1541	      else
1542		num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
1543	    }
1544	  if (wp == tw)
1545	    conv_error ();
1546
1547	  if (!(flags & SUPPRESS))
1548	    {
1549	      if (! number_signed)
1550		{
1551		  if (need_longlong && (flags & LONGDBL))
1552		    *ARG (unsigned LONGLONG int *) = num.uq;
1553		  else if (need_long && (flags & LONG))
1554		    *ARG (unsigned long int *) = num.ul;
1555		  else if (flags & SHORT)
1556		    *ARG (unsigned short int *)
1557		      = (unsigned short int) num.ul;
1558		  else if (!(flags & CHAR))
1559		    *ARG (unsigned int *) = (unsigned int) num.ul;
1560		  else
1561		    *ARG (unsigned char *) = (unsigned char) num.ul;
1562		}
1563	      else
1564		{
1565		  if (need_longlong && (flags & LONGDBL))
1566		    *ARG (LONGLONG int *) = num.q;
1567		  else if (need_long && (flags & LONG))
1568		    *ARG (long int *) = num.l;
1569		  else if (flags & SHORT)
1570		    *ARG (short int *) = (short int) num.l;
1571		  else if (!(flags & CHAR))
1572		    *ARG (int *) = (int) num.l;
1573		  else
1574		    *ARG (signed char *) = (signed char) num.ul;
1575		}
1576	      ++done;
1577	    }
1578	  break;
1579
1580	case L_('e'):	/* Floating-point numbers.  */
1581	case L_('E'):
1582	case L_('f'):
1583	case L_('F'):
1584	case L_('g'):
1585	case L_('G'):
1586	case L_('a'):
1587	case L_('A'):
1588	  c = inchar ();
1589	  if (c == EOF)
1590	    input_error ();
1591
1592	  /* Check for a sign.  */
1593	  if (c == L_('-') || c == L_('+'))
1594	    {
1595	      negative = c == L_('-');
1596	      if (width == 0 || inchar () == EOF)
1597		/* EOF is only an input error before we read any chars.  */
1598		conv_error ();
1599	      if (! ISDIGIT (c) && TOLOWER (c) != L_('i')
1600		  && TOLOWER (c) != L_('n'))
1601		{
1602#ifdef COMPILE_WSCANF
1603		  if (c != decimal)
1604		    {
1605		      /* This is no valid number.  */
1606		      ungetc (c, s);
1607		      conv_error ();
1608		    }
1609#else
1610		  /* Match against the decimal point.  At this point
1611                     we are taking advantage of the fact that we can
1612                     push more than one character back.  This is
1613                     (almost) never necessary since the decimal point
1614                     string hopefully never contains more than one
1615                     byte.  */
1616		  const char *cmpp = decimal;
1617		  int avail = width > 0 ? width : INT_MAX;
1618
1619		  while ((unsigned char) *cmpp == c && avail > 0)
1620		    if (*++cmpp == '\0')
1621		      break;
1622		    else
1623		      {
1624			if (inchar () == EOF)
1625			  break;
1626			--avail;
1627		      }
1628
1629		  if (*cmpp != '\0')
1630		    {
1631		      /* This is no valid number.  */
1632		      while (1)
1633			{
1634			  ungetc (c, s);
1635			  if (cmpp == decimal)
1636			    break;
1637			  c = (unsigned char) *--cmpp;
1638			}
1639
1640		      conv_error ();
1641		    }
1642		  if (width > 0)
1643		    width = avail;
1644#endif
1645		}
1646	      if (width > 0)
1647		--width;
1648	    }
1649	  else
1650	    negative = 0;
1651
1652	  /* Take care for the special arguments "nan" and "inf".  */
1653	  if (TOLOWER (c) == L_('n'))
1654	    {
1655	      /* Maybe "nan".  */
1656	      ADDW (c);
1657	      if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a'))
1658		conv_error ();
1659	      if (width > 0)
1660		--width;
1661	      ADDW (c);
1662	      if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1663		conv_error ();
1664	      if (width > 0)
1665		--width;
1666	      ADDW (c);
1667	      /* It is "nan".  */
1668	      goto scan_float;
1669	    }
1670	  else if (TOLOWER (c) == L_('i'))
1671	    {
1672	      /* Maybe "inf" or "infinity".  */
1673	      ADDW (c);
1674	      if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1675		conv_error ();
1676	      if (width > 0)
1677		--width;
1678	      ADDW (c);
1679	      if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f'))
1680		conv_error ();
1681	      if (width > 0)
1682		--width;
1683	      ADDW (c);
1684	      /* It is as least "inf".  */
1685	      if (width != 0 && inchar () != EOF)
1686		{
1687		  if (TOLOWER (c) == L_('i'))
1688		    {
1689		      if (width > 0)
1690			--width;
1691		      /* Now we have to read the rest as well.  */
1692		      ADDW (c);
1693		      if (width == 0 || inchar () == EOF
1694			  || TOLOWER (c) != L_('n'))
1695			conv_error ();
1696		      if (width > 0)
1697			--width;
1698		      ADDW (c);
1699		      if (width == 0 || inchar () == EOF
1700			  || TOLOWER (c) != L_('i'))
1701			conv_error ();
1702		      if (width > 0)
1703			--width;
1704		      ADDW (c);
1705		      if (width == 0 || inchar () == EOF
1706			  || TOLOWER (c) != L_('t'))
1707			conv_error ();
1708		      if (width > 0)
1709			--width;
1710		      ADDW (c);
1711		      if (width == 0 || inchar () == EOF
1712			  || TOLOWER (c) != L_('y'))
1713			conv_error ();
1714		      if (width > 0)
1715			--width;
1716		      ADDW (c);
1717		    }
1718		  else
1719		    /* Never mind.  */
1720		    ungetc (c, s);
1721		}
1722	      goto scan_float;
1723	    }
1724
1725	  is_hexa = 0;
1726	  exp_char = L_('e');
1727	  if (width != 0 && c == L_('0'))
1728	    {
1729	      ADDW (c);
1730	      c = inchar ();
1731	      if (width > 0)
1732		--width;
1733	      if (width != 0 && TOLOWER (c) == L_('x'))
1734		{
1735		  /* It is a number in hexadecimal format.  */
1736		  ADDW (c);
1737
1738		  is_hexa = 1;
1739		  exp_char = L_('p');
1740
1741		  /* Grouping is not allowed.  */
1742		  flags &= ~GROUP;
1743		  c = inchar ();
1744		  if (width > 0)
1745		    --width;
1746		}
1747	    }
1748
1749	  got_dot = got_e = 0;
1750	  do
1751	    {
1752	      if (ISDIGIT (c))
1753		ADDW (c);
1754	      else if (!got_e && is_hexa && ISXDIGIT (c))
1755		ADDW (c);
1756	      else if (got_e && wp[wpsize - 1] == exp_char
1757		       && (c == L_('-') || c == L_('+')))
1758		ADDW (c);
1759	      else if (wpsize > 0 && !got_e && TOLOWER (c) == exp_char)
1760		{
1761		  ADDW (exp_char);
1762		  got_e = got_dot = 1;
1763		}
1764	      else
1765		{
1766#ifdef COMPILE_WSCANF
1767		  if (! got_dot && c == decimal)
1768		    {
1769		      ADDW (c);
1770		      got_dot = 1;
1771		    }
1772		  else if (thousands != L'\0' && ! got_dot && c == thousands)
1773		    ADDW (c);
1774		  else
1775		    {
1776		      /* The last read character is not part of the number
1777			 anymore.  */
1778		      ungetc (c, s);
1779		      break;
1780		    }
1781#else
1782		  const char *cmpp = decimal;
1783		  int avail = width > 0 ? width : INT_MAX;
1784
1785		  if (! got_dot)
1786		    {
1787		      while ((unsigned char) *cmpp == c && avail > 0)
1788			if (*++cmpp == '\0')
1789			  break;
1790			else
1791			  {
1792			    if (inchar () == EOF)
1793			      break;
1794			    --avail;
1795			  }
1796		    }
1797
1798		  if (*cmpp == '\0')
1799		    {
1800		      /* Add all the characters.  */
1801		      for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
1802			ADDW ((unsigned char) *cmpp);
1803		      if (width > 0)
1804			width = avail;
1805		      got_dot = 1;
1806		    }
1807		  else
1808		    {
1809		      /* Figure out whether it is a thousands separator.
1810			 There is one problem: we possibly read more than
1811			 one character.  We cannot push them back but since
1812			 we know that parts of the `decimal' string matched,
1813			 we can compare against it.  */
1814		      const char *cmp2p = thousands;
1815
1816		      if (thousands != NULL && ! got_dot)
1817			{
1818			  while (cmp2p < cmpp
1819				 && *cmp2p == decimal[cmp2p - thousands])
1820			    ++cmp2p;
1821			  if (cmp2p == cmpp)
1822			    {
1823			      while ((unsigned char) *cmp2p == c && avail > 0)
1824				if (*++cmp2p == '\0')
1825				  break;
1826				else
1827				  {
1828				    if (inchar () == EOF)
1829				      break;
1830				    --avail;
1831				  }
1832			    }
1833			}
1834
1835		      if (cmp2p != NULL && *cmp2p == '\0')
1836			{
1837			  /* Add all the characters.  */
1838			  for (cmpp = thousands; *cmpp != '\0'; ++cmpp)
1839			    ADDW ((unsigned char) *cmpp);
1840			  if (width > 0)
1841			    width = avail;
1842			}
1843		      else
1844			{
1845			  /* The last read character is not part of the number
1846			     anymore.  */
1847			  ungetc (c, s);
1848			  break;
1849			}
1850		    }
1851#endif
1852		}
1853	      if (width > 0)
1854		--width;
1855	    }
1856	  while (width != 0 && inchar () != EOF);
1857
1858	  /* Have we read any character?  If we try to read a number
1859	     in hexadecimal notation and we have read only the `0x'
1860	     prefix or no exponent this is an error.  */
1861	  if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e)))
1862	    conv_error ();
1863
1864	scan_float:
1865	  /* Convert the number.  */
1866	  ADDW (L_('\0'));
1867	  if (flags & LONGDBL)
1868	    {
1869	      long double d = __strtold_internal (wp, &tw, flags & GROUP);
1870	      if (!(flags & SUPPRESS) && tw != wp)
1871		*ARG (long double *) = negative ? -d : d;
1872	    }
1873	  else if (flags & LONG)
1874	    {
1875	      double d = __strtod_internal (wp, &tw, flags & GROUP);
1876	      if (!(flags & SUPPRESS) && tw != wp)
1877		*ARG (double *) = negative ? -d : d;
1878	    }
1879	  else
1880	    {
1881	      float d = __strtof_internal (wp, &tw, flags & GROUP);
1882	      if (!(flags & SUPPRESS) && tw != wp)
1883		*ARG (float *) = negative ? -d : d;
1884	    }
1885
1886	  if (tw == wp)
1887	    conv_error ();
1888
1889	  if (!(flags & SUPPRESS))
1890	    ++done;
1891	  break;
1892
1893	case L_('['):	/* Character class.  */
1894	  if (flags & LONG)
1895	    STRING_ARG (wstr, wchar_t);
1896	  else
1897	    STRING_ARG (str, char);
1898
1899	  if (*f == L_('^'))
1900	    {
1901	      ++f;
1902	      not_in = 1;
1903	    }
1904	  else
1905	    not_in = 0;
1906
1907	  if (width < 0)
1908	    /* There is no width given so there is also no limit on the
1909	       number of characters we read.  Therefore we set width to
1910	       a very high value to make the algorithm easier.  */
1911	    width = INT_MAX;
1912
1913#ifdef COMPILE_WSCANF
1914	  /* Find the beginning and the end of the scanlist.  We are not
1915	     creating a lookup table since it would have to be too large.
1916	     Instead we search each time through the string.  This is not
1917	     a constant lookup time but who uses this feature deserves to
1918	     be punished.  */
1919	  tw = (wchar_t *) f;	/* Marks the beginning.  */
1920
1921	  if (*f == L']')
1922	    ++f;
1923
1924	  while ((fc = *f++) != L'\0' && fc != L']');
1925
1926	  if (fc == L'\0')
1927	    conv_error ();
1928	  wp = (wchar_t *) f - 1;
1929#else
1930	  /* Fill WP with byte flags indexed by character.
1931	     We will use this flag map for matching input characters.  */
1932	  if (wpmax < UCHAR_MAX + 1)
1933	    {
1934	      wpmax = UCHAR_MAX + 1;
1935	      wp = (char *) alloca (wpmax);
1936	    }
1937	  memset (wp, '\0', UCHAR_MAX + 1);
1938
1939	  fc = *f;
1940	  if (fc == ']' || fc == '-')
1941	    {
1942	      /* If ] or - appears before any char in the set, it is not
1943		 the terminator or separator, but the first char in the
1944		 set.  */
1945	      wp[fc] = 1;
1946	      ++f;
1947	    }
1948
1949	  while ((fc = *f++) != '\0' && fc != ']')
1950	    if (fc == '-' && *f != '\0' && *f != ']'
1951		&& (unsigned char) f[-2] <= (unsigned char) *f)
1952	      {
1953		/* Add all characters from the one before the '-'
1954		   up to (but not including) the next format char.  */
1955		for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
1956		  wp[fc] = 1;
1957	      }
1958	    else
1959	      /* Add the character to the flag map.  */
1960	      wp[fc] = 1;
1961
1962	  if (fc == '\0')
1963	    conv_error();
1964#endif
1965
1966	  if (flags & LONG)
1967	    {
1968	      size_t now = read_in;
1969#ifdef COMPILE_WSCANF
1970	      if (inchar () == WEOF)
1971		input_error ();
1972
1973	      do
1974		{
1975		  wchar_t *runp;
1976
1977		  /* Test whether it's in the scanlist.  */
1978		  runp = tw;
1979		  while (runp < wp)
1980		    {
1981		      if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp
1982			  && runp != tw
1983			  && (unsigned int) runp[-1] <= (unsigned int) runp[1])
1984			{
1985			  /* Match against all characters in between the
1986			     first and last character of the sequence.  */
1987			  wchar_t wc;
1988
1989			  for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
1990			    if (wc == c)
1991			      break;
1992
1993			  if (wc <= runp[1] && !not_in)
1994			    break;
1995			  if (wc <= runp[1] && not_in)
1996			    {
1997			      /* The current character is not in the
1998                                 scanset.  */
1999			      ungetc (c, s);
2000			      goto out;
2001			    }
2002
2003			  runp += 2;
2004			}
2005		      else
2006			{
2007			  if (*runp == c && !not_in)
2008			    break;
2009			  if (*runp == c && not_in)
2010			    {
2011				  ungetc (c, s);
2012			      goto out;
2013			    }
2014
2015			  ++runp;
2016			}
2017		    }
2018
2019		  if (runp == wp && !not_in)
2020		    {
2021		      ungetc (c, s);
2022		      goto out;
2023		    }
2024
2025		  if (!(flags & SUPPRESS))
2026		    {
2027		      *wstr++ = c;
2028
2029		      if ((flags & MALLOC)
2030			  && wstr == (wchar_t *) *strptr + strsize)
2031			{
2032			  /* Enlarge the buffer.  */
2033			  wstr = (wchar_t *) realloc (*strptr,
2034						      (2 * strsize)
2035						      * sizeof (wchar_t));
2036			  if (wstr == NULL)
2037			    {
2038			      /* Can't allocate that much.  Last-ditch
2039				 effort.  */
2040			      wstr = (wchar_t *)
2041				realloc (*strptr, (strsize + 1)
2042						  * sizeof (wchar_t));
2043			      if (wstr == NULL)
2044				{
2045				  /* We lose.  Oh well.  Terminate the string
2046				     and stop converting, so at least we don't
2047				     skip any input.  */
2048				  ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2049				  ++done;
2050				  conv_error ();
2051				}
2052			      else
2053				{
2054				  *strptr = (char *) wstr;
2055				  wstr += strsize;
2056				  ++strsize;
2057				}
2058			    }
2059			  else
2060			    {
2061			      *strptr = (char *) wstr;
2062			      wstr += strsize;
2063			      strsize *= 2;
2064			    }
2065			}
2066		    }
2067		}
2068	      while (--width > 0 && inchar () != WEOF);
2069	    out:
2070#else
2071	      char buf[MB_LEN_MAX];
2072	      size_t cnt = 0;
2073	      mbstate_t cstate;
2074
2075	      if (inchar () == EOF)
2076		input_error ();
2077
2078	      memset (&cstate, '\0', sizeof (cstate));
2079
2080	      do
2081		{
2082		  if (wp[c] == not_in)
2083		    {
2084		      ungetc_not_eof (c, s);
2085		      break;
2086		    }
2087
2088		  /* This is easy.  */
2089		  if (!(flags & SUPPRESS))
2090		    {
2091		      size_t n;
2092
2093		      /* Convert it into a wide character.  */
2094		      buf[0] = c;
2095		      n = __mbrtowc (wstr, buf, 1, &cstate);
2096
2097		      if (n == (size_t) -2)
2098			{
2099			  /* Possibly correct character, just not enough
2100			     input.  */
2101			  ++cnt;
2102			  assert (cnt < MB_CUR_MAX);
2103			  continue;
2104			}
2105
2106		      ++wstr;
2107		      if ((flags & MALLOC)
2108			  && wstr == (wchar_t *) *strptr + strsize)
2109			{
2110			  /* Enlarge the buffer.  */
2111			  wstr = (wchar_t *) realloc (*strptr,
2112						      (2 * strsize
2113						       * sizeof (wchar_t)));
2114			  if (wstr == NULL)
2115			    {
2116			      /* Can't allocate that much.  Last-ditch
2117				 effort.  */
2118			      wstr = (wchar_t *)
2119				realloc (*strptr, ((strsize + 1)
2120						   * sizeof (wchar_t)));
2121			      if (wstr == NULL)
2122				{
2123				  /* We lose.  Oh well.  Terminate the
2124				     string and stop converting,
2125				     so at least we don't skip any input.  */
2126				  ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2127				  ++done;
2128				  conv_error ();
2129				}
2130			      else
2131				{
2132				  *strptr = (char *) wstr;
2133				  wstr += strsize;
2134				  ++strsize;
2135				}
2136			    }
2137			  else
2138			    {
2139			      *strptr = (char *) wstr;
2140			      wstr += strsize;
2141			      strsize *= 2;
2142			    }
2143			}
2144		    }
2145
2146		  if (--width <= 0)
2147		    break;
2148		}
2149	      while (inchar () != EOF);
2150
2151	      if (cnt != 0)
2152		/* We stopped in the middle of recognizing another
2153		   character.  That's a problem.  */
2154		encode_error ();
2155#endif
2156
2157	      if (now == read_in)
2158		/* We haven't succesfully read any character.  */
2159		conv_error ();
2160
2161	      if (!(flags & SUPPRESS))
2162		{
2163		  *wstr++ = L'\0';
2164
2165		  if ((flags & MALLOC)
2166		      && wstr - (wchar_t *) *strptr != strsize)
2167		    {
2168		      wchar_t *cp = (wchar_t *)
2169			realloc (*strptr, ((wstr - (wchar_t *) *strptr)
2170					   * sizeof(wchar_t)));
2171		      if (cp != NULL)
2172			*strptr = (char *) cp;
2173		    }
2174
2175		  ++done;
2176		}
2177	    }
2178	  else
2179	    {
2180	      size_t now = read_in;
2181
2182	      if (inchar () == EOF)
2183		input_error ();
2184
2185#ifdef COMPILE_WSCANF
2186
2187	      memset (&state, '\0', sizeof (state));
2188
2189	      do
2190		{
2191		  wchar_t *runp;
2192		  size_t n;
2193
2194		  /* Test whether it's in the scanlist.  */
2195		  runp = tw;
2196		  while (runp < wp)
2197		    {
2198		      if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp
2199			  && runp != tw
2200			  && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2201			{
2202			  /* Match against all characters in between the
2203			     first and last character of the sequence.  */
2204			  wchar_t wc;
2205
2206			  for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
2207			    if (wc == c)
2208			      break;
2209
2210			  if (wc <= runp[1] && !not_in)
2211			    break;
2212			  if (wc <= runp[1] && not_in)
2213			    {
2214			      /* The current character is not in the
2215                                 scanset.  */
2216			      ungetc (c, s);
2217			      goto out2;
2218			    }
2219
2220			  runp += 2;
2221			}
2222		      else
2223			{
2224			  if (*runp == c && !not_in)
2225			    break;
2226			  if (*runp == c && not_in)
2227			    {
2228			      ungetc (c, s);
2229			      goto out2;
2230			    }
2231
2232			  ++runp;
2233			}
2234		    }
2235
2236		  if (runp == wp && !not_in)
2237		    {
2238		      ungetc (c, s);
2239		      goto out2;
2240		    }
2241
2242		  if (!(flags & SUPPRESS))
2243		    {
2244		      if ((flags & MALLOC)
2245			  && str + MB_CUR_MAX >= *strptr + strsize)
2246			{
2247			  /* Enlarge the buffer.  */
2248			  size_t strleng = str - *strptr;
2249			  char *newstr;
2250
2251			  newstr = (char *) realloc (*strptr, 2 * strsize);
2252			  if (newstr == NULL)
2253			    {
2254			      /* Can't allocate that much.  Last-ditch
2255				 effort.  */
2256			      newstr = (char *) realloc (*strptr,
2257							 strleng + MB_CUR_MAX);
2258			      if (newstr == NULL)
2259				{
2260				  /* We lose.  Oh well.  Terminate the string
2261				     and stop converting, so at least we don't
2262				     skip any input.  */
2263				  ((char *) (*strptr))[strleng] = '\0';
2264				  ++done;
2265				  conv_error ();
2266				}
2267			      else
2268				{
2269				  *strptr = newstr;
2270				  str = newstr + strleng;
2271				  strsize = strleng + MB_CUR_MAX;
2272				}
2273			    }
2274			  else
2275			    {
2276			      *strptr = newstr;
2277			      str = newstr + strleng;
2278			      strsize *= 2;
2279			    }
2280			}
2281		    }
2282
2283		  n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
2284		  if (n == (size_t) -1)
2285		    encode_error ();
2286
2287		  assert (n <= MB_CUR_MAX);
2288		  str += n;
2289		}
2290	      while (--width > 0 && inchar () != WEOF);
2291	    out2:
2292#else
2293	      do
2294		{
2295		  if (wp[c] == not_in)
2296		    {
2297		      ungetc_not_eof (c, s);
2298		      break;
2299		    }
2300
2301		  /* This is easy.  */
2302		  if (!(flags & SUPPRESS))
2303		    {
2304		      *str++ = c;
2305		      if ((flags & MALLOC)
2306			  && (char *) str == *strptr + strsize)
2307			{
2308			  /* Enlarge the buffer.  */
2309			  str = (char *) realloc (*strptr, 2 * strsize);
2310			  if (str == NULL)
2311			    {
2312			      /* Can't allocate that much.  Last-ditch
2313				 effort.  */
2314			      str = (char *) realloc (*strptr, strsize + 1);
2315			      if (str == NULL)
2316				{
2317				  /* We lose.  Oh well.  Terminate the
2318				     string and stop converting,
2319				     so at least we don't skip any input.  */
2320				  ((char *) (*strptr))[strsize - 1] = '\0';
2321				  ++done;
2322				  conv_error ();
2323				}
2324			      else
2325				{
2326				  *strptr = (char *) str;
2327				  str += strsize;
2328				  ++strsize;
2329				}
2330			    }
2331			  else
2332			    {
2333			      *strptr = (char *) str;
2334			      str += strsize;
2335			      strsize *= 2;
2336			    }
2337			}
2338		    }
2339		}
2340	      while (--width > 0 && inchar () != EOF);
2341#endif
2342
2343	      if (now == read_in)
2344		/* We haven't succesfully read any character.  */
2345		conv_error ();
2346
2347	      if (!(flags & SUPPRESS))
2348		{
2349#ifdef COMPILE_WSCANF
2350		  /* We have to emit the code to get into the initial
2351		     state.  */
2352		  char buf[MB_LEN_MAX];
2353		  size_t n = __wcrtomb (buf, L'\0', &state);
2354		  if (n > 0 && (flags & MALLOC)
2355		      && str + n >= *strptr + strsize)
2356		    {
2357		      /* Enlarge the buffer.  */
2358		      size_t strleng = str - *strptr;
2359		      char *newstr;
2360
2361		      newstr = (char *) realloc (*strptr, strleng + n + 1);
2362		      if (newstr == NULL)
2363			{
2364			  /* We lose.  Oh well.  Terminate the string
2365			     and stop converting, so at least we don't
2366			     skip any input.  */
2367			  ((char *) (*strptr))[strleng] = '\0';
2368			  ++done;
2369			  conv_error ();
2370			}
2371		      else
2372			{
2373			  *strptr = newstr;
2374			  str = newstr + strleng;
2375			  strsize = strleng + n + 1;
2376			}
2377		    }
2378
2379		  str = __mempcpy (str, buf, n);
2380#endif
2381		  *str++ = '\0';
2382
2383		  if ((flags & MALLOC) && str - *strptr != strsize)
2384		    {
2385		      char *cp = (char *) realloc (*strptr, str - *strptr);
2386		      if (cp != NULL)
2387			*strptr = cp;
2388		    }
2389
2390		  ++done;
2391		}
2392	    }
2393	  break;
2394
2395	case L_('p'):	/* Generic pointer.  */
2396	  base = 16;
2397	  /* A PTR must be the same size as a `long int'.  */
2398	  flags &= ~(SHORT|LONGDBL);
2399	  if (need_long)
2400	    flags |= LONG;
2401	  number_signed = 0;
2402	  read_pointer = 1;
2403	  goto number;
2404
2405	default:
2406	  /* If this is an unknown format character punt.  */
2407	  conv_error ();
2408	}
2409    }
2410
2411  /* The last thing we saw int the format string was a white space.
2412     Consume the last white spaces.  */
2413  if (skip_space)
2414    {
2415      do
2416	c = inchar ();
2417      while (ISSPACE (c));
2418      ungetc (c, s);
2419    }
2420
2421  /* Unlock stream.  */
2422  UNLOCK_STREAM (s);
2423
2424  return done;
2425}
2426
2427#ifdef USE_IN_LIBIO
2428# ifdef COMPILE_WSCANF
2429int
2430__vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
2431{
2432  return _IO_vfwscanf (s, format, argptr, NULL);
2433}
2434# else
2435int
2436__vfscanf (FILE *s, const char *format, va_list argptr)
2437{
2438  return _IO_vfscanf (s, format, argptr, NULL);
2439}
2440# endif
2441#endif
2442
2443#ifdef COMPILE_WSCANF
2444weak_alias (__vfwscanf, vfwscanf)
2445#else
2446weak_alias (__vfscanf, vfscanf)
2447#endif
2448