scanf '%n' fix.

C. Scott Ananian cscott at cscott.net
Thu Mar 10 00:33:57 CST 2005


Changelog:
  - Allow scanf to continue parsing format string after a '%n'.
    (Previously, 'st' wasn't being set, so we'd stop after %n even if
    we weren't done with the format string.)  Also set 'suppress'
    so that the result value returned after a %n is correct.
  - Add tests for scanf to check proper handling of '%s %n%s'.

This fixes a bug I'm seeing in the Windows version of 'sd', a program for 
square dance callers ( http://www.lynette.org/sd/ ).
  --scott
                          ( http://cscott.net/ )

Index: dlls/msvcrt/scanf.h
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/scanf.h,v
retrieving revision 1.19
diff -u -p -r1.19 scanf.h
--- dlls/msvcrt/scanf.h	28 Jan 2005 11:27:26 -0000	1.19
+++ dlls/msvcrt/scanf.h	10 Mar 2005 06:28:04 -0000
@@ -427,6 +427,19 @@ _FUNCTION_ {
  			int*n = va_arg(ap, int*);
  			*n = consumed - (nch!=_EOF_);
  		    }
+		    /* This is an odd one: according to the standard,
+		     * "Execution of a %n directive does not increment the
+		     * assignment count returned at the completion of
+		     * execution" even if it wasn't suppressed with the
+		     * '*' flag.  The Corrigendum to the standard seems
+		     * to contradict this (comment out the assignment to
+		     * suppress below if you want to implement these
+		     * alternate semantics) but the windows program I'm
+		     * looking at expects the behavior I've coded here
+		     * (which happens to be what glibc does as well).
+		     */
+		    suppress = 1;
+		    st = 1;
  	        }
  		break;
  	    case '[': {
Index: dlls/msvcrt/tests/scanf.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/tests/scanf.c,v
retrieving revision 1.16
diff -u -p -r1.16 scanf.c
--- dlls/msvcrt/tests/scanf.c	28 Jan 2005 11:27:26 -0000	1.16
+++ dlls/msvcrt/tests/scanf.c	10 Mar 2005 06:28:04 -0000
@@ -117,6 +117,14 @@ static void test_sscanf( void )
      ok(hour == 18, "Field 1 incorrect: %d\n", hour);
      ok(min == 59, "Field 2 incorrect: %d\n", min);
      ok(c == 0x55, "Field 3 incorrect: 0x%02x\n", c);
+
+    /* Check %n (also whitespace in format strings and %s) */
+    buffer[0]=0; buffer1[0]=0;
+    ret = sscanf("abc   def", "%s %n%s", buffer, &number_so_far, buffer1);
+    ok(strcmp(buffer, "abc")==0, "First %%s read incorrectly: %s\n", buffer);
+    ok(strcmp(buffer1,"def")==0, "Second %%s read incorrectly: %s\n", buffer1);
+    ok(number_so_far==6, "%%n yielded wrong result: %d\n", number_so_far);
+    ok(ret == 2, "%%n shouldn't count as a conversion: %d\n", ret);
  }

  START_TEST(scanf)



More information about the wine-patches mailing list