/*** *initmon.c - contains __init_monetary * * Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved. * *Purpose: * Contains the locale-category initialization function: __init_monetary(). * * Each initialization function sets up locale-specific information * for their category, for use by functions which are affected by * their locale category. * * *** For internal use by setlocale() only *** * *******************************************************************************/ #include #include #include #include #include #include #include static int __cdecl _get_lc_lconv(struct lconv *l); static void __cdecl _free_lc_lconv(struct lconv *l); /* Pointer to non-C locale lconv */ static struct lconv *__lconv_intl = NULL; /* * Note that __lconv_c is used when the monetary category is in the C locale * but the numeric category may not necessarily be in the C locale. */ /*** *int __init_monetary() - initialization for LC_MONETARY locale category. * *Purpose: * In non-C locales, read the localized monetary strings into * __lconv_intl, and also copy the numeric strings from __lconv into * __lconv_intl. Set __lconv to point to __lconv_intl. The old * __lconv_intl is not freed until the new one is fully established. * * In the C locale, the monetary fields in lconv are filled with * contain C locale values. Any allocated __lconv_intl fields are freed. * * At startup, __lconv points to a static lconv structure containing * C locale strings. This structure is never used again if * __init_monetary is called. * *Entry: * None. * *Exit: * 0 success * 1 fail * *Exceptions: * *******************************************************************************/ int __cdecl __init_monetary ( void ) { struct lconv *lc; if (__lc_handle[LC_MONETARY] != _CLOCALEHANDLE) { /* Allocate structure filled with NULL pointers */ if ((lc = (struct lconv *) _calloc_crt (1, sizeof(struct lconv))) == NULL) return 1; if (_get_lc_lconv (lc)) { _free_lc_lconv (lc); _free_crt (lc); return 1; } /* Copy numeric locale fields */ lc->decimal_point = __lconv->decimal_point; lc->thousands_sep = __lconv->thousands_sep; lc->grouping = __lconv->grouping; __lconv = lc; /* point to new one */ _free_lc_lconv (__lconv_intl); /* free the old one */ _free_crt (__lconv_intl); __lconv_intl = lc; return 0; } else { /* * Copy numeric locale fields (not necessarily C locale) * to static structure. Note that __lconv_c numeric locale * fields may contain non-C locale information, but * monetary locale fields always contain C locale info. */ __lconv_c.decimal_point = __lconv->decimal_point; __lconv_c.thousands_sep = __lconv->thousands_sep; __lconv_c.grouping = __lconv->grouping; __lconv = &__lconv_c; /* point to new one */ _free_lc_lconv (__lconv_intl); /* free the old one */ _free_crt (__lconv_intl); __lconv_intl = NULL; return 0; } } static void fix_grouping( char *grouping ) { /* * ANSI specifies that the fields should contain "\3" [\3\0] to indicate * thousands groupings (100,000,000.00 for example). * NT uses "3;0"; ASCII 3 instead of value 3 and the ';' is extra. * So here we convert the NT version to the ANSI version. */ while (*grouping) { /* convert '3' to '\3' */ if (*grouping >= '0' && *grouping <= '9') { *grouping = *grouping - '0'; grouping++; } /* remove ';' */ else if (*grouping == ';') { char *tmp = grouping; do *tmp = *(tmp+1); while (*++tmp); } /* unknown (illegal) character, ignore */ else grouping++; } } /* * Get the lconv fields. */ static int __cdecl _get_lc_lconv ( struct lconv *l ) { int ret = 0; /* Currency is country--not language--dependent. NT work-around. */ LCID ctryid=MAKELCID(__lc_id[LC_MONETARY].wCountry, SORT_DEFAULT); if (l == NULL) return -1; ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SINTLSYMBOL, (void *)&l->int_curr_symbol); ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SCURRENCY, (void *)&l->currency_symbol); ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONDECIMALSEP, (void *)&l->mon_decimal_point); ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONTHOUSANDSEP, (void *)&l->mon_thousands_sep); ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONGROUPING, (void *)&l->mon_grouping); fix_grouping(l->mon_grouping); ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SPOSITIVESIGN, (void *)&l->positive_sign); ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SNEGATIVESIGN, (void *)&l->negative_sign); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IINTLCURRDIGITS, (void *)&l->int_frac_digits); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_ICURRDIGITS, (void *)&l->frac_digits); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSYMPRECEDES, (void *)&l->p_cs_precedes); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSEPBYSPACE, (void *)&l->p_sep_by_space); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSYMPRECEDES, (void *)&l->n_cs_precedes); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSEPBYSPACE, (void *)&l->n_sep_by_space); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSIGNPOSN, (void *)&l->p_sign_posn); ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSIGNPOSN, (void *)&l->n_sign_posn); return ret; } /* * Free the lconv strings. * Numeric values do not need to be freed. */ static void __cdecl _free_lc_lconv ( struct lconv *l ) { if (l == NULL) return; if (l->int_curr_symbol != __lconv_static_null) { _free_crt (l->int_curr_symbol); _free_crt (l->currency_symbol); _free_crt (l->mon_decimal_point); _free_crt (l->mon_thousands_sep); _free_crt (l->mon_grouping); _free_crt (l->positive_sign); _free_crt (l->negative_sign); } /* Don't need to make these pointers NULL */ }