Signed-off-by: Chip Davis cdavis@codeweavers.com --- dlls/msvcrt/locale.c | 275 ++++++++++++++++++++++++++----------------- 1 file changed, 164 insertions(+), 111 deletions(-)
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index aee39a0eafbe..6370b7e3a9a7 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -58,6 +58,21 @@ BOOL initial_locale = TRUE; static char cloc_clmap[256]; static char cloc_cumap[256];
+#if _MSVCR_VER >= 100 +static const MSVCRT_wchar_t emptyW[] = {0}; +static const MSVCRT_wchar_t cloc_dec_point[] = {'.', 0}; +#endif +static struct MSVCRT_lconv cloc_lconv = +{ + ".", "", "", + "", "", "", "", "", "", "", CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX +#if _MSVCR_VER >= 100 + , + cloc_dec_point, emptyW, + emptyW, emptyW, emptyW, emptyW, emptyW, emptyW +#endif +}; + static const MSVCRT_wchar_t sun[] = {'S','u','n',0}; static const MSVCRT_wchar_t mon[] = {'M','o','n',0}; static const MSVCRT_wchar_t tue[] = {'T','u','e',0}; @@ -853,6 +868,14 @@ int CDECL __lconv_init(void) { /* this is used to make chars unsigned */ charmax = 255; + cloc_lconv.int_frac_digits = charmax; + cloc_lconv.frac_digits = charmax; + cloc_lconv.p_cs_precedes = charmax; + cloc_lconv.p_sep_by_space = charmax; + cloc_lconv.n_cs_precedes = charmax; + cloc_lconv.n_sep_by_space = charmax; + cloc_lconv.p_sign_posn = charmax; + cloc_lconv.n_sign_posn = charmax; return 0; }
@@ -913,31 +936,42 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) }
if(locinfo->lconv) { - MSVCRT_free(locinfo->lconv->decimal_point); - MSVCRT_free(locinfo->lconv->thousands_sep); - MSVCRT_free(locinfo->lconv->grouping); - MSVCRT_free(locinfo->lconv->int_curr_symbol); - MSVCRT_free(locinfo->lconv->currency_symbol); - MSVCRT_free(locinfo->lconv->mon_decimal_point); - MSVCRT_free(locinfo->lconv->mon_thousands_sep); - MSVCRT_free(locinfo->lconv->mon_grouping); - MSVCRT_free(locinfo->lconv->positive_sign); - MSVCRT_free(locinfo->lconv->negative_sign); + if(locinfo->lconv_num_refcount + && !InterlockedDecrement(locinfo->lconv_num_refcount)) { + MSVCRT_free(locinfo->lconv->decimal_point); + MSVCRT_free(locinfo->lconv->thousands_sep); + MSVCRT_free(locinfo->lconv->grouping); #if _MSVCR_VER >= 100 - MSVCRT_free(locinfo->lconv->_W_decimal_point); - MSVCRT_free(locinfo->lconv->_W_thousands_sep); - MSVCRT_free(locinfo->lconv->_W_int_curr_symbol); - MSVCRT_free(locinfo->lconv->_W_currency_symbol); - MSVCRT_free(locinfo->lconv->_W_mon_decimal_point); - MSVCRT_free(locinfo->lconv->_W_mon_thousands_sep); - MSVCRT_free(locinfo->lconv->_W_positive_sign); - MSVCRT_free(locinfo->lconv->_W_negative_sign); + MSVCRT_free(locinfo->lconv->_W_decimal_point); + MSVCRT_free(locinfo->lconv->_W_thousands_sep); #endif + MSVCRT_free(locinfo->lconv_num_refcount); + } + if(locinfo->lconv_mon_refcount + && !InterlockedDecrement(locinfo->lconv_mon_refcount)) { + MSVCRT_free(locinfo->lconv->int_curr_symbol); + MSVCRT_free(locinfo->lconv->currency_symbol); + MSVCRT_free(locinfo->lconv->mon_decimal_point); + MSVCRT_free(locinfo->lconv->mon_thousands_sep); + MSVCRT_free(locinfo->lconv->mon_grouping); + MSVCRT_free(locinfo->lconv->positive_sign); + MSVCRT_free(locinfo->lconv->negative_sign); +#if _MSVCR_VER >= 100 + MSVCRT_free(locinfo->lconv->_W_int_curr_symbol); + MSVCRT_free(locinfo->lconv->_W_currency_symbol); + MSVCRT_free(locinfo->lconv->_W_mon_decimal_point); + MSVCRT_free(locinfo->lconv->_W_mon_thousands_sep); + MSVCRT_free(locinfo->lconv->_W_positive_sign); + MSVCRT_free(locinfo->lconv->_W_negative_sign); +#endif + MSVCRT_free(locinfo->lconv_mon_refcount); + } + if(locinfo->lconv_intl_refcount + && !InterlockedDecrement(locinfo->lconv_intl_refcount)) { + MSVCRT_free(locinfo->lconv_intl_refcount); + MSVCRT_free(locinfo->lconv); + } } - MSVCRT_free(locinfo->lconv_intl_refcount); - MSVCRT_free(locinfo->lconv_num_refcount); - MSVCRT_free(locinfo->lconv_mon_refcount); - MSVCRT_free(locinfo->lconv);
if(locinfo->ctype1_refcount && !InterlockedDecrement(locinfo->ctype1_refcount)) { @@ -1204,13 +1238,6 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, memset(locinfo, 0, sizeof(MSVCRT_threadlocinfo)); locinfo->refcount = 1;
- locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv)); - if(!locinfo->lconv) { - free_locinfo(locinfo); - return NULL; - } - memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv)); - if(locale_name[MSVCRT_LC_COLLATE] && !init_category_name(locale_name[MSVCRT_LC_COLLATE], locale_len[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) { @@ -1337,6 +1364,38 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->pcumap = cloc_cumap; }
+ if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY]) + && !category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { + locinfo->lconv = old_locinfo->lconv; + locinfo->lconv_intl_refcount = old_locinfo->lconv_intl_refcount; + if(locinfo->lconv_intl_refcount) + InterlockedIncrement(locinfo->lconv_intl_refcount); + } else if((lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) + || (lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) + || (!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY]) + && old_locinfo->lc_handle[MSVCRT_LC_MONETARY]) + || (!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC]) + && old_locinfo->lc_handle[MSVCRT_LC_NUMERIC])) { + locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv)); + locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); + if(!locinfo->lconv || !locinfo->lconv_intl_refcount) { + MSVCRT_free(locinfo->lconv); + MSVCRT_free(locinfo->lconv_intl_refcount); + locinfo->lconv = NULL; + locinfo->lconv_intl_refcount = NULL; + free_locinfo(locinfo); + return NULL; + } + memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv)); + *locinfo->lconv_intl_refcount = 1; + } else { + locinfo->lconv = &cloc_lconv; + } + if(locale_name[MSVCRT_LC_MONETARY] && !init_category_name(locale_name[MSVCRT_LC_MONETARY], locale_len[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) { @@ -1347,6 +1406,35 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) { copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_MONETARY); + locinfo->lconv_mon_refcount = old_locinfo->lconv_mon_refcount; + if(locinfo->lconv_mon_refcount) + InterlockedIncrement(locinfo->lconv_mon_refcount); + if(category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { + locinfo->lconv->int_curr_symbol = old_locinfo->lconv->int_curr_symbol; + locinfo->lconv->currency_symbol = old_locinfo->lconv->currency_symbol; + locinfo->lconv->mon_decimal_point = old_locinfo->lconv->mon_decimal_point; + locinfo->lconv->mon_thousands_sep = old_locinfo->lconv->mon_thousands_sep; + locinfo->lconv->mon_grouping = old_locinfo->lconv->mon_grouping; + locinfo->lconv->positive_sign = old_locinfo->lconv->positive_sign; + locinfo->lconv->negative_sign = old_locinfo->lconv->negative_sign; + locinfo->lconv->int_frac_digits = old_locinfo->lconv->int_frac_digits; + locinfo->lconv->frac_digits = old_locinfo->lconv->frac_digits; + locinfo->lconv->p_cs_precedes = old_locinfo->lconv->p_cs_precedes; + locinfo->lconv->p_sep_by_space = old_locinfo->lconv->p_sep_by_space; + locinfo->lconv->n_cs_precedes = old_locinfo->lconv->n_cs_precedes; + locinfo->lconv->n_sep_by_space = old_locinfo->lconv->n_sep_by_space; + locinfo->lconv->p_sign_posn = old_locinfo->lconv->p_sign_posn; + locinfo->lconv->n_sign_posn = old_locinfo->lconv->n_sign_posn; +#if _MSVCR_VER >= 100 + locinfo->lconv->_W_int_curr_symbol = old_locinfo->lconv->_W_int_curr_symbol; + locinfo->lconv->_W_currency_symbol = old_locinfo->lconv->_W_currency_symbol; + locinfo->lconv->_W_mon_decimal_point = old_locinfo->lconv->_W_mon_decimal_point; + locinfo->lconv->_W_mon_thousands_sep = old_locinfo->lconv->_W_mon_thousands_sep; + locinfo->lconv->_W_positive_sign = old_locinfo->lconv->_W_positive_sign; + locinfo->lconv->_W_negative_sign = old_locinfo->lconv->_W_negative_sign; +#endif + } } else if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) { @@ -1354,14 +1442,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; }
- locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); locinfo->lconv_mon_refcount = MSVCRT_malloc(sizeof(int)); - if(!locinfo->lconv_intl_refcount || !locinfo->lconv_mon_refcount) { + if(!locinfo->lconv_mon_refcount) { free_locinfo(locinfo); return NULL; }
- *locinfo->lconv_intl_refcount = 1; *locinfo->lconv_mon_refcount = 1;
i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SINTLSYMBOL @@ -1558,60 +1644,33 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; } } else { - locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->mon_decimal_point = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->mon_thousands_sep = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->mon_grouping = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->positive_sign = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->negative_sign = MSVCRT_malloc(sizeof(char)); - - if(!locinfo->lconv->int_curr_symbol || !locinfo->lconv->currency_symbol - || !locinfo->lconv->mon_decimal_point || !locinfo->lconv->mon_thousands_sep - || !locinfo->lconv->mon_grouping || !locinfo->lconv->positive_sign - || !locinfo->lconv->negative_sign) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->int_curr_symbol[0] = '\0'; - locinfo->lconv->currency_symbol[0] = '\0'; - locinfo->lconv->mon_decimal_point[0] = '\0'; - locinfo->lconv->mon_thousands_sep[0] = '\0'; - locinfo->lconv->mon_grouping[0] = '\0'; - locinfo->lconv->positive_sign[0] = '\0'; - locinfo->lconv->negative_sign[0] = '\0'; - locinfo->lconv->int_frac_digits = charmax; - locinfo->lconv->frac_digits = charmax; - locinfo->lconv->p_cs_precedes = charmax; - locinfo->lconv->p_sep_by_space = charmax; - locinfo->lconv->n_cs_precedes = charmax; - locinfo->lconv->n_sep_by_space = charmax; - locinfo->lconv->p_sign_posn = charmax; - locinfo->lconv->n_sign_posn = charmax; + if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { + locinfo->lconv->int_curr_symbol = ""; + locinfo->lconv->currency_symbol = ""; + locinfo->lconv->mon_decimal_point = ""; + locinfo->lconv->mon_thousands_sep = ""; + locinfo->lconv->mon_grouping = ""; + locinfo->lconv->positive_sign = ""; + locinfo->lconv->negative_sign = ""; + locinfo->lconv->int_frac_digits = charmax; + locinfo->lconv->frac_digits = charmax; + locinfo->lconv->p_cs_precedes = charmax; + locinfo->lconv->p_sep_by_space = charmax; + locinfo->lconv->n_cs_precedes = charmax; + locinfo->lconv->n_sep_by_space = charmax; + locinfo->lconv->p_sign_posn = charmax; + locinfo->lconv->n_sign_posn = charmax;
#if _MSVCR_VER >= 100 - locinfo->lconv->_W_int_curr_symbol = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_currency_symbol = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_mon_decimal_point = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_mon_thousands_sep = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_positive_sign = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_negative_sign = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - - if(!locinfo->lconv->_W_int_curr_symbol || !locinfo->lconv->_W_currency_symbol - || !locinfo->lconv->_W_mon_decimal_point || !locinfo->lconv->_W_mon_thousands_sep - || !locinfo->lconv->positive_sign || !locinfo->lconv->negative_sign) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->_W_int_curr_symbol[0] = '\0'; - locinfo->lconv->_W_currency_symbol[0] = '\0'; - locinfo->lconv->_W_mon_decimal_point[0] = '\0'; - locinfo->lconv->_W_mon_thousands_sep[0] = '\0'; - locinfo->lconv->_W_positive_sign[0] = '\0'; - locinfo->lconv->_W_negative_sign[0] = '\0'; + locinfo->lconv->_W_int_curr_symbol = emptyW; + locinfo->lconv->_W_currency_symbol = emptyW; + locinfo->lconv->_W_mon_decimal_point = emptyW; + locinfo->lconv->_W_mon_thousands_sep = emptyW; + locinfo->lconv->_W_positive_sign = emptyW; + locinfo->lconv->_W_negative_sign = emptyW; #endif + }
if(!init_category_name("C", 1, locinfo, MSVCRT_LC_MONETARY)) { free_locinfo(locinfo); @@ -1629,6 +1688,19 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_NUMERIC); + locinfo->lconv_num_refcount = old_locinfo->lconv_num_refcount; + if(locinfo->lconv_num_refcount) + InterlockedIncrement(locinfo->lconv_num_refcount); + if(category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) { + locinfo->lconv->decimal_point = old_locinfo->lconv->decimal_point; + locinfo->lconv->thousands_sep = old_locinfo->lconv->thousands_sep; + locinfo->lconv->grouping = old_locinfo->lconv->grouping; +#if _MSVCR_VER >= 100 + locinfo->lconv->_W_decimal_point = old_locinfo->lconv->_W_decimal_point; + locinfo->lconv->_W_thousands_sep = old_locinfo->lconv->_W_thousands_sep; +#endif + } } else if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC], locinfo, MSVCRT_LC_NUMERIC)) { @@ -1636,15 +1708,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; }
- if(!locinfo->lconv_intl_refcount) - locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); locinfo->lconv_num_refcount = MSVCRT_malloc(sizeof(int)); - if(!locinfo->lconv_intl_refcount || !locinfo->lconv_num_refcount) { + if(!locinfo->lconv_num_refcount) { free_locinfo(locinfo); return NULL; }
- *locinfo->lconv_intl_refcount = 1; *locinfo->lconv_num_refcount = 1;
i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_SDECIMAL @@ -1705,33 +1774,17 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; } } else { - locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[2])); - locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->grouping = MSVCRT_malloc(sizeof(char)); - if(!locinfo->lconv->decimal_point || !locinfo->lconv->thousands_sep - || !locinfo->lconv->grouping) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->decimal_point[0] = '.'; - locinfo->lconv->decimal_point[1] = '\0'; - locinfo->lconv->thousands_sep[0] = '\0'; - locinfo->lconv->grouping[0] = '\0'; + if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) { + locinfo->lconv->decimal_point = "."; + locinfo->lconv->thousands_sep = ""; + locinfo->lconv->grouping = "";
#if _MSVCR_VER >= 100 - locinfo->lconv->_W_decimal_point = MSVCRT_malloc(sizeof(MSVCRT_wchar_t[2])); - locinfo->lconv->_W_thousands_sep = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - - if(!locinfo->lconv->_W_decimal_point || !locinfo->lconv->_W_thousands_sep) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->_W_decimal_point[0] = '.'; - locinfo->lconv->_W_decimal_point[1] = '\0'; - locinfo->lconv->_W_thousands_sep[0] = '\0'; + locinfo->lconv->_W_decimal_point = cloc_dec_point; + locinfo->lconv->_W_thousands_sep = emptyW; #endif + }
if (!init_category_name("C", 1, locinfo, MSVCRT_LC_NUMERIC)) { free_locinfo(locinfo);