From: Chip Davis Subject: [PATCH v3] ucrtbase: Fix handling of tab and non-breaking space in iswctype(). Message-Id: <20191211232355.70180-1-cdavis@codeweavers.com> Date: Wed, 11 Dec 2019 17:23:55 -0600 It's just these two that are handled specially AFAICT. Signed-off-by: Chip Davis --- 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@CurrentScheduler@Concurrency@@SAIXZ"); p__CurrentScheduler__GetNumberOfVirtualProcessors = (void*)GetProcAddress(module, "?_GetNumberOfVirtualProcessors@_CurrentScheduler@details@Concurrency@@SAIXZ"); p_CurrentScheduler_Id = (void*)GetProcAddress(module, "?Id@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 #include +#include #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