mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
* stdio-common/vfscanf.c (_IO_vfwscanf): Add support for 'm'
modifier. Patch by Jakub Jelinek.
This commit is contained in:
parent
5e17d6b75b
commit
267c54dcef
@ -1,3 +1,8 @@
|
|||||||
|
2007-09-15 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* stdio-common/vfscanf.c (_IO_vfwscanf): Add support for 'm'
|
||||||
|
modifier. Patch by Jakub Jelinek.
|
||||||
|
|
||||||
2007-08-26 Jakub Jelinek <jakub@redhat.com>
|
2007-08-26 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/i386/Makefile (sysdep_routines): Add
|
* sysdeps/unix/sysv/linux/i386/Makefile (sysdep_routines): Add
|
||||||
|
@ -282,10 +282,7 @@
|
|||||||
|
|
||||||
/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
|
/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
|
||||||
inline semantics, unless -fgnu89-inline is used. */
|
inline semantics, unless -fgnu89-inline is used. */
|
||||||
#if !defined __cplusplus || __GNUC_PREREQ (4,3) \
|
#if !defined __cplusplus || __GNUC_PREREQ (4,3)
|
||||||
|| (defined __GNUC_RH_RELEASE__ && __GNUC__ == 4 \
|
|
||||||
&& __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 2 \
|
|
||||||
&& __GNUC_RH_RELEASE__ >= 23)
|
|
||||||
# if defined __GNUC_STDC_INLINE__ || defined __cplusplus
|
# if defined __GNUC_STDC_INLINE__ || defined __cplusplus
|
||||||
# define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
|
# define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
|
||||||
# define __extern_always_inline \
|
# define __extern_always_inline \
|
||||||
|
@ -60,12 +60,13 @@
|
|||||||
#define NOSKIP 0x0020 /* do not skip blanks */
|
#define NOSKIP 0x0020 /* do not skip blanks */
|
||||||
#define NUMBER_SIGNED 0x0040 /* signed integer */
|
#define NUMBER_SIGNED 0x0040 /* signed integer */
|
||||||
#define GROUP 0x0080 /* ': group numbers */
|
#define GROUP 0x0080 /* ': group numbers */
|
||||||
#define MALLOC 0x0100 /* a: malloc strings */
|
#define GNU_MALLOC 0x0100 /* a: malloc strings */
|
||||||
#define CHAR 0x0200 /* hh: char */
|
#define CHAR 0x0200 /* hh: char */
|
||||||
#define I18N 0x0400 /* I: use locale's digits */
|
#define I18N 0x0400 /* I: use locale's digits */
|
||||||
#define HEXA_FLOAT 0x0800 /* hexadecimal float */
|
#define HEXA_FLOAT 0x0800 /* hexadecimal float */
|
||||||
#define READ_POINTER 0x1000 /* this is a pointer value */
|
#define READ_POINTER 0x1000 /* this is a pointer value */
|
||||||
|
#define POSIX_MALLOC 0x2000 /* m: malloc strings */
|
||||||
|
#define MALLOC (GNU_MALLOC | POSIX_MALLOC)
|
||||||
|
|
||||||
#include <locale/localeinfo.h>
|
#include <locale/localeinfo.h>
|
||||||
#include <libioP.h>
|
#include <libioP.h>
|
||||||
@ -146,6 +147,21 @@
|
|||||||
if (done == 0) done = EOF; \
|
if (done == 0) done = EOF; \
|
||||||
goto errout; \
|
goto errout; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define add_ptr_to_free(ptr) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (ptrs_to_free == NULL \
|
||||||
|
|| ptrs_to_free->count == (sizeof (ptrs_to_free->ptrs) \
|
||||||
|
/ sizeof (ptrs_to_free->ptrs[0]))) \
|
||||||
|
{ \
|
||||||
|
struct ptrs_to_free *new_ptrs = alloca (sizeof (*ptrs_to_free)); \
|
||||||
|
new_ptrs->count = 0; \
|
||||||
|
new_ptrs->next = ptrs_to_free; \
|
||||||
|
ptrs_to_free = new_ptrs; \
|
||||||
|
} \
|
||||||
|
ptrs_to_free->ptrs[ptrs_to_free->count++] = (ptr); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
#define ARGCHECK(s, format) \
|
#define ARGCHECK(s, format) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
@ -169,6 +185,12 @@
|
|||||||
_IO_funlockfile (S); \
|
_IO_funlockfile (S); \
|
||||||
__libc_cleanup_region_end (0)
|
__libc_cleanup_region_end (0)
|
||||||
|
|
||||||
|
struct ptrs_to_free
|
||||||
|
{
|
||||||
|
size_t count;
|
||||||
|
struct ptrs_to_free *next;
|
||||||
|
char **ptrs[32];
|
||||||
|
};
|
||||||
|
|
||||||
/* Read formatted input from S according to the format string
|
/* Read formatted input from S according to the format string
|
||||||
FORMAT, using the argument list in ARG.
|
FORMAT, using the argument list in ARG.
|
||||||
@ -218,6 +240,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
#else
|
#else
|
||||||
const char *thousands;
|
const char *thousands;
|
||||||
#endif
|
#endif
|
||||||
|
struct ptrs_to_free *ptrs_to_free = NULL;
|
||||||
/* State for the conversions. */
|
/* State for the conversions. */
|
||||||
mbstate_t state;
|
mbstate_t state;
|
||||||
/* Integral holding variables. */
|
/* Integral holding variables. */
|
||||||
@ -493,8 +516,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
}
|
}
|
||||||
/* String conversions (%s, %[) take a `char **'
|
/* String conversions (%s, %[) take a `char **'
|
||||||
arg and fill it in with a malloc'd pointer. */
|
arg and fill it in with a malloc'd pointer. */
|
||||||
flags |= MALLOC;
|
flags |= GNU_MALLOC;
|
||||||
break;
|
break;
|
||||||
|
case L_('m'):
|
||||||
|
flags |= POSIX_MALLOC;
|
||||||
|
break;
|
||||||
case L_('z'):
|
case L_('z'):
|
||||||
if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
|
if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
|
||||||
flags |= LONGDBL;
|
flags |= LONGDBL;
|
||||||
@ -741,6 +767,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
if (flags & MALLOC) \
|
if (flags & MALLOC) \
|
||||||
{ \
|
{ \
|
||||||
/* The string is to be stored in a malloc'd buffer. */ \
|
/* The string is to be stored in a malloc'd buffer. */ \
|
||||||
|
/* For %mS using char ** is actually wrong, but \
|
||||||
|
shouldn't make a difference on any arch glibc \
|
||||||
|
supports and would unnecessarily complicate \
|
||||||
|
things. */ \
|
||||||
strptr = ARG (char **); \
|
strptr = ARG (char **); \
|
||||||
if (strptr == NULL) \
|
if (strptr == NULL) \
|
||||||
conv_error (); \
|
conv_error (); \
|
||||||
@ -748,6 +778,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
strsize = 100; \
|
strsize = 100; \
|
||||||
*strptr = (char *) malloc (strsize * sizeof (Type)); \
|
*strptr = (char *) malloc (strsize * sizeof (Type)); \
|
||||||
Str = (Type *) *strptr; \
|
Str = (Type *) *strptr; \
|
||||||
|
if (Str != NULL) \
|
||||||
|
add_ptr_to_free (strptr); \
|
||||||
|
else if (flags & POSIX_MALLOC) \
|
||||||
|
goto reteof; \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
Str = ARG (Type *); \
|
Str = ARG (Type *); \
|
||||||
@ -796,10 +830,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
strleng + MB_CUR_MAX);
|
strleng + MB_CUR_MAX);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the
|
/* We lose. Oh well. Terminate the
|
||||||
string and stop converting,
|
string and stop converting,
|
||||||
so at least we don't skip any input. */
|
so at least we don't skip any input. */
|
||||||
((char *) (*strptr))[strleng] = '\0';
|
((char *) (*strptr))[strleng] = '\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -843,10 +880,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
str = (char *) realloc (*strptr, strsize + 1);
|
str = (char *) realloc (*strptr, strsize + 1);
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the
|
/* We lose. Oh well. Terminate the
|
||||||
string and stop converting,
|
string and stop converting,
|
||||||
so at least we don't skip any input. */
|
so at least we don't skip any input. */
|
||||||
((char *) (*strptr))[strsize - 1] = '\0';
|
((char *) (*strptr))[strsize - 1] = '\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -886,10 +926,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
newstr = (char *) realloc (*strptr, strleng + n + 1);
|
newstr = (char *) realloc (*strptr, strleng + n + 1);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the string
|
/* We lose. Oh well. Terminate the string
|
||||||
and stop converting, so at least we don't
|
and stop converting, so at least we don't
|
||||||
skip any input. */
|
skip any input. */
|
||||||
((char *) (*strptr))[strleng] = '\0';
|
((char *) (*strptr))[strleng] = '\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -911,6 +954,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
if (cp != NULL)
|
if (cp != NULL)
|
||||||
*strptr = cp;
|
*strptr = cp;
|
||||||
}
|
}
|
||||||
|
strptr = NULL;
|
||||||
|
|
||||||
++done;
|
++done;
|
||||||
}
|
}
|
||||||
@ -964,10 +1008,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
* sizeof (wchar_t));
|
* sizeof (wchar_t));
|
||||||
if (wstr == NULL)
|
if (wstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the string
|
/* We lose. Oh well. Terminate the string
|
||||||
and stop converting, so at least we don't
|
and stop converting, so at least we don't
|
||||||
skip any input. */
|
skip any input. */
|
||||||
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -1033,10 +1080,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
* sizeof (wchar_t)));
|
* sizeof (wchar_t)));
|
||||||
if (wstr == NULL)
|
if (wstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the
|
/* We lose. Oh well. Terminate the
|
||||||
string and stop converting, so at
|
string and stop converting, so at
|
||||||
least we don't skip any input. */
|
least we don't skip any input. */
|
||||||
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -1072,6 +1122,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
if (cp != NULL)
|
if (cp != NULL)
|
||||||
*strptr = (char *) cp;
|
*strptr = (char *) cp;
|
||||||
}
|
}
|
||||||
|
strptr = NULL;
|
||||||
|
|
||||||
++done;
|
++done;
|
||||||
}
|
}
|
||||||
@ -2219,10 +2270,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
* sizeof (wchar_t));
|
* sizeof (wchar_t));
|
||||||
if (wstr == NULL)
|
if (wstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the string
|
/* We lose. Oh well. Terminate the string
|
||||||
and stop converting, so at least we don't
|
and stop converting, so at least we don't
|
||||||
skip any input. */
|
skip any input. */
|
||||||
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -2298,10 +2352,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
* sizeof (wchar_t)));
|
* sizeof (wchar_t)));
|
||||||
if (wstr == NULL)
|
if (wstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the
|
/* We lose. Oh well. Terminate the
|
||||||
string and stop converting,
|
string and stop converting,
|
||||||
so at least we don't skip any input. */
|
so at least we don't skip any input. */
|
||||||
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
((wchar_t *) (*strptr))[strsize - 1] = L'\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -2349,6 +2406,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
if (cp != NULL)
|
if (cp != NULL)
|
||||||
*strptr = (char *) cp;
|
*strptr = (char *) cp;
|
||||||
}
|
}
|
||||||
|
strptr = NULL;
|
||||||
|
|
||||||
++done;
|
++done;
|
||||||
}
|
}
|
||||||
@ -2435,10 +2493,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
strleng + MB_CUR_MAX);
|
strleng + MB_CUR_MAX);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the string
|
/* We lose. Oh well. Terminate the string
|
||||||
and stop converting, so at least we don't
|
and stop converting, so at least we don't
|
||||||
skip any input. */
|
skip any input. */
|
||||||
((char *) (*strptr))[strleng] = '\0';
|
((char *) (*strptr))[strleng] = '\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -2497,10 +2558,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
newsize = strsize + 1;
|
newsize = strsize + 1;
|
||||||
goto allocagain;
|
goto allocagain;
|
||||||
}
|
}
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the
|
/* We lose. Oh well. Terminate the
|
||||||
string and stop converting,
|
string and stop converting,
|
||||||
so at least we don't skip any input. */
|
so at least we don't skip any input. */
|
||||||
((char *) (*strptr))[strsize - 1] = '\0';
|
((char *) (*strptr))[strsize - 1] = '\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -2537,10 +2601,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
newstr = (char *) realloc (*strptr, strleng + n + 1);
|
newstr = (char *) realloc (*strptr, strleng + n + 1);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
{
|
{
|
||||||
|
if (flags & POSIX_MALLOC)
|
||||||
|
goto reteof;
|
||||||
/* We lose. Oh well. Terminate the string
|
/* We lose. Oh well. Terminate the string
|
||||||
and stop converting, so at least we don't
|
and stop converting, so at least we don't
|
||||||
skip any input. */
|
skip any input. */
|
||||||
((char *) (*strptr))[strleng] = '\0';
|
((char *) (*strptr))[strleng] = '\0';
|
||||||
|
strptr = NULL;
|
||||||
++done;
|
++done;
|
||||||
conv_error ();
|
conv_error ();
|
||||||
}
|
}
|
||||||
@ -2562,6 +2629,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
if (cp != NULL)
|
if (cp != NULL)
|
||||||
*strptr = cp;
|
*strptr = cp;
|
||||||
}
|
}
|
||||||
|
strptr = NULL;
|
||||||
|
|
||||||
++done;
|
++done;
|
||||||
}
|
}
|
||||||
@ -2600,6 +2668,31 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
|||||||
if (errp != NULL)
|
if (errp != NULL)
|
||||||
*errp |= errval;
|
*errp |= errval;
|
||||||
|
|
||||||
|
if (done == EOF)
|
||||||
|
{
|
||||||
|
reteof:
|
||||||
|
if (__builtin_expect (ptrs_to_free != NULL, 0))
|
||||||
|
{
|
||||||
|
struct ptrs_to_free *p = ptrs_to_free;
|
||||||
|
while (p != NULL)
|
||||||
|
{
|
||||||
|
for (size_t cnt = 0; cnt < p->count; ++cnt)
|
||||||
|
{
|
||||||
|
free (*p->ptrs[cnt]);
|
||||||
|
*p->ptrs[cnt] = NULL;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
free (ptrs_to_free);
|
||||||
|
ptrs_to_free = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
else if (__builtin_expect (strptr != NULL, 0))
|
||||||
|
{
|
||||||
|
free (*strptr);
|
||||||
|
*strptr = NULL;
|
||||||
|
}
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user