From d07a30cd9a2e83c0edd9a4d8d554b372bdab6767 Mon Sep 17 00:00:00 2001 From: Santiago Fernandez Madero Date: Sat, 21 Mar 2020 00:32:41 -0700 Subject: [PATCH] Add System.Globalization.Native support for Windows (#33704) * Add System.Globalization.Native support for Windows * PR Feedback * Fix build and address more feedback * More PR Feedback * Fix OSX build and update lib name in dllimport * Remove un-necessary include and update issue link --- src/coreclr/build-runtime.cmd | 2 +- src/coreclr/build.cmd | 2 +- .../src/dlls/mscoree/coreclr/CMakeLists.txt | 2 +- .../src/libraries-native/CMakeLists.txt | 10 ++- .../src/libraries-native/entrypoints.c | 9 +-- src/coreclr/src/vm/dllimport.cpp | 2 +- src/coreclr/src/vm/ecalllist.h | 2 - src/libraries/Native/Unix/CMakeLists.txt | 2 + src/libraries/Native/Unix/Common/pal_atomic.h | 19 +++++ .../Native/Unix/Common/pal_compiler.h | 14 +++- .../CMakeLists.txt | 69 ++++++++++--------- .../configure.cmake | 36 +++++----- .../pal_calendarData.c | 27 +++++--- .../System.Globalization.Native/pal_casing.c | 4 ++ .../pal_collation.c | 21 +++--- .../pal_collation.h | 1 + .../System.Globalization.Native/pal_icushim.c | 44 ++++++++++-- .../pal_icushim_internal.h | 20 +++++- .../System.Globalization.Native/pal_idna.c | 7 ++ .../pal_localeNumberData.c | 6 +- .../pal_localeStringData.c | 4 +- .../pal_timeZoneInfo.c | 3 +- 22 files changed, 204 insertions(+), 102 deletions(-) create mode 100644 src/libraries/Native/Unix/Common/pal_atomic.h diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index 3ec6d5df29d9f..77e64097a09b1 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -500,7 +500,7 @@ if %__BuildNative% EQU 1 ( echo %__MsgPrefix%Regenerating the Visual Studio solution - set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" + set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" "-DCLR_REPO_ROOT_DIR=%__RepoRootDir%" call "%__SourceDir%\pal\tools\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs! if not !errorlevel! == 0 ( echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project! diff --git a/src/coreclr/build.cmd b/src/coreclr/build.cmd index fac90f6d29615..995f181602ea5 100644 --- a/src/coreclr/build.cmd +++ b/src/coreclr/build.cmd @@ -561,7 +561,7 @@ if %__BuildNative% EQU 1 ( echo %__MsgPrefix%Regenerating the Visual Studio solution - set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" + set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" !___CrossBuildDefine! "-DCLR_CMAKE_PGO_INSTRUMENT=%__PgoInstrument%" "-DCLR_CMAKE_OPTDATA_PATH=%__PgoOptDataPath%" "-DCLR_CMAKE_PGO_OPTIMIZE=%__PgoOptimize%" "-DCLR_ENG_NATIVE_DIR=%__RepoRootDir%/eng/native" "-DCLR_REPO_ROOT_DIR=%__RepoRootDir%" call "%__SourceDir%\pal\tools\gen-buildsys.cmd" "%__ProjectDir%" "%__IntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs! if not !errorlevel! == 0 ( echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project! diff --git a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt index 8b5365f49a1b1..bc111a0ecb14c 100644 --- a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt @@ -110,6 +110,7 @@ set(CORECLR_LIBRARIES utilcode v3binder libraries-native + System.Globalization.Native-Static interop ) @@ -136,7 +137,6 @@ else() ${END_WHOLE_ARCHIVE} mscorrc palrt - System.Globalization.Native-Static ) endif(CLR_CMAKE_TARGET_WIN32) diff --git a/src/coreclr/src/libraries-native/CMakeLists.txt b/src/coreclr/src/libraries-native/CMakeLists.txt index aaf7f9bbbb7ae..58a6e893b20ba 100644 --- a/src/coreclr/src/libraries-native/CMakeLists.txt +++ b/src/coreclr/src/libraries-native/CMakeLists.txt @@ -2,14 +2,12 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(GLOBALIZATION_NATIVE_DIR ${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/System.Globalization.Native) # Suppress exporting of the PAL APIs -add_definitions(-DPALEXPORT=) +add_definitions(-DPALEXPORT=EXTERN_C) -if(CLR_CMAKE_HOST_UNIX) - include_directories("${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/Common") - include_directories("${GLOBALIZATION_NATIVE_DIR}") +include_directories("${GLOBALIZATION_NATIVE_DIR}") +include_directories("${CLR_REPO_ROOT_DIR}/src/libraries/Native/Unix/Common") - add_subdirectory(${GLOBALIZATION_NATIVE_DIR} System.Globalization.Native) -endif() +add_subdirectory(${GLOBALIZATION_NATIVE_DIR} System.Globalization.Native) add_library(libraries-native STATIC diff --git a/src/coreclr/src/libraries-native/entrypoints.c b/src/coreclr/src/libraries-native/entrypoints.c index 75c5b7311b157..68553e99997af 100644 --- a/src/coreclr/src/libraries-native/entrypoints.c +++ b/src/coreclr/src/libraries-native/entrypoints.c @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#ifdef TARGET_UNIX - -#include "pal_types.h" +#include typedef uint16_t UChar; @@ -19,15 +17,13 @@ typedef uint16_t UChar; #include "pal_idna.h" #include "pal_normalization.h" #include "pal_timeZoneInfo.h" -#endif // TARGET_UNIX -#define FCFuncStart(name) extern const void* name[]; const void* name[] = { +#define FCFuncStart(name) EXTERN_C const void* name[]; const void* name[] = { #define FCFuncEnd() (void*)0x01 /* FCFuncFlag_EndOfArray */ }; #define QCFuncElement(name,impl) \ (void*)0x8 /* FCFuncFlag_QCall */, (void*)(impl), (void*)name, -#ifdef TARGET_UNIX FCFuncStart(gPalGlobalizationNative) QCFuncElement("ChangeCase", GlobalizationNative_ChangeCase) QCFuncElement("ChangeCaseInvariant", GlobalizationNative_ChangeCaseInvariant) @@ -64,4 +60,3 @@ FCFuncStart(gPalGlobalizationNative) QCFuncElement("ToAscii", GlobalizationNative_ToAscii) QCFuncElement("ToUnicode", GlobalizationNative_ToUnicode) FCFuncEnd() -#endif // TARGET_UNIX diff --git a/src/coreclr/src/vm/dllimport.cpp b/src/coreclr/src/vm/dllimport.cpp index 795ca668556fa..4875c57618060 100644 --- a/src/coreclr/src/vm/dllimport.cpp +++ b/src/coreclr/src/vm/dllimport.cpp @@ -4795,7 +4795,7 @@ void NDirect::PopulateNDirectMethodDesc(NDirectMethodDesc* pNMD, PInvokeStaticSi if (callConv == pmCallConvThiscall) ndirectflags |= NDirectMethodDesc::kThisCall; - if (pNMD->GetLoaderModule()->IsSystem() && (strcmp(szLibName, "QCall") == 0 || strcmp(szLibName, "System.Globalization.Native") == 0)) + if (pNMD->GetLoaderModule()->IsSystem() && (strcmp(szLibName, "QCall") == 0 || strcmp(szLibName, "libSystem.Globalization.Native") == 0)) { ndirectflags |= NDirectMethodDesc::kIsQCall; } diff --git a/src/coreclr/src/vm/ecalllist.h b/src/coreclr/src/vm/ecalllist.h index 3cbfa0e5ec40e..d28a28326619f 100644 --- a/src/coreclr/src/vm/ecalllist.h +++ b/src/coreclr/src/vm/ecalllist.h @@ -1239,11 +1239,9 @@ FCClassElement("FileLoadException", "System.IO", gFileLoadExceptionFuncs) FCClassElement("GC", "System", gGCInterfaceFuncs) FCClassElement("GCHandle", "System.Runtime.InteropServices", gGCHandleFuncs) FCClassElement("GCSettings", "System.Runtime", gGCSettingsFuncs) -#ifdef TARGET_UNIX #ifndef CROSSGEN_COMPILE FCClassElement("Globalization", "", gPalGlobalizationNative) #endif -#endif #ifdef FEATURE_COMINTEROP FCClassElement("IEnumerable", "System.Collections", gStdMngIEnumerableFuncs) FCClassElement("IEnumerator", "System.Collections", gStdMngIEnumeratorFuncs) diff --git a/src/libraries/Native/Unix/CMakeLists.txt b/src/libraries/Native/Unix/CMakeLists.txt index 5e9c0f04bf5e0..d921d23d2bf94 100644 --- a/src/libraries/Native/Unix/CMakeLists.txt +++ b/src/libraries/Native/Unix/CMakeLists.txt @@ -153,6 +153,7 @@ endif(CLR_CMAKE_TARGET_FREEBSD) # if(CLR_CMAKE_TARGET_UNIX) if (CLR_CMAKE_TARGET_DARWIN) + add_definitions(-DTARGET_DARWIN) add_link_options(-Wl,-bind_at_load) elseif (CLR_CMAKE_TARGET_ARCH_WASM) # No object stripping for WASM @@ -164,6 +165,7 @@ if(CLR_CMAKE_TARGET_UNIX) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CLR_ADDITIONAL_LINKER_FLAGS}" ) add_compile_options(${CLR_ADDITIONAL_COMPILER_OPTIONS}) + add_definitions(-DTARGET_UNIX) endif(CLR_CMAKE_TARGET_UNIX) function(install_library_and_symbols targetName) diff --git a/src/libraries/Native/Unix/Common/pal_atomic.h b/src/libraries/Native/Unix/Common/pal_atomic.h new file mode 100644 index 0000000000000..a2ebcf62612dc --- /dev/null +++ b/src/libraries/Native/Unix/Common/pal_atomic.h @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#if defined(TARGET_UNIX) +#include +#elif defined(TARGET_WINDOWS) +#include "windows.h" +#endif + +static int pal_atomic_cas_ptr(void* volatile* dest, void* exchange, void* comparand) +{ +#if defined(TARGET_UNIX) + return __atomic_compare_exchange_n(dest, exchange, comparand, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +#elif defined(TARGET_WINDOWS) + return InterlockedCompareExchangePointer(dest, exchange, comparand) == comparand; +#endif +} diff --git a/src/libraries/Native/Unix/Common/pal_compiler.h b/src/libraries/Native/Unix/Common/pal_compiler.h index 52471c6f7eb94..8661443fc9f45 100644 --- a/src/libraries/Native/Unix/Common/pal_compiler.h +++ b/src/libraries/Native/Unix/Common/pal_compiler.h @@ -20,5 +20,17 @@ #endif #ifndef PALEXPORT +#ifdef TARGET_UNIX #define PALEXPORT __attribute__ ((__visibility__ ("default"))) -#endif // ifndef PALEXPORT +#else +#define PALEXPORT +#endif +#endif // PALEXPORT + +#ifndef EXTERN_C +#ifdef __cplusplus +#define EXTERN_C extern "C" +#else +#define EXTERN_C extern +#endif // __cplusplus +#endif // EXTERN_C diff --git a/src/libraries/Native/Unix/System.Globalization.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.Globalization.Native/CMakeLists.txt index 25d0211e2d5ae..fbab4fad5868e 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.Globalization.Native/CMakeLists.txt @@ -1,45 +1,49 @@ project(System.Globalization.Native C) -add_compile_options(-Wno-switch-enum) -add_compile_options(-Wno-covered-switch-default) +if(CLR_CMAKE_TARGET_UNIX) + add_compile_options(-Wno-switch-enum) + add_compile_options(-Wno-covered-switch-default) -# Workaround for warnings produced by ICU headers -add_compile_options(-Wno-reserved-id-macro) -add_compile_options(-Wno-documentation) -add_compile_options(-Wno-documentation-unknown-command) + # Workaround for warnings produced by ICU headers + add_compile_options(-Wno-reserved-id-macro) + add_compile_options(-Wno-documentation) + add_compile_options(-Wno-documentation-unknown-command) -# Workaround for https://unicode-org.atlassian.net/browse/ICU-20601 -add_compile_options(-Wno-extra-semi-stmt) -add_compile_options(-Wno-unknown-warning-option) + # Workaround for https://unicode-org.atlassian.net/browse/ICU-20601 + add_compile_options(-Wno-extra-semi-stmt) + add_compile_options(-Wno-unknown-warning-option) -set(ICU_HOMEBREW_INC_PATH "/usr/local/opt/icu4c/include") + set(ICU_HOMEBREW_INC_PATH "/usr/local/opt/icu4c/include") -find_path(UTYPES_H "unicode/utypes.h" PATHS ${ICU_HOMEBREW_INC_PATH}) -if(UTYPES_H STREQUAL UTYPES_H-NOTFOUND) - message(FATAL_ERROR "Cannot find utypes.h, try installing libicu-dev (or the appropriate package for your platform)") - return() -endif() - -if(CLR_CMAKE_TARGET_DARWIN) - find_library(ICUCORE icucore) - if(ICUCORE STREQUAL ICUCORE-NOTFOUND) - message(FATAL_ERROR "Cannot find libicucore, skipping build for System.Globalization.Native. .NET globalization is not expected to function.") - return() - endif() - add_definitions(-DOSX_ICU_LIBRARY_PATH=\"${ICUCORE}\") - add_definitions(-DU_DISABLE_RENAMING) -else() - find_library(ICUUC icuuc) - if(ICUUC STREQUAL ICUUC-NOTFOUND) - message(FATAL_ERROR "Cannot find libicuuc, try installing libicu-dev (or the appropriate package for your platform)") + find_path(UTYPES_H "unicode/utypes.h" PATHS ${ICU_HOMEBREW_INC_PATH}) + if(UTYPES_H STREQUAL UTYPES_H-NOTFOUND) + message(FATAL_ERROR "Cannot find utypes.h, try installing libicu-dev (or the appropriate package for your platform)") return() endif() - find_library(ICUI18N icui18n) - if(ICUI18N STREQUAL ICUI18N-NOTFOUND) - message(FATAL_ERROR "Cannot find libicui18n, try installing libicu-dev (or the appropriate package for your platform)") - return() + if(CLR_CMAKE_TARGET_DARWIN) + find_library(ICUCORE icucore) + if(ICUCORE STREQUAL ICUCORE-NOTFOUND) + message(FATAL_ERROR "Cannot find libicucore, skipping build for System.Globalization.Native. .NET globalization is not expected to function.") + return() + endif() + add_definitions(-DOSX_ICU_LIBRARY_PATH=\"${ICUCORE}\") + add_definitions(-DU_DISABLE_RENAMING) + else() + find_library(ICUUC icuuc) + if(ICUUC STREQUAL ICUUC-NOTFOUND) + message(FATAL_ERROR "Cannot find libicuuc, try installing libicu-dev (or the appropriate package for your platform)") + return() + endif() + + find_library(ICUI18N icui18n) + if(ICUI18N STREQUAL ICUI18N-NOTFOUND) + message(FATAL_ERROR "Cannot find libicui18n, try installing libicu-dev (or the appropriate package for your platform)") + return() + endif() endif() + + include_directories(${UTYPES_H}) endif() include(configure.cmake) @@ -57,7 +61,6 @@ set(NATIVEGLOBALIZATION_SOURCES pal_icushim.c ) -include_directories(${UTYPES_H}) include_directories("../Common") if (GEN_SHARED_LIB) diff --git a/src/libraries/Native/Unix/System.Globalization.Native/configure.cmake b/src/libraries/Native/Unix/System.Globalization.Native/configure.cmake index 6114a1bb31ed6..68718edaea8b3 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/configure.cmake +++ b/src/libraries/Native/Unix/System.Globalization.Native/configure.cmake @@ -1,31 +1,33 @@ include(CheckCSourceCompiles) include(CheckSymbolExists) -set(CMAKE_REQUIRED_INCLUDES ${UTYPES_H} ${ICU_HOMEBREW_INC_PATH}) - if(CLR_CMAKE_TARGET_ANDROID) string(REPLACE ";" ":" ANDROID_RPATHS "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}:${CMAKE_SYSTEM_LIBRARY_PATH}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rpath ${ANDROID_RPATHS}") endif() -CHECK_C_SOURCE_COMPILES(" - #include - int main(void) { enum UDateFormatSymbolType e = UDAT_STANDALONE_SHORTER_WEEKDAYS; } -" HAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS) +if (CLR_CMAKE_TARGET_UNIX) + set(CMAKE_REQUIRED_INCLUDES ${UTYPES_H} ${ICU_HOMEBREW_INC_PATH}) -if(CLR_CMAKE_TARGET_DARWIN) - set(CMAKE_REQUIRED_LIBRARIES ${ICUCORE}) -else() - set(CMAKE_REQUIRED_LIBRARIES ${ICUUC} ${ICUI18N}) -endif() + CHECK_C_SOURCE_COMPILES(" + #include + int main(void) { enum UDateFormatSymbolType e = UDAT_STANDALONE_SHORTER_WEEKDAYS; } + " HAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS) -check_symbol_exists( - ucol_setMaxVariable - "unicode/ucol.h" - HAVE_SET_MAX_VARIABLE) + if(CLR_CMAKE_TARGET_DARWIN) + set(CMAKE_REQUIRED_LIBRARIES ${ICUCORE}) + else() + set(CMAKE_REQUIRED_LIBRARIES ${ICUUC} ${ICUI18N}) + endif() -unset(CMAKE_REQUIRED_LIBRARIES) -unset(CMAKE_REQUIRED_INCLUDES) + check_symbol_exists( + ucol_setMaxVariable + "unicode/ucol.h" + HAVE_SET_MAX_VARIABLE) + + unset(CMAKE_REQUIRED_LIBRARIES) + unset(CMAKE_REQUIRED_INCLUDES) +endif() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_calendarData.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_calendarData.c index 10bdcfafb3410..b687ac9071f12 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_calendarData.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_calendarData.c @@ -5,12 +5,22 @@ #include #include #include -#include - #include "pal_locale_internal.h" #include "pal_errors_internal.h" #include "pal_calendarData.h" +#if defined(TARGET_UNIX) +#include + +#define STRING_COPY(destination, numberOfElements, source) \ + strncpy(destination, source, numberOfElements); \ + destination[numberOfElements - 1] = 0; + +#elif defined(TARGET_WINDOWS) +#define strcasecmp _stricmp +#define STRING_COPY(destination, numberOfElements, source) strncpy_s(destination, numberOfElements, source, _TRUNCATE); +#endif + #define GREGORIAN_NAME "gregorian" #define JAPANESE_NAME "japanese" #define BUDDHIST_NAME "buddhist" @@ -226,7 +236,7 @@ static int InvokeCallbackForDatePattern(const char* locale, UErrorCode ignore = U_ZERO_ERROR; int32_t patternLen = udat_toPattern(pFormat, FALSE, NULL, 0, &ignore) + 1; - UChar* pattern = calloc((size_t)patternLen, sizeof(UChar)); + UChar* pattern = (UChar*)calloc((size_t)patternLen, sizeof(UChar)); if (pattern == NULL) { udat_close(pFormat); @@ -266,7 +276,7 @@ static int InvokeCallbackForDateTimePattern(const char* locale, UErrorCode ignore = U_ZERO_ERROR; int32_t patternLen = udatpg_getBestPattern(pGenerator, patternSkeleton, -1, NULL, 0, &ignore) + 1; - UChar* bestPattern = calloc((size_t)patternLen, sizeof(UChar)); + UChar* bestPattern = (UChar*)calloc((size_t)patternLen, sizeof(UChar)); if (bestPattern == NULL) { udatpg_close(pGenerator); @@ -306,8 +316,7 @@ static int32_t EnumSymbols(const char* locale, return FALSE; char localeWithCalendarName[ULOC_FULLNAME_CAPACITY]; - strncpy(localeWithCalendarName, locale, ULOC_FULLNAME_CAPACITY); - localeWithCalendarName[ULOC_FULLNAME_CAPACITY - 1] = 0; + STRING_COPY(localeWithCalendarName, sizeof(localeWithCalendarName), locale); uloc_setKeywordValue("calendar", GetCalendarName(calendarId), localeWithCalendarName, ULOC_FULLNAME_CAPACITY, &err); @@ -336,7 +345,7 @@ static int32_t EnumSymbols(const char* locale, } else { - symbolBuf = calloc((size_t)symbolLen, sizeof(UChar)); + symbolBuf = (UChar*)calloc((size_t)symbolLen, sizeof(UChar)); if (symbolBuf == NULL) { err = U_MEMORY_ALLOCATION_ERROR; @@ -414,9 +423,7 @@ static int32_t EnumAbbrevEraNames(const char* locale, char* localeNamePtr = localeNameBuf; char* parentNamePtr = parentNameBuf; - - strncpy(localeNamePtr, locale, ULOC_FULLNAME_CAPACITY); - localeNamePtr[ULOC_FULLNAME_CAPACITY - 1] = 0; + STRING_COPY(localeNamePtr, sizeof(localeNameBuf), locale); while (TRUE) { diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_casing.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_casing.c index 2e90f1481233e..263c71d70630c 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_casing.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_casing.c @@ -9,9 +9,11 @@ #include "pal_icushim_internal.h" #include "pal_casing.h" +#ifdef __clang__ // Workaround for warnings produced by U16_NEXT and U16_APPEND macro expansions #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-conversion" +#endif /* Function: @@ -146,4 +148,6 @@ void GlobalizationNative_ChangeCaseTurkish( } } +#ifdef __clang__ #pragma clang diagnostic pop +#endif diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c index c5ba1ca33efee..081a01693ecc8 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c @@ -12,6 +12,7 @@ #include "pal_errors_internal.h" #include "pal_collation.h" +#include "pal_atomic.h" c_static_assert_msg(UCOL_EQUAL == 0, "managed side requires 0 for equal strings"); c_static_assert_msg(UCOL_LESS < 0, "managed side requires less than zero for a < b"); @@ -168,7 +169,7 @@ static UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, i ((needsIgnoreWidthCustomRule || needsNotIgnoreWidthCustomRule) ? 5 * g_HalfFullCharsLength : 0); UChar* items; - customRules->items = items = malloc((size_t)capacity * sizeof(UChar)); + customRules->items = items = (UChar*)malloc((size_t)capacity * sizeof(UChar)); if (customRules->items == NULL) { free(customRules); @@ -267,7 +268,7 @@ static UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t o const UChar* localeRules = ucol_getRules(pCollator, &localeRulesLength); int32_t completeRulesLength = localeRulesLength + customRuleLength + 1; - UChar* completeRules = calloc((size_t)completeRulesLength, sizeof(UChar)); + UChar* completeRules = (UChar*)calloc((size_t)completeRulesLength, sizeof(UChar)); for (int i = 0; i < localeRulesLength; i++) { @@ -403,8 +404,7 @@ static const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32 pCollator = CloneCollatorWithOptions(pSortHandle->collatorsPerOption[0], options, pErr); UCollator* pNull = NULL; - // we are not using the standard atomic_compare_exchange_strong to workaround bugs in clang 5.0 (https://bugs.llvm.org/show_bug.cgi?id=37457) - if (!__atomic_compare_exchange_n(&pSortHandle->collatorsPerOption[options], &pNull, pCollator, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) + if (!pal_atomic_cas_ptr((void* volatile*)&pSortHandle->collatorsPerOption[options], &pNull, pCollator)) { ucol_close(pCollator); pCollator = pSortHandle->collatorsPerOption[options]; @@ -419,7 +419,7 @@ int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle) { UErrorCode err = U_ZERO_ERROR; const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, 0, &err); - int32_t result = 0; + int32_t result = -1; if (U_SUCCESS(err)) { @@ -428,9 +428,6 @@ int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle) else { assert(FALSE && "Unexpected ucol_getVersion to fail."); - - // we didn't use UCOL_TAILORINGS_VERSION because it is deprecated in ICU v5 - result = UCOL_RUNTIME_VERSION << 16 | UCOL_BUILDER_VERSION; } return result; } @@ -569,11 +566,15 @@ int32_t GlobalizationNative_IndexOfOrdinalIgnoreCase( { UChar32 srcCodepoint, trgCodepoint; +#ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-conversion" +#endif U16_NEXT(src, srcIdx, cwSourceLength, srcCodepoint); U16_NEXT(trg, trgIdx, cwTargetLength, trgCodepoint); +#ifdef __clang__ #pragma clang diagnostic pop +#endif if (!AreEqualOrdinalIgnoreCase(srcCodepoint, trgCodepoint)) { @@ -852,11 +853,15 @@ int32_t GlobalizationNative_CompareStringOrdinalIgnoreCase( { UChar32 str1Codepoint, str2Codepoint; +#ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-conversion" +#endif U16_NEXT(lpStr1, str1Idx, cwStr1Length, str1Codepoint); U16_NEXT(lpStr2, str2Idx, cwStr2Length, str2Codepoint); +#ifdef __clang__ #pragma clang diagnostic pop +#endif if (str1Codepoint != str2Codepoint && u_toupper(str1Codepoint) != u_toupper(str2Codepoint)) { diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.h b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.h index dd2fcc4252c1e..3d04ba735517f 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.h +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.h @@ -14,6 +14,7 @@ PALEXPORT ResultCode GlobalizationNative_GetSortHandle(const char* lpLocaleName, PALEXPORT void GlobalizationNative_CloseSortHandle(SortHandle* pSortHandle); +// If we fail to get the sort version we will fallback to -1 as the sort version. PALEXPORT int32_t GlobalizationNative_GetSortVersion(SortHandle* pSortHandle); PALEXPORT int32_t GlobalizationNative_CompareString(SortHandle* pSortHandle, diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c index bb418e8573e8f..51e60a0a14b3b 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.c @@ -3,7 +3,13 @@ // See the LICENSE file in the project root for more information. // +#if defined(TARGET_UNIX) #include +#elif defined(TARGET_WINDOWS) +#include +#include +#include +#endif #include #include #include @@ -20,7 +26,22 @@ FOR_ALL_ICU_FUNCTIONS static void* libicuuc = NULL; static void* libicui18n = NULL; -#ifdef __APPLE__ +#if defined(TARGET_WINDOWS) + +static int FindICULibs() +{ + libicuuc = LoadLibraryExW(L"icu.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (libicuuc == NULL) + { + return FALSE; + } + + // Windows has a single dll for icu. + libicui18n = libicuuc; + return TRUE; +} + +#elif defined(TARGET_DARWIN) static int FindICULibs() { @@ -42,7 +63,7 @@ static int FindICULibs() return TRUE; } -#else // __APPLE__ +#else // !TARGET_WINDOWS && !TARGET_DARWIN #define VERSION_PREFIX_NONE "" #define VERSION_PREFIX_SUSE "suse" @@ -242,7 +263,7 @@ static int FindICULibs(const char* versionPrefix, char* symbolName, char* symbol FindLibWithMajorMinorSubVersion(versionPrefix, symbolName, symbolVersion); } -#endif // __APPLE__ +#endif // GlobalizationNative_LoadICU // This method get called from the managed side during the globalization initialization. @@ -250,7 +271,18 @@ static int FindICULibs(const char* versionPrefix, char* symbolName, char* symbol // return 0 if failed to load ICU and 1 otherwise int32_t GlobalizationNative_LoadICU() { -#ifdef __APPLE__ +#if defined(TARGET_WINDOWS) + + if (!FindICULibs()) + { + return FALSE; + } + +#define PER_FUNCTION_BLOCK(fn, lib) \ + fn##_ptr = (__typeof(fn)*)GetProcAddress((HMODULE)lib, #fn); \ + if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %u\n", #fn, GetLastError()); abort(); } + +#elif defined(TARGET_DARWIN) if (!FindICULibs()) { @@ -262,7 +294,7 @@ int32_t GlobalizationNative_LoadICU() fn##_ptr = (__typeof(fn)*)dlsym(lib, #fn); \ if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %s\n", #fn, dlerror()); abort(); } -#else // __APPLE__ +#else // !TARGET_WINDOWS && !TARGET_DARWIN char symbolName[128]; char symbolVersion[MaxICUVersionStringLength + 1] = ""; @@ -282,7 +314,7 @@ int32_t GlobalizationNative_LoadICU() fn##_ptr = (__typeof(fn)*)dlsym(lib, symbolName); \ if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from " #lib "\nError: %s\n", symbolName, dlerror()); abort(); } -#endif // __APPLE__ +#endif FOR_ALL_ICU_FUNCTIONS #undef PER_FUNCTION_BLOCK diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h index c6a48f964a2a0..2ee8fab76b09b 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h @@ -8,6 +8,8 @@ #pragma once +#if defined(TARGET_UNIX) + #include "config.h" #define U_DISABLE_RENAMING 1 @@ -33,6 +35,21 @@ #include #include +#elif defined(TARGET_WINDOWS) + +#include "icu.h" + +#ifndef __typeof +#define __typeof decltype +#endif + +#define HAVE_SET_MAX_VARIABLE 1 +#define UDAT_STANDALONE_SHORTER_WEEKDAYS 1 + +#endif + +#include "pal_compiler.h" + // List of all functions from the ICU libraries that are used in the System.Globalization.Native.so #define FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \ PER_FUNCTION_BLOCK(u_charsToUChars, libicuuc) \ @@ -131,13 +148,14 @@ FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \ PER_FUNCTION_BLOCK(ucol_setMaxVariable, libicui18n) #else + #define FOR_ALL_ICU_FUNCTIONS \ FOR_ALL_UNCONDITIONAL_ICU_FUNCTIONS \ PER_FUNCTION_BLOCK(ucol_setVariableTop, libicui18n) #endif // Declare pointers to all the used ICU functions -#define PER_FUNCTION_BLOCK(fn, lib) extern __typeof(fn)* fn##_ptr; +#define PER_FUNCTION_BLOCK(fn, lib) EXTERN_C __typeof(fn)* fn##_ptr; FOR_ALL_ICU_FUNCTIONS #undef PER_FUNCTION_BLOCK diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_idna.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_idna.c index 97fe2315511d5..403145a905279 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_idna.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_idna.c @@ -8,6 +8,13 @@ #include "pal_icushim_internal.h" #include "pal_idna.h" +#if defined(TARGET_WINDOWS) +// Windows icu headers doesn't define this member as it is marked as deprecated as of ICU 55. +enum { + UIDNA_ALLOW_UNASSIGNED=1 +}; +#endif + static const uint32_t AllowUnassigned = 0x1; static const uint32_t UseStd3AsciiRules = 0x2; diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_localeNumberData.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_localeNumberData.c index b05ae709a278d..2465f02faf56c 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_localeNumberData.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_localeNumberData.c @@ -87,13 +87,13 @@ static char* NormalizeNumericPattern(const UChar* srcPattern, int isNegative) if (isNegative && !minusAdded) { int length = (iEnd - iStart) + 2; - destPattern = calloc((size_t)length, sizeof(char)); + destPattern = (char*)calloc((size_t)length, sizeof(char)); destPattern[index++] = '-'; } else { int length = (iEnd - iStart) + 1; - destPattern = calloc((size_t)length, sizeof(char)); + destPattern = (char*)calloc((size_t)length, sizeof(char)); } for (int i = iStart; i <= iEnd; i++) @@ -162,7 +162,7 @@ static int GetNumericPattern(const UNumberFormat* pNumberFormat, UErrorCode ignore = U_ZERO_ERROR; int32_t icuPatternLength = unum_toPattern(pNumberFormat, FALSE, NULL, 0, &ignore) + 1; - UChar* icuPattern = calloc((size_t)icuPatternLength, sizeof(UChar)); + UChar* icuPattern = (UChar*)calloc((size_t)icuPatternLength, sizeof(UChar)); if (icuPattern == NULL) { return U_MEMORY_ALLOCATION_ERROR; diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_localeStringData.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_localeStringData.c index f0894b73ee100..0c2c94a8390ed 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_localeStringData.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_localeStringData.c @@ -78,7 +78,7 @@ static UErrorCode GetLocaleIso639LanguageTwoLetterName(const char* locale, UChar UErrorCode status = U_ZERO_ERROR, ignore = U_ZERO_ERROR; int32_t length = uloc_getLanguage(locale, NULL, 0, &ignore) + 1; - char* buf = calloc((size_t)length, sizeof(char)); + char* buf = (char*)calloc((size_t)length, sizeof(char)); if (buf == NULL) { return U_MEMORY_ALLOCATION_ERROR; @@ -121,7 +121,7 @@ static UErrorCode GetLocaleIso3166CountryName(const char* locale, UChar* value, UErrorCode status = U_ZERO_ERROR, ignore = U_ZERO_ERROR; int32_t length = uloc_getCountry(locale, NULL, 0, &ignore) + 1; - char* buf = calloc((size_t)length, sizeof(char)); + char* buf = (char*)calloc((size_t)length, sizeof(char)); if (buf == NULL) { return U_MEMORY_ALLOCATION_ERROR; diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_timeZoneInfo.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_timeZoneInfo.c index 537464dd2358a..c6eb7f3e4c842 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_timeZoneInfo.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_timeZoneInfo.c @@ -4,7 +4,6 @@ // #include -#include #include "pal_errors_internal.h" #include "pal_locale_internal.h" @@ -26,7 +25,7 @@ ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName, int32_t timeZoneIdLength = -1; // timeZoneId is NULL-terminated UCalendar* calendar = ucal_open(timeZoneId, timeZoneIdLength, locale, UCAL_DEFAULT, &err); - // TODO (https://github.com/dotnet/corefx/issues/5741): need to support Generic names, but ICU "C" api + // TODO (https://github.com/dotnet/runtime/issues/16232): need to support Generic names, but ICU "C" api // has no public option for this. For now, just use the ICU standard name for both Standard and Generic // (which is the same behavior on Windows with the mincore TIME_ZONE_INFORMATION APIs). ucal_getTimeZoneDisplayName(