* libc/stdio/vfscanf.c (__SVFSCANF_R): Support scanf(%1$s).

Avoid warning when !FLOATING_POINT.
* libc/stdio/vfprintf.c (_VFPRINTF_R): Simplify _NO_POS_ARGS
slightly.
This commit is contained in:
Eric Blake 2007-05-23 20:36:28 +00:00
parent fc2000254c
commit 9a3ec8622b
3 changed files with 116 additions and 43 deletions

View File

@ -1,3 +1,10 @@
2007-05-23 Eric Blake <ebb9@byu.net>
* libc/stdio/vfscanf.c (__SVFSCANF_R): Support scanf(%1$s).
Avoid warning when !FLOATING_POINT.
* libc/stdio/vfprintf.c (_VFPRINTF_R): Simplify _NO_POS_ARGS
slightly.
2007-05-23 Corinna Vinschen <vinschen@redhat.com> 2007-05-23 Corinna Vinschen <vinschen@redhat.com>
* libc/argz/argz_create_sep.c (argz_create_sep): Initialize *argz_len * libc/argz/argz_create_sep.c (argz_create_sep): Initialize *argz_len

View File

@ -126,7 +126,7 @@ static char *rcsid = "$Id$";
#endif #endif
#define _NO_POS_ARGS #define _NO_POS_ARGS
#if defined _WANT_IO_POS_ARGS #ifdef _WANT_IO_POS_ARGS
# undef _NO_POS_ARGS # undef _NO_POS_ARGS
#endif #endif
@ -385,9 +385,9 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
register struct __siov *iovp;/* for PRINT macro */ register struct __siov *iovp;/* for PRINT macro */
register int flags; /* flags as above */ register int flags; /* flags as above */
char *fmt_anchor; /* current format spec being processed */ char *fmt_anchor; /* current format spec being processed */
#ifndef _NO_POS_ARGS
int N; /* arg number */ int N; /* arg number */
int arg_index; /* index into args processed directly */ int arg_index; /* index into args processed directly */
#ifndef _NO_POS_ARGS
int numargs; /* number of varargs read */ int numargs; /* number of varargs read */
char *saved_fmt; /* saved fmt pointer */ char *saved_fmt; /* saved fmt pointer */
union arg_val args[MAX_POS_ARGS]; union arg_val args[MAX_POS_ARGS];
@ -474,15 +474,15 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
#ifndef _NO_POS_ARGS #ifndef _NO_POS_ARGS
# define GET_ARG(n, ap, type) \ # define GET_ARG(n, ap, type) \
(is_pos_arg \ (is_pos_arg \
? n < numargs \ ? (n < numargs \
? args[n].val_##type \ ? args[n].val_##type \
: get_arg (data, n, fmt_anchor, &ap, &numargs, args, arg_type, &saved_fmt)->val_##type \ : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
: arg_index++ < numargs \ arg_type, &saved_fmt)->val_##type) \
: (arg_index++ < numargs \
? args[n].val_##type \ ? args[n].val_##type \
: numargs < MAX_POS_ARGS \ : (numargs < MAX_POS_ARGS \
? args[numargs++].val_##type = va_arg (ap, type) \ ? args[numargs++].val_##type = va_arg (ap, type) \
: va_arg (ap, type) \ : va_arg (ap, type))))
)
#else #else
# define GET_ARG(n, ap, type) (va_arg (ap, type)) # define GET_ARG(n, ap, type) (va_arg (ap, type))
#endif #endif
@ -538,8 +538,8 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
uio.uio_resid = 0; uio.uio_resid = 0;
uio.uio_iovcnt = 0; uio.uio_iovcnt = 0;
ret = 0; ret = 0;
arg_index = 0;
#ifndef _NO_POS_ARGS #ifndef _NO_POS_ARGS
arg_index = 0;
saved_fmt = NULL; saved_fmt = NULL;
arg_type[0] = -1; arg_type[0] = -1;
numargs = 0; numargs = 0;
@ -580,8 +580,8 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
width = 0; width = 0;
prec = -1; prec = -1;
sign = '\0'; sign = '\0';
N = arg_index;
#ifndef _NO_POS_ARGS #ifndef _NO_POS_ARGS
N = arg_index;
is_pos_arg = 0; is_pos_arg = 0;
#endif #endif
@ -609,9 +609,9 @@ reswitch: switch (ch) {
flags |= ALT; flags |= ALT;
goto rflag; goto rflag;
case '*': case '*':
n = N;
#ifndef _NO_POS_ARGS #ifndef _NO_POS_ARGS
/* we must check for positional arg used for dynamic width */ /* we must check for positional arg used for dynamic width */
n = N;
old_is_pos_arg = is_pos_arg; old_is_pos_arg = is_pos_arg;
is_pos_arg = 0; is_pos_arg = 0;
if (is_digit (*fmt)) { if (is_digit (*fmt)) {
@ -661,9 +661,9 @@ reswitch: switch (ch) {
goto rflag; goto rflag;
case '.': case '.':
if ((ch = *fmt++) == '*') { if ((ch = *fmt++) == '*') {
n = N;
#ifndef _NO_POS_ARGS #ifndef _NO_POS_ARGS
/* we must check for positional arg used for dynamic width */ /* we must check for positional arg used for dynamic width */
n = N;
old_is_pos_arg = is_pos_arg; old_is_pos_arg = is_pos_arg;
is_pos_arg = 0; is_pos_arg = 0;
if (is_digit (*fmt)) { if (is_digit (*fmt)) {

View File

@ -113,11 +113,8 @@ Supporting OS subroutines required:
#include <limits.h> #include <limits.h>
#include <wchar.h> #include <wchar.h>
#include <string.h> #include <string.h>
#ifdef _HAVE_STDC
#include <stdarg.h> #include <stdarg.h>
#else #include <errno.h>
#include <varargs.h>
#endif
#include "local.h" #include "local.h"
#ifdef INTEGER_ONLY #ifdef INTEGER_ONLY
@ -169,6 +166,18 @@ extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
# undef _NO_LONGLONG # undef _NO_LONGLONG
#endif #endif
#define _NO_POS_ARGS
#ifdef _WANT_IO_POS_ARGS
# undef _NO_POS_ARGS
# ifdef NL_ARGMAX
# define MAX_POS_ARGS NL_ARGMAX
# else
# define MAX_POS_ARGS 32
# endif
static void * get_arg (int, va_list *, int *, void **);
#endif /* _WANT_IO_POS_ARGS */
/* /*
* Flags used during conversion. * Flags used during conversion.
*/ */
@ -276,6 +285,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
register char *p0; /* saves original value of p when necessary */ register char *p0; /* saves original value of p when necessary */
int nassigned; /* number of fields assigned */ int nassigned; /* number of fields assigned */
int nread; /* number of characters consumed from fp */ int nread; /* number of characters consumed from fp */
#ifndef _NO_POS_ARGS
int N; /* arg number */
int arg_index = 0; /* index into args processed directly */
int numargs = 0; /* number of varargs read */
void *args[MAX_POS_ARGS]; /* positional args read */
int is_pos_arg; /* is current format positional? */
#endif
int base = 0; /* base argument to strtol/strtoul */ int base = 0; /* base argument to strtol/strtoul */
int nbytes = 1; /* number of bytes read from fmt string */ int nbytes = 1; /* number of bytes read from fmt string */
wchar_t wc; /* wchar to use to read format string */ wchar_t wc; /* wchar to use to read format string */
@ -291,9 +307,11 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
char *cp; char *cp;
short *sp; short *sp;
int *ip; int *ip;
#ifdef FLOATING_POINT
float *flp; float *flp;
_LONG_DOUBLE *ldp; _LONG_DOUBLE *ldp;
double *dp; double *dp;
#endif
long *lp; long *lp;
#ifndef _NO_LONGLONG #ifndef _NO_LONGLONG
long long *llp; long long *llp;
@ -303,6 +321,22 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
static _CONST short basefix[17] = static _CONST short basefix[17] =
{10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
/* Macro to support positional arguments */
#ifndef _NO_POS_ARGS
# define GET_ARG(n, ap, type) \
((type) (is_pos_arg \
? (n < numargs \
? args[n] \
: get_arg (n, &ap, &numargs, args)) \
: (arg_index++ < numargs \
? args[n] \
: (numargs < MAX_POS_ARGS \
? args[numargs++] = va_arg (ap, void *) \
: va_arg (ap, void *)))))
#else
# define GET_ARG(n, ap, type) (va_arg (ap, type))
#endif
_flockfile (fp); _flockfile (fp);
nassigned = 0; nassigned = 0;
@ -332,6 +366,10 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
goto literal; goto literal;
width = 0; width = 0;
flags = 0; flags = 0;
#ifndef _NO_POS_ARGS
N = arg_index;
is_pos_arg = 0;
#endif
/* /*
* switch on the format. continue if done; break once format * switch on the format. continue if done; break once format
@ -439,6 +477,19 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
width = width * 10 + c - '0'; width = width * 10 + c - '0';
goto again; goto again;
#ifndef _NO_POS_ARGS
case '$':
if (width <= MAX_POS_ARGS)
{
N = width - 1;
is_pos_arg = 1;
width = 0;
goto again;
}
rptr->_errno = EINVAL;
goto input_failure;
#endif /* !_NO_POS_ARGS */
/* /*
* Conversions. Those marked `compat' are for * Conversions. Those marked `compat' are for
* 4.[123]BSD compatibility. * 4.[123]BSD compatibility.
@ -540,31 +591,31 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
#ifdef _WANT_IO_C99_FORMATS #ifdef _WANT_IO_C99_FORMATS
if (flags & CHAR) if (flags & CHAR)
{ {
cp = va_arg (ap, char *); cp = GET_ARG (N, ap, char *);
*cp = nread; *cp = nread;
} }
else else
#endif #endif
if (flags & SHORT) if (flags & SHORT)
{ {
sp = va_arg (ap, short *); sp = GET_ARG (N, ap, short *);
*sp = nread; *sp = nread;
} }
else if (flags & LONG) else if (flags & LONG)
{ {
lp = va_arg (ap, long *); lp = GET_ARG (N, ap, long *);
*lp = nread; *lp = nread;
} }
#ifndef _NO_LONGLONG #ifndef _NO_LONGLONG
else if (flags & LONGDBL) else if (flags & LONGDBL)
{ {
llp = va_arg (ap, long long*); llp = GET_ARG (N, ap, long long*);
*llp = nread; *llp = nread;
} }
#endif #endif
else else
{ {
ip = va_arg (ap, int *); ip = GET_ARG (N, ap, int *);
*ip = nread; *ip = nread;
} }
continue; continue;
@ -626,7 +677,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
if (flags & LONG) if (flags & LONG)
{ {
if ((flags & SUPPRESS) == 0) if ((flags & SUPPRESS) == 0)
wcp = va_arg (ap, wchar_t *); wcp = GET_ARG (N, ap, wchar_t *);
else else
wcp = NULL; wcp = NULL;
n = 0; n = 0;
@ -690,7 +741,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
} }
else else
{ {
size_t r = fread ((_PTR) va_arg (ap, char *), 1, width, fp); size_t r = fread ((_PTR) GET_ARG (N, ap, char *), 1, width, fp);
if (r == 0) if (r == 0)
goto input_failure; goto input_failure;
@ -724,7 +775,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
} }
else else
{ {
p0 = p = va_arg (ap, char *); p0 = p = GET_ARG (N, ap, char *);
while (ccltab[*fp->_p]) while (ccltab[*fp->_p])
{ {
fp->_r--; fp->_r--;
@ -755,7 +806,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
{ {
/* Process %S and %ls placeholders */ /* Process %S and %ls placeholders */
if ((flags & SUPPRESS) == 0) if ((flags & SUPPRESS) == 0)
wcp = va_arg (ap, wchar_t *); wcp = GET_ARG (N, ap, wchar_t *);
else else
wcp = &wc; wcp = &wc;
n = 0; n = 0;
@ -814,7 +865,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
} }
else else
{ {
p0 = p = va_arg (ap, char *); p0 = p = GET_ARG (N, ap, char *);
while (!isspace (*fp->_p)) while (!isspace (*fp->_p))
{ {
fp->_r--; fp->_r--;
@ -993,22 +1044,22 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
*p = 0; *p = 0;
res = (*ccfn) (rptr, buf, (char **) NULL, base); res = (*ccfn) (rptr, buf, (char **) NULL, base);
if (flags & POINTER) if (flags & POINTER)
*(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res; *(GET_ARG (N, ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res;
#ifdef _WANT_IO_C99_FORMATS #ifdef _WANT_IO_C99_FORMATS
else if (flags & CHAR) else if (flags & CHAR)
{ {
cp = va_arg (ap, char *); cp = GET_ARG (N, ap, char *);
*cp = res; *cp = res;
} }
#endif #endif
else if (flags & SHORT) else if (flags & SHORT)
{ {
sp = va_arg (ap, short *); sp = GET_ARG (N, ap, short *);
*sp = res; *sp = res;
} }
else if (flags & LONG) else if (flags & LONG)
{ {
lp = va_arg (ap, long *); lp = GET_ARG (N, ap, long *);
*lp = res; *lp = res;
} }
#ifndef _NO_LONGLONG #ifndef _NO_LONGLONG
@ -1019,13 +1070,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
resll = _strtoull_r (rptr, buf, (char **) NULL, base); resll = _strtoull_r (rptr, buf, (char **) NULL, base);
else else
resll = _strtoll_r (rptr, buf, (char **) NULL, base); resll = _strtoll_r (rptr, buf, (char **) NULL, base);
llp = va_arg (ap, long long*); llp = GET_ARG (N, ap, long long*);
*llp = resll; *llp = resll;
} }
#endif #endif
else else
{ {
ip = va_arg (ap, int *); ip = GET_ARG (N, ap, int *);
*ip = res; *ip = res;
} }
nassigned++; nassigned++;
@ -1257,17 +1308,17 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
if (flags & LONG) if (flags & LONG)
{ {
dp = va_arg (ap, double *); dp = GET_ARG (N, ap, double *);
*dp = res; *dp = res;
} }
else if (flags & LONGDBL) else if (flags & LONGDBL)
{ {
ldp = va_arg (ap, _LONG_DOUBLE *); ldp = GET_ARG (N, ap, _LONG_DOUBLE *);
*ldp = QUAD_RES; *ldp = QUAD_RES;
} }
else else
{ {
flp = va_arg (ap, float *); flp = GET_ARG (N, ap, float *);
if (isnan (res)) if (isnan (res))
*flp = nanf (NULL); *flp = nanf (NULL);
else else
@ -1288,3 +1339,18 @@ all_done:
_funlockfile (fp); _funlockfile (fp);
return nassigned; return nassigned;
} }
#ifndef _NO_POS_ARGS
/* Process all intermediate arguments. Fortunately, with scanf, all
intermediate arguments are sizeof(void*), so we don't need to scan
ahead in the format string. */
static void *
get_arg (int n, va_list *ap, int *numargs_p, void **args)
{
int numargs = *numargs_p;
while (n >= numargs)
args[numargs++] = va_arg (*ap, void *);
*numargs_p = numargs;
return args[n];
}
#endif /* !_NO_POS_ARGS */