Remove K&R compatibility.
[glibc.git] / stdio-common / vfscanf.c
blobb50e7b83235a3ef22cc9ef90a9ea6886ec414854
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
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 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
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>
33 #ifdef __GNUC__
34 # define HAVE_LONGLONG
35 # define LONGLONG long long
36 #else
37 # define LONGLONG long
38 #endif
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
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
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 */
67 #ifdef USE_IN_LIBIO
68 # include <libioP.h>
69 # include <libio.h>
71 # undef va_list
72 # define va_list _IO_va_list
74 # ifdef COMPILE_WPRINTF
75 # define ungetc(c, s) ((void) (c == WEOF \
76 || (--read_in, \
77 _IO_sputbackwc (s, c))))
78 # define inchar() (c == WEOF ? WEOF \
79 : ((c = _IO_getwc_unlocked (s)), \
80 (void) (c != WEOF && ++read_in), c))
82 # define MEMCPY(d, s, n) wmemcpy (d, s, n)
83 # define ISSPACE(Ch) iswspace (Ch)
84 # define ISDIGIT(Ch) iswdigit (Ch)
85 # define ISXDIGIT(Ch) iswxdigit (Ch)
86 # define TOLOWER(Ch) towlower (Ch)
87 # define ORIENT if (s->_vtable_offset == 0 && _IO_fwide (s, 1) != 1)\
88 return EOF
89 # define __strtoll_internal __wcstoll_internal
90 # define __strtoull_internal __wcstoull_internal
91 # define __strtol_internal __wcstol_internal
92 # define __strtoul_internal __wcstoul_internal
93 # define __strtold_internal __wcstold_internal
94 # define __strtod_internal __wcstod_internal
95 # define __strtof_internal __wcstof_internal
97 # define L_(Str) L##Str
98 # define CHAR_T wchar_t
99 # define UCHAR_T unsigned int
100 # define WINT_T wint_t
101 # else
102 # define ungetc(c, s) ((void) ((int) c == EOF \
103 || (--read_in, \
104 _IO_sputbackc (s, (unsigned char) c))))
105 # define inchar() (c == EOF ? EOF \
106 : ((c = _IO_getc_unlocked (s)), \
107 (void) (c != EOF && ++read_in), c))
108 # define MEMCPY(d, s, n) memcpy (d, s, n)
109 # define ISSPACE(Ch) isspace (Ch)
110 # define ISDIGIT(Ch) isdigit (Ch)
111 # define ISXDIGIT(Ch) isxdigit (Ch)
112 # define TOLOWER(Ch) tolower (Ch)
113 # define ORIENT if (_IO_fwide (s, -1) != -1) return EOF
115 # define L_(Str) Str
116 # define CHAR_T char
117 # define UCHAR_T unsigned char
118 # define WINT_T int
119 # endif
121 # define encode_error() do { \
122 if (errp != NULL) *errp |= 4; \
123 _IO_funlockfile (s); \
124 __libc_cleanup_end (0); \
125 __set_errno (EILSEQ); \
126 return done; \
127 } while (0)
128 # define conv_error() do { \
129 if (errp != NULL) *errp |= 2; \
130 _IO_funlockfile (s); \
131 __libc_cleanup_end (0); \
132 return done; \
133 } while (0)
134 # define input_error() do { \
135 _IO_funlockfile (s); \
136 if (errp != NULL) *errp |= 1; \
137 __libc_cleanup_end (0); \
138 return done ?: EOF; \
139 } while (0)
140 # define memory_error() do { \
141 _IO_funlockfile (s); \
142 __set_errno (ENOMEM); \
143 __libc_cleanup_end (0); \
144 return EOF; \
145 } while (0)
146 # define ARGCHECK(s, format) \
147 do \
149 /* Check file argument for consistence. */ \
150 CHECK_FILE (s, EOF); \
151 if (s->_flags & _IO_NO_READS) \
153 __set_errno (EBADF); \
154 return EOF; \
156 else if (format == NULL) \
158 MAYBE_SET_EINVAL; \
159 return EOF; \
161 } while (0)
162 # define LOCK_STREAM(S) \
163 __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
164 _IO_flockfile (S)
165 # define UNLOCK_STREAM(S) \
166 _IO_funlockfile (S); \
167 __libc_cleanup_region_end (0)
168 #else
169 # define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s))
170 # define inchar() (c == EOF ? EOF \
171 : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
172 # define MEMCPY(d, s, n) memcpy (d, s, n)
173 # define ISSPACE(Ch) isspace (Ch)
174 # define ISDIGIT(Ch) isdigit (Ch)
175 # define ISXDIGIT(Ch) isxdigit (Ch)
176 # define TOLOWER(Ch) tolower (Ch)
178 # define L_(Str) Str
179 # define CHAR_T char
180 # define UCHAR_T unsigned char
181 # define WINT_T int
183 # define encode_error() do { \
184 funlockfile (s); \
185 __set_errno (EILSEQ); \
186 return done; \
187 } while (0)
188 # define conv_error() do { \
189 funlockfile (s); \
190 return done; \
191 } while (0)
192 # define input_error() do { \
193 funlockfile (s); \
194 return done ?: EOF; \
195 } while (0)
196 # define memory_error() do { \
197 funlockfile (s); \
198 __set_errno (ENOMEM); \
199 return EOF; \
200 } while (0)
201 # define ARGCHECK(s, format) \
202 do \
204 /* Check file argument for consistence. */ \
205 if (!__validfp (s) || !s->__mode.__read) \
207 __set_errno (EBADF); \
208 return EOF; \
210 else if (format == NULL) \
212 __set_errno (EINVAL); \
213 return EOF; \
215 } while (0)
216 #if 1
217 /* XXX For now !!! */
218 # define flockfile(S) /* nothing */
219 # define funlockfile(S) /* nothing */
220 # define LOCK_STREAM(S)
221 # define UNLOCK_STREAM(S)
222 #else
223 # define LOCK_STREAM(S) \
224 __libc_cleanup_region_start (&__funlockfile, (S)); \
225 __flockfile (S)
226 # define UNLOCK_STREAM(S) \
227 __funlockfile (S); \
228 __libc_cleanup_region_end (0)
229 #endif
230 #endif
233 /* Read formatted input from S according to the format string
234 FORMAT, using the argument list in ARG.
235 Return the number of assignments made, or -1 for an input error. */
236 #ifdef USE_IN_LIBIO
237 # ifdef COMPILE_WPRINTF
239 _IO_vfwscanf (s, format, argptr, errp)
240 _IO_FILE *s;
241 const wchar_t *format;
242 _IO_va_list argptr;
243 int *errp;
244 # else
246 _IO_vfscanf (s, format, argptr, errp)
247 _IO_FILE *s;
248 const char *format;
249 _IO_va_list argptr;
250 int *errp;
251 # endif
252 #else
254 __vfscanf (FILE *s, const char *format, va_list argptr)
255 #endif
257 va_list arg;
258 register const CHAR_T *f = format;
259 register UCHAR_T fc; /* Current character of the format. */
260 register size_t done = 0; /* Assignments done. */
261 register size_t read_in = 0; /* Chars read in. */
262 register WINT_T c = 0; /* Last char read. */
263 register int width; /* Maximum field width. */
264 register int flags; /* Modifiers for current format element. */
266 /* Status for reading F-P nums. */
267 char got_dot, got_e, negative;
268 /* If a [...] is a [^...]. */
269 CHAR_T not_in;
270 #define exp_char not_in
271 /* Base for integral numbers. */
272 int base;
273 /* Signedness for integral numbers. */
274 int number_signed;
275 #define is_hexa number_signed
276 /* Decimal point character. */
277 wchar_t decimal;
278 /* The thousands character of the current locale. */
279 wchar_t thousands;
280 /* State for the conversions. */
281 mbstate_t state;
282 /* Integral holding variables. */
283 union
285 long long int q;
286 unsigned long long int uq;
287 long int l;
288 unsigned long int ul;
289 } num;
290 /* Character-buffer pointer. */
291 char *str = NULL;
292 wchar_t *wstr = NULL;
293 char **strptr = NULL;
294 size_t strsize = 0;
295 /* We must not react on white spaces immediately because they can
296 possibly be matched even if in the input stream no character is
297 available anymore. */
298 int skip_space = 0;
299 /* Nonzero if we are reading a pointer. */
300 int read_pointer;
301 /* Workspace. */
302 CHAR_T *tw; /* Temporary pointer. */
303 CHAR_T *wp = NULL; /* Workspace. */
304 size_t wpmax = 0; /* Maximal size of workspace. */
305 size_t wpsize; /* Currently used bytes in workspace. */
306 #define ADDW(Ch) \
307 do \
309 if (wpsize == wpmax) \
311 CHAR_T *old = wp; \
312 wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
313 wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t)); \
314 if (old != NULL) \
315 MEMCPY (wp, old, wpsize); \
317 wp[wpsize++] = (Ch); \
319 while (0)
321 #ifdef __va_copy
322 __va_copy (arg, argptr);
323 #else
324 arg = (va_list) argptr;
325 #endif
327 #ifdef ORIENT
328 ORIENT;
329 #endif
331 ARGCHECK (s, format);
333 /* Figure out the decimal point character. */
334 memset (&state, '\0', sizeof (state));
335 if (__mbrtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
336 strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT)), &state)
337 <= 0)
338 decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
339 /* Figure out the thousands separator character. */
340 memset (&state, '\0', sizeof (state));
341 if (__mbrtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
342 strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)),
343 &state) <= 0)
344 thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
346 /* Lock the stream. */
347 LOCK_STREAM (s);
350 #ifndef COMPILE_WPRINTF
351 /* From now on we use `state' to convert the format string. */
352 memset (&state, '\0', sizeof (state));
353 #endif
355 /* Run through the format string. */
356 while (*f != '\0')
358 unsigned int argpos;
359 /* Extract the next argument, which is of type TYPE.
360 For a %N$... spec, this is the Nth argument from the beginning;
361 otherwise it is the next argument after the state now in ARG. */
362 #ifdef __va_copy
363 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
364 ({ unsigned int pos = argpos; \
365 va_list arg; \
366 __va_copy (arg, argptr); \
367 while (--pos > 0) \
368 (void) va_arg (arg, void *); \
369 va_arg (arg, type); \
371 #else
372 # if 0
373 /* XXX Possible optimization. */
374 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
375 ({ va_list arg = (va_list) argptr; \
376 arg = (va_list) ((char *) arg \
377 + (argpos - 1) \
378 * __va_rounded_size (void *)); \
379 va_arg (arg, type); \
381 # else
382 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
383 ({ unsigned int pos = argpos; \
384 va_list arg = (va_list) argptr; \
385 while (--pos > 0) \
386 (void) va_arg (arg, void *); \
387 va_arg (arg, type); \
389 # endif
390 #endif
392 #ifndef COMPILE_WPRINTF
393 if (!isascii (*f))
395 /* Non-ASCII, may be a multibyte. */
396 int len = __mbrlen (f, strlen (f), &state);
397 if (len > 0)
401 c = inchar ();
402 if (c == EOF)
403 input_error ();
404 else if (c != *f++)
406 ungetc (c, s);
407 conv_error ();
410 while (--len > 0);
411 continue;
414 #endif
416 fc = *f++;
417 if (fc != '%')
419 /* Remember to skip spaces. */
420 if (ISSPACE (fc))
422 skip_space = 1;
423 continue;
426 /* Read a character. */
427 c = inchar ();
429 /* Characters other than format specs must just match. */
430 if (c == EOF)
431 input_error ();
433 /* We saw white space char as the last character in the format
434 string. Now it's time to skip all leading white space. */
435 if (skip_space)
437 while (ISSPACE (c))
438 if (inchar () == EOF && errno == EINTR)
439 conv_error ();
440 skip_space = 0;
443 if (c != fc)
445 ungetc (c, s);
446 conv_error ();
449 continue;
452 /* This is the start of the conversion string. */
453 flags = 0;
455 /* Not yet decided whether we read a pointer or not. */
456 read_pointer = 0;
458 /* Initialize state of modifiers. */
459 argpos = 0;
461 /* Prepare temporary buffer. */
462 wpsize = 0;
464 /* Check for a positional parameter specification. */
465 if (ISDIGIT (*f))
467 argpos = *f++ - L_('0');
468 while (ISDIGIT (*f))
469 argpos = argpos * 10 + (*f++ - L_('0'));
470 if (*f == L_('$'))
471 ++f;
472 else
474 /* Oops; that was actually the field width. */
475 width = argpos;
476 flags |= WIDTH;
477 argpos = 0;
478 goto got_width;
482 /* Check for the assignment-suppressing and the number grouping flag. */
483 while (*f == L_('*') || *f == L_('\''))
484 switch (*f++)
486 case L_('*'):
487 flags |= SUPPRESS;
488 break;
489 case L_('\''):
490 flags |= GROUP;
491 break;
494 /* We have seen width. */
495 if (ISDIGIT (*f))
496 flags |= WIDTH;
498 /* Find the maximum field width. */
499 width = 0;
500 while (ISDIGIT (*f))
502 width *= 10;
503 width += *f++ - L_('0');
505 got_width:
506 if (width == 0)
507 width = -1;
509 /* Check for type modifiers. */
510 switch (*f++)
512 case L_('h'):
513 /* ints are short ints or chars. */
514 if (*f == L_('h'))
516 ++f;
517 flags |= CHAR;
519 else
520 flags |= SHORT;
521 break;
522 case L_('l'):
523 if (*f == L_('l'))
525 /* A double `l' is equivalent to an `L'. */
526 ++f;
527 flags |= LONGDBL | LONG;
529 else
530 /* ints are long ints. */
531 flags |= LONG;
532 break;
533 case L_('q'):
534 case L_('L'):
535 /* doubles are long doubles, and ints are long long ints. */
536 flags |= LONGDBL | LONG;
537 break;
538 case L_('a'):
539 /* The `a' is used as a flag only if followed by `s', `S' or
540 `['. */
541 if (*f != L_('s') && *f != L_('S') && *f != L_('['))
543 --f;
544 break;
546 /* String conversions (%s, %[) take a `char **'
547 arg and fill it in with a malloc'd pointer. */
548 flags |= MALLOC;
549 break;
550 case L_('z'):
551 if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
552 flags |= LONGDBL;
553 else if (sizeof (size_t) > sizeof (unsigned int))
554 flags |= LONG;
555 break;
556 case L_('j'):
557 if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
558 flags |= LONGDBL;
559 else if (sizeof (uintmax_t) > sizeof (unsigned int))
560 flags |= LONG;
561 break;
562 case L_('t'):
563 if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
564 flags |= LONGDBL;
565 else if (sizeof (ptrdiff_t) > sizeof (int))
566 flags |= LONG;
567 break;
568 default:
569 /* Not a recognized modifier. Backup. */
570 --f;
571 break;
574 /* End of the format string? */
575 if (*f == L_('\0'))
576 conv_error ();
578 /* Find the conversion specifier. */
579 fc = *f++;
580 if (skip_space || (fc != L_('[') && fc != L_('c')
581 && fc != L_('C') && fc != L_('n')))
583 /* Eat whitespace. */
584 int save_errno = errno;
585 errno = 0;
587 if (inchar () == EOF && errno == EINTR)
588 input_error ();
589 while (ISSPACE (c));
590 errno = save_errno;
591 ungetc (c, s);
592 skip_space = 0;
595 switch (fc)
597 case L_('%'): /* Must match a literal '%'. */
598 c = inchar ();
599 if (c == EOF)
600 input_error ();
601 if (c != fc)
603 ungetc (c, s);
604 conv_error ();
606 break;
608 case L_('n'): /* Answer number of assignments done. */
609 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
610 with the 'n' conversion specifier. */
611 if (!(flags & SUPPRESS))
613 /* Don't count the read-ahead. */
614 if (need_longlong && (flags & LONGDBL))
615 *ARG (long long int *) = read_in;
616 else if (need_long && (flags & LONG))
617 *ARG (long int *) = read_in;
618 else if (flags & SHORT)
619 *ARG (short int *) = read_in;
620 else if (!(flags & CHAR))
621 *ARG (int *) = read_in;
622 else
623 *ARG (char *) = read_in;
625 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
626 /* We have a severe problem here. The ISO C standard
627 contradicts itself in explaining the effect of the %n
628 format in `scanf'. While in ISO C:1990 and the ISO C
629 Amendement 1:1995 the result is described as
631 Execution of a %n directive does not effect the
632 assignment count returned at the completion of
633 execution of the f(w)scanf function.
635 in ISO C Corrigendum 1:1994 the following was added:
637 Subclause 7.9.6.2
638 Add the following fourth example:
640 #include <stdio.h>
641 int d1, d2, n1, n2, i;
642 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
643 the value 123 is assigned to d1 and the value3 to n1.
644 Because %n can never get an input failure the value
645 of 3 is also assigned to n2. The value of d2 is not
646 affected. The value 3 is assigned to i.
648 We go for now with the historically correct code from ISO C,
649 i.e., we don't count the %n assignments. When it ever
650 should proof to be wrong just remove the #ifdef above. */
651 ++done;
652 #endif
654 break;
656 case L_('c'): /* Match characters. */
657 if ((flags & LONG) == 0)
659 if (!(flags & SUPPRESS))
661 str = ARG (char *);
662 if (str == NULL)
663 conv_error ();
666 c = inchar ();
667 if (c == EOF)
668 input_error ();
670 if (width == -1)
671 width = 1;
673 #ifdef COMPILE_WPRINTF
674 /* We have to convert the wide character(s) into multibyte
675 characters and store the result. */
676 memset (&state, '\0', sizeof (state));
680 size_t n;
682 n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
683 if (n == (size_t) -1)
684 /* No valid wide character. */
685 input_error ();
687 /* Increment the output pointer. Even if we don't
688 write anything. */
689 str += n;
691 while (--width > 0 && inchar () != EOF);
692 #else
693 if (!(flags & SUPPRESS))
696 *str++ = c;
697 while (--width > 0 && inchar () != EOF);
699 else
700 while (--width > 0 && inchar () != EOF);
701 #endif
703 if (!(flags & SUPPRESS))
704 ++done;
706 break;
708 /* FALLTHROUGH */
709 case L_('C'):
710 if (!(flags & SUPPRESS))
712 wstr = ARG (wchar_t *);
713 if (str == NULL)
714 conv_error ();
717 c = inchar ();
718 if (c == EOF)
719 input_error ();
721 #ifdef COMPILE_WPRINTF
722 /* Just store the incoming wide characters. */
723 if (!(flags & SUPPRESS))
726 *wstr++ = c;
727 while (--width > 0 && inchar () != EOF);
729 else
730 while (--width > 0 && inchar () != EOF);
731 #else
733 /* We have to convert the multibyte input sequence to wide
734 characters. */
735 char buf[MB_LEN_MAX];
736 mbstate_t cstate;
738 memset (&cstate, '\0', sizeof (cstate));
742 size_t cnt;
744 /* This is what we present the mbrtowc function first. */
745 buf[0] = c;
746 cnt = 1;
748 while (1)
750 size_t n;
752 n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
753 buf, cnt, &cstate);
755 if (n == (size_t) -2)
757 /* Possibly correct character, just not enough
758 input. */
759 assert (cnt < MB_CUR_MAX);
761 if (inchar () == EOF)
762 encode_error ();
764 buf[cnt++] = c;
765 continue;
768 if (n != cnt)
769 encode_error ();
771 /* We have a match. */
772 break;
775 /* Advance the result pointer. */
776 ++wstr;
778 while (--width > 0 && inchar () != EOF);
780 #endif
782 if (!(flags & SUPPRESS))
783 ++done;
785 break;
787 case L_('s'): /* Read a string. */
788 if (!(flags & LONG))
790 #define STRING_ARG(Str, Type) \
791 do if (!(flags & SUPPRESS)) \
793 if (flags & MALLOC) \
795 /* The string is to be stored in a malloc'd buffer. */ \
796 strptr = ARG (char **); \
797 if (strptr == NULL) \
798 conv_error (); \
799 /* Allocate an initial buffer. */ \
800 strsize = 100; \
801 *strptr = (char *) malloc (strsize * sizeof (Type)); \
802 Str = (Type *) *strptr; \
804 else \
805 Str = ARG (Type *); \
806 if (Str == NULL) \
807 conv_error (); \
808 } while (0)
809 STRING_ARG (str, char);
811 c = inchar ();
812 if (c == EOF)
813 input_error ();
815 #ifdef COMPILE_WPRINTF
816 memset (&state, '\0', sizeof (state));
817 #endif
821 if (ISSPACE (c))
823 ungetc (c, s);
824 break;
827 #ifdef COMPILE_WPRINTF
828 /* This is quite complicated. We have to convert the
829 wide characters into multibyte characters and then
830 store them. */
832 size_t n;
834 if (!(flags & SUPPRESS) && (flags & MALLOC)
835 && str + MB_CUR_MAX >= *strptr + strsize)
837 /* We have to enlarge the buffer if the `a' flag
838 was given. */
839 str = (char *) realloc (*strptr, strsize * 2);
840 if (str == NULL)
842 /* Can't allocate that much. Last-ditch
843 effort. */
844 str = (char *) realloc (*strptr, strsize + 1);
845 if (str == NULL)
847 /* We lose. Oh well. Terminate the
848 string and stop converting,
849 so at least we don't skip any input. */
850 ((char *) (*strptr))[strsize - 1] = '\0';
851 ++done;
852 conv_error ();
854 else
856 *strptr = (char *) str;
857 str += strsize;
858 ++strsize;
861 else
863 *strptr = (char *) str;
864 str += strsize;
865 strsize *= 2;
869 n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
870 if (n == (size_t) -1)
871 encode_error ();
873 assert (n <= MB_CUR_MAX);
874 str += n;
876 #else
877 /* This is easy. */
878 if (!(flags & SUPPRESS))
880 *str++ = c;
881 if ((flags & MALLOC)
882 && (char *) str == *strptr + strsize)
884 /* Enlarge the buffer. */
885 str = (char *) realloc (*strptr, 2 * strsize);
886 if (str == NULL)
888 /* Can't allocate that much. Last-ditch
889 effort. */
890 str = (char *) realloc (*strptr, strsize + 1);
891 if (str == NULL)
893 /* We lose. Oh well. Terminate the
894 string and stop converting,
895 so at least we don't skip any input. */
896 ((char *) (*strptr))[strsize - 1] = '\0';
897 ++done;
898 conv_error ();
900 else
902 *strptr = (char *) str;
903 str += strsize;
904 ++strsize;
907 else
909 *strptr = (char *) str;
910 str += strsize;
911 strsize *= 2;
915 #endif
917 while ((width <= 0 || --width > 0) && inchar () != EOF);
919 if (!(flags & SUPPRESS))
921 #ifdef COMPILE_WPRINTF
922 /* We have to emit the code to get into the intial
923 state. */
924 char buf[MB_LEN_MAX];
925 size_t n = wcrtomb (buf, L'\0', &state);
926 if (n > 0 && (flags & MALLOC)
927 && str + n >= *strptr + strsize)
929 /* Enlarge the buffer. */
930 str = (char *) realloc (*strptr,
931 (str + n + 1) - *strptr);
932 if (str == NULL)
934 /* We lose. Oh well. Terminate the string
935 and stop converting, so at least we don't
936 skip any input. */
937 ((char *) (*strptr))[strsize - 1] = '\0';
938 ++done;
939 conv_error ();
941 else
943 *strptr = (char *) str;
944 str = ((char *) *strptr) + strsize;
945 strsize = (str + n + 1) - *strptr;
949 str = __mempcpy (str, buf, n);
950 #endif
951 *str = '\0';
953 if ((flags & MALLOC) && str - *strptr != strsize)
955 char *cp = (char *) realloc (*strptr, str - *strptr);
956 if (cp != NULL)
957 *strptr = cp;
960 ++done;
962 break;
964 /* FALLTHROUGH */
966 case L_('S'):
968 #ifndef COMPILE_WPRINTF
969 mbstate_t cstate;
970 #endif
972 /* Wide character string. */
973 STRING_ARG (wstr, wchar_t);
975 c = inchar ();
976 if (c == EOF)
977 input_error ();
979 #ifndef COMPILE_WPRINTF
980 memset (&cstate, '\0', sizeof (cstate));
981 #endif
985 if (ISSPACE (c))
987 ungetc (c, s);
988 break;
991 #ifdef COMPILE_WPRINTF
992 /* This is easy. */
993 if (!(flags & SUPPRESS))
995 *wstr++ = c;
996 if ((flags & MALLOC)
997 && wstr == (wchar_t *) *strptr + strsize)
999 /* Enlarge the buffer. */
1000 wstr = (wchar_t *) realloc (*strptr,
1001 (2 * strsize)
1002 * sizeof (wchar_t));
1003 if (wstr == NULL)
1005 /* Can't allocate that much. Last-ditch
1006 effort. */
1007 wstr = (wchar_t *) realloc (*strptr,
1008 (strsize
1009 + sizeof (wchar_t)));
1010 if (wstr == NULL)
1012 /* We lose. Oh well. Terminate the string
1013 and stop converting, so at least we don't
1014 skip any input. */
1015 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1016 ++done;
1017 conv_error ();
1019 else
1021 *strptr = (char *) wstr;
1022 wstr += strsize;
1023 ++strsize;
1026 else
1028 *strptr = (char *) wstr;
1029 wstr += strsize;
1030 strsize *= 2;
1034 #else
1036 char buf[MB_LEN_MAX];
1037 size_t cnt;
1039 buf[0] = c;
1040 cnt = 1;
1042 while (1)
1044 size_t n;
1046 n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
1047 buf, cnt, &cstate);
1049 if (n == (size_t) -2)
1051 /* Possibly correct character, just not enough
1052 input. */
1053 assert (cnt < MB_CUR_MAX);
1055 if (inchar () == EOF)
1056 encode_error ();
1058 buf[cnt++] = c;
1059 continue;
1062 if (n != cnt)
1063 encode_error ();
1065 /* We have a match. */
1066 break;
1069 if (!(flags & SUPPRESS) && (flags & MALLOC)
1070 && wstr == (wchar_t *) *strptr + strsize)
1072 /* Enlarge the buffer. */
1073 wstr = (wchar_t *) realloc (*strptr,
1074 (2 * strsize
1075 * sizeof (wchar_t)));
1076 if (wstr == NULL)
1078 /* Can't allocate that much. Last-ditch effort. */
1079 wstr = (wchar_t *) realloc (*strptr,
1080 ((strsize + 1)
1081 * sizeof (wchar_t)));
1082 if (wstr == NULL)
1084 /* We lose. Oh well. Terminate the
1085 string and stop converting, so at
1086 least we don't skip any input. */
1087 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1088 ++done;
1089 conv_error ();
1091 else
1093 *strptr = (char *) wstr;
1094 wstr += strsize;
1095 ++strsize;
1098 else
1100 *strptr = (char *) wstr;
1101 wstr += strsize;
1102 strsize *= 2;
1106 #endif
1108 while ((width <= 0 || --width > 0) && inchar () != EOF);
1110 if (!(flags & SUPPRESS))
1112 *wstr++ = L'\0';
1114 if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
1116 wchar_t *cp = (wchar_t *) realloc (*strptr,
1117 ((wstr
1118 - (wchar_t *) *strptr)
1119 * sizeof(wchar_t)));
1120 if (cp != NULL)
1121 *strptr = (char *) cp;
1124 ++done;
1127 break;
1129 case L_('x'): /* Hexadecimal integer. */
1130 case L_('X'): /* Ditto. */
1131 base = 16;
1132 number_signed = 0;
1133 goto number;
1135 case L_('o'): /* Octal integer. */
1136 base = 8;
1137 number_signed = 0;
1138 goto number;
1140 case L_('u'): /* Unsigned decimal integer. */
1141 base = 10;
1142 number_signed = 0;
1143 goto number;
1145 case L_('d'): /* Signed decimal integer. */
1146 base = 10;
1147 number_signed = 1;
1148 goto number;
1150 case L_('i'): /* Generic number. */
1151 base = 0;
1152 number_signed = 1;
1154 number:
1155 c = inchar ();
1156 if (c == EOF)
1157 input_error ();
1159 /* Check for a sign. */
1160 if (c == L_('-') || c == L_('+'))
1162 ADDW (c);
1163 if (width > 0)
1164 --width;
1165 c = inchar ();
1168 /* Look for a leading indication of base. */
1169 if (width != 0 && c == L_('0'))
1171 if (width > 0)
1172 --width;
1174 ADDW (c);
1175 c = inchar ();
1177 if (width != 0 && TOLOWER (c) == L_('x'))
1179 if (base == 0)
1180 base = 16;
1181 if (base == 16)
1183 if (width > 0)
1184 --width;
1185 c = inchar ();
1188 else if (base == 0)
1189 base = 8;
1192 if (base == 0)
1193 base = 10;
1195 /* Read the number into workspace. */
1196 while (c != EOF && width != 0)
1198 if (base == 16 ? !ISXDIGIT (c) :
1199 ((!ISDIGIT (c) || c - L_('0') >= base) &&
1200 !((flags & GROUP) && base == 10 && c == thousands)))
1201 break;
1202 ADDW (c);
1203 if (width > 0)
1204 --width;
1206 c = inchar ();
1209 if (wpsize == 0 ||
1210 (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
1212 /* There was no number. If we are supposed to read a pointer
1213 we must recognize "(nil)" as well. */
1214 if (wpsize == 0 && read_pointer && (width < 0 || width >= 0)
1215 && c == '('
1216 && TOLOWER (inchar ()) == L_('n')
1217 && TOLOWER (inchar ()) == L_('i')
1218 && TOLOWER (inchar ()) == L_('l')
1219 && inchar () == L_(')'))
1220 /* We must produce the value of a NULL pointer. A single
1221 '0' digit is enough. */
1222 ADDW (L_('0'));
1223 else
1225 /* The last read character is not part of the number
1226 anymore. */
1227 ungetc (c, s);
1229 conv_error ();
1232 else
1233 /* The just read character is not part of the number anymore. */
1234 ungetc (c, s);
1236 /* Convert the number. */
1237 ADDW (L_('\0'));
1238 if (need_longlong && (flags & LONGDBL))
1240 if (number_signed)
1241 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
1242 else
1243 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
1245 else
1247 if (number_signed)
1248 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
1249 else
1250 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
1252 if (wp == tw)
1253 conv_error ();
1255 if (!(flags & SUPPRESS))
1257 if (! number_signed)
1259 if (need_longlong && (flags & LONGDBL))
1260 *ARG (unsigned LONGLONG int *) = num.uq;
1261 else if (need_long && (flags & LONG))
1262 *ARG (unsigned long int *) = num.ul;
1263 else if (flags & SHORT)
1264 *ARG (unsigned short int *)
1265 = (unsigned short int) num.ul;
1266 else if (!(flags & CHAR))
1267 *ARG (unsigned int *) = (unsigned int) num.ul;
1268 else
1269 *ARG (unsigned char *) = (unsigned char) num.ul;
1271 else
1273 if (need_longlong && (flags & LONGDBL))
1274 *ARG (LONGLONG int *) = num.q;
1275 else if (need_long && (flags & LONG))
1276 *ARG (long int *) = num.l;
1277 else if (flags & SHORT)
1278 *ARG (short int *) = (short int) num.l;
1279 else if (!(flags & CHAR))
1280 *ARG (int *) = (int) num.l;
1281 else
1282 *ARG (signed char *) = (signed char) num.ul;
1284 ++done;
1286 break;
1288 case L_('e'): /* Floating-point numbers. */
1289 case L_('E'):
1290 case L_('f'):
1291 case L_('g'):
1292 case L_('G'):
1293 case L_('a'):
1294 case L_('A'):
1295 c = inchar ();
1296 if (c == EOF)
1297 input_error ();
1299 /* Check for a sign. */
1300 if (c == L_('-') || c == L_('+'))
1302 negative = c == L_('-');
1303 if (width == 0 || inchar () == EOF)
1304 /* EOF is only an input error before we read any chars. */
1305 conv_error ();
1306 if (! ISDIGIT (c) && c != decimal)
1308 /* This is no valid number. */
1309 ungetc (c, s);
1310 input_error ();
1312 if (width > 0)
1313 --width;
1315 else
1316 negative = 0;
1318 /* Take care for the special arguments "nan" and "inf". */
1319 if (TOLOWER (c) == L_('n'))
1321 /* Maybe "nan". */
1322 ADDW (c);
1323 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a'))
1324 input_error ();
1325 if (width > 0)
1326 --width;
1327 ADDW (c);
1328 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1329 input_error ();
1330 if (width > 0)
1331 --width;
1332 ADDW (c);
1333 /* It is "nan". */
1334 goto scan_float;
1336 else if (TOLOWER (c) == L_('i'))
1338 /* Maybe "inf" or "infinity". */
1339 ADDW (c);
1340 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1341 input_error ();
1342 if (width > 0)
1343 --width;
1344 ADDW (c);
1345 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f'))
1346 input_error ();
1347 if (width > 0)
1348 --width;
1349 ADDW (c);
1350 /* It is as least "inf". */
1351 if (width != 0 && inchar () != EOF)
1353 if (TOLOWER (c) == L_('i'))
1355 if (width > 0)
1356 --width;
1357 /* Now we have to read the rest as well. */
1358 ADDW (c);
1359 if (width == 0 || inchar () == EOF
1360 || TOLOWER (c) != L_('n'))
1361 input_error ();
1362 if (width > 0)
1363 --width;
1364 ADDW (c);
1365 if (width == 0 || inchar () == EOF
1366 || TOLOWER (c) != L_('i'))
1367 input_error ();
1368 if (width > 0)
1369 --width;
1370 ADDW (c);
1371 if (width == 0 || inchar () == EOF
1372 || TOLOWER (c) != L_('t'))
1373 input_error ();
1374 if (width > 0)
1375 --width;
1376 ADDW (c);
1377 if (width == 0 || inchar () == EOF
1378 || TOLOWER (c) != L_('y'))
1379 input_error ();
1380 if (width > 0)
1381 --width;
1382 ADDW (c);
1384 else
1385 /* Never mind. */
1386 ungetc (c, s);
1388 goto scan_float;
1391 is_hexa = 0;
1392 exp_char = L_('e');
1393 if (width != 0 && c == L_('0'))
1395 ADDW (c);
1396 c = inchar ();
1397 if (width > 0)
1398 --width;
1399 if (width != 0 && TOLOWER (c) == L_('x'))
1401 /* It is a number in hexadecimal format. */
1402 ADDW (c);
1404 is_hexa = 1;
1405 exp_char = L_('p');
1407 /* Grouping is not allowed. */
1408 flags &= ~GROUP;
1409 c = inchar ();
1410 if (width > 0)
1411 --width;
1415 got_dot = got_e = 0;
1418 if (ISDIGIT (c))
1419 ADDW (c);
1420 else if (!got_e && is_hexa && ISXDIGIT (c))
1421 ADDW (c);
1422 else if (got_e && wp[wpsize - 1] == exp_char
1423 && (c == L_('-') || c == L_('+')))
1424 ADDW (c);
1425 else if (wpsize > 0 && !got_e && TOLOWER (c) == exp_char)
1427 ADDW (exp_char);
1428 got_e = got_dot = 1;
1430 else if (c == decimal && !got_dot)
1432 ADDW (c);
1433 got_dot = 1;
1435 else if ((flags & GROUP) && c == thousands && !got_dot)
1436 ADDW (c);
1437 else
1439 /* The last read character is not part of the number
1440 anymore. */
1441 ungetc (c, s);
1442 break;
1444 if (width > 0)
1445 --width;
1447 while (width != 0 && inchar () != EOF);
1449 /* Have we read any character? If we try to read a number
1450 in hexadecimal notation and we have read only the `0x'
1451 prefix or no exponent this is an error. */
1452 if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e)))
1453 conv_error ();
1455 scan_float:
1456 /* Convert the number. */
1457 ADDW (L_('\0'));
1458 if (flags & LONGDBL)
1460 long double d = __strtold_internal (wp, &tw, flags & GROUP);
1461 if (!(flags & SUPPRESS) && tw != wp)
1462 *ARG (long double *) = negative ? -d : d;
1464 else if (flags & LONG)
1466 double d = __strtod_internal (wp, &tw, flags & GROUP);
1467 if (!(flags & SUPPRESS) && tw != wp)
1468 *ARG (double *) = negative ? -d : d;
1470 else
1472 float d = __strtof_internal (wp, &tw, flags & GROUP);
1473 if (!(flags & SUPPRESS) && tw != wp)
1474 *ARG (float *) = negative ? -d : d;
1477 if (tw == wp)
1478 conv_error ();
1480 if (!(flags & SUPPRESS))
1481 ++done;
1482 break;
1484 case L_('['): /* Character class. */
1485 if (flags & LONG)
1486 STRING_ARG (wstr, wchar_t);
1487 else
1488 STRING_ARG (str, char);
1490 if (*f == L_('^'))
1492 ++f;
1493 not_in = 1;
1495 else
1496 not_in = 0;
1498 if (width < 0)
1499 /* There is no width given so there is also no limit on the
1500 number of characters we read. Therefore we set width to
1501 a very high value to make the algorithm easier. */
1502 width = INT_MAX;
1504 #ifdef COMPILE_WPRINTF
1505 /* Find the beginning and the end of the scanlist. We are not
1506 creating a lookup table since it would have to be too large.
1507 Instead we search each time through the string. This is not
1508 a constant lookup time but who uses this feature deserves to
1509 be punished. */
1510 tw = (wchar_t *) f; /* Marks the beginning. */
1512 if (*f == ']' || *f == '-')
1513 ++f;
1515 while ((fc = *f++) != L'\0' && fc != L']');
1517 if (fc == L'\0')
1518 conv_error ();
1519 wp = (wchar_t *) f - 1;
1520 #else
1521 /* Fill WP with byte flags indexed by character.
1522 We will use this flag map for matching input characters. */
1523 if (wpmax < UCHAR_MAX)
1525 wpmax = UCHAR_MAX;
1526 wp = (char *) alloca (wpmax);
1528 memset (wp, '\0', UCHAR_MAX);
1530 fc = *f;
1531 if (fc == ']' || fc == '-')
1533 /* If ] or - appears before any char in the set, it is not
1534 the terminator or separator, but the first char in the
1535 set. */
1536 wp[fc] = 1;
1537 ++f;
1540 tw = (char *) f;
1541 while ((fc = *f++) != '\0' && fc != ']')
1542 if (fc == '-' && *f != '\0' && *f != ']' && f - 2 != tw
1543 && (unsigned char) f[-2] <= (unsigned char) *f)
1545 /* Add all characters from the one before the '-'
1546 up to (but not including) the next format char. */
1547 for (fc = f[-2]; fc < *f; ++fc)
1548 wp[fc] = 1;
1550 else
1551 /* Add the character to the flag map. */
1552 wp[fc] = 1;
1554 if (fc == '\0')
1555 conv_error();
1556 #endif
1558 if (flags & LONG)
1560 size_t now = read_in;
1561 #ifdef COMPILE_WPRINTF
1564 wchar_t *runp;
1566 if (inchar () == WEOF)
1567 break;
1569 /* Test whether it's in the scanlist. */
1570 runp = tw;
1571 while (runp < wp)
1573 if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
1574 && runp != tw
1575 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
1577 /* Match against all characters in between the
1578 first and last character of the sequence. */
1579 wchar_t wc;
1581 for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
1582 if (wc == c)
1583 break;
1585 if (wc == runp[1] && !not_in)
1586 break;
1587 if (wc == runp[1] && not_in)
1589 /* The current character is not in the
1590 scanset. */
1591 ungetwc (c, s);
1592 goto out;
1595 else
1597 if (*runp == runp[1] && !not_in)
1598 break;
1599 if (*runp != runp[1] && not_in)
1601 ungetwc (c ,s);
1602 goto out;
1606 ++runp;
1609 if (!(flags & SUPPRESS))
1611 *wstr++ = c;
1613 if ((flags & MALLOC)
1614 && wstr == (wchar_t *) *strptr + strsize)
1616 /* Enlarge the buffer. */
1617 wstr = (wchar_t *) realloc (*strptr,
1618 (2 * strsize)
1619 * sizeof (wchar_t));
1620 if (wstr == NULL)
1622 /* Can't allocate that much. Last-ditch
1623 effort. */
1624 wstr = (wchar_t *)
1625 realloc (*strptr, (strsize
1626 + sizeof (wchar_t)));
1627 if (wstr == NULL)
1629 /* We lose. Oh well. Terminate the string
1630 and stop converting, so at least we don't
1631 skip any input. */
1632 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1633 ++done;
1634 conv_error ();
1636 else
1638 *strptr = (char *) wstr;
1639 wstr += strsize;
1640 ++strsize;
1643 else
1645 *strptr = (char *) wstr;
1646 wstr += strsize;
1647 strsize *= 2;
1652 while (--width > 0);
1653 out:
1654 #else
1655 char buf[MB_LEN_MAX];
1656 size_t cnt = 0;
1657 mbstate_t cstate;
1659 memset (&cstate, '\0', sizeof (cstate));
1663 again:
1664 if (inchar () == EOF)
1665 break;
1667 if (wp[c] == not_in)
1669 ungetc (c, s);
1670 break;
1673 /* This is easy. */
1674 if (!(flags & SUPPRESS))
1676 size_t n;
1678 /* Convert it into a wide character. */
1679 n = __mbrtowc (wstr, buf, cnt, &cstate);
1681 if (n == (size_t) -2)
1683 /* Possibly correct character, just not enough
1684 input. */
1685 assert (cnt < MB_CUR_MAX);
1686 goto again;
1689 if (n != cnt)
1690 encode_error ();
1692 ++wstr;
1693 if ((flags & MALLOC)
1694 && wstr == (wchar_t *) *strptr + strsize)
1696 /* Enlarge the buffer. */
1697 wstr = (wchar_t *) realloc (*strptr,
1698 (2 * strsize
1699 * sizeof (wchar_t)));
1700 if (wstr == NULL)
1702 /* Can't allocate that much. Last-ditch
1703 effort. */
1704 wstr = (wchar_t *)
1705 realloc (*strptr, ((strsize + 1)
1706 * sizeof (wchar_t)));
1707 if (wstr == NULL)
1709 /* We lose. Oh well. Terminate the
1710 string and stop converting,
1711 so at least we don't skip any input. */
1712 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1713 ++done;
1714 conv_error ();
1716 else
1718 *strptr = (char *) wstr;
1719 wstr += strsize;
1720 ++strsize;
1723 else
1725 *strptr = (char *) wstr;
1726 wstr += strsize;
1727 strsize *= 2;
1732 while (--width > 0);
1734 if (cnt != 0)
1735 /* We stopped in the middle of recognizing another
1736 character. That's a problem. */
1737 encode_error ();
1738 #endif
1740 if (now == read_in)
1741 /* We haven't succesfully read any character. */
1742 conv_error ();
1744 if (!(flags & SUPPRESS))
1746 *wstr++ = L'\0';
1748 if ((flags & MALLOC)
1749 && wstr - (wchar_t *) *strptr != strsize)
1751 wchar_t *cp = (wchar_t *)
1752 realloc (*strptr, ((wstr - (wchar_t *) *strptr)
1753 * sizeof(wchar_t)));
1754 if (cp != NULL)
1755 *strptr = (char *) cp;
1758 ++done;
1761 else
1763 size_t now = read_in;
1764 #ifdef COMPILE_WPRINTF
1766 memset (&state, '\0', sizeof (state));
1770 wchar_t *runp;
1771 size_t n;
1773 if (inchar () == WEOF)
1774 break;
1776 /* Test whether it's in the scanlist. */
1777 runp = tw;
1778 while (runp < wp)
1780 if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
1781 && runp != tw
1782 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
1784 /* Match against all characters in between the
1785 first and last character of the sequence. */
1786 wchar_t wc;
1788 for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
1789 if (wc == c)
1790 break;
1792 if (wc == runp[1] && !not_in)
1793 break;
1794 if (wc == runp[1] && not_in)
1796 /* The current character is not in the
1797 scanset. */
1798 ungetwc (c, s);
1799 goto out2;
1802 else
1804 if (*runp == runp[1] && !not_in)
1805 break;
1806 if (*runp != runp[1] && not_in)
1808 ungetwc (c ,s);
1809 goto out2;
1813 ++runp;
1816 if (!(flags & SUPPRESS))
1818 if ((flags & MALLOC)
1819 && str + MB_CUR_MAX >= *strptr + strsize)
1821 /* Enlarge the buffer. */
1822 str = (char *) realloc (*strptr, 2 * strsize);
1823 if (str == NULL)
1825 /* Can't allocate that much. Last-ditch
1826 effort. */
1827 str = (char *) realloc (*strptr, strsize + 1);
1828 if (str == NULL)
1830 /* We lose. Oh well. Terminate the string
1831 and stop converting, so at least we don't
1832 skip any input. */
1833 (*strptr)[strsize - 1] = '\0';
1834 ++done;
1835 conv_error ();
1837 else
1839 *strptr = str;
1840 str += strsize;
1841 ++strsize;
1844 else
1846 *strptr = str;
1847 str += strsize;
1848 strsize *= 2;
1853 n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
1854 if (n == (size_t) -1)
1855 encode_error ();
1857 assert (n <= MB_CUR_MAX);
1858 str += n;
1860 while (--width > 0);
1861 out2:
1862 #else
1865 if (inchar () == EOF)
1866 break;
1868 if (wp[c] == not_in)
1870 ungetc (c, s);
1871 break;
1874 /* This is easy. */
1875 if (!(flags & SUPPRESS))
1877 *str++ = c;
1878 if ((flags & MALLOC)
1879 && (char *) str == *strptr + strsize)
1881 /* Enlarge the buffer. */
1882 str = (char *) realloc (*strptr, 2 * strsize);
1883 if (str == NULL)
1885 /* Can't allocate that much. Last-ditch
1886 effort. */
1887 str = (char *) realloc (*strptr, strsize + 1);
1888 if (str == NULL)
1890 /* We lose. Oh well. Terminate the
1891 string and stop converting,
1892 so at least we don't skip any input. */
1893 ((char *) (*strptr))[strsize - 1] = '\0';
1894 ++done;
1895 conv_error ();
1897 else
1899 *strptr = (char *) str;
1900 str += strsize;
1901 ++strsize;
1904 else
1906 *strptr = (char *) str;
1907 str += strsize;
1908 strsize *= 2;
1913 while (--width > 0);
1914 #endif
1916 if (now == read_in)
1917 /* We haven't succesfully read any character. */
1918 conv_error ();
1920 if (!(flags & SUPPRESS))
1922 #ifdef COMPILE_WPRINTF
1923 /* We have to emit the code to get into the intial
1924 state. */
1925 char buf[MB_LEN_MAX];
1926 size_t n = wcrtomb (buf, L'\0', &state);
1927 if (n > 0 && (flags & MALLOC)
1928 && str + n >= *strptr + strsize)
1930 /* Enlarge the buffer. */
1931 str = (char *) realloc (*strptr,
1932 (str + n + 1) - *strptr);
1933 if (str == NULL)
1935 /* We lose. Oh well. Terminate the string
1936 and stop converting, so at least we don't
1937 skip any input. */
1938 ((char *) (*strptr))[strsize - 1] = '\0';
1939 ++done;
1940 conv_error ();
1942 else
1944 *strptr = (char *) str;
1945 str = ((char *) *strptr) + strsize;
1946 strsize = (str + n + 1) - *strptr;
1950 str = __mempcpy (str, buf, n);
1951 #endif
1952 *str = '\0';
1954 if ((flags & MALLOC) && str - *strptr != strsize)
1956 char *cp = (char *) realloc (*strptr, str - *strptr);
1957 if (cp != NULL)
1958 *strptr = cp;
1961 ++done;
1964 break;
1966 case L_('p'): /* Generic pointer. */
1967 base = 16;
1968 /* A PTR must be the same size as a `long int'. */
1969 flags &= ~(SHORT|LONGDBL);
1970 if (need_long)
1971 flags |= LONG;
1972 number_signed = 0;
1973 read_pointer = 1;
1974 goto number;
1976 default:
1977 /* If this is an unknown format character punt. */
1978 conv_error ();
1982 /* The last thing we saw int the format string was a white space.
1983 Consume the last white spaces. */
1984 if (skip_space)
1987 c = inchar ();
1988 while (ISSPACE (c));
1989 ungetc (c, s);
1992 /* Unlock stream. */
1993 UNLOCK_STREAM (s);
1995 return done;
1998 #ifdef USE_IN_LIBIO
1999 # ifdef COMPILE_WPRINTF
2001 __vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
2003 return _IO_vfwscanf (s, format, argptr, NULL);
2005 # else
2007 __vfscanf (FILE *s, const char *format, va_list argptr)
2009 return _IO_vfscanf (s, format, argptr, NULL);
2011 # endif
2012 #endif
2014 #ifdef COMPILE_WPRINTF
2015 weak_alias (__vfwscanf, vfwscanf)
2016 #else
2017 weak_alias (__vfscanf, vfscanf)
2018 #endif