This source file includes following definitions.
- setlocale_null_androidfix
- setlocale_null_unlocked
- __declspec
- setlocale_null_with_lock
- setlocale_null_with_lock
- setlocale_null_r
- setlocale_null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include "setlocale_null.h"
23
24 #include <errno.h>
25 #include <locale.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #if defined _WIN32 && !defined __CYGWIN__
29 # include <wchar.h>
30 #endif
31
32 #if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
33 # if defined _WIN32 && !defined __CYGWIN__
34
35 # define WIN32_LEAN_AND_MEAN
36 # include <windows.h>
37
38 # elif HAVE_PTHREAD_API
39
40 # include <pthread.h>
41 # if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
42 # include <threads.h>
43 # pragma weak thrd_exit
44 # define c11_threads_in_use() (thrd_exit != NULL)
45 # else
46 # define c11_threads_in_use() 0
47 # endif
48
49 # elif HAVE_THREADS_H
50
51 # include <threads.h>
52
53 # endif
54 #endif
55
56
57 #undef setlocale
58
59 static const char *
60 setlocale_null_androidfix (int category)
61 {
62 const char *result = setlocale (category, NULL);
63
64 #ifdef __ANDROID__
65 if (result == NULL)
66 switch (category)
67 {
68 case LC_CTYPE:
69 case LC_NUMERIC:
70 case LC_TIME:
71 case LC_COLLATE:
72 case LC_MONETARY:
73 case LC_MESSAGES:
74 case LC_ALL:
75 case LC_PAPER:
76 case LC_NAME:
77 case LC_ADDRESS:
78 case LC_TELEPHONE:
79 case LC_MEASUREMENT:
80 result = "C";
81 break;
82 default:
83 break;
84 }
85 #endif
86
87 return result;
88 }
89
90 static int
91 setlocale_null_unlocked (int category, char *buf, size_t bufsize)
92 {
93 #if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER
94
95
96
97 const wchar_t *result = _wsetlocale (category, NULL);
98
99 if (result == NULL)
100 {
101
102 if (bufsize > 0)
103
104
105
106 buf[0] = '\0';
107 return EINVAL;
108 }
109 else
110 {
111 size_t length = wcslen (result);
112 if (length < bufsize)
113 {
114 size_t i;
115
116
117 for (i = 0; i <= length; i++)
118 buf[i] = result[i];
119
120 return 0;
121 }
122 else
123 {
124 if (bufsize > 0)
125 {
126
127
128
129 size_t i;
130
131
132 for (i = 0; i < bufsize; i++)
133 buf[i] = result[i];
134 buf[bufsize - 1] = '\0';
135 }
136 return ERANGE;
137 }
138 }
139 #else
140 const char *result = setlocale_null_androidfix (category);
141
142 if (result == NULL)
143 {
144
145 if (bufsize > 0)
146
147
148
149 buf[0] = '\0';
150 return EINVAL;
151 }
152 else
153 {
154 size_t length = strlen (result);
155 if (length < bufsize)
156 {
157 memcpy (buf, result, length + 1);
158 return 0;
159 }
160 else
161 {
162 if (bufsize > 0)
163 {
164
165
166
167 memcpy (buf, result, bufsize - 1);
168 buf[bufsize - 1] = '\0';
169 }
170 return ERANGE;
171 }
172 }
173 #endif
174 }
175
176 #if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
177
178
179
180
181
182 # undef gl_get_setlocale_null_lock
183
184 # if defined _WIN32 && !defined __CYGWIN__
185
186 extern __declspec(dllimport) CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
187
188 static int
189 setlocale_null_with_lock (int category, char *buf, size_t bufsize)
190 {
191 CRITICAL_SECTION *lock = gl_get_setlocale_null_lock ();
192 int ret;
193
194 EnterCriticalSection (lock);
195 ret = setlocale_null_unlocked (category, buf, bufsize);
196 LeaveCriticalSection (lock);
197
198 return ret;
199 }
200
201 # elif HAVE_PTHREAD_API
202
203 extern
204 # if defined _WIN32 || defined __CYGWIN__
205 __declspec(dllimport)
206 # endif
207 pthread_mutex_t *gl_get_setlocale_null_lock (void);
208
209 # if HAVE_WEAK_SYMBOLS
210
211
212 # pragma weak pthread_mutex_lock
213 # pragma weak pthread_mutex_unlock
214
215
216 # pragma weak pthread_mutexattr_gettype
217
218 # define pthread_in_use() \
219 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
220
221 # else
222 # define pthread_in_use() 1
223 # endif
224
225 static int
226 setlocale_null_with_lock (int category, char *buf, size_t bufsize)
227 {
228 if (pthread_in_use())
229 {
230 pthread_mutex_t *lock = gl_get_setlocale_null_lock ();
231 int ret;
232
233 if (pthread_mutex_lock (lock))
234 abort ();
235 ret = setlocale_null_unlocked (category, buf, bufsize);
236 if (pthread_mutex_unlock (lock))
237 abort ();
238
239 return ret;
240 }
241 else
242 return setlocale_null_unlocked (category, buf, bufsize);
243 }
244
245 # elif HAVE_THREADS_H
246
247 extern mtx_t *gl_get_setlocale_null_lock (void);
248
249 static int
250 setlocale_null_with_lock (int category, char *buf, size_t bufsize)
251 {
252 mtx_t *lock = gl_get_setlocale_null_lock ();
253 int ret;
254
255 if (mtx_lock (lock) != thrd_success)
256 abort ();
257 ret = setlocale_null_unlocked (category, buf, bufsize);
258 if (mtx_unlock (lock) != thrd_success)
259 abort ();
260
261 return ret;
262 }
263
264 # endif
265
266 #endif
267
268 int
269 setlocale_null_r (int category, char *buf, size_t bufsize)
270 {
271 #if SETLOCALE_NULL_ALL_MTSAFE
272 # if SETLOCALE_NULL_ONE_MTSAFE
273
274 return setlocale_null_unlocked (category, buf, bufsize);
275
276 # else
277
278 if (category == LC_ALL)
279 return setlocale_null_unlocked (category, buf, bufsize);
280 else
281 return setlocale_null_with_lock (category, buf, bufsize);
282
283 # endif
284 #else
285 # if SETLOCALE_NULL_ONE_MTSAFE
286
287 if (category == LC_ALL)
288 return setlocale_null_with_lock (category, buf, bufsize);
289 else
290 return setlocale_null_unlocked (category, buf, bufsize);
291
292 # else
293
294 return setlocale_null_with_lock (category, buf, bufsize);
295
296 # endif
297 #endif
298 }
299
300 const char *
301 setlocale_null (int category)
302 {
303 #if SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE
304 return setlocale_null_androidfix (category);
305 #else
306
307
308
309
310
311
312
313
314
315
316
317 if (category == LC_ALL)
318 {
319 # if SETLOCALE_NULL_ALL_MTSAFE
320 return setlocale_null_androidfix (LC_ALL);
321 # else
322 char buf[SETLOCALE_NULL_ALL_MAX];
323 static char resultbuf[SETLOCALE_NULL_ALL_MAX];
324
325 if (setlocale_null_r (LC_ALL, buf, sizeof (buf)))
326 return "C";
327 strcpy (resultbuf, buf);
328 return resultbuf;
329 # endif
330 }
331 else
332 {
333 # if SETLOCALE_NULL_ONE_MTSAFE
334 return setlocale_null_androidfix (category);
335 # else
336 enum
337 {
338 LC_CTYPE_INDEX,
339 LC_NUMERIC_INDEX,
340 LC_TIME_INDEX,
341 LC_COLLATE_INDEX,
342 LC_MONETARY_INDEX,
343 LC_MESSAGES_INDEX,
344 # ifdef LC_PAPER
345 LC_PAPER_INDEX,
346 # endif
347 # ifdef LC_NAME
348 LC_NAME_INDEX,
349 # endif
350 # ifdef LC_ADDRESS
351 LC_ADDRESS_INDEX,
352 # endif
353 # ifdef LC_TELEPHONE
354 LC_TELEPHONE_INDEX,
355 # endif
356 # ifdef LC_MEASUREMENT
357 LC_MEASUREMENT_INDEX,
358 # endif
359 # ifdef LC_IDENTIFICATION
360 LC_IDENTIFICATION_INDEX,
361 # endif
362 LC_INDICES_COUNT
363 }
364 i;
365 char buf[SETLOCALE_NULL_MAX];
366 static char resultbuf[LC_INDICES_COUNT][SETLOCALE_NULL_MAX];
367 int err;
368
369 err = setlocale_null_r (category, buf, sizeof (buf));
370 if (err == EINVAL)
371 return NULL;
372 if (err)
373 return "C";
374
375 switch (category)
376 {
377 case LC_CTYPE: i = LC_CTYPE_INDEX; break;
378 case LC_NUMERIC: i = LC_NUMERIC_INDEX; break;
379 case LC_TIME: i = LC_TIME_INDEX; break;
380 case LC_COLLATE: i = LC_COLLATE_INDEX; break;
381 case LC_MONETARY: i = LC_MONETARY_INDEX; break;
382 case LC_MESSAGES: i = LC_MESSAGES_INDEX; break;
383 # ifdef LC_PAPER
384 case LC_PAPER: i = LC_PAPER_INDEX; break;
385 # endif
386 # ifdef LC_NAME
387 case LC_NAME: i = LC_NAME_INDEX; break;
388 # endif
389 # ifdef LC_ADDRESS
390 case LC_ADDRESS: i = LC_ADDRESS_INDEX; break;
391 # endif
392 # ifdef LC_TELEPHONE
393 case LC_TELEPHONE: i = LC_TELEPHONE_INDEX; break;
394 # endif
395 # ifdef LC_MEASUREMENT
396 case LC_MEASUREMENT: i = LC_MEASUREMENT_INDEX; break;
397 # endif
398 # ifdef LC_IDENTIFICATION
399 case LC_IDENTIFICATION: i = LC_IDENTIFICATION_INDEX; break;
400 # endif
401 default:
402
403 abort ();
404 }
405
406 strcpy (resultbuf[i], buf);
407 return resultbuf[i];
408 # endif
409 }
410 #endif
411 }