From be69ea41ebade5819509b32e1b41ce1853392611 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 18 Mar 1995 20:44:21 +0000 Subject: [PATCH] Sat Mar 18 14:07:08 1995 Roland McGrath * 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. --- ChangeLog | 10 ++++++ stdio/vfscanf.c | 75 +++++++++++++++++++++++++++++++------------- stdlib/strtol.c | 4 ++- sysdeps/mach/hurd/closedir.c | 1 + 4 files changed, 68 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0d54c13..88cdb2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Sat Mar 18 14:07:08 1995 Roland McGrath + + * 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 * Makefile (subdirs): Put elf last. diff --git a/stdio/vfscanf.c b/stdio/vfscanf.c index 9a9e3bb..cacf16f 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 1c63afb..a6c1957 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 bb970ae..6ac86a6 100644 --- a/sysdeps/mach/hurd/closedir.c +++ b/sysdeps/mach/hurd/closedir.c @@ -23,6 +23,7 @@ Cambridge, MA 02139, USA. */ #include #include #include +#include /* Close the directory stream DIRP. Return 0 if successful, -1 if not. */ -- 2.7.4