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" 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: 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 +#include +#include + +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; +}