Commit 6d2a9af4 authored by Shaun Ren's avatar Shaun Ren Committed by Alexandre Julliard

msvcrt: Fix strncmp return value.

Some programs, such as Final Fantasy IV (3D remake), expect strncmp to return exactly +/-1 when the strings are not equal. Signed-off-by: 's avatarShaun Ren <sren@codeweavers.com>
parent 1b3f61d7
...@@ -21745,7 +21745,9 @@ wine_fn_config_makefile dlls/msvcr120 enable_msvcr120 ...@@ -21745,7 +21745,9 @@ wine_fn_config_makefile dlls/msvcr120 enable_msvcr120
wine_fn_config_makefile dlls/msvcr120/tests enable_tests wine_fn_config_makefile dlls/msvcr120/tests enable_tests
wine_fn_config_makefile dlls/msvcr120_app enable_msvcr120_app wine_fn_config_makefile dlls/msvcr120_app enable_msvcr120_app
wine_fn_config_makefile dlls/msvcr70 enable_msvcr70 wine_fn_config_makefile dlls/msvcr70 enable_msvcr70
wine_fn_config_makefile dlls/msvcr70/tests enable_tests
wine_fn_config_makefile dlls/msvcr71 enable_msvcr71 wine_fn_config_makefile dlls/msvcr71 enable_msvcr71
wine_fn_config_makefile dlls/msvcr71/tests enable_tests
wine_fn_config_makefile dlls/msvcr80 enable_msvcr80 wine_fn_config_makefile dlls/msvcr80 enable_msvcr80
wine_fn_config_makefile dlls/msvcr80/tests enable_tests wine_fn_config_makefile dlls/msvcr80/tests enable_tests
wine_fn_config_makefile dlls/msvcr90 enable_msvcr90 wine_fn_config_makefile dlls/msvcr90 enable_msvcr90
......
...@@ -2851,7 +2851,9 @@ WINE_CONFIG_MAKEFILE(dlls/msvcr120) ...@@ -2851,7 +2851,9 @@ WINE_CONFIG_MAKEFILE(dlls/msvcr120)
WINE_CONFIG_MAKEFILE(dlls/msvcr120/tests) WINE_CONFIG_MAKEFILE(dlls/msvcr120/tests)
WINE_CONFIG_MAKEFILE(dlls/msvcr120_app) WINE_CONFIG_MAKEFILE(dlls/msvcr120_app)
WINE_CONFIG_MAKEFILE(dlls/msvcr70) WINE_CONFIG_MAKEFILE(dlls/msvcr70)
WINE_CONFIG_MAKEFILE(dlls/msvcr70/tests)
WINE_CONFIG_MAKEFILE(dlls/msvcr71) WINE_CONFIG_MAKEFILE(dlls/msvcr71)
WINE_CONFIG_MAKEFILE(dlls/msvcr71/tests)
WINE_CONFIG_MAKEFILE(dlls/msvcr80) WINE_CONFIG_MAKEFILE(dlls/msvcr80)
WINE_CONFIG_MAKEFILE(dlls/msvcr80/tests) WINE_CONFIG_MAKEFILE(dlls/msvcr80/tests)
WINE_CONFIG_MAKEFILE(dlls/msvcr90) WINE_CONFIG_MAKEFILE(dlls/msvcr90)
......
...@@ -237,6 +237,9 @@ static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t,_locale_t); ...@@ -237,6 +237,9 @@ static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t,_locale_t);
static char* (__cdecl *p_setlocale)(int, const char*); static char* (__cdecl *p_setlocale)(int, const char*);
static size_t (__cdecl *p___strncnt)(const char*, size_t); static size_t (__cdecl *p___strncnt)(const char*, size_t);
static int (__cdecl *p_strcmp)(const char *, const char *);
static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
/* make sure we use the correct errno */ /* make sure we use the correct errno */
#undef errno #undef errno
#define errno (*p_errno()) #define errno (*p_errno())
...@@ -277,6 +280,9 @@ static BOOL init(void) ...@@ -277,6 +280,9 @@ static BOOL init(void)
SET(p_CurrentScheduler_Detach, "?Detach@CurrentScheduler@Concurrency@@SAXXZ"); SET(p_CurrentScheduler_Detach, "?Detach@CurrentScheduler@Concurrency@@SAXXZ");
SET(p_CurrentScheduler_Id, "?Id@CurrentScheduler@Concurrency@@SAIXZ"); SET(p_CurrentScheduler_Id, "?Id@CurrentScheduler@Concurrency@@SAIXZ");
SET(p_strcmp, "strcmp");
SET(p_strncmp, "strncmp");
if(sizeof(void*) == 8) { /* 64-bit initialization */ if(sizeof(void*) == 8) { /* 64-bit initialization */
SET(pSpinWait_ctor_yield, "??0?$_SpinWait@$00@details@Concurrency@@QEAA@P6AXXZ@Z"); SET(pSpinWait_ctor_yield, "??0?$_SpinWait@$00@details@Concurrency@@QEAA@P6AXXZ@Z");
SET(pSpinWait_dtor, "??_F?$_SpinWait@$00@details@Concurrency@@QEAAXXZ"); SET(pSpinWait_dtor, "??_F?$_SpinWait@$00@details@Concurrency@@QEAAXXZ");
...@@ -1106,6 +1112,46 @@ static void test___strncnt(void) ...@@ -1106,6 +1112,46 @@ static void test___strncnt(void)
} }
} }
static void test_strcmp(void)
{
int ret = p_strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
#ifdef _WIN64
ret = p_strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
#else
ret = p_strncmp( "", "abc", 3 );
ok( ret == 0 - 'a', "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == 'c' - 0xa0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 0xb0 - 0xa0, "wrong ret %d\n", ret );
#endif
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(msvcr100) START_TEST(msvcr100)
{ {
if (!init()) if (!init())
...@@ -1126,4 +1172,5 @@ START_TEST(msvcr100) ...@@ -1126,4 +1172,5 @@ START_TEST(msvcr100)
test__memicmp_l(); test__memicmp_l();
test_setlocale(); test_setlocale();
test___strncnt(); test___strncnt();
test_strcmp();
} }
...@@ -52,6 +52,9 @@ static unsigned int (CDECL *p__CurrentScheduler__Id)(void); ...@@ -52,6 +52,9 @@ static unsigned int (CDECL *p__CurrentScheduler__Id)(void);
static Context* (__cdecl *p_Context_CurrentContext)(void); static Context* (__cdecl *p_Context_CurrentContext)(void);
static _Context* (__cdecl *p__Context__CurrentContext)(_Context*); static _Context* (__cdecl *p__Context__CurrentContext)(_Context*);
static int (__cdecl *p_strcmp)(const char *, const char *);
static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y) #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y)
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
...@@ -84,6 +87,9 @@ static BOOL init(void) ...@@ -84,6 +87,9 @@ static BOOL init(void)
SET(p_Context_CurrentContext, "?CurrentContext@Context@Concurrency@@SAPAV12@XZ"); SET(p_Context_CurrentContext, "?CurrentContext@Context@Concurrency@@SAPAV12@XZ");
} }
SET(p_strcmp, "strcmp");
SET(p_strncmp, "strncmp");
return TRUE; return TRUE;
} }
...@@ -192,6 +198,37 @@ static void test_CurrentContext(void) ...@@ -192,6 +198,37 @@ static void test_CurrentContext(void)
ok(ret == &_ctx, "expected %p, got %p\n", &_ctx, ret); ok(ret == &_ctx, "expected %p, got %p\n", &_ctx, ret);
} }
static void test_strcmp(void)
{
int ret = p_strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(msvcr110) START_TEST(msvcr110)
{ {
if (!init()) return; if (!init()) return;
...@@ -199,4 +236,5 @@ START_TEST(msvcr110) ...@@ -199,4 +236,5 @@ START_TEST(msvcr110)
test_setlocale(); test_setlocale();
test___strncnt(); test___strncnt();
test_CurrentContext(); test_CurrentContext();
test_strcmp();
} }
...@@ -220,6 +220,8 @@ static float (__cdecl *p_nexttowardf)(float, double); ...@@ -220,6 +220,8 @@ static float (__cdecl *p_nexttowardf)(float, double);
static double (__cdecl *p_nexttowardl)(double, double); static double (__cdecl *p_nexttowardl)(double, double);
static wctrans_t (__cdecl *p_wctrans)(const char*); static wctrans_t (__cdecl *p_wctrans)(const char*);
static wint_t (__cdecl *p_towctrans)(wint_t, wctrans_t); static wint_t (__cdecl *p_towctrans)(wint_t, wctrans_t);
static int (__cdecl *p_strcmp)(const char *, const char *);
static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
/* make sure we use the correct errno */ /* make sure we use the correct errno */
#undef errno #undef errno
...@@ -306,6 +308,8 @@ static BOOL init(void) ...@@ -306,6 +308,8 @@ static BOOL init(void)
SET(p_wctrans, "wctrans"); SET(p_wctrans, "wctrans");
SET(p_towctrans, "towctrans"); SET(p_towctrans, "towctrans");
SET(p__Context__CurrentContext, "?_CurrentContext@_Context@details@Concurrency@@SA?AV123@XZ"); SET(p__Context__CurrentContext, "?_CurrentContext@_Context@details@Concurrency@@SA?AV123@XZ");
SET(p_strcmp, "strcmp");
SET(p_strncmp, "strncmp");
if(sizeof(void*) == 8) { /* 64-bit initialization */ if(sizeof(void*) == 8) { /* 64-bit initialization */
SET(p__StructuredTaskCollection_ctor, SET(p__StructuredTaskCollection_ctor,
"??0_StructuredTaskCollection@details@Concurrency@@QEAA@PEAV_CancellationTokenState@12@@Z"); "??0_StructuredTaskCollection@details@Concurrency@@QEAA@PEAV_CancellationTokenState@12@@Z");
...@@ -1591,6 +1595,37 @@ static void test_StructuredTaskCollection(void) ...@@ -1591,6 +1595,37 @@ static void test_StructuredTaskCollection(void)
CloseHandle(chore_evt2); CloseHandle(chore_evt2);
} }
static void test_strcmp(void)
{
int ret = p_strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(msvcr120) START_TEST(msvcr120)
{ {
if (!init()) return; if (!init()) return;
...@@ -1614,4 +1649,5 @@ START_TEST(msvcr120) ...@@ -1614,4 +1649,5 @@ START_TEST(msvcr120)
test_towctrans(); test_towctrans();
test_CurrentContext(); test_CurrentContext();
test_StructuredTaskCollection(); test_StructuredTaskCollection();
test_strcmp();
} }
TESTDLL = msvcr70.dll
C_SRCS = \
msvcr70.c
/*
* Copyright 2022 Shaun Ren for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#include <errno.h>
#include "wine/test.h"
static int (__cdecl *p_strcmp)(const char *, const char *);
static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hcrt,y)
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
static BOOL init(void)
{
HMODULE hcrt;
SetLastError(0xdeadbeef);
hcrt = LoadLibraryA("msvcr70.dll");
if (!hcrt) {
win_skip("msvcr70.dll not installed (got %ld)\n", GetLastError());
return FALSE;
}
SET(p_strcmp, "strcmp");
SET(p_strncmp, "strncmp");
return TRUE;
}
static void test_strcmp(void)
{
int ret = p_strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(msvcr70)
{
if(!init())
return;
test_strcmp();
}
TESTDLL = msvcr71.dll
C_SRCS = \
msvcr71.c
/*
* Copyright 2022 Shaun Ren for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#include <errno.h>
#include "wine/test.h"
static int (__cdecl *p_strcmp)(const char *, const char *);
static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hcrt,y)
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
static BOOL init(void)
{
HMODULE hcrt;
SetLastError(0xdeadbeef);
hcrt = LoadLibraryA("msvcr71.dll");
if (!hcrt) {
win_skip("msvcr71.dll not installed (got %ld)\n", GetLastError());
return FALSE;
}
SET(p_strcmp, "strcmp");
SET(p_strncmp, "strncmp");
return TRUE;
}
static void test_strcmp(void)
{
int ret = p_strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(msvcr71)
{
if(!init())
return;
test_strcmp();
}
...@@ -60,6 +60,8 @@ static ioinfo **__pioinfo; ...@@ -60,6 +60,8 @@ static ioinfo **__pioinfo;
static int (__cdecl *p__open)(const char *, int, ...); static int (__cdecl *p__open)(const char *, int, ...);
static int (__cdecl *p__close)(int); static int (__cdecl *p__close)(int);
static intptr_t (__cdecl *p__get_osfhandle)(int); static intptr_t (__cdecl *p__get_osfhandle)(int);
static int (__cdecl *p_strcmp)(const char *, const char *);
static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hcrt,y) #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hcrt,y)
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
...@@ -79,6 +81,9 @@ static BOOL init(void) ...@@ -79,6 +81,9 @@ static BOOL init(void)
SET(p__close,"_close"); SET(p__close,"_close");
SET(p__get_osfhandle, "_get_osfhandle"); SET(p__get_osfhandle, "_get_osfhandle");
SET(p_strcmp, "strcmp");
SET(p_strncmp, "strncmp");
return TRUE; return TRUE;
} }
...@@ -139,10 +144,51 @@ static void test_ioinfo_flags(void) ...@@ -139,10 +144,51 @@ static void test_ioinfo_flags(void)
free(tempf); free(tempf);
} }
static void test_strcmp(void)
{
int ret = p_strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
#ifdef _WIN64
ret = p_strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
#else
ret = p_strncmp( "", "abc", 3 );
ok( ret == 0 - 'a', "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == 'c' - 0xa0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 0xb0 - 0xa0, "wrong ret %d\n", ret );
#endif
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(msvcr80) START_TEST(msvcr80)
{ {
if(!init()) if(!init())
return; return;
test_ioinfo_flags(); test_ioinfo_flags();
test_strcmp();
} }
...@@ -171,6 +171,8 @@ static int (__cdecl *p____mb_cur_max_l_func)(_locale_t locale); ...@@ -171,6 +171,8 @@ static int (__cdecl *p____mb_cur_max_l_func)(_locale_t locale);
static _locale_t (__cdecl *p__create_locale)(int, const char*); static _locale_t (__cdecl *p__create_locale)(int, const char*);
static void (__cdecl *p__free_locale)(_locale_t); static void (__cdecl *p__free_locale)(_locale_t);
static _locale_t (__cdecl *p__get_current_locale)(void); static _locale_t (__cdecl *p__get_current_locale)(void);
static int (__cdecl *p_strcmp)(const char *, const char *);
static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
struct __lc_time_data { struct __lc_time_data {
const char *short_wday[7]; const char *short_wday[7];
...@@ -471,6 +473,8 @@ static BOOL init(void) ...@@ -471,6 +473,8 @@ static BOOL init(void)
SET(p__create_locale, "_create_locale"); SET(p__create_locale, "_create_locale");
SET(p__free_locale, "_free_locale"); SET(p__free_locale, "_free_locale");
SET(p__get_current_locale, "_get_current_locale"); SET(p__get_current_locale, "_get_current_locale");
SET(p_strcmp, "strcmp");
SET(p_strncmp, "strncmp");
if (sizeof(void *) == 8) if (sizeof(void *) == 8)
{ {
...@@ -2441,6 +2445,46 @@ static void test_ioinfo_flags(void) ...@@ -2441,6 +2445,46 @@ static void test_ioinfo_flags(void)
free(tempf); free(tempf);
} }
static void test_strcmp(void)
{
int ret = p_strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = p_strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
#ifdef _WIN64
ret = p_strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
#else
ret = p_strncmp( "", "abc", 3 );
ok( ret == 0 - 'a', "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == 'c' - 0xa0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 0xb0 - 0xa0, "wrong ret %d\n", ret );
#endif
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(msvcr90) START_TEST(msvcr90)
{ {
if(!init()) if(!init())
...@@ -2483,4 +2527,5 @@ START_TEST(msvcr90) ...@@ -2483,4 +2527,5 @@ START_TEST(msvcr90)
test____mb_cur_max_l_func(); test____mb_cur_max_l_func();
test__get_current_locale(); test__get_current_locale();
test_ioinfo_flags(); test_ioinfo_flags();
test_strcmp();
} }
...@@ -3292,7 +3292,14 @@ int __cdecl strncmp(const char *str1, const char *str2, size_t len) ...@@ -3292,7 +3292,14 @@ int __cdecl strncmp(const char *str1, const char *str2, size_t len)
{ {
if (!len) return 0; if (!len) return 0;
while (--len && *str1 && *str1 == *str2) { str1++; str2++; } while (--len && *str1 && *str1 == *str2) { str1++; str2++; }
#if defined(_WIN64) || defined(_UCRT) || _MSVCR_VER == 70 || _MSVCR_VER == 71 || _MSVCR_VER >= 110
if ((unsigned char)*str1 > (unsigned char)*str2) return 1;
if ((unsigned char)*str1 < (unsigned char)*str2) return -1;
return 0;
#else
return (unsigned char)*str1 - (unsigned char)*str2; return (unsigned char)*str1 - (unsigned char)*str2;
#endif
} }
/********************************************************************* /*********************************************************************
......
...@@ -662,12 +662,21 @@ static void test_strcmp(void) ...@@ -662,12 +662,21 @@ static void test_strcmp(void)
ret = p_strncmp( "abc", "abcd", 3 ); ret = p_strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret ); ok( ret == 0, "wrong ret %d\n", ret );
#ifdef _WIN64
ret = p_strncmp( "", "abc", 3 ); ret = p_strncmp( "", "abc", 3 );
ok( ret == 0 - 'a' || ret == -1, "wrong ret %d\n", ret ); ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
#else
ret = p_strncmp( "", "abc", 3 );
ok( ret == 0 - 'a', "wrong ret %d\n", ret );
ret = p_strncmp( "abc", "ab\xa0", 4 ); ret = p_strncmp( "abc", "ab\xa0", 4 );
ok( ret == 'c' - 0xa0 || ret == -1, "wrong ret %d\n", ret ); ok( ret == 'c' - 0xa0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xb0", "ab\xa0", 3 ); ret = p_strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 0xb0 - 0xa0 || ret == 1, "wrong ret %d\n", ret ); ok( ret == 0xb0 - 0xa0, "wrong ret %d\n", ret );
#endif
ret = p_strncmp( "ab\xb0", "ab\xa0", 2 ); ret = p_strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret ); ok( ret == 0, "wrong ret %d\n", ret );
ret = p_strncmp( "ab\xc2", "ab\xc2", 3 ); ret = p_strncmp( "ab\xc2", "ab\xc2", 3 );
......
...@@ -602,6 +602,37 @@ static void test__mbbtype_l(void) ...@@ -602,6 +602,37 @@ static void test__mbbtype_l(void)
} }
} }
static void test_strcmp(void)
{
int ret = strcmp( "abc", "abcd" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = strcmp( "", "abc" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = strcmp( "abc", "ab\xa0" );
ok( ret == -1, "wrong ret %d\n", ret );
ret = strcmp( "ab\xb0", "ab\xa0" );
ok( ret == 1, "wrong ret %d\n", ret );
ret = strcmp( "ab\xc2", "ab\xc2" );
ok( ret == 0, "wrong ret %d\n", ret );
ret = strncmp( "abc", "abcd", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = strncmp( "", "abc", 3 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = strncmp( "abc", "ab\xa0", 4 );
ok( ret == -1, "wrong ret %d\n", ret );
ret = strncmp( "ab\xb0", "ab\xa0", 3 );
ok( ret == 1, "wrong ret %d\n", ret );
ret = strncmp( "ab\xb0", "ab\xa0", 2 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = strncmp( "ab\xc2", "ab\xc2", 3 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = strncmp( "abc", "abd", 0 );
ok( ret == 0, "wrong ret %d\n", ret );
ret = strncmp( "abc", "abc", 12 );
ok( ret == 0, "wrong ret %d\n", ret );
}
START_TEST(string) START_TEST(string)
{ {
ok(_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL, ok(_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
...@@ -619,4 +650,5 @@ START_TEST(string) ...@@ -619,4 +650,5 @@ START_TEST(string)
test_wcsnicmp(); test_wcsnicmp();
test_SpecialCasing(); test_SpecialCasing();
test__mbbtype_l(); test__mbbtype_l();
test_strcmp();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment