ReactOS 0.4.16-dev-853-g88d9285
initmon.cpp
Go to the documentation of this file.
1/***
2*initmon.c - contains __acrt_locale_initialize_monetary
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* Contains the locale-category initialization function: __acrt_locale_initialize_monetary().
8*
9* Each initialization function sets up locale-specific information
10* for their category, for use by functions which are affected by
11* their locale category.
12*
13* *** For internal use by setlocale() only ***
14*
15*******************************************************************************/
16
17#include <corecrt_internal.h>
18#include <locale.h>
19
20extern "C" {
21
22
23 // Enclaves have no ability to create new locales.
24#ifndef _UCRT_ENCLAVE_BUILD
25
26static void fix_grouping(_Inout_z_ char *);
27
28/*
29 * Note that __acrt_lconv_c is used when the monetary category is in the C locale
30 * but the numeric category may not necessarily be in the C locale.
31 */
32
33
34/***
35*int __acrt_locale_initialize_monetary() - initialization for LC_MONETARY locale category.
36*
37*Purpose:
38* In non-C locales, read the localized monetary strings into
39* __acrt_lconv_intl, and also copy the numeric strings from __acrt_lconv into
40* __acrt_lconv_intl. Set __acrt_lconv to point to __acrt_lconv_intl. The old
41* __acrt_lconv_intl is not freed until the new one is fully established.
42*
43* In the C locale, the monetary fields in lconv are filled with
44* contain C locale values. Any allocated __acrt_lconv_intl fields are freed.
45*
46* At startup, __acrt_lconv points to a static lconv structure containing
47* C locale strings. This structure is never used again if
48* __acrt_locale_initialize_monetary is called.
49*
50*Entry:
51* None.
52*
53*Exit:
54* 0 success
55* 1 fail
56*
57*Exceptions:
58*
59*******************************************************************************/
60
63 )
64{
65 struct lconv *lc;
66 int ret;
67 wchar_t* ctrylocalename;
68 long *lc_refcount;
69 long *lconv_mon_refcount = nullptr;
71
72 locinfo.locinfo = ploci;
73 locinfo.mbcinfo = 0;
74
75 if ( (ploci->locale_name[LC_MONETARY] != nullptr) ||
76 (ploci->locale_name[LC_NUMERIC] != nullptr) )
77 {
78 /*
79 * Allocate structure filled with nullptr pointers
80 */
81 if ((lc = _calloc_crt_t(lconv, 1).detach()) == nullptr)
82 return 1;
83
84 /*
85 * Allocate a new reference counter for the lconv structure
86 */
87 if ( (lc_refcount = _calloc_crt_t(long, 1).detach()) == nullptr )
88 {
89 _free_crt(lc);
90 return 1;
91 }
92
93 if ( ploci->locale_name[LC_MONETARY] != nullptr )
94 {
95 /*
96 * Allocate a new reference counter for the numeric info
97 */
98 if ( (lconv_mon_refcount = _calloc_crt_t(long, 1).detach()) == nullptr )
99 {
100 _free_crt(lc);
101 _free_crt(lc_refcount);
102 return 1;
103 }
104
105 /*
106 * Currency is country--not language--dependent. NT
107 * work-around.
108 */
109 ctrylocalename = ploci->locale_name[LC_MONETARY];
110
111 ret = 0;
112
113 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, ctrylocalename,
114 LOCALE_SINTLSYMBOL, (void *)&lc->int_curr_symbol );
115 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, ctrylocalename,
116 LOCALE_SCURRENCY, (void *)&lc->currency_symbol );
117 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, ctrylocalename,
119 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, ctrylocalename,
121 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, ctrylocalename,
122 LOCALE_SMONGROUPING, (void *)&lc->mon_grouping );
123
124 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, ctrylocalename,
125 LOCALE_SPOSITIVESIGN, (void *)&lc->positive_sign);
126 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_STR_TYPE, ctrylocalename,
127 LOCALE_SNEGATIVESIGN, (void *)&lc->negative_sign);
128
129 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
131 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
132 LOCALE_ICURRDIGITS, (void *)&lc->frac_digits);
133 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
135 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
137 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
139 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
141 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
142 LOCALE_IPOSSIGNPOSN, (void *)&lc->p_sign_posn);
143 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_INT_TYPE, ctrylocalename,
144 LOCALE_INEGSIGNPOSN, (void *)&lc->n_sign_posn);
145
146 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, ctrylocalename,
148 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, ctrylocalename,
149 LOCALE_SCURRENCY, (void *)&lc->_W_currency_symbol );
150 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, ctrylocalename,
152 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, ctrylocalename,
154 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, ctrylocalename,
156 ret |= __acrt_GetLocaleInfoA(&locinfo, LC_WSTR_TYPE, ctrylocalename,
158
159 if ( ret != 0 ) {
161 _free_crt(lc);
162 _free_crt(lc_refcount);
163 _free_crt(lconv_mon_refcount);
164 return 1;
165 }
166
168 }
169 else {
170 /*
171 * C locale for monetary category (the numeric category fields,
172 * which are NOT of the C locale, get fixed up below). Note
173 * that __acrt_lconv_c is copied, rather than directly assigning
174 * the fields of lc because of the uncertainty of the values of
175 * the int_frac_digits,..., n_sign_posn fields (SCHAR_MAX or
176 * UCHAR_MAX, depending on whether or a compliand was built
177 * with -J.
178 */
179 *lc = __acrt_lconv_c;
180 }
181
182 /*
183 * Copy the numeric locale fields from the old struct
184 */
185 lc->decimal_point = ploci->lconv->decimal_point;
186 lc->thousands_sep = ploci->lconv->thousands_sep;
187 lc->grouping = ploci->lconv->grouping;
188 lc->_W_decimal_point = ploci->lconv->_W_decimal_point;
189 lc->_W_thousands_sep = ploci->lconv->_W_thousands_sep;
190
191 *lc_refcount = 1;
192 if (lconv_mon_refcount)
193 *lconv_mon_refcount = 1;
194 }
195 else {
196 /*
197 * C locale for BOTH monetary and numeric categories.
198 */
199 lconv_mon_refcount = nullptr;
200 lc_refcount = nullptr;
201 lc = &__acrt_lconv_c; /* point to new one */
202
203 }
204
205 if ( (ploci->lconv_mon_refcount != nullptr) &&
207 {
208 _ASSERTE(*ploci->lconv_mon_refcount > 0);
209 }
210 if ( (ploci->lconv_intl_refcount != nullptr) &&
212 {
213 _free_crt(ploci->lconv);
215 }
216 ploci->lconv_mon_refcount = lconv_mon_refcount;
217 ploci->lconv_intl_refcount = lc_refcount;
218 ploci->lconv = lc; /* point to new one */
219
220 return 0;
221}
222
223static void fix_grouping(
224 char *grouping
225 )
226{
227 /*
228 * ANSI specifies that the fields should contain "\3" [\3\0] to indicate
229 * thousands groupings (100,000,000.00 for example).
230 * NT uses "3;0"; ASCII 3 instead of value 3 and the ';' is extra.
231 * So here we convert the NT version to the ANSI version.
232 */
233
234 while (*grouping)
235 {
236 /* convert '3' to '\3' */
237 if (*grouping >= '0' && *grouping <= '9')
238 {
239 *grouping = *grouping - '0';
240 grouping++;
241 }
242
243 /* remove ';' */
244 else if (*grouping == ';')
245 {
246 char *tmp = grouping;
247
248 do
249 *tmp = *(tmp+1);
250 while (*++tmp);
251 }
252
253 /* unknown (illegal) character, ignore */
254 else
255 grouping++;
256 }
257}
258
259#endif /* _UCRT_ENCLAVE_BUILD */
260
261/*
262 * Free the lconv monetary strings.
263 * Numeric values do not need to be freed.
264 */
266{
267 if (l == nullptr)
268 return;
269
270 if ( l->int_curr_symbol != __acrt_lconv_c.int_curr_symbol )
271 _free_crt(l->int_curr_symbol);
272
273 if ( l->currency_symbol != __acrt_lconv_c.currency_symbol )
274 _free_crt(l->currency_symbol);
275
276 if ( l->mon_decimal_point != __acrt_lconv_c.mon_decimal_point )
277 _free_crt(l->mon_decimal_point);
278
279 if ( l->mon_thousands_sep != __acrt_lconv_c.mon_thousands_sep )
280 _free_crt(l->mon_thousands_sep);
281
282 if ( l->mon_grouping != __acrt_lconv_c.mon_grouping )
283 _free_crt(l->mon_grouping);
284
285 if ( l->positive_sign != __acrt_lconv_c.positive_sign )
286 _free_crt(l->positive_sign);
287
288 if ( l->negative_sign != __acrt_lconv_c.negative_sign )
289 _free_crt(l->negative_sign);
290
291 if ( l->_W_int_curr_symbol != __acrt_lconv_c._W_int_curr_symbol )
292 _free_crt(l->_W_int_curr_symbol);
293
294 if ( l->_W_currency_symbol != __acrt_lconv_c._W_currency_symbol )
295 _free_crt(l->_W_currency_symbol);
296
297 if ( l->_W_mon_decimal_point != __acrt_lconv_c._W_mon_decimal_point )
298 _free_crt(l->_W_mon_decimal_point);
299
300 if ( l->_W_mon_thousands_sep != __acrt_lconv_c._W_mon_thousands_sep )
301 _free_crt(l->_W_mon_thousands_sep);
302
303 if ( l->_W_positive_sign != __acrt_lconv_c._W_positive_sign )
304 _free_crt(l->_W_positive_sign);
305
306 if ( l->_W_negative_sign != __acrt_lconv_c._W_negative_sign )
307 _free_crt(l->_W_negative_sign);
308}
309
310
311
312} // extern "C"
#define __cdecl
Definition: accygwin.h:79
#define InterlockedDecrement
Definition: armddk.h:52
r l[0]
Definition: byte_order.h:168
#define LC_WSTR_TYPE
#define LC_INT_TYPE
int __cdecl __acrt_GetLocaleInfoA(_In_opt_ _locale_t _Locale, _In_ int _LCType, _In_ LPCWSTR _LocaleName, _In_ LCTYPE _FieldType, _Out_ void *_Address)
#define LC_STR_TYPE
#define _ASSERTE(expr)
Definition: crtdbg.h:114
#define LC_NUMERIC
Definition: locale.h:21
#define LC_MONETARY
Definition: locale.h:20
void __cdecl __acrt_locale_free_monetary(lconv *l)
Definition: initmon.cpp:265
static void fix_grouping(_Inout_z_ char *)
int __cdecl __acrt_locale_initialize_monetary(__crt_locale_data *ploci)
Definition: initmon.cpp:61
#define _free_crt
#define _Inout_z_
Definition: no_sal2.h:166
else locinfo
Definition: scanf.h:159
wchar_t * locale_name[6]
struct lconv * lconv
Definition: locale.h:29
wchar_t * _W_decimal_point
Definition: locale.h:54
char * mon_thousands_sep
Definition: locale.h:36
wchar_t * _W_mon_thousands_sep
Definition: locale.h:59
char p_sign_posn
Definition: locale.h:46
char * int_curr_symbol
Definition: locale.h:33
char p_sep_by_space
Definition: locale.h:43
char * positive_sign
Definition: locale.h:38
char * decimal_point
Definition: locale.h:30
char * grouping
Definition: locale.h:32
wchar_t * _W_thousands_sep
Definition: locale.h:55
char int_frac_digits
Definition: locale.h:40
wchar_t * _W_mon_decimal_point
Definition: locale.h:58
char frac_digits
Definition: locale.h:41
char n_sep_by_space
Definition: locale.h:45
char * mon_grouping
Definition: locale.h:37
char n_cs_precedes
Definition: locale.h:44
char * mon_decimal_point
Definition: locale.h:35
wchar_t * _W_int_curr_symbol
Definition: locale.h:56
char n_sign_posn
Definition: locale.h:47
char * currency_symbol
Definition: locale.h:34
wchar_t * _W_currency_symbol
Definition: locale.h:57
char p_cs_precedes
Definition: locale.h:42
char * thousands_sep
Definition: locale.h:31
wchar_t * _W_positive_sign
Definition: locale.h:60
char * negative_sign
Definition: locale.h:39
wchar_t * _W_negative_sign
Definition: locale.h:61
int ret
#define LOCALE_ICURRDIGITS
Definition: winnls.h:56
#define LOCALE_INEGSEPBYSPACE
Definition: winnls.h:126
#define LOCALE_INEGSIGNPOSN
Definition: winnls.h:122
#define LOCALE_IINTLCURRDIGITS
Definition: winnls.h:57
#define LOCALE_IPOSSYMPRECEDES
Definition: winnls.h:123
#define LOCALE_SPOSITIVESIGN
Definition: winnls.h:119
#define LOCALE_SMONDECIMALSEP
Definition: winnls.h:53
#define LOCALE_INEGSYMPRECEDES
Definition: winnls.h:125
#define LOCALE_SMONTHOUSANDSEP
Definition: winnls.h:54
#define LOCALE_IPOSSIGNPOSN
Definition: winnls.h:121
#define LOCALE_SNEGATIVESIGN
Definition: winnls.h:120
#define LOCALE_SINTLSYMBOL
Definition: winnls.h:52
#define LOCALE_SMONGROUPING
Definition: winnls.h:55
#define LOCALE_SCURRENCY
Definition: winnls.h:51
#define LOCALE_IPOSSEPBYSPACE
Definition: winnls.h:124