[PATCH v3] ucrtbase: Fix handling of tab and non-breaking space in iswctype().

Chip Davis cdavis at codeweavers.com
Wed Dec 11 17:23:55 CST 2019


It's just these two that are handled specially AFAICT.

Signed-off-by: Chip Davis <cdavis at codeweavers.com>
---

Notes:
    v2: Fix build.
    v3: Fix sign extension bug.

 dlls/msvcr100/msvcr100.spec    |  2 +-
 dlls/msvcr110/msvcr110.spec    |  2 +-
 dlls/msvcr110/tests/msvcr110.c | 30 +++++++++++++++++++++++++
 dlls/msvcr120/msvcr120.spec    |  2 +-
 dlls/msvcr70/msvcr70.spec      |  2 +-
 dlls/msvcr71/msvcr71.spec      |  2 +-
 dlls/msvcr80/msvcr80.spec      |  2 +-
 dlls/msvcr90/msvcr90.spec      |  2 +-
 dlls/msvcrt/msvcrt.spec        |  2 +-
 dlls/msvcrt/tests/string.c     | 28 +++++++++++++++++++++++
 dlls/msvcrt/wcs.c              | 29 +++++++++++++++++-------
 dlls/ucrtbase/tests/misc.c     | 41 +++++++++++++++++++++++++++++-----
 dlls/ucrtbase/ucrtbase.spec    |  2 +-
 13 files changed, 123 insertions(+), 23 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 560e14b33b8..177b67298b2 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -1719,7 +1719,7 @@
 @ cdecl iswalpha(long) ntdll.iswalpha
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec
index 2316535e5d1..376c36cd159 100644
--- a/dlls/msvcr110/msvcr110.spec
+++ b/dlls/msvcr110/msvcr110.spec
@@ -2077,7 +2077,7 @@
 @ cdecl iswalpha(long) ntdll.iswalpha
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcr110/tests/msvcr110.c b/dlls/msvcr110/tests/msvcr110.c
index 09876131f07..862d2bfce74 100644
--- a/dlls/msvcr110/tests/msvcr110.c
+++ b/dlls/msvcr110/tests/msvcr110.c
@@ -33,6 +33,7 @@
 
 static char* (CDECL *p_setlocale)(int category, const char* locale);
 static size_t (CDECL *p___strncnt)(const char *str, size_t count);
+static int (CDECL *p_iswctype)(wchar_t, wctype_t);
 
 static unsigned int (CDECL *p_CurrentScheduler_GetNumberOfVirtualProcessors)(void);
 static unsigned int (CDECL *p__CurrentScheduler__GetNumberOfVirtualProcessors)(void);
@@ -52,6 +53,7 @@ static BOOL init(void)
 
     p_setlocale = (void*)GetProcAddress(module, "setlocale");
     p___strncnt = (void*)GetProcAddress(module, "__strncnt");
+    p_iswctype = (void*)GetProcAddress(module, "iswctype");
     p_CurrentScheduler_GetNumberOfVirtualProcessors = (void*)GetProcAddress(module, "?GetNumberOfVirtualProcessors at CurrentScheduler@Concurrency@@SAIXZ");
     p__CurrentScheduler__GetNumberOfVirtualProcessors = (void*)GetProcAddress(module, "?_GetNumberOfVirtualProcessors at _CurrentScheduler@details at Concurrency@@SAIXZ");
     p_CurrentScheduler_Id = (void*)GetProcAddress(module, "?Id at CurrentScheduler@Concurrency@@SAIXZ");
@@ -143,10 +145,38 @@ static void test___strncnt(void)
     }
 }
 
+static void test_iswctype(void)
+{
+    static const struct {
+        WCHAR c;
+        int t;
+        int r;
+    } tests[] = {
+        { '0', C1_DIGIT, C1_DIGIT },
+        { '9', C1_DIGIT, C1_DIGIT },
+        { 'a', C1_DIGIT, 0 },
+        { 'a', C1_LOWER, C1_LOWER },
+        { 0xa0, C1_BLANK, C1_BLANK },
+        { 0xe0, _ALPHA, C1_ALPHA|C1_LOWER },
+        { 0xff16, C1_DIGIT, C1_DIGIT },
+        { 0x0660, C1_DIGIT, C1_DIGIT },
+        { 0x0ce6, C1_DIGIT, C1_DIGIT }
+    };
+    int i, r;
+
+    p_setlocale(LC_ALL, "C");
+    for (i = 0; i < ARRAY_SIZE(tests); i++)
+    {
+        r = p_iswctype(tests[i].c, tests[i].t);
+        ok(r == tests[i].r, "iswctype returned %x for %x\n", r, tests[i].c);
+    }
+}
+
 START_TEST(msvcr110)
 {
     if (!init()) return;
     test_CurrentScheduler(); /* MUST be first (at least among Concurrency tests) */
     test_setlocale();
     test___strncnt();
+    test_iswctype();
 }
diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec
index 903f4b7ce38..f04a0ec3494 100644
--- a/dlls/msvcr120/msvcr120.spec
+++ b/dlls/msvcr120/msvcr120.spec
@@ -2230,7 +2230,7 @@
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswblank(long) MSVCRT_iswblank
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcr70/msvcr70.spec b/dlls/msvcr70/msvcr70.spec
index a014cf50365..d1457e8a32e 100644
--- a/dlls/msvcr70/msvcr70.spec
+++ b/dlls/msvcr70/msvcr70.spec
@@ -754,7 +754,7 @@
 @ cdecl iswalpha(long) ntdll.iswalpha
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcr71/msvcr71.spec b/dlls/msvcr71/msvcr71.spec
index 21b73d3a75c..72f292e64f0 100644
--- a/dlls/msvcr71/msvcr71.spec
+++ b/dlls/msvcr71/msvcr71.spec
@@ -750,7 +750,7 @@
 @ cdecl iswalpha(long) ntdll.iswalpha
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 402e6efc109..9e5f03685ce 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -1401,7 +1401,7 @@
 @ cdecl iswalpha(long) ntdll.iswalpha
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index 8a079abe254..8c54c5f762d 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -1374,7 +1374,7 @@
 @ cdecl iswalpha(long) ntdll.iswalpha
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index b3b9cca0b97..0d6b17eb6d8 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -1340,7 +1340,7 @@
 @ cdecl iswalpha(long) ntdll.iswalpha
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 1be4dcb129c..5b215728ad4 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -4024,6 +4024,33 @@ static void test_iswdigit(void)
     }
 }
 
+static void test_iswctype(void)
+{
+    static const struct {
+        WCHAR c;
+        int t;
+        int r;
+    } tests[] = {
+        { '0', C1_DIGIT, C1_DIGIT },
+        { '9', C1_DIGIT, C1_DIGIT },
+        { 'a', C1_DIGIT, 0 },
+        { 'a', C1_LOWER, C1_LOWER },
+        { 0xa0, C1_BLANK, C1_BLANK },
+        { 0xe0, _ALPHA, C1_ALPHA|C1_LOWER },
+        { 0xff16, C1_DIGIT, C1_DIGIT },
+        { 0x0660, C1_DIGIT, C1_DIGIT },
+        { 0x0ce6, C1_DIGIT, C1_DIGIT }
+    };
+    int i, r;
+
+    setlocale(LC_ALL, "C");
+    for (i = 0; i < ARRAY_SIZE(tests); i++)
+    {
+        r = iswctype(tests[i].c, tests[i].t);
+        ok(r == tests[i].r, "iswctype returned %x for %x\n", r, tests[i].c);
+    }
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -4167,4 +4194,5 @@ START_TEST(string)
     test_C_locale();
     test_strstr();
     test_iswdigit();
+    test_iswctype();
 }
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 1ae292423c0..e54e2bb8d1f 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -1845,6 +1845,27 @@ MSVCRT_size_t CDECL MSVCRT_wcrtomb( char *dst, MSVCRT_wchar_t ch, MSVCRT_mbstate
     return MSVCRT_wctomb(dst, ch);
 }
 
+/*********************************************************************
+ *		_iswctype_l (MSVCRT.@)
+ */
+int CDECL MSVCRT__iswctype_l(MSVCRT_wchar_t wc, MSVCRT_wctype_t type, MSVCRT__locale_t locale)
+{
+    int ret = (get_char_typeW(wc) & 0xffff) & type;
+
+#if _MSVCR_VER >= 140
+    if (wc == '\t' || wc == 0x00a0) ret &= ~MSVCRT__BLANK;
+#endif
+    return ret;
+}
+
+/*********************************************************************
+ *		iswctype (MSVCRT.@)
+ */
+int CDECL MSVCRT_iswctype(MSVCRT_wchar_t wc, MSVCRT_wctype_t type)
+{
+    return MSVCRT__iswctype_l( wc, type, NULL );
+}
+
 /*********************************************************************
  *		iswalnum (MSVCRT.@)
  */
@@ -2021,14 +2042,6 @@ int CDECL MSVCRT__iswxdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
     return isxdigitW( wc );
 }
 
-/*********************************************************************
- *		_iswctype_l (MSVCRT.@)
- */
-INT CDECL MSVCRT__iswctype_l( MSVCRT_wchar_t wc, MSVCRT_wctype_t type, MSVCRT__locale_t locale )
-{
-    return (get_char_typeW(wc) & 0xffff) & type;
-}
-
 /*********************************************************************
  *		_iswblank_l (MSVCRT.@)
  */
diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c
index f637997a0d1..c9b04b7dd47 100644
--- a/dlls/ucrtbase/tests/misc.c
+++ b/dlls/ucrtbase/tests/misc.c
@@ -33,6 +33,7 @@
 
 #include <windef.h>
 #include <winbase.h>
+#include <winnls.h>
 #include "wine/test.h"
 
 #define DEFINE_EXPECT(func) \
@@ -154,6 +155,7 @@ static MSVCRT_lldiv_t* (CDECL *p_lldiv)(MSVCRT_lldiv_t*,LONGLONG,LONGLONG);
 static int (CDECL *p__isctype)(int,int);
 static int (CDECL *p_isblank)(int);
 static int (CDECL *p__isblank_l)(int,_locale_t);
+static int (CDECL *p_iswctype)(int,int);
 static int (CDECL *p__iswctype_l)(int,int,_locale_t);
 static int (CDECL *p_iswblank)(int);
 static int (CDECL *p__iswblank_l)(wint_t,_locale_t);
@@ -531,6 +533,7 @@ static BOOL init(void)
     p__isctype = (void*)GetProcAddress(module, "_isctype");
     p_isblank = (void*)GetProcAddress(module, "isblank");
     p__isblank_l = (void*)GetProcAddress(module, "_isblank_l");
+    p_iswctype = (void*)GetProcAddress(module, "iswctype");
     p__iswctype_l = (void*)GetProcAddress(module, "_iswctype_l");
     p_iswblank = (void*)GetProcAddress(module, "iswblank");
     p__iswblank_l = (void*)GetProcAddress(module, "_iswblank_l");
@@ -647,21 +650,46 @@ static void test_isblank(void)
     for(c = 0; c <= 0xffff; c++) {
         if(c == '\t' || c == ' ' || c == 0x3000 || c == 0xfeff) {
             if(c == '\t')
-                todo_wine ok(!p__iswctype_l(c, _BLANK, NULL), "tab shouldn't be blank\n");
+                ok(!p__iswctype_l(c, _BLANK, NULL), "tab shouldn't be blank\n");
             else
                 ok(p__iswctype_l(c, _BLANK, NULL), "%d should be blank\n", c);
             ok(p_iswblank(c), "%d should be blank\n", c);
             ok(p__iswblank_l(c, NULL), "%d should be blank\n", c);
         } else {
-            todo_wine_if(c == 0xa0) {
-                ok(!p__iswctype_l(c, _BLANK, NULL), "%d shouldn't be blank\n", c);
-                ok(!p_iswblank(c), "%d shouldn't be blank\n", c);
-                ok(!p__iswblank_l(c, NULL), "%d shouldn't be blank\n", c);
-            }
+            ok(!p__iswctype_l(c, _BLANK, NULL), "%d shouldn't be blank\n", c);
+            ok(!p_iswblank(c), "%d shouldn't be blank\n", c);
+            ok(!p__iswblank_l(c, NULL), "%d shouldn't be blank\n", c);
         }
     }
 }
 
+static void test_iswctype(void)
+{
+    static const struct {
+        WCHAR c;
+        int t;
+        int r;
+    } tests[] = {
+        { '0', C1_DIGIT, C1_DIGIT },
+        { '9', C1_DIGIT, C1_DIGIT },
+        { 'a', C1_DIGIT, 0 },
+        { 'a', C1_LOWER, C1_LOWER },
+        { 0xa0, C1_BLANK, 0 },
+        { 0xe0, _ALPHA, C1_ALPHA|C1_LOWER },
+        { 0xff16, C1_DIGIT, C1_DIGIT },
+        { 0x0660, C1_DIGIT, C1_DIGIT },
+        { 0x0ce6, C1_DIGIT, C1_DIGIT }
+    };
+    int i, r;
+
+    p_setlocale(LC_ALL, "C");
+    for (i = 0; i < ARRAY_SIZE(tests); i++)
+    {
+        r = p_iswctype(tests[i].c, tests[i].t);
+        ok(r == tests[i].r, "iswctype returned %x for %x\n", r, tests[i].c);
+    }
+}
+
 static struct MSVCRT__exception exception;
 
 static int CDECL matherr_callback(struct MSVCRT__exception *e)
@@ -1460,6 +1488,7 @@ START_TEST(misc)
     test__sopen_s();
     test_lldiv();
     test_isblank();
+    test_iswctype();
     test_math_errors();
     test_asctime();
     test_strftime();
diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec
index 1293dd62f16..ca474dce9f9 100644
--- a/dlls/ucrtbase/ucrtbase.spec
+++ b/dlls/ucrtbase/ucrtbase.spec
@@ -2364,7 +2364,7 @@
 @ cdecl iswascii(long) MSVCRT_iswascii
 @ cdecl iswblank(long) MSVCRT_iswblank
 @ cdecl iswcntrl(long) MSVCRT_iswcntrl
-@ cdecl iswctype(long long) ntdll.iswctype
+@ cdecl iswctype(long long) MSVCRT_iswctype
 @ cdecl iswdigit(long) MSVCRT_iswdigit
 @ cdecl iswgraph(long) MSVCRT_iswgraph
 @ cdecl iswlower(long) MSVCRT_iswlower
-- 
2.21.0




More information about the wine-devel mailing list