delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/11/17/16:35:40

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
Date: Mon, 17 Nov 2003 21:46:31 +0000
From: "Richard Dawe" <rich AT phekda DOT freeserve DOT co DOT uk>
Sender: rich AT phekda DOT freeserve DOT co DOT uk
To: djgpp-workers AT delorie DOT com
X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6
Subject: Problems with sscanf & suppressions, revision 2 [PATCH]
Message-Id: <E1ALrQ7-0001UT-00@phekda.freeserve.co.uk>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Below is a revised version of the patch to fix problems with sscanf
and suppressions. sscanf returns the number of fields assigned.
The previous version of the patch was incorrectly counting
the suppressed fields as "assigned". This has been fixed.

(I updated the test cases, before fixing the code.)

OK to commit? I'd like to get this into DJGPP 2.04 beta 1, if possible.

Thanks, bye, Rich =]

Index: src/libc/ansi/stdio/doscan.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdio/doscan.c,v
retrieving revision 1.14
diff -p -u -3 -r1.14 doscan.c
--- src/libc/ansi/stdio/doscan.c	8 Nov 2003 12:19:40 -0000	1.14
+++ src/libc/ansi/stdio/doscan.c	17 Nov 2003 21:30:26 -0000
@@ -144,7 +144,7 @@ _doscan_low(FILE *iop, int (*scan_getc)(
       }
     }
     if (ch == '\0')
-      return(-1);
+      return(EOF);
 
     if (ch == 'n')
     {
@@ -167,12 +167,12 @@ _doscan_low(FILE *iop, int (*scan_getc)(
 	       &fileended))
     {
       if (ptr)
-        nmatch++;
+	nmatch++;
     }
     else
     {
-      if (fileended && nmatch==0)
-        return(-1);
+      if (fileended)
+        return(EOF);
       return(nmatch);
     }
     break;
@@ -198,7 +198,7 @@ _doscan_low(FILE *iop, int (*scan_getc)(
     if (ch1 != EOF) nchars++;
     if (ch1 != ch) {
       if (ch1==EOF)
-	return(nmatch? nmatch: -1);
+	return(nmatch? nmatch: EOF);
       scan_ungetc(ch1, iop);
       nchars--;
       return(nmatch);
@@ -351,11 +351,10 @@ _instr(char *ptr, int type, int len, FIL
        int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
 {
   register int ch;
-  register char *optr;
   int ignstp;
+  int matched = 0;
 
   *eofptr = 0;
-  optr = ptr;
   if (type=='c' && len==30000)
     len = 1;
   ignstp = 0;
@@ -369,6 +368,7 @@ _instr(char *ptr, int type, int len, FIL
   else if (type=='[')
     ignstp = STP;
   while (ch!=EOF && (_sctab[ch & 0xff]&ignstp)==0) {
+    matched = 1;
     if (ptr)
       *ptr++ = ch;
     if (--len <= 0)
@@ -388,10 +388,8 @@ _instr(char *ptr, int type, int len, FIL
     nchars--;
     *eofptr = 1;
   }
-  if (!ptr)
-    return(1);
-  if (ptr!=optr) {
-    if (type!='c')
+  if (matched) {
+    if (ptr && type!='c')
       *ptr++ = '\0';
     return(1);
   }
@@ -409,11 +407,12 @@ _getccl(const unsigned char *s)
     t++;
     s++;
   }
-  for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++)
+  for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++) {
     if (t)
       _sctab[c] &= ~STP;
     else
       _sctab[c] |= STP;
+  }
   if ((c = *s) == ']' || c == '-') { /* first char is special */
     if (t)
       _sctab[c] |= STP;
Index: tests/libc/ansi/stdio/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/tests/libc/ansi/stdio/makefile,v
retrieving revision 1.10
diff -p -u -3 -r1.10 makefile
--- tests/libc/ansi/stdio/makefile	8 Nov 2003 12:19:40 -0000	1.10
+++ tests/libc/ansi/stdio/makefile	17 Nov 2003 21:30:26 -0000
@@ -18,6 +18,7 @@ SRC += printf.c
 SRC += printf2.c
 SRC += sscanf.c
 SRC += sscanf2.c
+SRC += sscanf3.c
 SRC += tmpnam.c
 SRC += tremove.c
 SRC += tscanf.c
Index: src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.163
diff -p -u -3 -r1.163 wc204.txi
--- src/docs/kb/wc204.txi	14 Nov 2003 08:39:53 -0000	1.163
+++ src/docs/kb/wc204.txi	17 Nov 2003 21:30:30 -0000
@@ -1036,3 +1036,9 @@ This means that @code{%T} and @code{%X} 
 @vindex __djgpp_stack_overflow_eip AT r{ added}
 @findex __djgpp_stack_overflow_exit AT r{ added}
 A stack overflow handler was added.
+
+@findex scanf AT r{, and assignment suppression}
+A bug was fixed in the @code{scanf} family of functions,
+when suppressing assignment of conversions to variables.
+Previously the @code{scanf} family of functions could return
+a match failure at EOF instead of @code{EOF}.
--- /dev/null	2003-11-17 21:42:17.000000000 +0000
+++ tests/libc/ansi/stdio/sscanf3.c	2003-11-17 21:19:26.000000000 +0000
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct {
+  const char *input;
+  const char *fmt;
+
+  const int expected;
+  const char expected_c[2];
+  const char expected_c2[2];
+
+  char c[2];
+  char c2[2];
+} sscanf_testcase_t;
+
+sscanf_testcase_t sscanf_testcases[] = {
+  /* No assignment */
+  { "", "%*[0123456789]%*c", EOF, "", "" },
+  { "X", "%*[0123456789]%*c", 0, "", "" },
+  { "1", "%*[0123456789]%*c", EOF, "", "" },
+  { "1X2", "%*[0123456789]%*[0123456789]", 0, "", "" },
+  { "1,2", "%*[0123456789],%*[0123456789]", 0, "", "" },
+
+  /* Assign first */
+  { "", "%[0123456789]%*c", EOF, "", "" },
+  { "X", "%[0123456789]%*c", 0, "", "" },
+  { "1", "%[0123456789]%*c", EOF, "1", "" },
+  { "1X2", "%[0123456789]%*[0123456789]", 1, "1", "" },
+  { "1,2", "%[0123456789],%*[0123456789]", 1, "1", "" },
+
+  /* Assign second */
+  { "", "%*[0123456789]%c", EOF, "", "" },
+  { "X", "%*[0123456789]%c", 0, "", "" },
+  { "1", "%*[0123456789]%c", EOF, "", "" },
+  { "1X2", "%*[0123456789]%[0123456789]", 0, "", "" },
+  { "1,2", "%*[0123456789],%[0123456789]", 1, "2", "" },
+
+  /* Assign both */
+  { "", "%[0123456789]%c", EOF, "", "" },
+  { "X", "%[0123456789]%c", 0, "", "" },
+  { "1", "%[0123456789]%c", EOF, "1", "" },
+  { "1X2", "%[0123456789]%[0123456789]", 1, "1", "" },
+  { "1,2", "%[0123456789],%[0123456789]", 2, "1", "2" },
+
+  /* Terminator */
+  { NULL, NULL, 0 }
+};
+
+int
+main (void)
+{
+  int ok = 1;
+  int ret;
+  int i;
+
+  for (i = 0; sscanf_testcases[i].input != NULL; i++)
+  {
+    sscanf_testcases[i].c[0]
+      = sscanf_testcases[i].c2[0]
+      = 0;
+    ret = sscanf(sscanf_testcases[i].input,
+		 sscanf_testcases[i].fmt,
+		 sscanf_testcases[i].c,
+		 sscanf_testcases[i].c2);
+    if (   (ret != sscanf_testcases[i].expected)
+	|| (strcmp(sscanf_testcases[i].c, sscanf_testcases[i].expected_c))
+	|| (strcmp(sscanf_testcases[i].c2, sscanf_testcases[i].expected_c2)))
+    {
+      printf("Test %d: FAIL: (\"%s\", \"%s\");\n"
+	     "\texpected %d;\n"
+	     "\texpected c1 '%s';\n"
+	     "\texpected c2 '%s';\n"
+	     "\tgot %d;\n"
+	     "\tc == '%s'\n"
+	     "\tc2 == '%s'\n",
+	     i + 1,
+	     sscanf_testcases[i].input,
+	     sscanf_testcases[i].fmt,
+	     sscanf_testcases[i].expected,
+	     sscanf_testcases[i].expected_c,
+	     sscanf_testcases[i].expected_c2,
+	     ret,
+	     sscanf_testcases[i].c,
+	     sscanf_testcases[i].c2);
+      ok = 0;
+    }
+  }
+
+  puts(ok ? "PASS" : "FAIL");
+  return ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019