From 3867ee645cc03dba836667728d60cabbae111255 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 17 Jul 1996 19:32:22 +0000 Subject: Wed Jul 17 20:41:30 1996 Ulrich Drepper * stdio-common/vfscanf.c: Major change. Now read character from stream only if needed. Before it was read after the previous character was used. Bug reported by Martin Goik * stdio-common/tstscanf.c: Change test program so that return value is != 0 if one test failed. * sysdeps/m68k/Makefile (crypt): Variable removed. * sysdeps/sparc/Makefile: Likewise. --- stdio-common/tstscanf.c | 36 ++++++++++++++- stdio-common/vfscanf.c | 114 +++++++++++++++++++++++++++++++----------------- 2 files changed, 110 insertions(+), 40 deletions(-) (limited to 'stdio-common') diff --git a/stdio-common/tstscanf.c b/stdio-common/tstscanf.c index 005dc2dfce..59a47a3d80 100644 --- a/stdio-common/tstscanf.c +++ b/stdio-common/tstscanf.c @@ -39,7 +39,7 @@ DEFUN(main, (argc, argv), int argc AND char **argv) sscanf ("conversion] Zero flag Ze]ro#\n", "%*[^]] %[^#]\n", buf); if (strcmp (buf, "] Zero flag Ze]ro") != 0) { - fputs ("test failed!", stderr); + fputs ("test failed!\n", stderr); return 1; } @@ -64,6 +64,8 @@ DEFUN(main, (argc, argv), int argc AND char **argv) "sscanf (\"thompson\", \"%%s\", name) == %d, name == \"%s\"\n", sscanf ("thompson", "%s", name), name); + if (strcmp (name, "thompson") != 0) + return 1; } fputs ("Testing scanf (vfscanf)\n", out); @@ -76,8 +78,12 @@ DEFUN(main, (argc, argv), int argc AND char **argv) n = fscanf (in, "%d%f%s", &i, &x, name); fprintf (out, "n = %d, i = %d, x = %f, name = \"%.50s\"\n", n, i, x, name); + if (n != 3 || i != 25 || x != 5.432F || strcmp (name, "thompson")) + return 1; } fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in)); + if (strcmp (buf, "\n")) + return 1; fputs ("Test 2:\n", out); { int i; @@ -85,24 +91,52 @@ DEFUN(main, (argc, argv), int argc AND char **argv) char name[50]; (void) fscanf (in, "%2d%f%*d %[0123456789]", &i, &x, name); fprintf (out, "i = %d, x = %f, name = \"%.50s\"\n", i, x, name); + if (i != 56 || x != 789.0F || strcmp(name, "56")) + return 1; } fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in)); + if (strcmp (buf, "a72\n")) + return 1; fputs ("Test 3:\n", out); { + static struct { + int count; + float quant; + const char *units; + const char *item; + } ok[] = { + { 3, 2.0F, "quarts", "oil" }, + { 2, -12.8F, "degrees", "" }, + { 0, 0.0F, "", "" }, + { 3, 10.0F, "LBS", "fertilizer" }, + { 3, 100.0F, "rgs", "energy" }, + { -1, 0.0F, "", "" }}; + int rounds = 0; float quant; char units[21], item[21]; while (!feof (in) && !ferror (in)) { int count; + + if (rounds++ >= sizeof (ok) / sizeof (ok[0])) + return 1; + quant = 0.0; units[0] = item[0] = '\0'; count = fscanf (in, "%f%20s of %20s", &quant, units, item); (void) fscanf (in, "%*[^\n]"); fprintf (out, "count = %d, quant = %f, item = %.21s, units = %.21s\n", count, quant, item, units); + if (count != ok[rounds-1].count || quant != ok[rounds-1].quant + || strcmp (item, ok[rounds-1].item) + || strcmp (units, ok[rounds-1].units)) + return 1; } } + buf[0] = '\0'; fprintf (out, "Residual: \"%s\"\n", fgets (buf, sizeof (buf), in)); + if (strcmp (buf, "")) + return 1; if (out != stdout) pclose (out); diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index badaa2f93d..41b9f51f08 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -51,11 +51,10 @@ Cambridge, MA 02139, USA. */ # include # define va_list _IO_va_list -# define ungetc(c, s) _IO_ungetc (c, s) +# define ungetc(c, s) (--read_in, _IO_ungetc (c, s)) # define inchar() ((c = _IO_getc_unlocked (s)), (void) ++read_in, c) # define conv_error() do { \ if (errp != NULL) *errp |= 2; \ - if (c != EOF) _IO_ungetc (c, s); \ _IO_funlockfile (s); \ return done; \ } while (0) @@ -81,10 +80,10 @@ Cambridge, MA 02139, USA. */ } \ } while (0) #else +# define ungetc(c, s) (--read_in, ungetc (c, s)) # define inchar() ((c = getc (s)), (void) ++read_in, c) # define conv_error() do { \ funlockfile (s); \ - ungetc (c, s); \ return done; \ } while (0) # define input_error() do { \ @@ -197,8 +196,6 @@ __vfscanf (FILE *s, const char *format, va_list argptr) /* Lock the stream. */ flockfile (s); - c = inchar (); - /* Run through the format string. */ while (*f != '\0') { @@ -231,13 +228,18 @@ __vfscanf (FILE *s, const char *format, va_list argptr) int len = mblen (f, strlen (f)); if (len > 0) { - while (len-- > 0) - if (c == EOF) - input_error (); - else if (c == *f++) - (void) inchar (); - else - conv_error (); + do + { + c = inchar (); + if (c == EOF) + input_error (); + else if (c != *f++) + { + ungetc (c, s); + conv_error (); + } + } + while (--len > 0); continue; } } @@ -252,6 +254,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr) continue; } + /* Read a character. */ + c = inchar (); + /* Characters other than format specs must just match. */ if (c == EOF) input_error (); @@ -265,10 +270,11 @@ __vfscanf (FILE *s, const char *format, va_list argptr) skip_space = 0; } - if (c == fc) - (void) inchar (); - else - conv_error (); + if (c != fc) + { + ungetc (c, s); + conv_error (); + } continue; } @@ -378,17 +384,22 @@ __vfscanf (FILE *s, const char *format, va_list argptr) if (skip_space || (fc != '[' && fc != 'c' && fc != 'n')) { /* Eat whitespace. */ - while (isspace (c)) + do (void) inchar (); + while (isspace (c)); + ungetc (c, s); skip_space = 0; } switch (fc) { case '%': /* Must match a literal '%'. */ + c = inchar (); if (c != fc) - conv_error (); - inchar (); + { + ungetc (c, s); + conv_error (); + } break; case 'n': /* Answer number of assignments done. */ @@ -397,13 +408,13 @@ __vfscanf (FILE *s, const char *format, va_list argptr) if (!(flags & SUPPRESS)) /* Don't count the read-ahead. */ if (flags & LONGDBL) - *ARG (long long int *) = read_in - 1; + *ARG (long long int *) = read_in; else if (flags & LONG) - *ARG (long int *) = read_in - 1; + *ARG (long int *) = read_in; else if (flags & SHORT) - *ARG (short int *) = read_in - 1; + *ARG (short int *) = read_in; else - *ARG (int *) = read_in - 1; + *ARG (int *) = read_in; break; case 'c': /* Match characters. */ @@ -414,6 +425,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) conv_error (); } + c = inchar (); if (c == EOF) input_error (); @@ -424,10 +436,10 @@ __vfscanf (FILE *s, const char *format, va_list argptr) { do *str++ = c; - while (inchar () != EOF && --width > 0); + while (--width > 0 && inchar () != EOF); } else - while (inchar () != EOF && --width > 0); + while (--width > 0 && inchar () != EOF); if (!(flags & SUPPRESS)) ++done; @@ -455,13 +467,17 @@ __vfscanf (FILE *s, const char *format, va_list argptr) } STRING_ARG; + c = inchar (); if (c == EOF) input_error (); do { if (isspace (c)) - break; + { + ungetc (c, s); + break; + } #define STRING_ADD_CHAR(c) \ if (!(flags & SUPPRESS)) \ { \ @@ -499,7 +515,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) } \ } STRING_ADD_CHAR (c); - } while (inchar () != EOF && (width <= 0 || --width > 0)); + } while ((width <= 0 || --width > 0) && inchar () != EOF); if (!(flags & SUPPRESS)) { @@ -534,6 +550,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) number_signed = 1; number: + c = inchar (); if (c == EOF) input_error (); @@ -543,7 +560,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) ADDW (c); if (width > 0) --width; - (void) inchar (); + c = inchar (); } /* Look for a leading indication of base. */ @@ -553,7 +570,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) --width; ADDW (c); - (void) inchar (); + c = inchar (); if (width != 0 && tolower (c) == 'x') { @@ -563,7 +580,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) { if (width > 0) --width; - (void) inchar (); + c = inchar (); } } else if (base == 0) @@ -584,9 +601,12 @@ __vfscanf (FILE *s, const char *format, va_list argptr) if (width > 0) --width; - (void) inchar (); + c = inchar (); } + /* The just read character is not part of the number anymore. */ + ungetc (c, s); + if (wpsize == 0 || (wpsize == 1 && (wp[0] == '+' || wp[0] == '-'))) /* There was no number. */ @@ -645,6 +665,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) case 'f': case 'g': case 'G': + c = inchar (); if (c == EOF) input_error (); @@ -688,6 +709,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr) } while (inchar () != EOF && width != 0); + /* The last read character is not part of the number anymore. */ + ungetc (c, s); + if (wpsize == 0) conv_error (); @@ -722,8 +746,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr) case '[': /* Character class. */ STRING_ARG; + c = inchar (); if (c == EOF) - input_error(); + input_error (); if (*f == '^') { @@ -767,18 +792,25 @@ __vfscanf (FILE *s, const char *format, va_list argptr) wp[fc] = 1; } if (fc == '\0') - conv_error(); + { + ungetc (c, s); + conv_error(); + } - num.ul = read_in; + num.ul = read_in - 1; /* -1 because we already read one char. */ do { if (wp[c] == not_in) - break; + { + ungetc (c, s); + break; + } STRING_ADD_CHAR (c); if (width > 0) --width; } - while (inchar () != EOF && width != 0); + while (width != 0 && inchar () != EOF); + if (read_in == num.ul) conv_error (); @@ -802,13 +834,17 @@ __vfscanf (FILE *s, const char *format, va_list argptr) /* The last thing we saw int the format string was a white space. Consume the last white spaces. */ if (skip_space) - while (isspace (c)) - (void) inchar (); + { + do + c = inchar (); + while (isspace (c)); + ungetc (c, s); + } /* Unlock stream. */ funlockfile (s); - return ((void) (c == EOF || ungetc (c, s)), done); + return done; } #ifdef USE_IN_LIBIO -- cgit 1.4.1