Mail Archives: djgpp-workers/2003/11/17/16:35:40
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 -