newlib: vf[w]scanf: Implement POSIX %m modifier
* The new code is guarded with _WANT_IO_POSIX_EXTENSIONS, but this is automatically enabled with _WANT_IO_C99_FORMATS for now. * vfscanf neglects to implement %l[, so %ml[ is not implemented yet either. * Sidenote: vfwscanf doesn't allow ranges in %[ yet. Strictly this is allowed per POSIX, but it differes from vfscanf as well as from glibc. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
27c1a7972c
commit
d43863f569
|
@ -212,6 +212,7 @@ static void * get_arg (int, va_list *, int *, void **);
|
|||
#define SUPPRESS 0x10 /* suppress assignment */
|
||||
#define POINTER 0x20 /* weird %p pointer (`fake hex') */
|
||||
#define NOSKIP 0x40 /* do not skip blanks */
|
||||
#define MALLOC 0x80 /* handle 'm' modifier */
|
||||
|
||||
/*
|
||||
* The following are used in numeric conversions only:
|
||||
|
@ -453,6 +454,122 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
#ifdef _MB_CAPABLE
|
||||
mbstate_t state; /* value to keep track of multibyte state */
|
||||
#endif
|
||||
#ifdef _WANT_IO_C99_FORMATS
|
||||
#define _WANT_IO_POSIX_EXTENSIONS
|
||||
#endif
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
/* POSIX requires that fscanf frees all allocated strings from 'm'
|
||||
conversions in case it returns EOF. m_ptr is used to keep track.
|
||||
It will be allocated on the stack the first time an 'm' conversion
|
||||
takes place, and it will be free'd on return from the function.
|
||||
This implementation tries to save space by only allocating 8
|
||||
pointer slots at a time. Most scenarios should never have to call
|
||||
realloc again. This implementation allows only up to 65528 'm'
|
||||
conversions per fscanf invocation for now. That should be enough
|
||||
for almost all scenarios, right? */
|
||||
struct m_ptrs {
|
||||
void ***m_arr; /* Array of pointer args to 'm' conversion */
|
||||
uint16_t m_siz; /* Number of slots in m_arr */
|
||||
uint16_t m_cnt; /* Number of valid entries in m_arr */
|
||||
} *m_ptr = NULL;
|
||||
#define init_m_ptr() \
|
||||
do \
|
||||
{ \
|
||||
if (!m_ptr) \
|
||||
{ \
|
||||
m_ptr = (struct m_ptrs *) alloca (sizeof *m_ptr); \
|
||||
m_ptr->m_arr = NULL; \
|
||||
m_ptr->m_siz = 0; \
|
||||
m_ptr->m_cnt = 0; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#define push_m_ptr(arg) \
|
||||
do \
|
||||
{ \
|
||||
if (m_ptr->m_cnt >= m_ptr->m_siz) \
|
||||
{ \
|
||||
void ***n = NULL; \
|
||||
\
|
||||
if (m_ptr->m_siz + 8 > 0 && m_ptr->m_siz + 8 < UINT16_MAX) \
|
||||
n = (void ***) realloc (m_ptr->m_arr, \
|
||||
(m_ptr->m_siz + 8) * \
|
||||
sizeof (void **)); \
|
||||
if (!n) \
|
||||
{ \
|
||||
nassigned = EOF; \
|
||||
goto match_failure; \
|
||||
} \
|
||||
m_ptr->m_arr = n; \
|
||||
m_ptr->m_siz += 8; \
|
||||
} \
|
||||
m_ptr->m_arr[m_ptr->m_cnt++] = (void **) (arg); \
|
||||
} \
|
||||
while (0)
|
||||
#define alloc_m_ptr(_type, _p, _p0, _p_p, _w) \
|
||||
({ \
|
||||
_p_p = GET_ARG (N, ap, _type **); \
|
||||
if (!_p_p) \
|
||||
goto match_failure; \
|
||||
_p0 = (_type *) malloc ((_w) * sizeof (_type)); \
|
||||
if (!_p0) \
|
||||
{ \
|
||||
nassigned = EOF; \
|
||||
goto match_failure; \
|
||||
} \
|
||||
*_p_p = _p0; \
|
||||
push_m_ptr (_p_p); \
|
||||
_p = _p0; \
|
||||
_w; \
|
||||
})
|
||||
#define realloc_m_ptr(_type, _p, _p0, _p_p, _w) \
|
||||
({ \
|
||||
size_t _nw = (_w); \
|
||||
if (_p_p && _p - _p0 == _nw) \
|
||||
{ \
|
||||
_p0 = (_type *) realloc (_p0, (_nw << 1) * sizeof (_type)); \
|
||||
if (!_p0) \
|
||||
{ \
|
||||
nassigned = EOF; \
|
||||
goto match_failure; \
|
||||
} \
|
||||
_p = _p0 + _nw; \
|
||||
*_p_p = _p0; \
|
||||
_nw <<= 1; \
|
||||
} \
|
||||
_nw; \
|
||||
})
|
||||
#define shrink_m_ptr(_type, _p_p, _w, _cw) \
|
||||
({ \
|
||||
size_t _nw = (_w); \
|
||||
if (_p_p && _nw < _cw) \
|
||||
{ \
|
||||
_type *_np_p = (_type *) \
|
||||
realloc (*_p_p, _nw * sizeof (_type)); \
|
||||
if (_np_p) \
|
||||
*_p_p = _np_p; \
|
||||
} \
|
||||
})
|
||||
#define free_m_ptr() \
|
||||
do \
|
||||
{ \
|
||||
if (m_ptr) \
|
||||
{ \
|
||||
if (nassigned == EOF) \
|
||||
{ \
|
||||
int i; \
|
||||
for (i = 0; i < m_ptr->m_cnt; ++i) \
|
||||
{ \
|
||||
free (*m_ptr->m_arr[i]); \
|
||||
*m_ptr->m_arr[i] = NULL; \
|
||||
} \
|
||||
} \
|
||||
if (m_ptr->m_arr) \
|
||||
free (m_ptr->m_arr); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
#define CCFN_PARAMS _PARAMS((struct _reent *, const char *, char **, int))
|
||||
u_long (*ccfn)CCFN_PARAMS=0; /* conversion function (strtol/strtoul) */
|
||||
|
@ -564,7 +681,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
continue;
|
||||
|
||||
case '*':
|
||||
if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||
if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS | MALLOC))
|
||||
|| width)
|
||||
goto match_failure;
|
||||
flags |= SUPPRESS;
|
||||
|
@ -645,6 +762,14 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
flags |= LONGDBL;
|
||||
goto again;
|
||||
#endif /* _WANT_IO_C99_FORMATS */
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
case 'm':
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | MALLOC))
|
||||
goto match_failure;
|
||||
init_m_ptr ();
|
||||
flags |= MALLOC;
|
||||
goto again;
|
||||
#endif
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
|
@ -656,14 +781,14 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | MALLOC))
|
||||
goto match_failure;
|
||||
width = width * 10 + c - '0';
|
||||
goto again;
|
||||
|
||||
#ifndef _NO_POS_ARGS
|
||||
case '$':
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS | MALLOC))
|
||||
goto match_failure;
|
||||
if (width <= MAX_POS_ARGS)
|
||||
{
|
||||
|
@ -851,12 +976,21 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
|
||||
if (flags & LONG)
|
||||
{
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
wchar_t **wcp_p = NULL;
|
||||
wchar_t *wcp0 = NULL;
|
||||
size_t width0 = 0;
|
||||
#endif
|
||||
mbstate_t state;
|
||||
memset (&state, 0, sizeof (mbstate_t));
|
||||
if ((flags & SUPPRESS) == 0)
|
||||
wcp = GET_ARG (N, ap, wchar_t *);
|
||||
else
|
||||
if (flags & SUPPRESS)
|
||||
wcp = NULL;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
else if (flags & MALLOC)
|
||||
width0 = alloc_m_ptr (wchar_t, wcp, wcp0, wcp_p, width);
|
||||
#endif
|
||||
else
|
||||
wcp = GET_ARG (N, ap, wchar_t *);
|
||||
n = 0;
|
||||
while (width != 0)
|
||||
{
|
||||
|
@ -885,6 +1019,9 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
break;
|
||||
}
|
||||
}
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (wchar_t, wcp_p, width0 - width, width0);
|
||||
#endif
|
||||
if (!(flags & SUPPRESS))
|
||||
nassigned++;
|
||||
}
|
||||
|
@ -919,10 +1056,20 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
}
|
||||
else
|
||||
{
|
||||
size_t r = _fread_r (rptr, (_PTR) GET_ARG (N, ap, char *), 1, width, fp);
|
||||
|
||||
size_t r;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
char **p_p = NULL;
|
||||
if (flags & MALLOC)
|
||||
alloc_m_ptr (char, p, p0, p_p, width);
|
||||
else
|
||||
#endif
|
||||
p = GET_ARG (N, ap, char *);
|
||||
r = _fread_r (rptr, p, 1, width, fp);
|
||||
if (r == 0)
|
||||
goto input_failure;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (char, p_p, r, width);
|
||||
#endif
|
||||
nread += r;
|
||||
nassigned++;
|
||||
}
|
||||
|
@ -953,11 +1100,22 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
}
|
||||
else
|
||||
{
|
||||
p0 = p = GET_ARG (N, ap, char *);
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
char **p_p = NULL;
|
||||
size_t p_siz = 0;
|
||||
|
||||
if (flags & MALLOC)
|
||||
p_siz = alloc_m_ptr (char, p, p0, p_p, 32);
|
||||
else
|
||||
#endif
|
||||
p0 = p = GET_ARG (N, ap, char *);
|
||||
while (ccltab[*fp->_p])
|
||||
{
|
||||
fp->_r--;
|
||||
*p++ = *fp->_p++;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
p_siz = realloc_m_ptr (char, p, p0, p_p, p_siz);
|
||||
#endif
|
||||
if (--width == 0)
|
||||
break;
|
||||
if (BufferEmpty)
|
||||
|
@ -971,6 +1129,9 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
if (n == 0)
|
||||
goto match_failure;
|
||||
*p = 0;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (char, p_p, n + 1, p_siz);
|
||||
#endif
|
||||
nassigned++;
|
||||
}
|
||||
nread += n;
|
||||
|
@ -983,13 +1144,22 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
|
||||
if (flags & LONG)
|
||||
{
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
wchar_t **wcp_p = NULL;
|
||||
wchar_t *wcp0 = NULL;
|
||||
size_t wcp_siz = 0;
|
||||
#endif
|
||||
/* Process %S and %ls placeholders */
|
||||
mbstate_t state;
|
||||
memset (&state, 0, sizeof (mbstate_t));
|
||||
if ((flags & SUPPRESS) == 0)
|
||||
wcp = GET_ARG (N, ap, wchar_t *);
|
||||
else
|
||||
if (flags & SUPPRESS)
|
||||
wcp = &wc;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
else if (flags & MALLOC)
|
||||
wcp_siz = alloc_m_ptr (wchar_t, wcp, wcp0, wcp_p, 32);
|
||||
#endif
|
||||
else
|
||||
wcp = GET_ARG (N, ap, wchar_t *);
|
||||
n = 0;
|
||||
while (!isspace (*fp->_p) && width != 0)
|
||||
{
|
||||
|
@ -1014,7 +1184,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
nread += n;
|
||||
width -= 1;
|
||||
if ((flags & SUPPRESS) == 0)
|
||||
wcp += 1;
|
||||
{
|
||||
wcp += 1;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
wcp_siz = realloc_m_ptr (wchar_t, wcp, wcp0, wcp_p,
|
||||
wcp_siz);
|
||||
#endif
|
||||
}
|
||||
n = 0;
|
||||
}
|
||||
if (BufferEmpty)
|
||||
|
@ -1027,6 +1203,9 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
if (!(flags & SUPPRESS))
|
||||
{
|
||||
*wcp = L'\0';
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (wchar_t, wcp_p, wcp - wcp0 + 1, wcp_siz);
|
||||
#endif
|
||||
nassigned++;
|
||||
}
|
||||
}
|
||||
|
@ -1047,17 +1226,32 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
|||
}
|
||||
else
|
||||
{
|
||||
p0 = p = GET_ARG (N, ap, char *);
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
char **p_p = NULL;
|
||||
size_t p_siz = 0;
|
||||
|
||||
if (flags & MALLOC)
|
||||
p_siz = alloc_m_ptr (char, p, p0, p_p, 32);
|
||||
else
|
||||
#endif
|
||||
p0 = GET_ARG (N, ap, char *);
|
||||
p = p0;
|
||||
while (!isspace (*fp->_p))
|
||||
{
|
||||
fp->_r--;
|
||||
*p++ = *fp->_p++;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
p_siz = realloc_m_ptr (char, p, p0, p_p, p_siz);
|
||||
#endif
|
||||
if (--width == 0)
|
||||
break;
|
||||
if (BufferEmpty)
|
||||
break;
|
||||
}
|
||||
*p = 0;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (char, p_p, p - p0 + 1, p_siz);
|
||||
#endif
|
||||
nread += p - p0;
|
||||
nassigned++;
|
||||
}
|
||||
|
@ -1647,6 +1841,9 @@ match_failure:
|
|||
all_done:
|
||||
/* Return number of matches, which can be 0 on match failure. */
|
||||
_newlib_flockfile_end (fp);
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
free_m_ptr ();
|
||||
#endif
|
||||
return nassigned;
|
||||
}
|
||||
|
||||
|
|
|
@ -219,6 +219,7 @@ static void * get_arg (int, va_list *, int *, void **);
|
|||
#define SUPPRESS 0x10 /* suppress assignment */
|
||||
#define POINTER 0x20 /* weird %p pointer (`fake hex') */
|
||||
#define NOSKIP 0x40 /* do not skip blanks */
|
||||
#define MALLOC 0x80 /* handle 'm' modifier */
|
||||
|
||||
/*
|
||||
* The following are used in numeric conversions only:
|
||||
|
@ -424,6 +425,125 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
#ifndef _NO_LONGLONG
|
||||
long long *llp;
|
||||
#endif
|
||||
#ifdef _WANT_IO_C99_FORMATS
|
||||
#define _WANT_IO_POSIX_EXTENSIONS
|
||||
#endif
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
/* POSIX requires that fwscanf frees all allocated strings from 'm'
|
||||
conversions in case it returns EOF. m_ptr is used to keep track.
|
||||
It will be allocated on the stack the first time an 'm' conversion
|
||||
takes place, and it will be free'd on return from the function.
|
||||
This implementation tries to save space by only allocating 8
|
||||
pointer slots at a time. Most scenarios should never have to call
|
||||
realloc again. This implementation allows only up to 65528 'm'
|
||||
conversions per fwscanf invocation for now. That should be enough
|
||||
for almost all scenarios, right? */
|
||||
struct m_ptrs {
|
||||
void ***m_arr; /* Array of pointer args to 'm' conversion */
|
||||
uint16_t m_siz; /* Number of slots in m_arr */
|
||||
uint16_t m_cnt; /* Number of valid entries in m_arr */
|
||||
} *m_ptr = NULL;
|
||||
#define init_m_ptr() \
|
||||
do \
|
||||
{ \
|
||||
if (!m_ptr) \
|
||||
{ \
|
||||
m_ptr = (struct m_ptrs *) alloca (sizeof *m_ptr); \
|
||||
m_ptr->m_arr = NULL; \
|
||||
m_ptr->m_siz = 0; \
|
||||
m_ptr->m_cnt = 0; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#define push_m_ptr(arg) \
|
||||
do \
|
||||
{ \
|
||||
if (m_ptr->m_cnt >= m_ptr->m_siz) \
|
||||
{ \
|
||||
void ***n = NULL; \
|
||||
\
|
||||
if (m_ptr->m_siz + 8 > 0 && m_ptr->m_siz + 8 < UINT16_MAX) \
|
||||
n = (void ***) realloc (m_ptr->m_arr, \
|
||||
(m_ptr->m_siz + 8) * \
|
||||
sizeof (void **)); \
|
||||
if (!n) \
|
||||
{ \
|
||||
nassigned = EOF; \
|
||||
goto match_failure; \
|
||||
} \
|
||||
m_ptr->m_arr = n; \
|
||||
m_ptr->m_siz += 8; \
|
||||
} \
|
||||
m_ptr->m_arr[m_ptr->m_cnt++] = (void **) (arg); \
|
||||
} \
|
||||
while (0)
|
||||
#define alloc_m_ptr(_type, _p, _p0, _p_p, _w) \
|
||||
({ \
|
||||
_p_p = GET_ARG (N, ap, _type **); \
|
||||
if (!_p_p) \
|
||||
goto match_failure; \
|
||||
_p0 = (_type *) malloc ((_w) * sizeof (_type)); \
|
||||
if (!_p0) \
|
||||
{ \
|
||||
nassigned = EOF; \
|
||||
goto match_failure; \
|
||||
} \
|
||||
*_p_p = _p0; \
|
||||
push_m_ptr (_p_p); \
|
||||
_p = _p0; \
|
||||
_w; \
|
||||
})
|
||||
#define realloc_m_ptr(_type, _p, _p0, _p_p, _w) \
|
||||
({ \
|
||||
size_t _nw = (_w); \
|
||||
ptrdiff_t _dif = _p - _p0; \
|
||||
if (_p_p && \
|
||||
((sizeof (_type) == 1 && _dif >= _nw - MB_CUR_MAX) \
|
||||
|| (sizeof (_type) != 1 && _dif == _nw))) \
|
||||
{ \
|
||||
_p0 = (_type *) realloc (_p0, (_nw << 1) * sizeof (_type)); \
|
||||
if (!_p0) \
|
||||
{ \
|
||||
nassigned = EOF; \
|
||||
goto match_failure; \
|
||||
} \
|
||||
_p = _p0 + _dif; \
|
||||
*_p_p = _p0; \
|
||||
_nw <<= 1; \
|
||||
} \
|
||||
_nw; \
|
||||
})
|
||||
#define shrink_m_ptr(_type, _p_p, _w, _cw) \
|
||||
({ \
|
||||
size_t _nw = (_w); \
|
||||
if (_p_p && _nw < _cw) \
|
||||
{ \
|
||||
_type *_np_p = (_type *) \
|
||||
realloc (*_p_p, _nw * sizeof (_type)); \
|
||||
if (_np_p) \
|
||||
*_p_p = _np_p; \
|
||||
} \
|
||||
})
|
||||
#define free_m_ptr() \
|
||||
do \
|
||||
{ \
|
||||
if (m_ptr) \
|
||||
{ \
|
||||
if (nassigned == EOF) \
|
||||
{ \
|
||||
int i; \
|
||||
for (i = 0; i < m_ptr->m_cnt; ++i) \
|
||||
{ \
|
||||
free (*m_ptr->m_arr[i]); \
|
||||
*m_ptr->m_arr[i] = NULL; \
|
||||
} \
|
||||
} \
|
||||
if (m_ptr->m_arr) \
|
||||
free (m_ptr->m_arr); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
/* `basefix' is used to avoid `if' tests in the integer scanner */
|
||||
static _CONST short basefix[17] =
|
||||
|
@ -518,7 +638,7 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
continue;
|
||||
|
||||
case L'*':
|
||||
if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||
if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS | MALLOC))
|
||||
|| width)
|
||||
flags |= SUPPRESS;
|
||||
goto again;
|
||||
|
@ -598,6 +718,14 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
flags |= LONGDBL;
|
||||
goto again;
|
||||
#endif /* _WANT_IO_C99_FORMATS */
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
case 'm':
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | MALLOC))
|
||||
goto match_failure;
|
||||
init_m_ptr ();
|
||||
flags |= MALLOC;
|
||||
goto again;
|
||||
#endif
|
||||
|
||||
case L'0':
|
||||
case L'1':
|
||||
|
@ -609,14 +737,14 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
case L'7':
|
||||
case L'8':
|
||||
case L'9':
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | MALLOC))
|
||||
goto match_failure;
|
||||
width = width * 10 + c - L'0';
|
||||
goto again;
|
||||
|
||||
#ifndef _NO_POS_ARGS
|
||||
case L'$':
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||
if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS | MALLOC))
|
||||
goto match_failure;
|
||||
if (width <= MAX_POS_ARGS)
|
||||
{
|
||||
|
@ -787,7 +915,19 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
width = 1;
|
||||
if (flags & LONG)
|
||||
{
|
||||
if (!(flags & SUPPRESS))
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
wchar_t **p_p = NULL;
|
||||
wchar_t *p0 = NULL;
|
||||
size_t width0 = 0;
|
||||
#endif
|
||||
|
||||
if (flags & SUPPRESS)
|
||||
;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
else if (flags & MALLOC)
|
||||
width0 = alloc_m_ptr (wchar_t, p, p0, p_p, width);
|
||||
#endif
|
||||
else
|
||||
p = GET_ARG(N, ap, wchar_t *);
|
||||
n = 0;
|
||||
while (width-- != 0 && (wi = _fgetwc_r (rptr, fp)) != WEOF)
|
||||
|
@ -799,12 +939,27 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
if (n == 0)
|
||||
goto input_failure;
|
||||
nread += n;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (wchar_t, p_p, width0 - width, width0);
|
||||
#endif
|
||||
if (!(flags & SUPPRESS))
|
||||
nassigned++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(flags & SUPPRESS))
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
char **mbp_p = NULL;
|
||||
char *mbp0 = NULL;
|
||||
size_t width0 = 0;
|
||||
#endif
|
||||
|
||||
if (flags & SUPPRESS)
|
||||
;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
else if (flags & MALLOC)
|
||||
width0 = alloc_m_ptr (char, mbp, mbp0, mbp_p, width);
|
||||
#endif
|
||||
else
|
||||
mbp = GET_ARG(N, ap, char *);
|
||||
n = 0;
|
||||
memset ((_PTR)&mbs, '\0', sizeof (mbstate_t));
|
||||
|
@ -837,6 +992,9 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
if (n == 0)
|
||||
goto input_failure;
|
||||
nread += n;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (char, mbp_p, width0 - width, width0);
|
||||
#endif
|
||||
if (!(flags & SUPPRESS))
|
||||
nassigned++;
|
||||
}
|
||||
|
@ -860,27 +1018,58 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
}
|
||||
else if (flags & LONG)
|
||||
{
|
||||
p0 = p = GET_ARG(N, ap, wchar_t *);
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
wchar_t **p_p = NULL;
|
||||
size_t p_siz = 0;
|
||||
|
||||
if (flags & MALLOC)
|
||||
p_siz = alloc_m_ptr (wchar_t, p, p0, p_p, 32);
|
||||
else
|
||||
#endif
|
||||
p0 = p = GET_ARG(N, ap, wchar_t *);
|
||||
while ((wi = _fgetwc_r (rptr, fp)) != WEOF
|
||||
&& width-- != 0 && INCCL (wi))
|
||||
*p++ = (wchar_t) wi;
|
||||
{
|
||||
*p++ = (wchar_t) wi;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
p_siz = realloc_m_ptr (wchar_t, p, p0, p_p, p_siz);
|
||||
#endif
|
||||
}
|
||||
if (wi != WEOF)
|
||||
_ungetwc_r (rptr, wi, fp);
|
||||
n = p - p0;
|
||||
if (n == 0)
|
||||
goto match_failure;
|
||||
*p = L'\0';
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (wchar_t, p_p, n + 1, p_siz);
|
||||
#endif
|
||||
nassigned++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(flags & SUPPRESS))
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
char **mbp_p = NULL;
|
||||
char *mbp0 = NULL;
|
||||
size_t mbp_siz = 0;
|
||||
#endif
|
||||
|
||||
if (flags & SUPPRESS)
|
||||
;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
else if (flags & MALLOC)
|
||||
mbp_siz = alloc_m_ptr (char, mbp, mbp0, mbp_p, 32);
|
||||
#endif
|
||||
else
|
||||
mbp = GET_ARG(N, ap, char *);
|
||||
n = 0;
|
||||
memset ((_PTR) &mbs, '\0', sizeof (mbstate_t));
|
||||
while ((wi = _fgetwc_r (rptr, fp)) != WEOF
|
||||
&& width != 0 && INCCL (wi))
|
||||
{
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
mbp_siz = realloc_m_ptr (char, mbp, mbp0, mbp_p, mbp_siz);
|
||||
#endif
|
||||
if (width >= MB_CUR_MAX && !(flags & SUPPRESS))
|
||||
{
|
||||
nconv = _wcrtomb_r (rptr, mbp, wi, &mbs);
|
||||
|
@ -907,6 +1096,9 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
if (!(flags & SUPPRESS))
|
||||
{
|
||||
*mbp = 0;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (char, mbp_p, mbp - mbp0 + 1, mbp_siz);
|
||||
#endif
|
||||
nassigned++;
|
||||
}
|
||||
}
|
||||
|
@ -927,26 +1119,55 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
}
|
||||
else if (flags & LONG)
|
||||
{
|
||||
p0 = p = GET_ARG(N, ap, wchar_t *);
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
wchar_t **p_p = NULL;
|
||||
size_t p_siz = 0;
|
||||
|
||||
if (flags & MALLOC)
|
||||
p_siz = alloc_m_ptr (wchar_t, p, p0, p_p, 32);
|
||||
else
|
||||
#endif
|
||||
p0 = p = GET_ARG(N, ap, wchar_t *);
|
||||
while ((wi = _fgetwc_r (rptr, fp)) != WEOF
|
||||
&& width-- != 0 && !iswspace (wi))
|
||||
{
|
||||
*p++ = (wchar_t) wi;
|
||||
nread++;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
p_siz = realloc_m_ptr (wchar_t, p, p0, p_p, p_siz);
|
||||
#endif
|
||||
}
|
||||
if (wi != WEOF)
|
||||
_ungetwc_r (rptr, wi, fp);
|
||||
*p = L'\0';
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (wchar_t, p_p, p - p0 + 1, p_siz);
|
||||
#endif
|
||||
nassigned++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(flags & SUPPRESS))
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
char **mbp_p = NULL;
|
||||
char *mbp0 = NULL;
|
||||
size_t mbp_siz = 0;
|
||||
#endif
|
||||
|
||||
if (flags & SUPPRESS)
|
||||
;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
else if (flags & MALLOC)
|
||||
mbp_siz = alloc_m_ptr (char, mbp, mbp0, mbp_p, 32);
|
||||
#endif
|
||||
else
|
||||
mbp = GET_ARG(N, ap, char *);
|
||||
memset ((_PTR) &mbs, '\0', sizeof (mbstate_t));
|
||||
while ((wi = _fgetwc_r (rptr, fp)) != WEOF
|
||||
&& width != 0 && !iswspace (wi))
|
||||
{
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
mbp_siz = realloc_m_ptr (char, mbp, mbp0, mbp_p, mbp_siz);
|
||||
#endif
|
||||
if (width >= MB_CUR_MAX && !(flags & SUPPRESS))
|
||||
{
|
||||
nconv = wcrtomb(mbp, wi, &mbs);
|
||||
|
@ -973,6 +1194,9 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
|||
if (!(flags & SUPPRESS))
|
||||
{
|
||||
*mbp = 0;
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
shrink_m_ptr (char, mbp_p, mbp - mbp0 + 1, mbp_siz);
|
||||
#endif
|
||||
nassigned++;
|
||||
}
|
||||
}
|
||||
|
@ -1492,6 +1716,9 @@ match_failure:
|
|||
all_done:
|
||||
/* Return number of matches, which can be 0 on match failure. */
|
||||
_newlib_flockfile_end (fp);
|
||||
#ifdef _WANT_IO_POSIX_EXTENSIONS
|
||||
free_m_ptr ();
|
||||
#endif
|
||||
return nassigned;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue