|  | /* | 
|  | This Software is provided under the Zope Public License (ZPL) Version 2.1. | 
|  |  | 
|  | Copyright (c) 2011 by the mingw-w64 project | 
|  |  | 
|  | See the AUTHORS file for the list of contributors to the mingw-w64 project. | 
|  |  | 
|  | This license has been certified as open source. It has also been designated | 
|  | as GPL compatible by the Free Software Foundation (FSF). | 
|  |  | 
|  | Redistribution and use in source and binary forms, with or without | 
|  | modification, are permitted provided that the following conditions are met: | 
|  |  | 
|  | 1. Redistributions in source code must retain the accompanying copyright | 
|  | notice, this list of conditions, and the following disclaimer. | 
|  | 2. Redistributions in binary form must reproduce the accompanying | 
|  | copyright notice, this list of conditions, and the following disclaimer | 
|  | in the documentation and/or other materials provided with the | 
|  | distribution. | 
|  | 3. Names of the copyright holders must not be used to endorse or promote | 
|  | products derived from this software without prior written permission | 
|  | from the copyright holders. | 
|  | 4. The right to distribute this software or to use it for any purpose does | 
|  | not give you the right to use Servicemarks (sm) or Trademarks (tm) of | 
|  | the copyright holders.  Use of them is covered by separate agreement | 
|  | with the copyright holders. | 
|  | 5. If any files are modified, you must cause the modified files to carry | 
|  | prominent notices stating that you changed the files and the date of | 
|  | any change. | 
|  |  | 
|  | Disclaimer | 
|  |  | 
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED | 
|  | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
|  | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | 
|  | EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, | 
|  | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | 
|  | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
|  | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|  | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | 
|  | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | #define __LARGE_MBSTATE_T | 
|  |  | 
|  | #include <limits.h> | 
|  | #include <stddef.h> | 
|  | #include <stdarg.h> | 
|  | #include <stdio.h> | 
|  | #include <stdint.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  | #include <wchar.h> | 
|  | #include <ctype.h> | 
|  | #include <wctype.h> | 
|  | #include <locale.h> | 
|  | #include <errno.h> | 
|  |  | 
|  | #include "mingw_swformat.h" | 
|  |  | 
|  | #ifndef CP_UTF8 | 
|  | #define CP_UTF8 65001 | 
|  | #endif | 
|  |  | 
|  | #ifndef MB_ERR_INVALID_CHARS | 
|  | #define MB_ERR_INVALID_CHARS 0x00000008 | 
|  | #endif | 
|  |  | 
|  | /* Helper flags for conversion.  */ | 
|  | #define IS_C		0x0001 | 
|  | #define IS_S		0x0002 | 
|  | #define IS_L		0x0004 | 
|  | #define IS_LL		0x0008 | 
|  | #define IS_SIGNED_NUM	0x0010 | 
|  | #define IS_POINTER	0x0020 | 
|  | #define IS_HEX_FLOAT	0x0040 | 
|  | #define IS_SUPPRESSED	0x0080 | 
|  | #define USE_GROUP	0x0100 | 
|  | #define USE_GNU_ALLOC	0x0200 | 
|  | #define USE_POSIX_ALLOC	0x0400 | 
|  |  | 
|  | #define IS_ALLOC_USED	(USE_GNU_ALLOC | USE_POSIX_ALLOC) | 
|  |  | 
|  | static void * | 
|  | get_va_nth (va_list argp, unsigned int n) | 
|  | { | 
|  | va_list ap; | 
|  | if (!n) | 
|  | abort (); | 
|  | va_copy (ap, argp); | 
|  | while (--n > 0) | 
|  | (void) va_arg(ap, void *); | 
|  | return va_arg (ap, void *); | 
|  | } | 
|  |  | 
|  | static void | 
|  | optimize_alloc (char **p, char *end, size_t alloc_sz) | 
|  | { | 
|  | size_t need_sz; | 
|  | char *h; | 
|  |  | 
|  | if (!p || !*p) | 
|  | return; | 
|  |  | 
|  | need_sz = end - *p; | 
|  | if (need_sz == alloc_sz) | 
|  | return; | 
|  |  | 
|  | if ((h = (char *) realloc (*p, need_sz)) != NULL) | 
|  | *p = h; | 
|  | } | 
|  |  | 
|  | static void | 
|  | back_ch (int c, _IFPW *s, size_t *rin, int not_eof) | 
|  | { | 
|  | if (!not_eof && c == WEOF) | 
|  | return; | 
|  | if (s->is_string == 0) | 
|  | { | 
|  | FILE *fp = s->fp; | 
|  | ungetwc (c, fp); | 
|  | rin[0] -= 1; | 
|  | return; | 
|  | } | 
|  | rin[0] -= 1; | 
|  | s->bch[s->back_top] = c; | 
|  | s->back_top += 1; | 
|  | } | 
|  |  | 
|  | static int | 
|  | in_ch (_IFPW *s, size_t *rin) | 
|  | { | 
|  | int r; | 
|  | if (s->back_top) | 
|  | { | 
|  | s->back_top -= 1; | 
|  | r = s->bch[s->back_top]; | 
|  | rin[0] += 1; | 
|  | } | 
|  | else if (s->seen_eof) | 
|  | { | 
|  | return WEOF; | 
|  | } | 
|  | else if (s->is_string) | 
|  | { | 
|  | const wchar_t *ps = s->str; | 
|  | r = ((int) *ps) & 0xffff; | 
|  | ps++; | 
|  | if (r != 0) | 
|  | { | 
|  | rin[0] += 1; | 
|  | s->str = ps; | 
|  | return r; | 
|  | } | 
|  | s->seen_eof = 1; | 
|  | return WEOF; | 
|  | } | 
|  | else | 
|  | { | 
|  | FILE *fp = (FILE *) s->fp; | 
|  | r = getwc (fp); | 
|  | if (r != WEOF) | 
|  | rin[0] += 1; | 
|  | else s->seen_eof = 1; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | static int | 
|  | match_string (_IFPW *s, size_t *rin, wint_t *c, const wchar_t *str) | 
|  | { | 
|  | int ch = *c; | 
|  |  | 
|  | if (*str == 0) | 
|  | return 1; | 
|  |  | 
|  | if (*str != (wchar_t) towlower (ch)) | 
|  | return 0; | 
|  | ++str; | 
|  | while (*str != 0) | 
|  | { | 
|  | if ((ch = in_ch (s, rin)) == WEOF) | 
|  | { | 
|  | c[0] = ch; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (*str != (wchar_t) towlower (ch)) | 
|  | { | 
|  | c[0] = ch; | 
|  | return 0; | 
|  | } | 
|  | ++str; | 
|  | } | 
|  | c[0] = ch; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | struct gcollect | 
|  | { | 
|  | size_t count; | 
|  | struct gcollect *next; | 
|  | char **ptrs[32]; | 
|  | }; | 
|  |  | 
|  | static void | 
|  | release_ptrs (struct gcollect **pt, wchar_t **wbuf) | 
|  | { | 
|  | struct gcollect *pf; | 
|  | size_t cnt; | 
|  |  | 
|  | if (wbuf) | 
|  | { | 
|  | free (*wbuf); | 
|  | *wbuf = NULL; | 
|  | } | 
|  | if (!pt || (pf = *pt) == NULL) | 
|  | return; | 
|  | while (pf != NULL) | 
|  | { | 
|  | struct gcollect *pf_sv = pf; | 
|  | for (cnt = 0; cnt < pf->count; ++cnt) | 
|  | { | 
|  | free (*pf->ptrs[cnt]); | 
|  | *pf->ptrs[cnt] = NULL; | 
|  | } | 
|  | pf = pf->next; | 
|  | free (pf_sv); | 
|  | } | 
|  | *pt = NULL; | 
|  | } | 
|  |  | 
|  | static int | 
|  | cleanup_return (int rval, struct gcollect **pfree, char **strp, wchar_t **wbuf) | 
|  | { | 
|  | if (rval == EOF) | 
|  | release_ptrs (pfree, wbuf); | 
|  | else | 
|  | { | 
|  | if (pfree) | 
|  | { | 
|  | struct gcollect *pf = *pfree, *pf_sv; | 
|  | while (pf != NULL) | 
|  | { | 
|  | pf_sv = pf; | 
|  | pf = pf->next; | 
|  | free (pf_sv); | 
|  | } | 
|  | *pfree = NULL; | 
|  | } | 
|  | if (strp != NULL) | 
|  | { | 
|  | free (*strp); | 
|  | *strp = NULL; | 
|  | } | 
|  | if (wbuf) | 
|  | { | 
|  | free (*wbuf); | 
|  | *wbuf = NULL; | 
|  | } | 
|  | } | 
|  | return rval; | 
|  | } | 
|  |  | 
|  | static struct gcollect * | 
|  | resize_gcollect (struct gcollect *pf) | 
|  | { | 
|  | struct gcollect *np; | 
|  | if (pf && pf->count < 32) | 
|  | return pf; | 
|  | np = malloc (sizeof (struct gcollect)); | 
|  | np->count = 0; | 
|  | np->next = pf; | 
|  | return np; | 
|  | } | 
|  |  | 
|  | static wchar_t * | 
|  | resize_wbuf (size_t wpsz, size_t *wbuf_max_sz, wchar_t *old) | 
|  | { | 
|  | wchar_t *wbuf; | 
|  | size_t nsz; | 
|  | if (*wbuf_max_sz != wpsz) | 
|  | return old; | 
|  | nsz = (256 > (2 * wbuf_max_sz[0]) ? 256 : (2 * wbuf_max_sz[0])); | 
|  | if (!old) | 
|  | wbuf = (wchar_t *) malloc (nsz * sizeof (wchar_t)); | 
|  | else | 
|  | wbuf = (wchar_t *) realloc (old, nsz * sizeof (wchar_t)); | 
|  | if (!wbuf) | 
|  | { | 
|  | if (old) | 
|  | free (old); | 
|  | } | 
|  | else | 
|  | *wbuf_max_sz = nsz; | 
|  | return wbuf; | 
|  | } | 
|  |  | 
|  | int | 
|  | __cdecl | 
|  | __mingw_swformat (_IFPW *s, const wchar_t *format, va_list argp) | 
|  | { | 
|  | const wchar_t *f = format; | 
|  | struct gcollect *gcollect = NULL; | 
|  | size_t read_in = 0, wbuf_max_sz = 0; | 
|  | ssize_t str_sz = 0; | 
|  | char *str = NULL, **pstr = NULL;; | 
|  | wchar_t *wstr = NULL, *wbuf = NULL; | 
|  | wint_t c = 0, rval = 0; | 
|  | int ignore_ws = 0; | 
|  | va_list arg; | 
|  | size_t wbuf_cur_sz, str_len, read_in_sv, new_sz, n; | 
|  | unsigned int fc, npos; | 
|  | int width, flags, base = 0, errno_sv, clen; | 
|  | char seen_dot, seen_exp, is_neg, *nstr, buf[MB_LEN_MAX]; | 
|  | wchar_t wc, not_in, *tmp_wbuf_ptr, *temp_wbuf_end, *wbuf_iter; | 
|  | wint_t lc_decimal_point, lc_thousands_sep; | 
|  | mbstate_t state; | 
|  | union { | 
|  | unsigned long long ull; | 
|  | unsigned long ul; | 
|  | long long ll; | 
|  | long l; | 
|  | } cv_val; | 
|  |  | 
|  | arg = argp; | 
|  |  | 
|  | if (!s || s->fp == NULL || !format) | 
|  | { | 
|  | errno = EINVAL; | 
|  | return EOF; | 
|  | } | 
|  |  | 
|  | state = (mbstate_t){0}; | 
|  | clen = mbrtowc( &wc, localeconv()->decimal_point, 16, &state); | 
|  | lc_decimal_point = (clen > 0 ? wc : '.'); | 
|  | state = (mbstate_t){0}; | 
|  | clen = mbrtowc( &wc, localeconv()->thousands_sep, 16, &state); | 
|  | lc_thousands_sep = (clen > 0 ? wc : 0); | 
|  |  | 
|  | while (*f != 0) | 
|  | { | 
|  | fc = *f++; | 
|  | if (fc != '%') | 
|  | { | 
|  | if (iswspace (fc)) | 
|  | ignore_ws = 1; | 
|  | else | 
|  | { | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if (ignore_ws) | 
|  | { | 
|  | ignore_ws = 0; | 
|  | if (iswspace (c)) | 
|  | { | 
|  | do | 
|  | { | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | while (iswspace (c)); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (c != fc) | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | width = flags = 0; | 
|  | npos = 0; | 
|  | wbuf_cur_sz = 0; | 
|  |  | 
|  | if (iswdigit ((unsigned int) *f)) | 
|  | { | 
|  | const wchar_t *svf = f; | 
|  | npos = (unsigned int) *f++ - '0'; | 
|  | while (iswdigit ((unsigned int) *f)) | 
|  | npos = npos * 10 + ((unsigned int) *f++ - '0'); | 
|  | if (*f != '$') | 
|  | { | 
|  | npos = 0; | 
|  | f = svf; | 
|  | } | 
|  | else | 
|  | f++; | 
|  | } | 
|  |  | 
|  | do | 
|  | { | 
|  | if (*f == '*') | 
|  | flags |= IS_SUPPRESSED; | 
|  | else if (*f == '\'') | 
|  | { | 
|  | if (lc_thousands_sep) | 
|  | flags |= USE_GROUP; | 
|  | } | 
|  | else if (*f == 'I') | 
|  | { | 
|  | /* we don't support locale's digits (i18N), but ignore it for now silently.  */ | 
|  | ; | 
|  | #ifdef _WIN32 | 
|  | if (f[1] == '6' && f[2] == '4') | 
|  | { | 
|  | flags |= IS_LL | IS_L; | 
|  | f += 2; | 
|  | } | 
|  | else if (f[1] == '3' && f[2] == '2') | 
|  | { | 
|  | flags |= IS_L; | 
|  | f += 2; | 
|  | } | 
|  | else | 
|  | { | 
|  | #ifdef _WIN64 | 
|  | flags |= IS_LL | IS_L; | 
|  | #else | 
|  | flags |= IS_L; | 
|  | #endif | 
|  | } | 
|  | #endif | 
|  | } | 
|  | else | 
|  | break; | 
|  | ++f; | 
|  | } | 
|  | while (1); | 
|  |  | 
|  | while (iswdigit ((unsigned char) *f)) | 
|  | width = width * 10 + ((unsigned char) *f++ - '0'); | 
|  |  | 
|  | if (!width) | 
|  | width = -1; | 
|  |  | 
|  | switch (*f) | 
|  | { | 
|  | case 'h': | 
|  | ++f; | 
|  | flags |= (*f == 'h' ? IS_C : IS_S); | 
|  | if (*f == 'h') | 
|  | ++f; | 
|  | break; | 
|  | case 'l': | 
|  | ++f; | 
|  | flags |= (*f == 'l' ? IS_LL : 0) | IS_L; | 
|  | if (*f == 'l') | 
|  | ++f; | 
|  | break; | 
|  | case 'q': case 'L': | 
|  | ++f; | 
|  | flags |= IS_LL | IS_L; | 
|  | break; | 
|  | case 'a': | 
|  | if (f[1] != 's' && f[1] != 'S' && f[1] != '[') | 
|  | break; | 
|  | ++f; | 
|  | flags |= USE_GNU_ALLOC; | 
|  | break; | 
|  | case 'm': | 
|  | flags |= USE_POSIX_ALLOC; | 
|  | ++f; | 
|  | if (*f == 'l') | 
|  | { | 
|  | flags |= IS_L; | 
|  | ++f; | 
|  | } | 
|  | break; | 
|  | case 'z': | 
|  | #ifdef _WIN64 | 
|  | flags |= IS_LL | IS_L; | 
|  | #else | 
|  | flags |= IS_L; | 
|  | #endif | 
|  | ++f; | 
|  | break; | 
|  | case 'j': | 
|  | if (sizeof (uintmax_t) > sizeof (unsigned long)) | 
|  | flags |= IS_LL; | 
|  | else if (sizeof (uintmax_t) > sizeof (unsigned int)) | 
|  | flags |= IS_L; | 
|  | ++f; | 
|  | break; | 
|  | case 't': | 
|  | #ifdef _WIN64 | 
|  | flags |= IS_LL; | 
|  | #else | 
|  | flags |= IS_L; | 
|  | #endif | 
|  | ++f; | 
|  | break; | 
|  | case 0: | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (*f == 0) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  |  | 
|  | fc = *f++; | 
|  | if (ignore_ws || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) | 
|  | { | 
|  | errno_sv = errno; | 
|  | errno = 0; | 
|  | do | 
|  | { | 
|  | if ((c == WEOF || (c = in_ch (s, &read_in)) == WEOF) && errno == EINTR) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | while (iswspace (c)); | 
|  |  | 
|  | ignore_ws = 0; | 
|  | errno = errno_sv; | 
|  | back_ch (c, s, &read_in, 0); | 
|  | } | 
|  |  | 
|  | switch (fc) | 
|  | { | 
|  | case 'c': | 
|  | if ((flags & IS_L) != 0) | 
|  | fc = 'C'; | 
|  | break; | 
|  | case 's': | 
|  | if ((flags & IS_L) != 0) | 
|  | fc = 'S'; | 
|  | break; | 
|  | } | 
|  |  | 
|  | switch (fc) | 
|  | { | 
|  | case '%': | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | if (c != fc) | 
|  | { | 
|  | back_ch (c, s, &read_in, 1); | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 'n': | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_LL) != 0) | 
|  | *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = read_in; | 
|  | else if ((flags & IS_L) != 0) | 
|  | *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = read_in; | 
|  | else if ((flags & IS_S) != 0) | 
|  | *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = read_in; | 
|  | else if ((flags & IS_C) != 0) | 
|  | *(npos != 0 ? (char *) get_va_nth (argp, npos) : va_arg (arg, char *)) = read_in; | 
|  | else | 
|  | *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = read_in; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 'c': | 
|  | if (width == -1) | 
|  | width = 1; | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0) | 
|  | { | 
|  | if (npos != 0) | 
|  | pstr = (char **) get_va_nth (argp, npos); | 
|  | else | 
|  | pstr = va_arg (arg, char **); | 
|  |  | 
|  | if (!pstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | str_sz = 100; | 
|  | if ((str = *pstr = (char *) malloc (100)) == NULL) | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | gcollect = resize_gcollect (gcollect); | 
|  | gcollect->ptrs[gcollect->count++] = pstr; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (npos != 0) | 
|  | str = (char *) get_va_nth (argp, npos); | 
|  | else | 
|  | str = va_arg (arg, char *); | 
|  | if (!str) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | state = (mbstate_t){0}; | 
|  |  | 
|  | do | 
|  | { | 
|  | if ((flags & IS_SUPPRESSED) == 0 && (flags & USE_POSIX_ALLOC) != 0 | 
|  | && (str + MB_CUR_MAX) >= (*pstr + str_sz)) | 
|  | { | 
|  | new_sz = str_sz * 2; | 
|  | str_len = (str - *pstr); | 
|  | while ((nstr = (char *) realloc (*pstr, new_sz)) == NULL | 
|  | && new_sz > (str_len + MB_CUR_MAX)) | 
|  | new_sz = str_len + MB_CUR_MAX; | 
|  | if (!nstr) | 
|  | { | 
|  | release_ptrs (&gcollect, &wbuf); | 
|  | return EOF; | 
|  | } | 
|  | *pstr = nstr; | 
|  | str = nstr + str_len; | 
|  | str_sz = new_sz; | 
|  | } | 
|  |  | 
|  | n = wcrtomb ((flags & IS_SUPPRESSED) == 0 ? str : NULL, c, &state); | 
|  | if (n == (size_t) -1LL) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | str += n; | 
|  | } | 
|  | while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | optimize_alloc (pstr, str, str_sz); | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  |  | 
|  | break; | 
|  |  | 
|  | case 'C': | 
|  | if (width == -1) | 
|  | width = 1; | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0) | 
|  | { | 
|  | if (npos != 0) | 
|  | pstr = (char **) get_va_nth (argp, npos); | 
|  | else | 
|  | pstr = va_arg (arg, char **); | 
|  |  | 
|  | if (!pstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | str_sz = (width > 1024 ? 1024 : width); | 
|  | *pstr = (char *) malloc (str_sz * sizeof (wchar_t)); | 
|  | if ((wstr = (wchar_t *) *pstr) == NULL) | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if ((wstr = (wchar_t *) *pstr) != NULL) | 
|  | { | 
|  | gcollect = resize_gcollect (gcollect); | 
|  | gcollect->ptrs[gcollect->count++] = pstr; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if (npos != 0) | 
|  | wstr = (wchar_t *) get_va_nth (argp, npos); | 
|  | else | 
|  | wstr = va_arg (arg, wchar_t *); | 
|  | if (!wstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  |  | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | do | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0 | 
|  | && wstr == ((wchar_t *) *pstr + str_sz)) | 
|  | { | 
|  | new_sz = str_sz + (str_sz > width ? width - 1 : str_sz); | 
|  | while ((wstr = (wchar_t *) realloc (*pstr, | 
|  | new_sz * sizeof (wchar_t))) == NULL | 
|  | && new_sz > (size_t) (str_sz + 1)) | 
|  | new_sz = str_sz + 1; | 
|  | if (!wstr) | 
|  | { | 
|  | release_ptrs (&gcollect, &wbuf); | 
|  | return EOF; | 
|  | } | 
|  | *pstr = (char *) wstr; | 
|  | wstr += str_sz; | 
|  | str_sz = new_sz; | 
|  | } | 
|  | *wstr++ = c; | 
|  | } | 
|  | while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); | 
|  | } | 
|  | else | 
|  | { | 
|  | while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); | 
|  | } | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 's': | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0) | 
|  | { | 
|  | if (npos != 0) | 
|  | pstr = (char **) get_va_nth (argp, npos); | 
|  | else | 
|  | pstr = va_arg (arg, char **); | 
|  |  | 
|  | if (!pstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | str_sz = 100; | 
|  | if ((str = *pstr = (char *) malloc (100)) == NULL) | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | gcollect = resize_gcollect (gcollect); | 
|  | gcollect->ptrs[gcollect->count++] = pstr; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (npos != 0) | 
|  | str = (char *) get_va_nth (argp, npos); | 
|  | else | 
|  | str = va_arg (arg, char *); | 
|  | if (!str) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  |  | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | state = (mbstate_t){0}; | 
|  |  | 
|  | do | 
|  | { | 
|  | if (iswspace (c)) | 
|  | { | 
|  | back_ch (c, s, &read_in, 1); | 
|  | break; | 
|  | } | 
|  |  | 
|  | { | 
|  | if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0 | 
|  | && (str + MB_CUR_MAX) >= (*pstr + str_sz)) | 
|  | { | 
|  | new_sz = str_sz * 2; | 
|  | str_len = (str - *pstr); | 
|  |  | 
|  | while ((nstr = (char *) realloc (*pstr, new_sz)) == NULL | 
|  | && new_sz > (str_len + MB_CUR_MAX)) | 
|  | new_sz = str_len + MB_CUR_MAX; | 
|  | if (!nstr) | 
|  | { | 
|  | if ((flags & USE_POSIX_ALLOC) == 0) | 
|  | { | 
|  | (*pstr)[str_len] = 0; | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | *pstr = nstr; | 
|  | str = nstr + str_len; | 
|  | str_sz = new_sz; | 
|  | } | 
|  |  | 
|  | n = wcrtomb ((flags & IS_SUPPRESSED) == 0 ? str : NULL, c, | 
|  | &state); | 
|  | if (n == (size_t) -1LL) | 
|  | { | 
|  | errno = EILSEQ; | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  |  | 
|  | str += n; | 
|  | } | 
|  | } | 
|  | while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != WEOF); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | n = wcrtomb (buf, 0, &state); | 
|  | if (n > 0 && (flags & IS_ALLOC_USED) != 0 | 
|  | && (str + n) >= (*pstr + str_sz)) | 
|  | { | 
|  | str_len = (str - *pstr); | 
|  |  | 
|  | if ((nstr = (char *) realloc (*pstr, str_len + n + 1)) == NULL) | 
|  | { | 
|  | if ((flags & USE_POSIX_ALLOC) == 0) | 
|  | { | 
|  | (*pstr)[str_len] = 0; | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | *pstr = nstr; | 
|  | str = nstr + str_len; | 
|  | str_sz = str_len + n + 1; | 
|  | } | 
|  |  | 
|  | if (n) | 
|  | { | 
|  | memcpy (str, buf, n); | 
|  | str += n; | 
|  | } | 
|  | *str++ = 0; | 
|  |  | 
|  | optimize_alloc (pstr, str, str_sz); | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 'S': | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0) | 
|  | { | 
|  | if (npos != 0) | 
|  | pstr = (char **) get_va_nth (argp, npos); | 
|  | else | 
|  | pstr = va_arg (arg, char **); | 
|  |  | 
|  | if (!pstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | str_sz = 100; | 
|  | *pstr = (char *) malloc (100 * sizeof (wchar_t)); | 
|  | if ((wstr = (wchar_t *) *pstr) == NULL) | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | gcollect = resize_gcollect (gcollect); | 
|  | gcollect->ptrs[gcollect->count++] = pstr; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (npos != 0) | 
|  | wstr = (wchar_t *) get_va_nth (argp, npos); | 
|  | else | 
|  | wstr = va_arg (arg, wchar_t *); | 
|  | if (!wstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | do | 
|  | { | 
|  | if (iswspace (c)) | 
|  | { | 
|  | back_ch (c, s, &read_in, 1); | 
|  | break; | 
|  | } | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | *wstr++ = c; | 
|  | if ((flags & IS_ALLOC_USED) != 0 && wstr == ((wchar_t *) *pstr + str_sz)) | 
|  | { | 
|  | new_sz = str_sz * 2; | 
|  |  | 
|  | while ((wstr = (wchar_t *) realloc (*pstr, | 
|  | new_sz * sizeof (wchar_t))) == NULL | 
|  | && new_sz > (size_t) (str_sz + 1)) | 
|  | new_sz = str_sz + 1; | 
|  | if (!wstr) | 
|  | { | 
|  | if ((flags & USE_POSIX_ALLOC) == 0) | 
|  | { | 
|  | ((wchar_t *) (*pstr))[str_sz - 1] = 0; | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | *pstr = (char *) wstr; | 
|  | wstr += str_sz; | 
|  | str_sz = new_sz; | 
|  | } | 
|  | } | 
|  | } | 
|  | while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != WEOF); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | *wstr++ = 0; | 
|  |  | 
|  | optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 'd': case 'i': | 
|  | case 'o': case 'p': | 
|  | case 'u': | 
|  | case 'x': case 'X': | 
|  | switch (fc) | 
|  | { | 
|  | case 'd': | 
|  | flags |= IS_SIGNED_NUM; | 
|  | base = 10; | 
|  | break; | 
|  | case 'i': | 
|  | flags |= IS_SIGNED_NUM; | 
|  | base = 0; | 
|  | break; | 
|  | case 'o': | 
|  | base = 8; | 
|  | break; | 
|  | case 'p': | 
|  | base = 16; | 
|  | flags &= ~(IS_S | IS_LL | IS_L); | 
|  | #ifdef _WIN64 | 
|  | flags |= IS_LL; | 
|  | #endif | 
|  | flags |= IS_L | IS_POINTER; | 
|  | break; | 
|  | case 'u': | 
|  | base = 10; | 
|  | break; | 
|  | case 'x': case 'X': | 
|  | base = 16; | 
|  | break; | 
|  | } | 
|  |  | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if (c == '+' || c == '-') | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  |  | 
|  | if (width > 0) | 
|  | --width; | 
|  | c = in_ch (s, &read_in); | 
|  | } | 
|  |  | 
|  | if (width != 0 && c == '0') | 
|  | { | 
|  | if (width > 0) | 
|  | --width; | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  |  | 
|  | c = in_ch (s, &read_in); | 
|  |  | 
|  | if (width != 0 && towlower (c) == 'x') | 
|  | { | 
|  | if (!base) | 
|  | base = 16; | 
|  | if (base == 16) | 
|  | { | 
|  | if (width > 0) | 
|  | --width; | 
|  | c = in_ch (s, &read_in); | 
|  | } | 
|  | } | 
|  | else if (!base) | 
|  | base = 8; | 
|  | } | 
|  |  | 
|  | if (!base) | 
|  | base = 10; | 
|  |  | 
|  | while (c != WEOF && width != 0) | 
|  | { | 
|  | if (base == 16) | 
|  | { | 
|  | if (!iswxdigit (c)) | 
|  | break; | 
|  | } | 
|  | else if (!iswdigit (c) || (int) (c - '0') >= base) | 
|  | { | 
|  | if (base != 10 || (flags & USE_GROUP) == 0 || c != lc_thousands_sep) | 
|  | break; | 
|  | } | 
|  | if (c != lc_thousands_sep) | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | } | 
|  |  | 
|  | if (width > 0) | 
|  | --width; | 
|  |  | 
|  | c = in_ch (s, &read_in); | 
|  | } | 
|  |  | 
|  | if (!wbuf_cur_sz || (wbuf_cur_sz == 1 && (wbuf[0] == '+' || wbuf[0] == '-'))) | 
|  | { | 
|  | if (!wbuf_cur_sz && (flags & IS_POINTER) != 0 | 
|  | && match_string (s, &read_in, &c, L"(nil)")) | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = '0'; | 
|  | } | 
|  | else | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  | else | 
|  | back_ch (c, s, &read_in, 0); | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = 0; | 
|  |  | 
|  | if ((flags & IS_LL) != 0) | 
|  | { | 
|  | if ((flags & IS_SIGNED_NUM) != 0) | 
|  | cv_val.ll = wcstoll (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); | 
|  | else | 
|  | cv_val.ull = wcstoull (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((flags & IS_SIGNED_NUM) != 0) | 
|  | cv_val.l = wcstol (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); | 
|  | else | 
|  | cv_val.ul = wcstoul (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); | 
|  | } | 
|  | if (wbuf == tmp_wbuf_ptr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_SIGNED_NUM) != 0) | 
|  | { | 
|  | if ((flags & IS_LL) != 0) | 
|  | *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = cv_val.ll; | 
|  | else if ((flags & IS_L) != 0) | 
|  | *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = cv_val.l; | 
|  | else if ((flags & IS_S) != 0) | 
|  | *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = (short) cv_val.l; | 
|  | else if ((flags & IS_C) != 0) | 
|  | *(npos != 0 ? (signed char *) get_va_nth (argp, npos) : va_arg (arg, signed char *)) = (signed char) cv_val.ul; | 
|  | else | 
|  | *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = (int) cv_val.l; | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((flags & IS_LL) != 0) | 
|  | *(npos != 0 ? (unsigned long long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long long *)) = cv_val.ull; | 
|  | else if ((flags & IS_L) != 0) | 
|  | *(npos != 0 ? (unsigned long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long *)) = cv_val.ul; | 
|  | else if ((flags & IS_S) != 0) | 
|  | *(npos != 0 ? (unsigned short *) get_va_nth (argp, npos) : va_arg (arg, unsigned short *)) | 
|  | = (unsigned short) cv_val.ul; | 
|  | else if ((flags & IS_C) != 0) | 
|  | *(npos != 0 ? (unsigned char *) get_va_nth (argp, npos) : va_arg (arg, unsigned char *)) = (unsigned char) cv_val.ul; | 
|  | else | 
|  | *(npos != 0 ? (unsigned int *) get_va_nth (argp, npos) : va_arg (arg, unsigned int *)) = (unsigned int) cv_val.ul; | 
|  | } | 
|  | ++rval; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 'e': case 'E': | 
|  | case 'f': case 'F': | 
|  | case 'g': case 'G': | 
|  | case 'a': case 'A': | 
|  | if (width > 0) | 
|  | --width; | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | seen_dot = seen_exp = 0; | 
|  | is_neg = (c == '-' ? 1 : 0); | 
|  |  | 
|  | if (c == '-' || c == '+') | 
|  | { | 
|  | if (width == 0 || (c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | if (width > 0) | 
|  | --width; | 
|  | } | 
|  |  | 
|  | if (towlower (c) == 'n') | 
|  | { | 
|  | const wchar_t *match_txt = L"nan"; | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  |  | 
|  | ++match_txt; | 
|  | do | 
|  | { | 
|  | if (width == 0 || (c = in_ch (s, &read_in)) == WEOF | 
|  | || towlower (c) != match_txt[0]) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | if (width > 0) | 
|  | --width; | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | ++match_txt; | 
|  | } | 
|  | while (*match_txt != 0); | 
|  | } | 
|  | else if (towlower (c) == 'i') | 
|  | { | 
|  | const wchar_t *match_txt = L"inf"; | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  |  | 
|  | ++match_txt; | 
|  | do | 
|  | { | 
|  | if (width == 0 || (c = in_ch (s, &read_in)) == WEOF | 
|  | || towlower (c) != match_txt[0]) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | if (width > 0) | 
|  | --width; | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | ++match_txt; | 
|  | } | 
|  | while (*match_txt != 0); | 
|  |  | 
|  | if (width != 0 && (c = in_ch (s, &read_in)) != WEOF && towlower (c) == 'i') | 
|  | { | 
|  | match_txt = L"inity"; | 
|  | if (width > 0) | 
|  | --width; | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  |  | 
|  | ++match_txt; | 
|  | do | 
|  | { | 
|  | if (width == 0 || (c = in_ch (s, &read_in)) == WEOF | 
|  | || towlower (c) != match_txt[0]) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | if (width > 0) | 
|  | --width; | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | ++match_txt; | 
|  | } | 
|  | while (*match_txt != 0); | 
|  | } | 
|  | else if (width != 0 && c != WEOF) | 
|  | back_ch (c, s, &read_in, 0); | 
|  | } | 
|  | else | 
|  | { | 
|  | not_in = 'e'; | 
|  | if (width != 0 && c == '0') | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  |  | 
|  | c = in_ch (s, &read_in); | 
|  | if (width > 0) | 
|  | --width; | 
|  | if (width != 0 && towlower (c) == 'x') | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | flags |= IS_HEX_FLOAT; | 
|  | not_in = 'p'; | 
|  |  | 
|  | flags &= ~USE_GROUP; | 
|  | c = in_ch (s, &read_in); | 
|  | if (width > 0) | 
|  | --width; | 
|  | } | 
|  | } | 
|  |  | 
|  | while (1) | 
|  | { | 
|  | if (iswdigit (c)) | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | } | 
|  | else if (!seen_exp && (flags & IS_HEX_FLOAT) != 0 && iswxdigit (c)) | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | } | 
|  | else if (seen_exp && wbuf[wbuf_cur_sz - 1] == not_in | 
|  | && (c == '-' || c == '+')) | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  | } | 
|  | else if (wbuf_cur_sz > 0 && !seen_exp | 
|  | && (wchar_t) towlower (c) == not_in) | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = not_in; | 
|  |  | 
|  | seen_exp = seen_dot = 1; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (!seen_dot && c == lc_decimal_point) | 
|  | { | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = c; | 
|  |  | 
|  | seen_dot = 1; | 
|  | } | 
|  | else if ((flags & USE_GROUP) != 0 && !seen_dot && c == lc_thousands_sep) | 
|  | { | 
|  | /* As our conversion routines aren't supporting thousands | 
|  | separators, we are filtering them here.  */ | 
|  | } | 
|  | else | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (width == 0 || (c = in_ch (s, &read_in)) == WEOF) | 
|  | break; | 
|  |  | 
|  | if (width > 0) | 
|  | --width; | 
|  | } | 
|  |  | 
|  | if (wbuf_cur_sz == 0 || ((flags & IS_HEX_FLOAT) != 0 && wbuf_cur_sz == 2)) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  |  | 
|  | wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); | 
|  | wbuf[wbuf_cur_sz++] = 0; | 
|  |  | 
|  | if ((flags & IS_LL) != 0) | 
|  | { | 
|  | long double d = __mingw_wcstold (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); | 
|  | if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) | 
|  | *(npos != 0 ? (long double *) get_va_nth (argp, npos) : va_arg (arg, long double *)) = is_neg ? -d : d; | 
|  | } | 
|  | else if ((flags & IS_L) != 0) | 
|  | { | 
|  | double d = __mingw_wcstod (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); | 
|  | if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) | 
|  | *(npos != 0 ? (double *) get_va_nth (argp, npos) : va_arg (arg, double *)) = is_neg ? -d : d; | 
|  | } | 
|  | else | 
|  | { | 
|  | float d = __mingw_wcstof (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); | 
|  | if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) | 
|  | *(npos != 0 ? (float *) get_va_nth (argp, npos) : va_arg (arg, float *)) = is_neg ? -d : d; | 
|  | } | 
|  |  | 
|  | if (wbuf == tmp_wbuf_ptr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | ++rval; | 
|  | break; | 
|  |  | 
|  | case '[': | 
|  | if ((flags & IS_L) != 0) | 
|  | { | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0) | 
|  | { | 
|  | if (npos != 0) | 
|  | pstr = (char **) get_va_nth (argp, npos); | 
|  | else | 
|  | pstr = va_arg (arg, char **); | 
|  |  | 
|  | if (!pstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | str_sz = 100; | 
|  | *pstr = (char *) malloc (100 * sizeof (wchar_t)); | 
|  | if ((wstr = (wchar_t *) *pstr) == NULL) | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | gcollect = resize_gcollect (gcollect); | 
|  | gcollect->ptrs[gcollect->count++] = pstr; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (npos != 0) | 
|  | wstr = (wchar_t *) get_va_nth (argp, npos); | 
|  | else | 
|  | wstr = va_arg (arg, wchar_t *); | 
|  | if (!wstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  |  | 
|  | } | 
|  | else if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0) | 
|  | { | 
|  | if (npos != 0) | 
|  | pstr = (char **) get_va_nth (argp, npos); | 
|  | else | 
|  | pstr = va_arg (arg, char **); | 
|  |  | 
|  | if (!pstr) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | str_sz = 100; | 
|  | if ((str = *pstr = (char *) malloc (100)) == NULL) | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | gcollect = resize_gcollect (gcollect); | 
|  | gcollect->ptrs[gcollect->count++] = pstr; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (npos != 0) | 
|  | str = (char *) get_va_nth (argp, npos); | 
|  | else | 
|  | str = va_arg (arg, char *); | 
|  | if (!str) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  |  | 
|  | not_in = (*f == '^' ? 1 : 0); | 
|  | if (*f == '^') | 
|  | f++; | 
|  |  | 
|  | if (width < 0) | 
|  | width = INT_MAX; | 
|  |  | 
|  | tmp_wbuf_ptr = (wchar_t *) f; | 
|  |  | 
|  | if (*f == L']') | 
|  | ++f; | 
|  |  | 
|  | while ((fc = *f++) != 0 && fc != L']'); | 
|  |  | 
|  | if (fc == 0) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | temp_wbuf_end = (wchar_t *) f - 1; | 
|  |  | 
|  | if ((flags & IS_L) != 0) | 
|  | { | 
|  | read_in_sv = read_in; | 
|  |  | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | do | 
|  | { | 
|  | int ended = 0; | 
|  | for (wbuf_iter = tmp_wbuf_ptr; wbuf_iter < temp_wbuf_end;) | 
|  | { | 
|  | if (wbuf_iter[0] == '-' && wbuf_iter[1] != 0 | 
|  | && (wbuf_iter + 1) != temp_wbuf_end | 
|  | && wbuf_iter != tmp_wbuf_ptr | 
|  | && (unsigned int) wbuf_iter[-1] <= (unsigned int) wbuf_iter[1]) | 
|  | { | 
|  | for (wc = wbuf_iter[-1] + 1; wc <= wbuf_iter[1] && (wint_t) wc != c; ++wc); | 
|  |  | 
|  | if (wc <= wbuf_iter[1] && !not_in) | 
|  | break; | 
|  | if (wc <= wbuf_iter[1] && not_in) | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | ended = 1; | 
|  | break; | 
|  | } | 
|  |  | 
|  | wbuf_iter += 2; | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((wint_t) *wbuf_iter == c && !not_in) | 
|  | break; | 
|  | if ((wint_t) *wbuf_iter == c && not_in) | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | ended = 1; | 
|  | break; | 
|  | } | 
|  |  | 
|  | ++wbuf_iter; | 
|  | } | 
|  | } | 
|  | if (ended) | 
|  | break; | 
|  |  | 
|  | if (wbuf_iter == temp_wbuf_end && !not_in) | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | break; | 
|  | } | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | *wstr++ = c; | 
|  |  | 
|  | if ((flags & IS_ALLOC_USED) != 0 | 
|  | && wstr == ((wchar_t *) *pstr + str_sz)) | 
|  | { | 
|  | new_sz = str_sz * 2; | 
|  | while ((wstr = (wchar_t *) realloc (*pstr, | 
|  | new_sz * sizeof (wchar_t))) == NULL | 
|  | && new_sz > (size_t) (str_sz + 1)) | 
|  | new_sz = str_sz + 1; | 
|  | if (!wstr) | 
|  | { | 
|  | if ((flags & USE_POSIX_ALLOC) == 0) | 
|  | { | 
|  | ((wchar_t *) (*pstr))[str_sz - 1] = 0; | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | *pstr = (char *) wstr; | 
|  | wstr += str_sz; | 
|  | str_sz = new_sz; | 
|  | } | 
|  | } | 
|  | } | 
|  | while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); | 
|  |  | 
|  | if (read_in_sv == read_in) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | *wstr++ = 0; | 
|  |  | 
|  | optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | read_in_sv = read_in; | 
|  |  | 
|  | if ((c = in_ch (s, &read_in)) == WEOF) | 
|  | return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  |  | 
|  | state = (mbstate_t){0}; | 
|  |  | 
|  | do | 
|  | { | 
|  | int ended = 0; | 
|  | wbuf_iter = tmp_wbuf_ptr; | 
|  | while (wbuf_iter < temp_wbuf_end) | 
|  | { | 
|  | if (wbuf_iter[0] == '-' && wbuf_iter[1] != 0 | 
|  | && (wbuf_iter + 1) != temp_wbuf_end | 
|  | && wbuf_iter != tmp_wbuf_ptr | 
|  | && (unsigned int) wbuf_iter[-1] <= (unsigned int) wbuf_iter[1]) | 
|  | { | 
|  | for (wc = wbuf_iter[-1] + 1; wc <= wbuf_iter[1] && (wint_t) wc != c; ++wc); | 
|  |  | 
|  | if (wc <= wbuf_iter[1] && !not_in) | 
|  | break; | 
|  | if (wc <= wbuf_iter[1] && not_in) | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | ended = 1; | 
|  | break; | 
|  | } | 
|  |  | 
|  | wbuf_iter += 2; | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((wint_t) *wbuf_iter == c && !not_in) | 
|  | break; | 
|  | if ((wint_t) *wbuf_iter == c && not_in) | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | ended = 1; | 
|  | break; | 
|  | } | 
|  |  | 
|  | ++wbuf_iter; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (ended) | 
|  | break; | 
|  | if (wbuf_iter == temp_wbuf_end && !not_in) | 
|  | { | 
|  | back_ch (c, s, &read_in, 0); | 
|  | break; | 
|  | } | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | if ((flags & IS_ALLOC_USED) != 0 | 
|  | && (str + MB_CUR_MAX) >= (*pstr + str_sz)) | 
|  | { | 
|  | new_sz = str_sz * 2; | 
|  | str_len = (str - *pstr); | 
|  |  | 
|  | while ((nstr = (char *) realloc (*pstr, new_sz)) == NULL | 
|  | && new_sz > (str_len + MB_CUR_MAX)) | 
|  | new_sz = str_len + MB_CUR_MAX; | 
|  | if (!nstr) | 
|  | { | 
|  | if ((flags & USE_POSIX_ALLOC) == 0) | 
|  | { | 
|  | ((*pstr))[str_len] = 0; | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | *pstr = nstr; | 
|  | str = nstr + str_len; | 
|  | str_sz = new_sz; | 
|  | } | 
|  | } | 
|  |  | 
|  | n = wcrtomb ((flags & IS_SUPPRESSED) == 0 ? str : NULL, c, &state); | 
|  | if (n == (size_t) -1LL) | 
|  | { | 
|  | errno = EILSEQ; | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  |  | 
|  | str += n; | 
|  | } | 
|  | while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); | 
|  |  | 
|  | if (read_in_sv == read_in) | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  |  | 
|  | if ((flags & IS_SUPPRESSED) == 0) | 
|  | { | 
|  | n = wcrtomb (buf, 0, &state); | 
|  | if (n > 0 && (flags & IS_ALLOC_USED) != 0 | 
|  | && (str + n) >= (*pstr + str_sz)) | 
|  | { | 
|  | str_len = (str - *pstr); | 
|  |  | 
|  | if ((nstr = (char *) realloc (*pstr, str_len + n + 1)) == NULL) | 
|  | { | 
|  | if ((flags & USE_POSIX_ALLOC) == 0) | 
|  | { | 
|  | (*pstr)[str_len] = 0; | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); | 
|  | } | 
|  | *pstr = nstr; | 
|  | str = nstr + str_len; | 
|  | str_sz = str_len + n + 1; | 
|  | } | 
|  |  | 
|  | if (n) | 
|  | { | 
|  | memcpy (str, buf, n); | 
|  | str += n; | 
|  | } | 
|  | *str++ = 0; | 
|  |  | 
|  | optimize_alloc (pstr, str, str_sz); | 
|  | pstr = NULL; | 
|  | ++rval; | 
|  | } | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (ignore_ws) | 
|  | { | 
|  | while (iswspace ((c = in_ch (s, &read_in)))); | 
|  | back_ch (c, s, &read_in, 0); | 
|  | } | 
|  |  | 
|  | return cleanup_return (rval, &gcollect, pstr, &wbuf); | 
|  | } |