aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--stdio/vfscanf.c75
-rw-r--r--stdlib/strtol.c4
-rw-r--r--sysdeps/mach/hurd/closedir.c1
4 files changed, 68 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 0d54c13488..88cdb2a86e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Sat Mar 18 14:07:08 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * stdio/vfscanf.c: Grok positional parameter specs (i.e. %3$d
+ means %d from 3rd arg).
+
+ * sysdeps/mach/hurd/closedir.c: Include hurd/fd.h.
+
+ * stdlib/strtol.c: If !GROUP, set END to null. In loop, test only
+ END, not GROUP.
+
Fri Mar 17 12:58:37 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* Makefile (subdirs): Put elf last.
diff --git a/stdio/vfscanf.c b/stdio/vfscanf.c
index 9a9e3bb79c..cacf16f466 100644
--- a/stdio/vfscanf.c
+++ b/stdio/vfscanf.c
@@ -60,7 +60,7 @@ DEFUN(__vfscanf, (s, format, arg),
int group_flag; /* %' modifier flag. */
/* Type modifiers. */
- char is_short, is_long, is_long_double;
+ int is_short, is_long, is_long_double;
#ifdef HAVE_LONGLONG
/* We use the `L' modifier for `long long int'. */
#define is_longlong is_long_double
@@ -108,6 +108,18 @@ DEFUN(__vfscanf, (s, format, arg),
/* Run through the format string. */
while (*f != '\0')
{
+ unsigned int argpos;
+ /* Extract the next argument, which is of type TYPE.
+ For a %N$... spec, this is the Nth argument from the beginning;
+ otherwise it is the next argument after the state now in ARG. */
+#define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
+ ({ unsigned int pos = argpos; \
+ va_list arg = (va_list) argptr; \
+ while (--pos > 0) \
+ (void) va_arg (arg, void *); \
+ va_arg (arg, type); \
+ }))
+
if (!isascii (*f))
{
/* Non-ASCII, may be a multibyte. */
@@ -145,9 +157,30 @@ DEFUN(__vfscanf, (s, format, arg),
continue;
}
- /* Check for the assignment-suppressant and the number grouping flag. */
+ /* Initialize state of modifiers. */
+ argpos = 0;
do_assign = 1;
group_flag = 0;
+ is_short = is_long = is_long_double = malloc_string = 0;
+
+ /* Check for a positional parameter specification. */
+ if (isdigit (*f))
+ {
+ argpos = *f++ - '0';
+ while (isdigit (*f))
+ argpos = argpos * 10 + (*f++ - '0');
+ if (*f == '$')
+ ++f;
+ else
+ {
+ /* Oops; that was actually the field width. */
+ width = argpos;
+ argpos = 0;
+ goto got_width;
+ }
+ }
+
+ /* Check for the assignment-suppressant and the number grouping flag. */
while (*f == '*' || *f == '\'')
switch (*f++)
{
@@ -166,11 +199,11 @@ DEFUN(__vfscanf, (s, format, arg),
width *= 10;
width += *f++ - '0';
}
+ got_width:
if (width == 0)
width = -1;
/* Check for type modifiers. */
- is_short = is_long = is_long_double = malloc_string = 0;
while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
switch (*f++)
{
@@ -218,13 +251,13 @@ DEFUN(__vfscanf, (s, format, arg),
case 'n': /* Answer number of assignments done. */
if (do_assign)
- *va_arg(arg, int *) = read_in;
+ *ARG (int *) = read_in;
break;
case 'c': /* Match characters. */
if (do_assign)
{
- str = va_arg (arg, char *);
+ str = ARG (char *);
if (str == NULL)
conv_error ();
}
@@ -256,7 +289,7 @@ DEFUN(__vfscanf, (s, format, arg),
if (malloc_string) \
{ \
/* The string is to be stored in a malloc'd buffer. */ \
- strptr = va_arg (arg, char **); \
+ strptr = ARG (char **); \
if (strptr == NULL) \
conv_error (); \
/* Allocate an initial buffer. */ \
@@ -264,7 +297,7 @@ DEFUN(__vfscanf, (s, format, arg),
*strptr = str = malloc (strsize); \
} \
else \
- str = va_arg (arg, char *); \
+ str = ARG (char *); \
if (str == NULL) \
conv_error (); \
}
@@ -406,16 +439,16 @@ DEFUN(__vfscanf, (s, format, arg),
/* Convert the number. */
*w = '\0';
- if (number_signed)
+ if (is_longlong)
{
- if (is_longlong)
+ if (number_signed)
num.q = __strtoq_internal (work, &w, base, group_flag);
else
num.uq = __strtouq_internal (work, &w, base, group_flag);
}
else
{
- if (is_long_double)
+ if (number_signed)
num.l = __strtol_internal (work, &w, base, group_flag);
else
num.ul = __strtoul_internal (work, &w, base, group_flag);
@@ -428,25 +461,25 @@ DEFUN(__vfscanf, (s, format, arg),
if (! number_signed)
{
if (is_longlong)
- *va_arg (arg, unsigned LONGLONG int *) = num.uq;
+ *ARG (unsigned LONGLONG int *) = num.uq;
else if (is_long)
- *va_arg (arg, unsigned long int *) = num.ul;
+ *ARG (unsigned long int *) = num.ul;
else if (is_short)
- *va_arg (arg, unsigned short int *)
+ *ARG (unsigned short int *)
= (unsigned short int) num.ul;
else
- *va_arg (arg, unsigned int *) = (unsigned int) num.ul;
+ *ARG (unsigned int *) = (unsigned int) num.ul;
}
else
{
if (is_longlong)
- *va_arg (arg, LONGLONG int *) = num.q;
+ *ARG (LONGLONG int *) = num.q;
else if (is_long)
- *va_arg (arg, long int *) = num.l;
+ *ARG (long int *) = num.l;
else if (is_short)
- *va_arg (arg, short int *) = (short int) num.l;
+ *ARG (short int *) = (short int) num.l;
else
- *va_arg (arg, int *) = (int) num.l;
+ *ARG (int *) = (int) num.l;
}
++done;
}
@@ -505,19 +538,19 @@ DEFUN(__vfscanf, (s, format, arg),
{
long double d = __strtold_internal (work, &w, group_flag);
if (do_assign && w != work)
- *va_arg (arg, long double *) = d;
+ *ARG (long double *) = d;
}
else if (is_long)
{
double d = __strtod_internal (work, &w, group_flag);
if (do_assign && w != work)
- *va_arg (arg, double *) = d;
+ *ARG (double *) = d;
}
else
{
float d = __strtof_internal (work, &w, group_flag);
if (do_assign && w != work)
- *va_arg (arg, float *) = d;
+ *ARG (float *) = d;
}
if (w == work)
diff --git a/stdlib/strtol.c b/stdlib/strtol.c
index 1c63afb6fe..a6c19578a2 100644
--- a/stdlib/strtol.c
+++ b/stdlib/strtol.c
@@ -175,6 +175,8 @@ INTERNAL (strtol) (nptr, endptr, base, group)
else
end = correctly_grouped_prefix (s, end, thousands, grouping);
}
+ else
+ end = NULL;
cutoff = ULONG_MAX / (unsigned LONG int) base;
cutlim = ULONG_MAX % (unsigned LONG int) base;
@@ -183,7 +185,7 @@ INTERNAL (strtol) (nptr, endptr, base, group)
i = 0;
for (c = *s; c != '\0'; c = *++s)
{
- if (group && s == end)
+ if (s == end)
break;
if (isdigit (c))
c -= '0';
diff --git a/sysdeps/mach/hurd/closedir.c b/sysdeps/mach/hurd/closedir.c
index bb970aed9e..6ac86a6cd4 100644
--- a/sysdeps/mach/hurd/closedir.c
+++ b/sysdeps/mach/hurd/closedir.c
@@ -23,6 +23,7 @@ Cambridge, MA 02139, USA. */
#include <dirent.h>
#include <unistd.h>
#include <hurd.h>
+#include <hurd/fd.h>
/* Close the directory stream DIRP.
Return 0 if successful, -1 if not. */