2011-02-05 05:01:00 +08:00
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2019-10-29 05:25:13 +08:00
|
|
|
#define __LARGE_MBSTATE_T
|
|
|
|
|
2011-02-05 05:01:00 +08:00
|
|
|
#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>
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
|
|
|
|
/* internal stream structure with back-buffer. */
|
|
|
|
typedef struct _IFP
|
|
|
|
{
|
|
|
|
__extension__ union {
|
|
|
|
void *fp;
|
|
|
|
const char *str;
|
|
|
|
};
|
|
|
|
int bch[1024];
|
|
|
|
int is_string : 1;
|
|
|
|
int back_top;
|
|
|
|
int seen_eof : 1;
|
|
|
|
} _IFP;
|
|
|
|
|
|
|
|
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
|
2011-08-07 21:28:09 +08:00
|
|
|
optimize_alloc (char **p, char *end, size_t alloc_sz)
|
2011-02-05 05:01:00 +08:00
|
|
|
{
|
2011-08-07 21:28:09 +08:00
|
|
|
size_t need_sz;
|
2011-02-05 05:01:00 +08:00
|
|
|
char *h;
|
|
|
|
|
2011-08-07 21:28:09 +08:00
|
|
|
if (!p || !*p)
|
2011-02-05 05:01:00 +08:00
|
|
|
return;
|
2011-08-07 21:28:09 +08:00
|
|
|
|
|
|
|
need_sz = end - *p;
|
|
|
|
if (need_sz == alloc_sz)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((h = (char *) realloc (*p, need_sz)) != NULL)
|
2011-02-05 05:01:00 +08:00
|
|
|
*p = h;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
back_ch (int c, _IFP *s, size_t *rin, int not_eof)
|
|
|
|
{
|
|
|
|
if (!not_eof && c == EOF)
|
|
|
|
return;
|
|
|
|
if (s->is_string == 0)
|
|
|
|
{
|
|
|
|
FILE *fp = s->fp;
|
|
|
|
ungetc (c, fp);
|
|
|
|
rin[0] -= 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
rin[0] -= 1;
|
|
|
|
s->bch[s->back_top] = c;
|
|
|
|
s->back_top += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
in_ch (_IFP *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 EOF;
|
|
|
|
}
|
|
|
|
else if (s->is_string)
|
|
|
|
{
|
|
|
|
const char *ps = s->str;
|
|
|
|
r = ((int) *ps) & 0xff;
|
|
|
|
ps++;
|
|
|
|
if (r != 0)
|
|
|
|
{
|
|
|
|
rin[0] += 1;
|
|
|
|
s->str = ps;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
s->seen_eof = 1;
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FILE *fp = (FILE *) s->fp;
|
|
|
|
r = getc (fp);
|
|
|
|
if (r != EOF)
|
|
|
|
rin[0] += 1;
|
|
|
|
else s->seen_eof = 1;
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
match_string (_IFP *s, size_t *rin, int *c, const char *str)
|
|
|
|
{
|
|
|
|
int ch = *c;
|
|
|
|
|
|
|
|
if (*str == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (*str != (char) tolower (ch))
|
|
|
|
return 0;
|
|
|
|
++str;
|
|
|
|
while (*str != 0)
|
|
|
|
{
|
|
|
|
if ((ch = in_ch (s, rin)) == EOF)
|
|
|
|
{
|
|
|
|
c[0] = ch;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*str != (char) tolower (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, char **wbuf)
|
|
|
|
{
|
|
|
|
struct gcollect *pf;
|
|
|
|
size_t cnt;
|
|
|
|
|
2016-02-25 02:50:02 +08:00
|
|
|
if (wbuf)
|
|
|
|
{
|
|
|
|
free (*wbuf);
|
|
|
|
*wbuf = NULL;
|
|
|
|
}
|
2011-02-05 05:01:00 +08:00
|
|
|
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, char **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 char *
|
|
|
|
resize_wbuf (size_t wpsz, size_t *wbuf_max_sz, char *old)
|
|
|
|
{
|
|
|
|
char *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 = (char *) malloc (nsz);
|
|
|
|
else
|
|
|
|
wbuf = (char *) realloc (old, nsz);
|
|
|
|
if (!wbuf)
|
|
|
|
{
|
|
|
|
if (old)
|
|
|
|
free (old);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*wbuf_max_sz = nsz;
|
|
|
|
return wbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
__mingw_sformat (_IFP *s, const char *format, va_list argp)
|
|
|
|
{
|
|
|
|
const char *f = format;
|
|
|
|
struct gcollect *gcollect = NULL;
|
|
|
|
size_t read_in = 0, wbuf_max_sz = 0, cnt;
|
|
|
|
ssize_t str_sz = 0;
|
|
|
|
char *str = NULL, **pstr = NULL, *wbuf = NULL;
|
|
|
|
wchar_t *wstr = NULL;
|
|
|
|
int rval = 0, c = 0, ignore_ws = 0;
|
|
|
|
va_list arg;
|
|
|
|
unsigned char fc;
|
|
|
|
unsigned int npos;
|
2011-02-05 17:52:40 +08:00
|
|
|
int width, flags, base = 0, errno_sv;
|
2011-02-05 05:01:00 +08:00
|
|
|
size_t wbuf_cur_sz, read_in_sv, new_sz, n;
|
|
|
|
char seen_dot, seen_exp, is_neg, not_in;
|
|
|
|
char *tmp_wbuf_ptr, buf[MB_LEN_MAX];
|
|
|
|
const char *lc_decimal_point, *lc_thousands_sep;
|
|
|
|
mbstate_t state, cstate;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset (&state, 0, sizeof (state));
|
|
|
|
|
|
|
|
lc_decimal_point = localeconv()->decimal_point;
|
|
|
|
lc_thousands_sep = localeconv()->thousands_sep;
|
|
|
|
if (lc_thousands_sep != NULL && *lc_thousands_sep == 0)
|
|
|
|
lc_thousands_sep = NULL;
|
|
|
|
|
|
|
|
while (*f != 0)
|
|
|
|
{
|
|
|
|
if (!isascii ((unsigned char) *f))
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if ((len = mbrlen (f, strlen (f), &state)) > 0)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if ((c = in_ch (s, &read_in)) == EOF || c != (unsigned char) *f++)
|
|
|
|
{
|
|
|
|
back_ch (c, s, &read_in, 1);
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (--len > 0);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fc = *f++;
|
|
|
|
if (fc != '%')
|
|
|
|
{
|
|
|
|
if (isspace (fc))
|
|
|
|
ignore_ws = 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((c = in_ch (s, &read_in)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
if (ignore_ws)
|
|
|
|
{
|
|
|
|
ignore_ws = 0;
|
|
|
|
if (isspace (c))
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if ((c = in_ch (s, &read_in)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
while (isspace (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 (isdigit ((unsigned char) *f))
|
|
|
|
{
|
|
|
|
const char *svf = f;
|
|
|
|
npos = (unsigned char) *f++ - '0';
|
|
|
|
while (isdigit ((unsigned char) *f))
|
|
|
|
npos = npos * 10 + ((unsigned char) *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')
|
2013-02-13 19:53:45 +08:00
|
|
|
{
|
|
|
|
/* 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
|
|
|
|
}
|
2011-02-05 05:01:00 +08:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
++f;
|
|
|
|
}
|
|
|
|
while (1);
|
|
|
|
|
|
|
|
while (isdigit ((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
|
2013-02-13 19:53:45 +08:00
|
|
|
flags |= IS_LL | IS_L;
|
2011-02-05 05:01:00 +08:00
|
|
|
#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 == EOF || (c = in_ch (s, &read_in)) == EOF)
|
|
|
|
&& errno == EINTR)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
while (isspace (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)) == EOF)
|
|
|
|
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 = (width > 1024 ? 1024 : width);
|
|
|
|
if ((str = *pstr = (char *) malloc (str_sz)) == 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)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz))
|
|
|
|
{
|
|
|
|
new_sz = str_sz + (str_sz >= width ? width - 1 : str_sz);
|
|
|
|
while ((str = (char *) realloc (*pstr, new_sz)) == NULL
|
|
|
|
&& new_sz > (size_t) (str_sz + 1))
|
|
|
|
new_sz = str_sz + 1;
|
|
|
|
if (!str)
|
|
|
|
{
|
|
|
|
release_ptrs (&gcollect, &wbuf);
|
|
|
|
return EOF;
|
|
|
|
}
|
|
|
|
*pstr = str;
|
|
|
|
str += str_sz;
|
|
|
|
str_sz = new_sz;
|
|
|
|
}
|
|
|
|
*str++ = c;
|
|
|
|
}
|
|
|
|
while (--width > 0 && (c = in_ch (s, &read_in)) != EOF);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
while (--width > 0 && (c = in_ch (s, &read_in)) != EOF);
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
2011-08-07 21:28:09 +08:00
|
|
|
optimize_alloc (pstr, str, str_sz);
|
2011-02-05 05:01:00 +08:00
|
|
|
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);
|
|
|
|
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)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
memset (&cstate, 0, sizeof (cstate));
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
buf[0] = c;
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0 && (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;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate);
|
|
|
|
|
|
|
|
if (n == (size_t) -2)
|
|
|
|
{
|
|
|
|
if ((c = in_ch (s, &read_in)) == EOF)
|
|
|
|
{
|
|
|
|
errno = EILSEQ;
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[0] = c;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n != 1)
|
|
|
|
{
|
|
|
|
errno = EILSEQ;
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++wstr;
|
|
|
|
}
|
|
|
|
while (--width > 0 && (c = in_ch (s, &read_in)) != EOF);
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
2011-08-07 21:28:09 +08:00
|
|
|
optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t));
|
2011-02-05 05:01:00 +08:00
|
|
|
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)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (isspace (c))
|
|
|
|
{
|
|
|
|
back_ch (c, s, &read_in, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
*str++ = c;
|
|
|
|
if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz))
|
|
|
|
{
|
|
|
|
new_sz = str_sz * 2;
|
|
|
|
|
|
|
|
while ((str = (char *) realloc (*pstr, new_sz)) == NULL
|
|
|
|
&& new_sz > (size_t) (str_sz + 1))
|
|
|
|
new_sz = str_sz + 1;
|
|
|
|
if (!str)
|
|
|
|
{
|
|
|
|
if ((flags & USE_POSIX_ALLOC) == 0)
|
|
|
|
{
|
|
|
|
(*pstr)[str_sz - 1] = 0;
|
|
|
|
pstr = NULL;
|
|
|
|
++rval;
|
|
|
|
}
|
|
|
|
return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
*pstr = str;
|
|
|
|
str += str_sz;
|
|
|
|
str_sz = new_sz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != EOF);
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
*str++ = 0;
|
2011-08-07 21:28:09 +08:00
|
|
|
optimize_alloc (pstr, str, str_sz);
|
2011-02-05 05:01:00 +08:00
|
|
|
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)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
memset (&cstate, 0, sizeof (cstate));
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (isspace (c))
|
|
|
|
{
|
|
|
|
back_ch (c, s, &read_in, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[0] = c;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate);
|
|
|
|
|
|
|
|
if (n == (size_t) -2)
|
|
|
|
{
|
|
|
|
if ((c = in_ch (s, &read_in)) == EOF)
|
|
|
|
{
|
|
|
|
errno = EILSEQ;
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[0] = c;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n != 1)
|
|
|
|
{
|
|
|
|
errno = EILSEQ;
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
++wstr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0 && (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)) != EOF);
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
*wstr++ = 0;
|
2011-08-07 21:28:09 +08:00
|
|
|
optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t));
|
2011-02-05 05:01:00 +08:00
|
|
|
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)) == EOF)
|
|
|
|
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 && tolower (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 != EOF && width != 0)
|
|
|
|
{
|
|
|
|
if (base == 16)
|
|
|
|
{
|
|
|
|
if (!isxdigit (c))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (!isdigit (c) || (int) (c - '0') >= base)
|
|
|
|
{
|
|
|
|
const char *p = lc_thousands_sep;
|
|
|
|
int remain;
|
|
|
|
|
|
|
|
if (base != 10 || (flags & USE_GROUP) == 0)
|
|
|
|
break;
|
|
|
|
remain = width > 0 ? width : INT_MAX;
|
|
|
|
while ((unsigned char) *p == c && remain >= 0)
|
|
|
|
{
|
|
|
|
/* As our conversion routines aren't supporting thousands
|
|
|
|
separators, we are filtering them here. */
|
|
|
|
|
|
|
|
++p;
|
|
|
|
if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF)
|
|
|
|
break;
|
|
|
|
--remain;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p != 0)
|
|
|
|
{
|
|
|
|
if (p > lc_thousands_sep)
|
|
|
|
{
|
|
|
|
back_ch (c, s, &read_in, 0);
|
|
|
|
while (--p > lc_thousands_sep)
|
|
|
|
back_ch ((unsigned char) *p, s, &read_in, 1);
|
|
|
|
c = (unsigned char) *p;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width > 0)
|
|
|
|
width = remain;
|
2016-08-18 17:24:17 +08:00
|
|
|
--wbuf_cur_sz;
|
2011-02-05 05:01:00 +08:00
|
|
|
}
|
|
|
|
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, "(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))
|
|
|
|
{
|
|
|
|
if (flags & IS_SIGNED_NUM)
|
|
|
|
cv_val.ll = strtoll (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/);
|
|
|
|
else
|
|
|
|
cv_val.ull = strtoull (wbuf, &tmp_wbuf_ptr, base);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (flags & IS_SIGNED_NUM)
|
|
|
|
cv_val.l = strtol (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/);
|
|
|
|
else
|
|
|
|
cv_val.ul = strtoul (wbuf, &tmp_wbuf_ptr, base);
|
|
|
|
}
|
|
|
|
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)) == EOF)
|
|
|
|
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)) == EOF)
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
if (width > 0)
|
|
|
|
--width;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tolower (c) == 'n')
|
|
|
|
{
|
|
|
|
const char *match_txt = "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)) == EOF || tolower (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 (tolower (c) == 'i')
|
|
|
|
{
|
|
|
|
const char *match_txt = "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)) == EOF || tolower (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)) != EOF && tolower (c) == 'i')
|
|
|
|
{
|
|
|
|
match_txt = "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)) == EOF || tolower (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 != EOF)
|
|
|
|
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 && tolower (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 (isdigit (c) || (!seen_exp && (flags & IS_HEX_FLOAT) != 0 && isxdigit (c))
|
|
|
|
|| (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 && (char) tolower (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
|
|
|
|
{
|
|
|
|
const char *p = lc_decimal_point;
|
|
|
|
int remain = width > 0 ? width : INT_MAX;
|
|
|
|
|
|
|
|
if (! seen_dot)
|
|
|
|
{
|
|
|
|
while ((unsigned char) *p == c && remain >= 0)
|
|
|
|
{
|
|
|
|
++p;
|
|
|
|
if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF)
|
|
|
|
break;
|
|
|
|
--remain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p == 0)
|
|
|
|
{
|
|
|
|
for (p = lc_decimal_point; *p != 0; ++p)
|
|
|
|
{
|
|
|
|
wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
|
|
|
|
wbuf[wbuf_cur_sz++] = (unsigned char) *p;
|
|
|
|
}
|
|
|
|
if (width > 0)
|
|
|
|
width = remain;
|
|
|
|
seen_dot = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const char *pp = lc_thousands_sep;
|
|
|
|
|
|
|
|
if (!seen_dot && (flags & USE_GROUP) != 0)
|
|
|
|
{
|
|
|
|
while ((pp - lc_thousands_sep) < (p - lc_decimal_point)
|
|
|
|
&& *pp == lc_decimal_point[(pp - lc_thousands_sep)])
|
|
|
|
++pp;
|
|
|
|
if ((pp - lc_thousands_sep) == (p - lc_decimal_point))
|
|
|
|
{
|
|
|
|
while ((unsigned char) *pp == c && remain >= 0)
|
|
|
|
{
|
|
|
|
++pp;
|
|
|
|
if (*pp == 0 || !remain || (c = in_ch (s, &read_in)) == EOF)
|
|
|
|
break;
|
|
|
|
--remain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pp != NULL && *pp == 0)
|
|
|
|
{
|
|
|
|
/* As our conversion routines aren't supporting thousands
|
|
|
|
separators, we are filtering them here. */
|
|
|
|
if (width > 0)
|
|
|
|
width = remain;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
back_ch (c, s, &read_in, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width == 0 || (c = in_ch (s, &read_in)) == EOF)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (width > 0)
|
|
|
|
--width;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!wbuf_cur_sz || ((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 ld;
|
|
|
|
ld = __mingw_strtold (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 ? -ld : ld;
|
|
|
|
}
|
|
|
|
else if ((flags & IS_L) != 0)
|
|
|
|
{
|
|
|
|
double d;
|
|
|
|
d = (double) __mingw_strtold (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_strtof (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;
|
|
|
|
|
|
|
|
if (wbuf_max_sz < 256)
|
|
|
|
{
|
|
|
|
wbuf_max_sz = 256;
|
|
|
|
if (wbuf)
|
|
|
|
free (wbuf);
|
|
|
|
wbuf = (char *) malloc (wbuf_max_sz);
|
|
|
|
}
|
|
|
|
memset (wbuf, 0, 256);
|
|
|
|
|
|
|
|
fc = *f;
|
|
|
|
if (fc == ']' || fc == '-')
|
|
|
|
{
|
|
|
|
wbuf[fc] = 1;
|
|
|
|
++f;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((fc = *f++) != 0 && fc != ']')
|
|
|
|
{
|
|
|
|
if (fc == '-' && *f != 0 && *f != ']' && (unsigned char) f[-2] <= (unsigned char) *f)
|
|
|
|
{
|
|
|
|
for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
|
|
|
|
wbuf[fc] = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
wbuf[fc] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fc)
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
if ((flags & IS_L) != 0)
|
|
|
|
{
|
|
|
|
read_in_sv = read_in;
|
|
|
|
cnt = 0;
|
|
|
|
|
|
|
|
if ((c = in_ch (s, &read_in)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
memset (&cstate, 0, sizeof (cstate));
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (wbuf[c] == not_in)
|
|
|
|
{
|
|
|
|
back_ch (c, s, &read_in, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
buf[0] = c;
|
|
|
|
n = mbrtowc (wstr, buf, 1, &cstate);
|
|
|
|
|
|
|
|
if (n == (size_t) -2)
|
|
|
|
{
|
|
|
|
++cnt;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cnt = 0;
|
|
|
|
|
|
|
|
++wstr;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rval = EOF;
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
*pstr = (char *) wstr;
|
|
|
|
wstr += str_sz;
|
|
|
|
str_sz = new_sz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (--width <= 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while ((c = in_ch (s, &read_in)) != EOF);
|
|
|
|
|
|
|
|
if (cnt != 0)
|
|
|
|
{
|
|
|
|
errno = EILSEQ;
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read_in_sv == read_in)
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
*wstr++ = 0;
|
2011-08-07 21:28:09 +08:00
|
|
|
optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t));
|
2011-02-05 05:01:00 +08:00
|
|
|
pstr = NULL;
|
|
|
|
++rval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
read_in_sv = read_in;
|
|
|
|
|
|
|
|
if ((c = in_ch (s, &read_in)) == EOF)
|
|
|
|
return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (wbuf[c] == not_in)
|
|
|
|
{
|
|
|
|
back_ch (c, s, &read_in, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
*str++ = c;
|
|
|
|
if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz))
|
|
|
|
{
|
|
|
|
new_sz = str_sz * 2;
|
|
|
|
|
|
|
|
while ((str = (char *) realloc (*pstr, new_sz)) == NULL
|
|
|
|
&& new_sz > (size_t) (str_sz + 1))
|
|
|
|
new_sz = str_sz + 1;
|
|
|
|
if (!str)
|
|
|
|
{
|
|
|
|
if ((flags & USE_POSIX_ALLOC) == 0)
|
|
|
|
{
|
|
|
|
(*pstr)[str_sz - 1] = 0;
|
|
|
|
pstr = NULL;
|
|
|
|
++rval;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rval = EOF;
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
*pstr = str;
|
|
|
|
str += str_sz;
|
|
|
|
str_sz = new_sz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (--width > 0 && (c = in_ch (s, &read_in)) != EOF);
|
|
|
|
|
|
|
|
if (read_in_sv == read_in)
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
|
|
|
|
if ((flags & IS_SUPPRESSED) == 0)
|
|
|
|
{
|
|
|
|
*str++ = 0;
|
2011-08-07 21:28:09 +08:00
|
|
|
optimize_alloc (pstr, str, str_sz);
|
2011-02-05 05:01:00 +08:00
|
|
|
pstr = NULL;
|
|
|
|
++rval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ignore_ws)
|
|
|
|
{
|
|
|
|
while (isspace ((c = in_ch (s, &read_in))));
|
|
|
|
back_ch (c, s, &read_in, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cleanup_return (rval, &gcollect, pstr, &wbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
__mingw_vfscanf (FILE *s, const char *format, va_list argp)
|
|
|
|
{
|
|
|
|
_IFP ifp;
|
|
|
|
memset (&ifp, 0, sizeof (_IFP));
|
|
|
|
ifp.fp = s;
|
|
|
|
return __mingw_sformat (&ifp, format, argp);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
__mingw_vsscanf (const char *s, const char *format, va_list argp)
|
|
|
|
{
|
|
|
|
_IFP ifp;
|
|
|
|
memset (&ifp, 0, sizeof (_IFP));
|
|
|
|
ifp.str = s;
|
|
|
|
ifp.is_string = 1;
|
|
|
|
return __mingw_sformat (&ifp, format, argp);
|
|
|
|
}
|
|
|
|
|