X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/4388f060552cc537e71e957d32f35e9d75a61233..ef6cf650f4a75c3f97de06b51fa104f2069b9ea2:/icuSources/common/putil.cpp diff --git a/icuSources/common/putil.cpp b/icuSources/common/putil.cpp index 7c9536b5..46978812 100644 --- a/icuSources/common/putil.cpp +++ b/icuSources/common/putil.cpp @@ -1,7 +1,7 @@ /* ****************************************************************************** * -* Copyright (C) 1997-2012, International Business Machines +* Copyright (C) 1997-2016, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** @@ -52,6 +52,7 @@ #include "cstring.h" #include "locmap.h" #include "ucln_cmn.h" +#include "charstr.h" /* Include standard headers. */ #include @@ -87,25 +88,18 @@ # include # include /* EPT_CALL macro - this include must be after all other "QSYSINCs" */ # include /* For uprv_maximumPtr */ -#elif U_PLATFORM == U_PF_CLASSIC_MACOS -# include -# include -# include -# include -# include -# include -# define ICU_NO_USER_DATA_OVERRIDE 1 #elif U_PLATFORM == U_PF_OS390 # include "unicode/ucnv.h" /* Needed for UCNV_SWAP_LFNL_OPTION_STRING */ -#elif U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD +#elif U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM == U_PF_SOLARIS # include # include +# if U_PLATFORM == U_PF_SOLARIS +# ifndef _XPG4_2 +# define _XPG4_2 +# endif +# endif #elif U_PLATFORM == U_PF_QNX # include -#elif U_PLATFORM == U_PF_SOLARIS -# ifndef _XPG4_2 -# define _XPG4_2 -# endif #endif #if (U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(__STRICT_ANSI__) @@ -157,7 +151,7 @@ # define HAVE_GETTIMEOFDAY 0 #endif -#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) +U_NAMESPACE_USE /* Define the extension for data files, again... */ #define DATA_TYPE "dat" @@ -186,7 +180,7 @@ static const BitPatternConversion gInf = { (int64_t) INT64_C(0x7FF0000000000000) functions). ---------------------------------------------------------------------------*/ -#if U_PLATFORM_USES_ONLY_WIN32_API || U_PLATFORM == U_PF_CLASSIC_MACOS || U_PLATFORM == U_PF_OS400 +#if U_PLATFORM_USES_ONLY_WIN32_API || U_PLATFORM == U_PF_OS400 # undef U_POSIX_LOCALE #else # define U_POSIX_LOCALE 1 @@ -240,7 +234,7 @@ u_signBit(double d) { UDate fakeClock_t0 = 0; /** Time to start the clock from **/ UDate fakeClock_dt = 0; /** Offset (fake time - real time) **/ UBool fakeClock_set = FALSE; /** True if fake clock has spun up **/ -static UMTX fakeClockMutex = NULL; +static UMutex fakeClockMutex = U_MUTEX_INTIALIZER; static UDate getUTCtime_real() { struct timeval posixTime; @@ -305,21 +299,7 @@ uprv_getUTCtime() U_CAPI UDate U_EXPORT2 uprv_getRawUTCtime() { -#if U_PLATFORM == U_PF_CLASSIC_MACOS - time_t t, t1, t2; - struct tm tmrec; - - uprv_memset( &tmrec, 0, sizeof(tmrec) ); - tmrec.tm_year = 70; - tmrec.tm_mon = 0; - tmrec.tm_mday = 1; - t1 = mktime(&tmrec); /* seconds of 1/1/1970*/ - - time(&t); - uprv_memcpy( &tmrec, gmtime(&t), sizeof(tmrec) ); - t2 = mktime(&tmrec); /* seconds of current GMT*/ - return (UDate)(t2 - t1) * U_MILLIS_PER_SECOND; /* GMT (or UTC) in seconds since 1970*/ -#elif U_PLATFORM_USES_ONLY_WIN32_API +#if U_PLATFORM_USES_ONLY_WIN32_API FileTimeConversion winTime; GetSystemTimeAsFileTime(&winTime.fileTime); @@ -638,20 +618,30 @@ uprv_timezone() #else time_t t, t1, t2; struct tm tmrec; - UBool dst_checked; int32_t tdiff = 0; time(&t); uprv_memcpy( &tmrec, localtime(&t), sizeof(tmrec) ); - dst_checked = (tmrec.tm_isdst != 0); /* daylight savings time is checked*/ +#if U_PLATFORM != U_PF_IPHONE + UBool dst_checked = (tmrec.tm_isdst != 0); /* daylight savings time is checked*/ +#endif t1 = mktime(&tmrec); /* local time in seconds*/ uprv_memcpy( &tmrec, gmtime(&t), sizeof(tmrec) ); t2 = mktime(&tmrec); /* GMT (or UTC) in seconds*/ tdiff = t2 - t1; + +#if U_PLATFORM != U_PF_IPHONE /* imitate NT behaviour, which returns same timezone offset to GMT for - winter and summer*/ + winter and summer. + This does not work on all platforms. For instance, on glibc on Linux + and on Mac OS 10.5, tdiff calculated above remains the same + regardless of whether DST is in effect or not. iOS is another + platform where this does not work. Linux + glibc and Mac OS 10.5 + have U_TIMEZONE defined so that this code is not reached. + */ if (dst_checked) tdiff += 3600; +#endif return tdiff; #endif } @@ -664,12 +654,17 @@ uprv_timezone() extern U_IMPORT char *U_TZNAME[]; #endif -#if !UCONFIG_NO_FILE_IO && (U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD) +#if !UCONFIG_NO_FILE_IO && ((U_PLATFORM_IS_DARWIN_BASED && (U_PLATFORM != U_PF_IPHONE || defined(U_TIMEZONE))) || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM == U_PF_SOLARIS) /* These platforms are likely to use Olson timezone IDs. */ #define CHECK_LOCALTIME_LINK 1 #if U_PLATFORM_IS_DARWIN_BASED #include #define TZZONEINFO (TZDIR "/") +#elif U_PLATFORM == U_PF_SOLARIS +#define TZDEFAULT "/etc/localtime" +#define TZZONEINFO "/usr/share/lib/zoneinfo/" +#define TZZONEINFO2 "../usr/share/lib/zoneinfo/" +#define TZ_ENV_CHECK "localtime" #else #define TZDEFAULT "/etc/localtime" #define TZZONEINFO "/usr/share/zoneinfo/" @@ -822,7 +817,7 @@ static const char* remapShortTimeZone(const char *stdID, const char *dstID, int3 #ifdef DEBUG_TZNAME fprintf(stderr, "TZ=%s std=%s dst=%s daylight=%d offset=%d\n", getenv("TZ"), stdID, dstID, daylightType, offset); #endif - for (idx = 0; idx < LENGTHOF(OFFSET_ZONE_MAPPINGS); idx++) + for (idx = 0; idx < UPRV_LENGTHOF(OFFSET_ZONE_MAPPINGS); idx++) { if (offset == OFFSET_ZONE_MAPPINGS[idx].offsetSeconds && daylightType == OFFSET_ZONE_MAPPINGS[idx].daylightType @@ -999,8 +994,16 @@ uprv_tzname(int n) /* This code can be temporarily disabled to test tzname resolution later on. */ #ifndef DEBUG_TZNAME tzid = getenv("TZ"); - if (tzid != NULL && isValidOlsonID(tzid)) - { + if (tzid != NULL && isValidOlsonID(tzid) +#if U_PLATFORM == U_PF_SOLARIS + /* When TZ equals localtime on Solaris, check the /etc/localtime file. */ + && uprv_strcmp(tzid, TZ_ENV_CHECK) != 0 +#endif + ) { + /* The colon forces tzset() to treat the remainder as zoneinfo path */ + if (tzid[0] == ':') { + tzid++; + } /* This might be a good Olson ID. */ skipZoneIDPrefix(&tzid); return tzid; @@ -1025,6 +1028,17 @@ uprv_tzname(int n) { return (gTimeZoneBufferPtr = gTimeZoneBuffer + tzZoneInfoLen); } +#if U_PLATFORM == U_PF_SOLARIS + else + { + tzZoneInfoLen = uprv_strlen(TZZONEINFO2); + if (uprv_strncmp(gTimeZoneBuffer, TZZONEINFO2, tzZoneInfoLen) == 0 + && isValidOlsonID(gTimeZoneBuffer + tzZoneInfoLen)) + { + return (gTimeZoneBufferPtr = gTimeZoneBuffer + tzZoneInfoLen); + } + } +#endif } else { #if defined(SEARCH_TZFILE) DefaultTZInfo* tzInfo = (DefaultTZInfo*)uprv_malloc(sizeof(DefaultTZInfo)); @@ -1103,8 +1117,13 @@ uprv_tzname(int n) /* Get and set the ICU data directory --------------------------------------- */ +static icu::UInitOnce gDataDirInitOnce = U_INITONCE_INITIALIZER; static char *gDataDirectory = NULL; -#if U_POSIX_LOCALE + +UInitOnce gTimeZoneFilesInitOnce = U_INITONCE_INITIALIZER; +static CharString *gTimeZoneFilesDirectory = NULL; + +#if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API static char *gCorrectedPOSIXLocale = NULL; /* Heap allocated */ #endif @@ -1114,7 +1133,13 @@ static UBool U_CALLCONV putil_cleanup(void) uprv_free(gDataDirectory); } gDataDirectory = NULL; -#if U_POSIX_LOCALE + gDataDirInitOnce.reset(); + + delete gTimeZoneFilesDirectory; + gTimeZoneFilesDirectory = NULL; + gTimeZoneFilesInitOnce.reset(); + +#if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API if (gCorrectedPOSIXLocale) { uprv_free(gCorrectedPOSIXLocale); gCorrectedPOSIXLocale = NULL; @@ -1126,7 +1151,6 @@ static UBool U_CALLCONV putil_cleanup(void) /* * Set the data directory. * Make a copy of the passed string, and set the global data dir to point to it. - * TODO: see bug #2849, regarding thread safety. */ U_CAPI void U_EXPORT2 u_setDataDirectory(const char *directory) { @@ -1159,13 +1183,11 @@ u_setDataDirectory(const char *directory) { #endif } - umtx_lock(NULL); if (gDataDirectory && *gDataDirectory) { uprv_free(gDataDirectory); } gDataDirectory = newDataDir; ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); - umtx_unlock(NULL); } U_CAPI UBool U_EXPORT2 @@ -1204,20 +1226,19 @@ uprv_pathIsAbsolute(const char *path) # endif #endif -U_CAPI const char * U_EXPORT2 -u_getDataDirectory(void) { +static void U_CALLCONV dataDirectoryInitFn() { + /* If we already have the directory, then return immediately. Will happen if user called + * u_setDataDirectory(). + */ + if (gDataDirectory) { + return; + } + const char *path = NULL; #if defined(ICU_DATA_DIR_PREFIX_ENV_VAR) char datadir_path_buffer[PATH_MAX]; #endif - /* if we have the directory, then return it immediately */ - UMTX_CHECK(NULL, gDataDirectory, path); - - if(path) { - return path; - } - /* When ICU_NO_USER_DATA_OVERRIDE is defined, users aren't allowed to override ICU's data with the ICU_DATA environment variable. This prevents @@ -1268,117 +1289,106 @@ u_getDataDirectory(void) { } u_setDataDirectory(path); + return; +} + +U_CAPI const char * U_EXPORT2 +u_getDataDirectory(void) { + umtx_initOnce(gDataDirInitOnce, &dataDirectoryInitFn); return gDataDirectory; } +static void setTimeZoneFilesDir(const char *path, UErrorCode &status) { + if (U_FAILURE(status)) { + return; + } + gTimeZoneFilesDirectory->clear(); + gTimeZoneFilesDirectory->append(path, status); +#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) + char *p = gTimeZoneFilesDirectory->data(); + while (p = uprv_strchr(p, U_FILE_ALT_SEP_CHAR)) { + *p = U_FILE_SEP_CHAR; + } +#endif +} +#if U_PLATFORM_IMPLEMENTS_POSIX +#include +#if defined(U_TIMEZONE_FILES_DIR) +const char tzdirbuf[] = U_TIMEZONE_FILES_DIR; +enum { kTzfilenamebufLen = UPRV_LENGTHOF(tzdirbuf) + 24 }; // extra room for "/icutz44l.dat" or "/zoneinfo64.res" +#endif +#endif +#define TO_STRING(x) TO_STRING_2(x) +#define TO_STRING_2(x) #x +static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { + U_ASSERT(gTimeZoneFilesDirectory == NULL); + ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); + gTimeZoneFilesDirectory = new CharString(); + if (gTimeZoneFilesDirectory == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + const char *dir = getenv("ICU_TIMEZONE_FILES_DIR"); + UBool usingUTzFilesDir = FALSE; +#if defined(U_TIMEZONE_FILES_DIR) + if (dir == NULL) { + // dir = TO_STRING(U_TIMEZONE_FILES_DIR); + // Not sure why the above was done for this path only; + // it preserves unwanted quotes. + dir = tzdirbuf; + usingUTzFilesDir = TRUE; + } +#endif +#if U_PLATFORM_IMPLEMENTS_POSIX + if (dir != NULL) { + struct stat buf; + if (stat(dir, &buf) != 0) { + dir = NULL; + } +#if defined(U_TIMEZONE_FILES_DIR) + else if (usingUTzFilesDir) { + char tzfilenamebuf[kTzfilenamebufLen]; + uprv_strcpy(tzfilenamebuf, tzdirbuf); + uprv_strcat(tzfilenamebuf, U_FILE_SEP_STRING); +#if defined(U_TIMEZONE_PACKAGE) + uprv_strcat(tzfilenamebuf, U_TIMEZONE_PACKAGE); + uprv_strcat(tzfilenamebuf, ".dat"); +#else + uprv_strcat(tzfilenamebuf, "zoneinfo64.res"); +#endif + if (stat(tzfilenamebuf, &buf) != 0) { + dir = NULL; + } + } +#endif /* defined(U_TIMEZONE_FILES_DIR) */ + } +#endif /* U_PLATFORM_IMPLEMENTS_POSIX */ + if (dir == NULL) { + dir = ""; + } + setTimeZoneFilesDir(dir, status); +} -/* Macintosh-specific locale information ------------------------------------ */ -#if U_PLATFORM == U_PF_CLASSIC_MACOS - -typedef struct { - int32_t script; - int32_t region; - int32_t lang; - int32_t date_region; - const char* posixID; -} mac_lc_rec; - -/* Todo: This will be updated with a newer version from www.unicode.org web - page when it's available.*/ -#define MAC_LC_MAGIC_NUMBER -5 -#define MAC_LC_INIT_NUMBER -9 - -static const mac_lc_rec mac_lc_recs[] = { - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 0, "en_US", - /* United States*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 1, "fr_FR", - /* France*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 2, "en_GB", - /* Great Britain*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 3, "de_DE", - /* Germany*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 4, "it_IT", - /* Italy*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 5, "nl_NL", - /* Metherlands*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 6, "fr_BE", - /* French for Belgium or Lxembourg*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 7, "sv_SE", - /* Sweden*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 9, "da_DK", - /* Denmark*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 10, "pt_PT", - /* Portugal*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 11, "fr_CA", - /* French Canada*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 13, "is_IS", - /* Israel*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 14, "ja_JP", - /* Japan*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 15, "en_AU", - /* Australia*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 16, "ar_AE", - /* the Arabic world (?)*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 17, "fi_FI", - /* Finland*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 18, "fr_CH", - /* French for Switzerland*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 19, "de_CH", - /* German for Switzerland*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 20, "el_GR", - /* Greece*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 21, "is_IS", - /* Iceland ===*/ - /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 22, "",*/ - /* Malta ===*/ - /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 23, "",*/ - /* Cyprus ===*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 24, "tr_TR", - /* Turkey ===*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 25, "sh_YU", - /* Croatian system for Yugoslavia*/ - /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 33, "",*/ - /* Hindi system for India*/ - /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 34, "",*/ - /* Pakistan*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 41, "lt_LT", - /* Lithuania*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 42, "pl_PL", - /* Poland*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 43, "hu_HU", - /* Hungary*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 44, "et_EE", - /* Estonia*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 45, "lv_LV", - /* Latvia*/ - /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 46, "",*/ - /* Lapland [Ask Rich for the data. HS]*/ - /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 47, "",*/ - /* Faeroe Islands*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 48, "fa_IR", - /* Iran*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 49, "ru_RU", - /* Russia*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 50, "en_IE", - /* Ireland*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 51, "ko_KR", - /* Korea*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 52, "zh_CN", - /* People's Republic of China*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 53, "zh_TW", - /* Taiwan*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 54, "th_TH", - /* Thailand*/ - - /* fallback is en_US*/ - MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, - MAC_LC_MAGIC_NUMBER, "en_US" -}; -#endif +U_CAPI const char * U_EXPORT2 +u_getTimeZoneFilesDirectory(UErrorCode *status) { + umtx_initOnce(gTimeZoneFilesInitOnce, &TimeZoneDataDirInitFn, *status); + return U_SUCCESS(*status) ? gTimeZoneFilesDirectory->data() : ""; +} + +U_CAPI void U_EXPORT2 +u_setTimeZoneFilesDirectory(const char *path, UErrorCode *status) { + umtx_initOnce(gTimeZoneFilesInitOnce, &TimeZoneDataDirInitFn, *status); + setTimeZoneFilesDir(path, *status); + + // Note: this function does some extra churn, first setting based on the + // environment, then immediately replacing with the value passed in. + // The logic is simpler that way, and performance shouldn't be an issue. +} + #if U_POSIX_LOCALE /* A helper function used by uprv_getPOSIXIDForDefaultLocale and @@ -1414,9 +1424,18 @@ static const char *uprv_getPOSIXIDForCategory(int category) { /* Maybe we got some garbage. Try something more reasonable */ posixID = getenv("LC_ALL"); + /* Solaris speaks POSIX - See IEEE Std 1003.1-2008 + * This is needed to properly handle empty env. variables + */ +#if U_PLATFORM == U_PF_SOLARIS + if ((posixID == 0) || (posixID[0] == '\0')) { + posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE"); + if ((posixID == 0) || (posixID[0] == '\0')) { +#else if (posixID == 0) { posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE"); if (posixID == 0) { +#endif posixID = getenv("LANG"); } } @@ -1444,6 +1463,7 @@ static const char *uprv_getPOSIXIDForDefaultLocale(void) return posixID; } +#if !U_CHARSET_IS_UTF8 /* Return just the POSIX id for the default codepage, whatever happens to be in * it. It gets the value from LC_CTYPE and indirectly from LC_ALL and LANG. */ @@ -1456,6 +1476,7 @@ static const char *uprv_getPOSIXIDForDefaultCodepage(void) return posixID; } #endif +#endif /* NOTE: The caller should handle thread safety */ U_CAPI const char* U_EXPORT2 @@ -1502,7 +1523,7 @@ The leftmost codepage (.xxx) wins. if ((p = uprv_strchr(posixID, '.')) != NULL) { /* assume new locale can't be larger than old one? */ - correctedPOSIXLocale = reinterpret_cast(uprv_malloc(uprv_strlen(posixID)+1)); + correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID)+1)); /* Exit on memory allocation error. */ if (correctedPOSIXLocale == NULL) { return NULL; @@ -1519,7 +1540,7 @@ The leftmost codepage (.xxx) wins. /* Note that we scan the *uncorrected* ID. */ if ((p = uprv_strrchr(posixID, '@')) != NULL) { if (correctedPOSIXLocale == NULL) { - correctedPOSIXLocale = reinterpret_cast(uprv_malloc(uprv_strlen(posixID)+1)); + correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID)+1)); /* Exit on memory allocation error. */ if (correctedPOSIXLocale == NULL) { return NULL; @@ -1587,49 +1608,31 @@ The leftmost codepage (.xxx) wins. return posixID; #elif U_PLATFORM_USES_ONLY_WIN32_API +#define POSIX_LOCALE_CAPACITY 64 UErrorCode status = U_ZERO_ERROR; - LCID id = GetThreadLocale(); - const char* locID = uprv_convertToPosix(id, &status); + char *correctedPOSIXLocale = 0; - if (U_FAILURE(status)) { - locID = "en_US"; - } - return locID; - -#elif U_PLATFORM == U_PF_CLASSIC_MACOS - int32_t script = MAC_LC_INIT_NUMBER; - /* = IntlScript(); or GetScriptManagerVariable(smSysScript);*/ - int32_t region = MAC_LC_INIT_NUMBER; - /* = GetScriptManagerVariable(smRegionCode);*/ - int32_t lang = MAC_LC_INIT_NUMBER; - /* = GetScriptManagerVariable(smScriptLang);*/ - int32_t date_region = MAC_LC_INIT_NUMBER; - const char* posixID = 0; - int32_t count = sizeof(mac_lc_recs) / sizeof(mac_lc_rec); - int32_t i; - Intl1Hndl ih; - - ih = (Intl1Hndl) GetIntlResource(1); - if (ih) - date_region = ((uint16_t)(*ih)->intl1Vers) >> 8; - - for (i = 0; i < count; i++) { - if ( ((mac_lc_recs[i].script == MAC_LC_MAGIC_NUMBER) - || (mac_lc_recs[i].script == script)) - && ((mac_lc_recs[i].region == MAC_LC_MAGIC_NUMBER) - || (mac_lc_recs[i].region == region)) - && ((mac_lc_recs[i].lang == MAC_LC_MAGIC_NUMBER) - || (mac_lc_recs[i].lang == lang)) - && ((mac_lc_recs[i].date_region == MAC_LC_MAGIC_NUMBER) - || (mac_lc_recs[i].date_region == date_region)) - ) - { - posixID = mac_lc_recs[i].posixID; - break; + if (gCorrectedPOSIXLocale != NULL) { + return gCorrectedPOSIXLocale; + } + + LCID id = GetThreadLocale(); + correctedPOSIXLocale = static_cast(uprv_malloc(POSIX_LOCALE_CAPACITY + 1)); + if (correctedPOSIXLocale) { + int32_t posixLen = uprv_convertToPosix(id, correctedPOSIXLocale, POSIX_LOCALE_CAPACITY, &status); + if (U_SUCCESS(status)) { + *(correctedPOSIXLocale + posixLen) = 0; + gCorrectedPOSIXLocale = correctedPOSIXLocale; + ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); + } else { + uprv_free(correctedPOSIXLocale); } } - return posixID; + if (gCorrectedPOSIXLocale == NULL) { + return "en_US"; + } + return gCorrectedPOSIXLocale; #elif U_PLATFORM == U_PF_OS400 /* locales are process scoped and are by definition thread safe */ @@ -1912,9 +1915,6 @@ int_getDefaultCodepage() return codepage; -#elif U_PLATFORM == U_PF_CLASSIC_MACOS - return "macintosh"; /* TODO: Macintosh Roman. There must be a better way. fixme! */ - #elif U_PLATFORM_USES_ONLY_WIN32_API static char codepage[64]; sprintf(codepage, "windows-%d", GetACP()); @@ -1927,7 +1927,10 @@ int_getDefaultCodepage() localeName = uprv_getPOSIXIDForDefaultCodepage(); uprv_memset(codesetName, 0, sizeof(codesetName)); -#if U_HAVE_NL_LANGINFO_CODESET + /* On Solaris nl_langinfo returns C locale values unless setlocale + * was called earlier. + */ +#if (U_HAVE_NL_LANGINFO_CODESET && U_PLATFORM != U_PF_SOLARIS) /* When available, check nl_langinfo first because it usually gives more useful names. It depends on LC_CTYPE. nl_langinfo may use the same buffer as setlocale. */ @@ -2091,6 +2094,7 @@ u_versionToString(const UVersionInfo versionArray, char *versionString) { U_CAPI void U_EXPORT2 u_getVersion(UVersionInfo versionArray) { + (void)copyright; // Suppress unused variable warning from clang. u_versionFromString(versionArray, U_ICU_VERSION); } @@ -2100,7 +2104,7 @@ u_getVersion(UVersionInfo versionArray) { #if U_ENABLE_DYLOAD -#if HAVE_DLOPEN && !U_PLATFORM_HAS_WIN32_API +#if HAVE_DLOPEN && !U_PLATFORM_USES_ONLY_WIN32_API #if HAVE_DLFCN_H @@ -2181,7 +2185,7 @@ uprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) { #endif -#elif U_PLATFORM_HAS_WIN32_API +#elif U_PLATFORM_USES_ONLY_WIN32_API U_INTERNAL void * U_EXPORT2 uprv_dl_open(const char *libName, UErrorCode *status) { @@ -2237,6 +2241,7 @@ uprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) { U_INTERNAL void * U_EXPORT2 uprv_dl_open(const char *libName, UErrorCode *status) { + (void)libName; if(U_FAILURE(*status)) return NULL; *status = U_UNSUPPORTED_ERROR; return NULL; @@ -2244,6 +2249,7 @@ uprv_dl_open(const char *libName, UErrorCode *status) { U_INTERNAL void U_EXPORT2 uprv_dl_close(void *lib, UErrorCode *status) { + (void)lib; if(U_FAILURE(*status)) return; *status = U_UNSUPPORTED_ERROR; return; @@ -2252,6 +2258,8 @@ uprv_dl_close(void *lib, UErrorCode *status) { U_INTERNAL UVoidFunction* U_EXPORT2 uprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) { + (void)lib; + (void)sym; if(U_SUCCESS(*status)) { *status = U_UNSUPPORTED_ERROR; }