Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2007-05-24 00:36:28 +0400
committerEric Blake <eblake@redhat.com>2007-05-24 00:36:28 +0400
commit9a3ec8622b2fb10c95112188c7f5ff1424c738e6 (patch)
tree11408957e1c8a6f7d7c5e1ab639eb3d1ab9aeac5 /newlib/libc/stdio
parentfc2000254c4a4e86e82a10078c9c068fca44b6c0 (diff)
* 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.
Diffstat (limited to 'newlib/libc/stdio')
-rw-r--r--newlib/libc/stdio/vfprintf.c40
-rw-r--r--newlib/libc/stdio/vfscanf.c112
2 files changed, 109 insertions, 43 deletions
diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c
index 72bd7e89e..e734cb19c 100644
--- a/newlib/libc/stdio/vfprintf.c
+++ b/newlib/libc/stdio/vfprintf.c
@@ -125,8 +125,8 @@ static char *rcsid = "$Id$";
# endif
#endif
-#define _NO_POS_ARGS
-#if defined _WANT_IO_POS_ARGS
+#define _NO_POS_ARGS
+#ifdef _WANT_IO_POS_ARGS
# undef _NO_POS_ARGS
#endif
@@ -385,9 +385,9 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
register struct __siov *iovp;/* for PRINT macro */
register int flags; /* flags as above */
char *fmt_anchor; /* current format spec being processed */
+#ifndef _NO_POS_ARGS
int N; /* arg number */
int arg_index; /* index into args processed directly */
-#ifndef _NO_POS_ARGS
int numargs; /* number of varargs read */
char *saved_fmt; /* saved fmt pointer */
union arg_val args[MAX_POS_ARGS];
@@ -472,21 +472,21 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
/* Macros to support positional arguments */
#ifndef _NO_POS_ARGS
-#define GET_ARG(n, ap, type) \
- ( is_pos_arg \
- ? n < numargs \
- ? args[n].val_##type \
- : get_arg (data, n, fmt_anchor, &ap, &numargs, args, arg_type, &saved_fmt)->val_##type \
- : arg_index++ < numargs \
- ? args[n].val_##type \
- : numargs < MAX_POS_ARGS \
- ? args[numargs++].val_##type = va_arg (ap, type) \
- : va_arg (ap, type) \
- )
+# define GET_ARG(n, ap, type) \
+ (is_pos_arg \
+ ? (n < numargs \
+ ? args[n].val_##type \
+ : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
+ arg_type, &saved_fmt)->val_##type) \
+ : (arg_index++ < numargs \
+ ? args[n].val_##type \
+ : (numargs < MAX_POS_ARGS \
+ ? args[numargs++].val_##type = va_arg (ap, type) \
+ : va_arg (ap, type))))
#else
-#define GET_ARG(n, ap, type) (va_arg (ap, type))
+# define GET_ARG(n, ap, type) (va_arg (ap, type))
#endif
-
+
/*
* To extend shorts properly, we need both signed and unsigned
* argument extraction methods.
@@ -538,8 +538,8 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
uio.uio_resid = 0;
uio.uio_iovcnt = 0;
ret = 0;
- arg_index = 0;
#ifndef _NO_POS_ARGS
+ arg_index = 0;
saved_fmt = NULL;
arg_type[0] = -1;
numargs = 0;
@@ -580,8 +580,8 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
width = 0;
prec = -1;
sign = '\0';
- N = arg_index;
#ifndef _NO_POS_ARGS
+ N = arg_index;
is_pos_arg = 0;
#endif
@@ -609,9 +609,9 @@ reswitch: switch (ch) {
flags |= ALT;
goto rflag;
case '*':
- n = N;
#ifndef _NO_POS_ARGS
/* we must check for positional arg used for dynamic width */
+ n = N;
old_is_pos_arg = is_pos_arg;
is_pos_arg = 0;
if (is_digit (*fmt)) {
@@ -661,9 +661,9 @@ reswitch: switch (ch) {
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
- n = N;
#ifndef _NO_POS_ARGS
/* we must check for positional arg used for dynamic width */
+ n = N;
old_is_pos_arg = is_pos_arg;
is_pos_arg = 0;
if (is_digit (*fmt)) {
diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c
index bd597b395..e73e8764f 100644
--- a/newlib/libc/stdio/vfscanf.c
+++ b/newlib/libc/stdio/vfscanf.c
@@ -113,11 +113,8 @@ Supporting OS subroutines required:
#include <limits.h>
#include <wchar.h>
#include <string.h>
-#ifdef _HAVE_STDC
#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
+#include <errno.h>
#include "local.h"
#ifdef INTEGER_ONLY
@@ -169,6 +166,18 @@ extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
# undef _NO_LONGLONG
#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.
*/
@@ -276,6 +285,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
register char *p0; /* saves original value of p when necessary */
int nassigned; /* number of fields assigned */
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 nbytes = 1; /* number of bytes read from fmt string */
wchar_t wc; /* wchar to use to read format string */
@@ -291,9 +307,11 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
char *cp;
short *sp;
int *ip;
+#ifdef FLOATING_POINT
float *flp;
_LONG_DOUBLE *ldp;
double *dp;
+#endif
long *lp;
#ifndef _NO_LONGLONG
long long *llp;
@@ -303,6 +321,22 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
static _CONST short basefix[17] =
{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);
nassigned = 0;
@@ -332,6 +366,10 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
goto literal;
width = 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
@@ -439,6 +477,19 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
width = width * 10 + c - '0';
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
* 4.[123]BSD compatibility.
@@ -540,31 +591,31 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
#ifdef _WANT_IO_C99_FORMATS
if (flags & CHAR)
{
- cp = va_arg (ap, char *);
+ cp = GET_ARG (N, ap, char *);
*cp = nread;
}
else
#endif
if (flags & SHORT)
{
- sp = va_arg (ap, short *);
+ sp = GET_ARG (N, ap, short *);
*sp = nread;
}
else if (flags & LONG)
{
- lp = va_arg (ap, long *);
+ lp = GET_ARG (N, ap, long *);
*lp = nread;
}
#ifndef _NO_LONGLONG
else if (flags & LONGDBL)
{
- llp = va_arg (ap, long long*);
+ llp = GET_ARG (N, ap, long long*);
*llp = nread;
}
#endif
else
{
- ip = va_arg (ap, int *);
+ ip = GET_ARG (N, ap, int *);
*ip = nread;
}
continue;
@@ -626,7 +677,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
if (flags & LONG)
{
if ((flags & SUPPRESS) == 0)
- wcp = va_arg (ap, wchar_t *);
+ wcp = GET_ARG (N, ap, wchar_t *);
else
wcp = NULL;
n = 0;
@@ -690,7 +741,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
}
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)
goto input_failure;
@@ -724,7 +775,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
}
else
{
- p0 = p = va_arg (ap, char *);
+ p0 = p = GET_ARG (N, ap, char *);
while (ccltab[*fp->_p])
{
fp->_r--;
@@ -755,7 +806,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
{
/* Process %S and %ls placeholders */
if ((flags & SUPPRESS) == 0)
- wcp = va_arg (ap, wchar_t *);
+ wcp = GET_ARG (N, ap, wchar_t *);
else
wcp = &wc;
n = 0;
@@ -814,7 +865,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
}
else
{
- p0 = p = va_arg (ap, char *);
+ p0 = p = GET_ARG (N, ap, char *);
while (!isspace (*fp->_p))
{
fp->_r--;
@@ -993,22 +1044,22 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
*p = 0;
res = (*ccfn) (rptr, buf, (char **) NULL, base);
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
else if (flags & CHAR)
{
- cp = va_arg (ap, char *);
+ cp = GET_ARG (N, ap, char *);
*cp = res;
}
#endif
else if (flags & SHORT)
{
- sp = va_arg (ap, short *);
+ sp = GET_ARG (N, ap, short *);
*sp = res;
}
else if (flags & LONG)
{
- lp = va_arg (ap, long *);
+ lp = GET_ARG (N, ap, long *);
*lp = res;
}
#ifndef _NO_LONGLONG
@@ -1019,13 +1070,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
resll = _strtoull_r (rptr, buf, (char **) NULL, base);
else
resll = _strtoll_r (rptr, buf, (char **) NULL, base);
- llp = va_arg (ap, long long*);
+ llp = GET_ARG (N, ap, long long*);
*llp = resll;
}
#endif
else
{
- ip = va_arg (ap, int *);
+ ip = GET_ARG (N, ap, int *);
*ip = res;
}
nassigned++;
@@ -1257,17 +1308,17 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
if (flags & LONG)
{
- dp = va_arg (ap, double *);
+ dp = GET_ARG (N, ap, double *);
*dp = res;
}
else if (flags & LONGDBL)
{
- ldp = va_arg (ap, _LONG_DOUBLE *);
+ ldp = GET_ARG (N, ap, _LONG_DOUBLE *);
*ldp = QUAD_RES;
}
else
{
- flp = va_arg (ap, float *);
+ flp = GET_ARG (N, ap, float *);
if (isnan (res))
*flp = nanf (NULL);
else
@@ -1288,3 +1339,18 @@ all_done:
_funlockfile (fp);
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 */