/src/Python-3.8.3/Modules/_localemodule.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*********************************************************** |
2 | | Copyright (C) 1997, 2002, 2003, 2007, 2008 Martin von Loewis |
3 | | |
4 | | Permission to use, copy, modify, and distribute this software and its |
5 | | documentation for any purpose and without fee is hereby granted, |
6 | | provided that the above copyright notice appear in all copies. |
7 | | |
8 | | This software comes with no warranty. Use at your own risk. |
9 | | |
10 | | ******************************************************************/ |
11 | | |
12 | | #define PY_SSIZE_T_CLEAN |
13 | | #include "Python.h" |
14 | | #include "pycore_fileutils.h" |
15 | | |
16 | | #include <stdio.h> |
17 | | #include <locale.h> |
18 | | #include <string.h> |
19 | | #include <ctype.h> |
20 | | |
21 | | #ifdef HAVE_ERRNO_H |
22 | | #include <errno.h> |
23 | | #endif |
24 | | |
25 | | #ifdef HAVE_LANGINFO_H |
26 | | #include <langinfo.h> |
27 | | #endif |
28 | | |
29 | | #ifdef HAVE_LIBINTL_H |
30 | | #include <libintl.h> |
31 | | #endif |
32 | | |
33 | | #ifdef HAVE_WCHAR_H |
34 | | #include <wchar.h> |
35 | | #endif |
36 | | |
37 | | #if defined(MS_WINDOWS) |
38 | | #define WIN32_LEAN_AND_MEAN |
39 | | #include <windows.h> |
40 | | #endif |
41 | | |
42 | | PyDoc_STRVAR(locale__doc__, "Support for POSIX locales."); |
43 | | |
44 | | static PyObject *Error; |
45 | | |
46 | | /* support functions for formatting floating point numbers */ |
47 | | |
48 | | PyDoc_STRVAR(setlocale__doc__, |
49 | | "(integer,string=None) -> string. Activates/queries locale processing."); |
50 | | |
51 | | /* the grouping is terminated by either 0 or CHAR_MAX */ |
52 | | static PyObject* |
53 | | copy_grouping(const char* s) |
54 | 0 | { |
55 | 0 | int i; |
56 | 0 | PyObject *result, *val = NULL; |
57 | |
|
58 | 0 | if (s[0] == '\0') { |
59 | | /* empty string: no grouping at all */ |
60 | 0 | return PyList_New(0); |
61 | 0 | } |
62 | | |
63 | 0 | for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++) |
64 | 0 | ; /* nothing */ |
65 | |
|
66 | 0 | result = PyList_New(i+1); |
67 | 0 | if (!result) |
68 | 0 | return NULL; |
69 | | |
70 | 0 | i = -1; |
71 | 0 | do { |
72 | 0 | i++; |
73 | 0 | val = PyLong_FromLong(s[i]); |
74 | 0 | if (val == NULL) { |
75 | 0 | Py_DECREF(result); |
76 | 0 | return NULL; |
77 | 0 | } |
78 | 0 | PyList_SET_ITEM(result, i, val); |
79 | 0 | } while (s[i] != '\0' && s[i] != CHAR_MAX); |
80 | | |
81 | 0 | return result; |
82 | 0 | } |
83 | | |
84 | | static PyObject* |
85 | | PyLocale_setlocale(PyObject* self, PyObject* args) |
86 | 0 | { |
87 | 0 | int category; |
88 | 0 | char *locale = NULL, *result; |
89 | 0 | PyObject *result_object; |
90 | |
|
91 | 0 | if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale)) |
92 | 0 | return NULL; |
93 | | |
94 | | #if defined(MS_WINDOWS) |
95 | | if (category < LC_MIN || category > LC_MAX) |
96 | | { |
97 | | PyErr_SetString(Error, "invalid locale category"); |
98 | | return NULL; |
99 | | } |
100 | | #endif |
101 | | |
102 | 0 | if (locale) { |
103 | | /* set locale */ |
104 | 0 | result = setlocale(category, locale); |
105 | 0 | if (!result) { |
106 | | /* operation failed, no setting was changed */ |
107 | 0 | PyErr_SetString(Error, "unsupported locale setting"); |
108 | 0 | return NULL; |
109 | 0 | } |
110 | 0 | result_object = PyUnicode_DecodeLocale(result, NULL); |
111 | 0 | if (!result_object) |
112 | 0 | return NULL; |
113 | 0 | } else { |
114 | | /* get locale */ |
115 | 0 | result = setlocale(category, NULL); |
116 | 0 | if (!result) { |
117 | 0 | PyErr_SetString(Error, "locale query failed"); |
118 | 0 | return NULL; |
119 | 0 | } |
120 | 0 | result_object = PyUnicode_DecodeLocale(result, NULL); |
121 | 0 | } |
122 | 0 | return result_object; |
123 | 0 | } |
124 | | |
125 | | static int |
126 | | locale_is_ascii(const char *str) |
127 | 0 | { |
128 | 0 | return (strlen(str) == 1 && ((unsigned char)str[0]) <= 127); |
129 | 0 | } |
130 | | |
131 | | static int |
132 | | locale_decode_monetary(PyObject *dict, struct lconv *lc) |
133 | 0 | { |
134 | 0 | int change_locale; |
135 | 0 | change_locale = (!locale_is_ascii(lc->int_curr_symbol) |
136 | 0 | || !locale_is_ascii(lc->currency_symbol) |
137 | 0 | || !locale_is_ascii(lc->mon_decimal_point) |
138 | 0 | || !locale_is_ascii(lc->mon_thousands_sep)); |
139 | | |
140 | | /* Keep a copy of the LC_CTYPE locale */ |
141 | 0 | char *oldloc = NULL, *loc = NULL; |
142 | 0 | if (change_locale) { |
143 | 0 | oldloc = setlocale(LC_CTYPE, NULL); |
144 | 0 | if (!oldloc) { |
145 | 0 | PyErr_SetString(PyExc_RuntimeWarning, |
146 | 0 | "failed to get LC_CTYPE locale"); |
147 | 0 | return -1; |
148 | 0 | } |
149 | | |
150 | 0 | oldloc = _PyMem_Strdup(oldloc); |
151 | 0 | if (!oldloc) { |
152 | 0 | PyErr_NoMemory(); |
153 | 0 | return -1; |
154 | 0 | } |
155 | | |
156 | 0 | loc = setlocale(LC_MONETARY, NULL); |
157 | 0 | if (loc != NULL && strcmp(loc, oldloc) == 0) { |
158 | 0 | loc = NULL; |
159 | 0 | } |
160 | |
|
161 | 0 | if (loc != NULL) { |
162 | | /* Only set the locale temporarily the LC_CTYPE locale |
163 | | to the LC_MONETARY locale if the two locales are different and |
164 | | at least one string is non-ASCII. */ |
165 | 0 | setlocale(LC_CTYPE, loc); |
166 | 0 | } |
167 | 0 | } |
168 | | |
169 | 0 | int res = -1; |
170 | |
|
171 | 0 | #define RESULT_STRING(ATTR) \ |
172 | 0 | do { \ |
173 | 0 | PyObject *obj; \ |
174 | 0 | obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \ |
175 | 0 | if (obj == NULL) { \ |
176 | 0 | goto done; \ |
177 | 0 | } \ |
178 | 0 | if (PyDict_SetItemString(dict, Py_STRINGIFY(ATTR), obj) < 0) { \ |
179 | 0 | Py_DECREF(obj); \ |
180 | 0 | goto done; \ |
181 | 0 | } \ |
182 | 0 | Py_DECREF(obj); \ |
183 | 0 | } while (0) |
184 | |
|
185 | 0 | RESULT_STRING(int_curr_symbol); |
186 | 0 | RESULT_STRING(currency_symbol); |
187 | 0 | RESULT_STRING(mon_decimal_point); |
188 | 0 | RESULT_STRING(mon_thousands_sep); |
189 | 0 | #undef RESULT_STRING |
190 | | |
191 | 0 | res = 0; |
192 | |
|
193 | 0 | done: |
194 | 0 | if (loc != NULL) { |
195 | 0 | setlocale(LC_CTYPE, oldloc); |
196 | 0 | } |
197 | 0 | PyMem_Free(oldloc); |
198 | 0 | return res; |
199 | 0 | } |
200 | | |
201 | | PyDoc_STRVAR(localeconv__doc__, |
202 | | "() -> dict. Returns numeric and monetary locale-specific parameters."); |
203 | | |
204 | | static PyObject* |
205 | | PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored)) |
206 | 0 | { |
207 | 0 | PyObject* result; |
208 | 0 | struct lconv *lc; |
209 | 0 | PyObject *x; |
210 | |
|
211 | 0 | result = PyDict_New(); |
212 | 0 | if (!result) { |
213 | 0 | return NULL; |
214 | 0 | } |
215 | | |
216 | | /* if LC_NUMERIC is different in the C library, use saved value */ |
217 | 0 | lc = localeconv(); |
218 | | |
219 | | /* hopefully, the localeconv result survives the C library calls |
220 | | involved herein */ |
221 | |
|
222 | 0 | #define RESULT(key, obj)\ |
223 | 0 | do { \ |
224 | 0 | if (obj == NULL) \ |
225 | 0 | goto failed; \ |
226 | 0 | if (PyDict_SetItemString(result, key, obj) < 0) { \ |
227 | 0 | Py_DECREF(obj); \ |
228 | 0 | goto failed; \ |
229 | 0 | } \ |
230 | 0 | Py_DECREF(obj); \ |
231 | 0 | } while (0) |
232 | |
|
233 | 0 | #define RESULT_STRING(s)\ |
234 | 0 | do { \ |
235 | 0 | x = PyUnicode_DecodeLocale(lc->s, NULL); \ |
236 | 0 | RESULT(#s, x); \ |
237 | 0 | } while (0) |
238 | |
|
239 | 0 | #define RESULT_INT(i)\ |
240 | 0 | do { \ |
241 | 0 | x = PyLong_FromLong(lc->i); \ |
242 | 0 | RESULT(#i, x); \ |
243 | 0 | } while (0) |
244 | | |
245 | | /* Monetary information: LC_MONETARY encoding */ |
246 | 0 | if (locale_decode_monetary(result, lc) < 0) { |
247 | 0 | goto failed; |
248 | 0 | } |
249 | 0 | x = copy_grouping(lc->mon_grouping); |
250 | 0 | RESULT("mon_grouping", x); |
251 | | |
252 | 0 | RESULT_STRING(positive_sign); |
253 | 0 | RESULT_STRING(negative_sign); |
254 | 0 | RESULT_INT(int_frac_digits); |
255 | 0 | RESULT_INT(frac_digits); |
256 | 0 | RESULT_INT(p_cs_precedes); |
257 | 0 | RESULT_INT(p_sep_by_space); |
258 | 0 | RESULT_INT(n_cs_precedes); |
259 | 0 | RESULT_INT(n_sep_by_space); |
260 | 0 | RESULT_INT(p_sign_posn); |
261 | 0 | RESULT_INT(n_sign_posn); |
262 | | |
263 | | /* Numeric information: LC_NUMERIC encoding */ |
264 | 0 | PyObject *decimal_point, *thousands_sep; |
265 | 0 | if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) { |
266 | 0 | goto failed; |
267 | 0 | } |
268 | | |
269 | 0 | if (PyDict_SetItemString(result, "decimal_point", decimal_point) < 0) { |
270 | 0 | Py_DECREF(decimal_point); |
271 | 0 | Py_DECREF(thousands_sep); |
272 | 0 | goto failed; |
273 | 0 | } |
274 | 0 | Py_DECREF(decimal_point); |
275 | |
|
276 | 0 | if (PyDict_SetItemString(result, "thousands_sep", thousands_sep) < 0) { |
277 | 0 | Py_DECREF(thousands_sep); |
278 | 0 | goto failed; |
279 | 0 | } |
280 | 0 | Py_DECREF(thousands_sep); |
281 | |
|
282 | 0 | x = copy_grouping(lc->grouping); |
283 | 0 | RESULT("grouping", x); |
284 | | |
285 | 0 | return result; |
286 | | |
287 | 0 | failed: |
288 | 0 | Py_DECREF(result); |
289 | 0 | return NULL; |
290 | |
|
291 | 0 | #undef RESULT |
292 | 0 | #undef RESULT_STRING |
293 | 0 | #undef RESULT_INT |
294 | 0 | } |
295 | | |
296 | | #if defined(HAVE_WCSCOLL) |
297 | | PyDoc_STRVAR(strcoll__doc__, |
298 | | "string,string -> int. Compares two strings according to the locale."); |
299 | | |
300 | | static PyObject* |
301 | | PyLocale_strcoll(PyObject* self, PyObject* args) |
302 | 0 | { |
303 | 0 | PyObject *os1, *os2, *result = NULL; |
304 | 0 | wchar_t *ws1 = NULL, *ws2 = NULL; |
305 | |
|
306 | 0 | if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2)) |
307 | 0 | return NULL; |
308 | | /* Convert the unicode strings to wchar[]. */ |
309 | 0 | ws1 = PyUnicode_AsWideCharString(os1, NULL); |
310 | 0 | if (ws1 == NULL) |
311 | 0 | goto done; |
312 | 0 | ws2 = PyUnicode_AsWideCharString(os2, NULL); |
313 | 0 | if (ws2 == NULL) |
314 | 0 | goto done; |
315 | | /* Collate the strings. */ |
316 | 0 | result = PyLong_FromLong(wcscoll(ws1, ws2)); |
317 | 0 | done: |
318 | | /* Deallocate everything. */ |
319 | 0 | if (ws1) PyMem_FREE(ws1); |
320 | 0 | if (ws2) PyMem_FREE(ws2); |
321 | 0 | return result; |
322 | 0 | } |
323 | | #endif |
324 | | |
325 | | #ifdef HAVE_WCSXFRM |
326 | | PyDoc_STRVAR(strxfrm__doc__, |
327 | | "strxfrm(string) -> string.\n\ |
328 | | \n\ |
329 | | Return a string that can be used as a key for locale-aware comparisons."); |
330 | | |
331 | | static PyObject* |
332 | | PyLocale_strxfrm(PyObject* self, PyObject* args) |
333 | 0 | { |
334 | 0 | PyObject *str; |
335 | 0 | Py_ssize_t n1; |
336 | 0 | wchar_t *s = NULL, *buf = NULL; |
337 | 0 | size_t n2; |
338 | 0 | PyObject *result = NULL; |
339 | |
|
340 | 0 | if (!PyArg_ParseTuple(args, "U:strxfrm", &str)) |
341 | 0 | return NULL; |
342 | | |
343 | 0 | s = PyUnicode_AsWideCharString(str, &n1); |
344 | 0 | if (s == NULL) |
345 | 0 | goto exit; |
346 | 0 | if (wcslen(s) != (size_t)n1) { |
347 | 0 | PyErr_SetString(PyExc_ValueError, |
348 | 0 | "embedded null character"); |
349 | 0 | goto exit; |
350 | 0 | } |
351 | | |
352 | | /* assume no change in size, first */ |
353 | 0 | n1 = n1 + 1; |
354 | 0 | buf = PyMem_New(wchar_t, n1); |
355 | 0 | if (!buf) { |
356 | 0 | PyErr_NoMemory(); |
357 | 0 | goto exit; |
358 | 0 | } |
359 | 0 | errno = 0; |
360 | 0 | n2 = wcsxfrm(buf, s, n1); |
361 | 0 | if (errno && errno != ERANGE) { |
362 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
363 | 0 | goto exit; |
364 | 0 | } |
365 | 0 | if (n2 >= (size_t)n1) { |
366 | | /* more space needed */ |
367 | 0 | wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t)); |
368 | 0 | if (!new_buf) { |
369 | 0 | PyErr_NoMemory(); |
370 | 0 | goto exit; |
371 | 0 | } |
372 | 0 | buf = new_buf; |
373 | 0 | errno = 0; |
374 | 0 | n2 = wcsxfrm(buf, s, n2+1); |
375 | 0 | if (errno) { |
376 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
377 | 0 | goto exit; |
378 | 0 | } |
379 | 0 | } |
380 | 0 | result = PyUnicode_FromWideChar(buf, n2); |
381 | 0 | exit: |
382 | 0 | PyMem_Free(buf); |
383 | 0 | PyMem_Free(s); |
384 | 0 | return result; |
385 | 0 | } |
386 | | #endif |
387 | | |
388 | | #if defined(MS_WINDOWS) |
389 | | static PyObject* |
390 | | PyLocale_getdefaultlocale(PyObject* self, PyObject *Py_UNUSED(ignored)) |
391 | | { |
392 | | char encoding[20]; |
393 | | char locale[100]; |
394 | | |
395 | | PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); |
396 | | |
397 | | if (GetLocaleInfo(LOCALE_USER_DEFAULT, |
398 | | LOCALE_SISO639LANGNAME, |
399 | | locale, sizeof(locale))) { |
400 | | Py_ssize_t i = strlen(locale); |
401 | | locale[i++] = '_'; |
402 | | if (GetLocaleInfo(LOCALE_USER_DEFAULT, |
403 | | LOCALE_SISO3166CTRYNAME, |
404 | | locale+i, (int)(sizeof(locale)-i))) |
405 | | return Py_BuildValue("ss", locale, encoding); |
406 | | } |
407 | | |
408 | | /* If we end up here, this windows version didn't know about |
409 | | ISO639/ISO3166 names (it's probably Windows 95). Return the |
410 | | Windows language identifier instead (a hexadecimal number) */ |
411 | | |
412 | | locale[0] = '0'; |
413 | | locale[1] = 'x'; |
414 | | if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE, |
415 | | locale+2, sizeof(locale)-2)) { |
416 | | return Py_BuildValue("ss", locale, encoding); |
417 | | } |
418 | | |
419 | | /* cannot determine the language code (very unlikely) */ |
420 | | Py_INCREF(Py_None); |
421 | | return Py_BuildValue("Os", Py_None, encoding); |
422 | | } |
423 | | #endif |
424 | | |
425 | | #ifdef HAVE_LANGINFO_H |
426 | | #define LANGINFO(X) {#X, X} |
427 | | static struct langinfo_constant{ |
428 | | char* name; |
429 | | int value; |
430 | | } langinfo_constants[] = |
431 | | { |
432 | | /* These constants should exist on any langinfo implementation */ |
433 | | LANGINFO(DAY_1), |
434 | | LANGINFO(DAY_2), |
435 | | LANGINFO(DAY_3), |
436 | | LANGINFO(DAY_4), |
437 | | LANGINFO(DAY_5), |
438 | | LANGINFO(DAY_6), |
439 | | LANGINFO(DAY_7), |
440 | | |
441 | | LANGINFO(ABDAY_1), |
442 | | LANGINFO(ABDAY_2), |
443 | | LANGINFO(ABDAY_3), |
444 | | LANGINFO(ABDAY_4), |
445 | | LANGINFO(ABDAY_5), |
446 | | LANGINFO(ABDAY_6), |
447 | | LANGINFO(ABDAY_7), |
448 | | |
449 | | LANGINFO(MON_1), |
450 | | LANGINFO(MON_2), |
451 | | LANGINFO(MON_3), |
452 | | LANGINFO(MON_4), |
453 | | LANGINFO(MON_5), |
454 | | LANGINFO(MON_6), |
455 | | LANGINFO(MON_7), |
456 | | LANGINFO(MON_8), |
457 | | LANGINFO(MON_9), |
458 | | LANGINFO(MON_10), |
459 | | LANGINFO(MON_11), |
460 | | LANGINFO(MON_12), |
461 | | |
462 | | LANGINFO(ABMON_1), |
463 | | LANGINFO(ABMON_2), |
464 | | LANGINFO(ABMON_3), |
465 | | LANGINFO(ABMON_4), |
466 | | LANGINFO(ABMON_5), |
467 | | LANGINFO(ABMON_6), |
468 | | LANGINFO(ABMON_7), |
469 | | LANGINFO(ABMON_8), |
470 | | LANGINFO(ABMON_9), |
471 | | LANGINFO(ABMON_10), |
472 | | LANGINFO(ABMON_11), |
473 | | LANGINFO(ABMON_12), |
474 | | |
475 | | #ifdef RADIXCHAR |
476 | | /* The following are not available with glibc 2.0 */ |
477 | | LANGINFO(RADIXCHAR), |
478 | | LANGINFO(THOUSEP), |
479 | | /* YESSTR and NOSTR are deprecated in glibc, since they are |
480 | | a special case of message translation, which should be rather |
481 | | done using gettext. So we don't expose it to Python in the |
482 | | first place. |
483 | | LANGINFO(YESSTR), |
484 | | LANGINFO(NOSTR), |
485 | | */ |
486 | | LANGINFO(CRNCYSTR), |
487 | | #endif |
488 | | |
489 | | LANGINFO(D_T_FMT), |
490 | | LANGINFO(D_FMT), |
491 | | LANGINFO(T_FMT), |
492 | | LANGINFO(AM_STR), |
493 | | LANGINFO(PM_STR), |
494 | | |
495 | | /* The following constants are available only with XPG4, but... |
496 | | AIX 3.2. only has CODESET. |
497 | | OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have |
498 | | a few of the others. |
499 | | Solution: ifdef-test them all. */ |
500 | | #ifdef CODESET |
501 | | LANGINFO(CODESET), |
502 | | #endif |
503 | | #ifdef T_FMT_AMPM |
504 | | LANGINFO(T_FMT_AMPM), |
505 | | #endif |
506 | | #ifdef ERA |
507 | | LANGINFO(ERA), |
508 | | #endif |
509 | | #ifdef ERA_D_FMT |
510 | | LANGINFO(ERA_D_FMT), |
511 | | #endif |
512 | | #ifdef ERA_D_T_FMT |
513 | | LANGINFO(ERA_D_T_FMT), |
514 | | #endif |
515 | | #ifdef ERA_T_FMT |
516 | | LANGINFO(ERA_T_FMT), |
517 | | #endif |
518 | | #ifdef ALT_DIGITS |
519 | | LANGINFO(ALT_DIGITS), |
520 | | #endif |
521 | | #ifdef YESEXPR |
522 | | LANGINFO(YESEXPR), |
523 | | #endif |
524 | | #ifdef NOEXPR |
525 | | LANGINFO(NOEXPR), |
526 | | #endif |
527 | | #ifdef _DATE_FMT |
528 | | /* This is not available in all glibc versions that have CODESET. */ |
529 | | LANGINFO(_DATE_FMT), |
530 | | #endif |
531 | | {0, 0} |
532 | | }; |
533 | | |
534 | | PyDoc_STRVAR(nl_langinfo__doc__, |
535 | | "nl_langinfo(key) -> string\n" |
536 | | "Return the value for the locale information associated with key."); |
537 | | |
538 | | static PyObject* |
539 | | PyLocale_nl_langinfo(PyObject* self, PyObject* args) |
540 | 0 | { |
541 | 0 | int item, i; |
542 | 0 | if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item)) |
543 | 0 | return NULL; |
544 | | /* Check whether this is a supported constant. GNU libc sometimes |
545 | | returns numeric values in the char* return value, which would |
546 | | crash PyUnicode_FromString. */ |
547 | 0 | for (i = 0; langinfo_constants[i].name; i++) |
548 | 0 | if (langinfo_constants[i].value == item) { |
549 | | /* Check NULL as a workaround for GNU libc's returning NULL |
550 | | instead of an empty string for nl_langinfo(ERA). */ |
551 | 0 | const char *result = nl_langinfo(item); |
552 | 0 | result = result != NULL ? result : ""; |
553 | 0 | return PyUnicode_DecodeLocale(result, NULL); |
554 | 0 | } |
555 | 0 | PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant"); |
556 | 0 | return NULL; |
557 | 0 | } |
558 | | #endif /* HAVE_LANGINFO_H */ |
559 | | |
560 | | #ifdef HAVE_LIBINTL_H |
561 | | |
562 | | PyDoc_STRVAR(gettext__doc__, |
563 | | "gettext(msg) -> string\n" |
564 | | "Return translation of msg."); |
565 | | |
566 | | static PyObject* |
567 | | PyIntl_gettext(PyObject* self, PyObject *args) |
568 | 0 | { |
569 | 0 | char *in; |
570 | 0 | if (!PyArg_ParseTuple(args, "s", &in)) |
571 | 0 | return 0; |
572 | 0 | return PyUnicode_DecodeLocale(gettext(in), NULL); |
573 | 0 | } |
574 | | |
575 | | PyDoc_STRVAR(dgettext__doc__, |
576 | | "dgettext(domain, msg) -> string\n" |
577 | | "Return translation of msg in domain."); |
578 | | |
579 | | static PyObject* |
580 | | PyIntl_dgettext(PyObject* self, PyObject *args) |
581 | 0 | { |
582 | 0 | char *domain, *in; |
583 | 0 | if (!PyArg_ParseTuple(args, "zs", &domain, &in)) |
584 | 0 | return 0; |
585 | 0 | return PyUnicode_DecodeLocale(dgettext(domain, in), NULL); |
586 | 0 | } |
587 | | |
588 | | PyDoc_STRVAR(dcgettext__doc__, |
589 | | "dcgettext(domain, msg, category) -> string\n" |
590 | | "Return translation of msg in domain and category."); |
591 | | |
592 | | static PyObject* |
593 | | PyIntl_dcgettext(PyObject *self, PyObject *args) |
594 | 0 | { |
595 | 0 | char *domain, *msgid; |
596 | 0 | int category; |
597 | 0 | if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category)) |
598 | 0 | return 0; |
599 | 0 | return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL); |
600 | 0 | } |
601 | | |
602 | | PyDoc_STRVAR(textdomain__doc__, |
603 | | "textdomain(domain) -> string\n" |
604 | | "Set the C library's textdmain to domain, returning the new domain."); |
605 | | |
606 | | static PyObject* |
607 | | PyIntl_textdomain(PyObject* self, PyObject* args) |
608 | 0 | { |
609 | 0 | char *domain; |
610 | 0 | if (!PyArg_ParseTuple(args, "z", &domain)) |
611 | 0 | return 0; |
612 | 0 | domain = textdomain(domain); |
613 | 0 | if (!domain) { |
614 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
615 | 0 | return NULL; |
616 | 0 | } |
617 | 0 | return PyUnicode_DecodeLocale(domain, NULL); |
618 | 0 | } |
619 | | |
620 | | PyDoc_STRVAR(bindtextdomain__doc__, |
621 | | "bindtextdomain(domain, dir) -> string\n" |
622 | | "Bind the C library's domain to dir."); |
623 | | |
624 | | static PyObject* |
625 | | PyIntl_bindtextdomain(PyObject* self,PyObject*args) |
626 | 0 | { |
627 | 0 | char *domain, *dirname, *current_dirname; |
628 | 0 | PyObject *dirname_obj, *dirname_bytes = NULL, *result; |
629 | 0 | if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj)) |
630 | 0 | return 0; |
631 | 0 | if (!strlen(domain)) { |
632 | 0 | PyErr_SetString(Error, "domain must be a non-empty string"); |
633 | 0 | return 0; |
634 | 0 | } |
635 | 0 | if (dirname_obj != Py_None) { |
636 | 0 | if (!PyUnicode_FSConverter(dirname_obj, &dirname_bytes)) |
637 | 0 | return NULL; |
638 | 0 | dirname = PyBytes_AsString(dirname_bytes); |
639 | 0 | } else { |
640 | 0 | dirname_bytes = NULL; |
641 | 0 | dirname = NULL; |
642 | 0 | } |
643 | 0 | current_dirname = bindtextdomain(domain, dirname); |
644 | 0 | if (current_dirname == NULL) { |
645 | 0 | Py_XDECREF(dirname_bytes); |
646 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
647 | 0 | return NULL; |
648 | 0 | } |
649 | 0 | result = PyUnicode_DecodeLocale(current_dirname, NULL); |
650 | 0 | Py_XDECREF(dirname_bytes); |
651 | 0 | return result; |
652 | 0 | } |
653 | | |
654 | | #ifdef HAVE_BIND_TEXTDOMAIN_CODESET |
655 | | PyDoc_STRVAR(bind_textdomain_codeset__doc__, |
656 | | "bind_textdomain_codeset(domain, codeset) -> string\n" |
657 | | "Bind the C library's domain to codeset."); |
658 | | |
659 | | static PyObject* |
660 | | PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args) |
661 | 0 | { |
662 | 0 | char *domain,*codeset; |
663 | 0 | if (!PyArg_ParseTuple(args, "sz", &domain, &codeset)) |
664 | 0 | return NULL; |
665 | 0 | codeset = bind_textdomain_codeset(domain, codeset); |
666 | 0 | if (codeset) { |
667 | 0 | return PyUnicode_DecodeLocale(codeset, NULL); |
668 | 0 | } |
669 | 0 | Py_RETURN_NONE; |
670 | 0 | } |
671 | | #endif |
672 | | |
673 | | #endif |
674 | | |
675 | | static struct PyMethodDef PyLocale_Methods[] = { |
676 | | {"setlocale", (PyCFunction) PyLocale_setlocale, |
677 | | METH_VARARGS, setlocale__doc__}, |
678 | | {"localeconv", PyLocale_localeconv, METH_NOARGS, localeconv__doc__}, |
679 | | #ifdef HAVE_WCSCOLL |
680 | | {"strcoll", (PyCFunction) PyLocale_strcoll, |
681 | | METH_VARARGS, strcoll__doc__}, |
682 | | #endif |
683 | | #ifdef HAVE_WCSXFRM |
684 | | {"strxfrm", (PyCFunction) PyLocale_strxfrm, |
685 | | METH_VARARGS, strxfrm__doc__}, |
686 | | #endif |
687 | | #if defined(MS_WINDOWS) |
688 | | {"_getdefaultlocale", PyLocale_getdefaultlocale, METH_NOARGS}, |
689 | | #endif |
690 | | #ifdef HAVE_LANGINFO_H |
691 | | {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo, |
692 | | METH_VARARGS, nl_langinfo__doc__}, |
693 | | #endif |
694 | | #ifdef HAVE_LIBINTL_H |
695 | | {"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS, |
696 | | gettext__doc__}, |
697 | | {"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS, |
698 | | dgettext__doc__}, |
699 | | {"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS, |
700 | | dcgettext__doc__}, |
701 | | {"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS, |
702 | | textdomain__doc__}, |
703 | | {"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS, |
704 | | bindtextdomain__doc__}, |
705 | | #ifdef HAVE_BIND_TEXTDOMAIN_CODESET |
706 | | {"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset, |
707 | | METH_VARARGS, bind_textdomain_codeset__doc__}, |
708 | | #endif |
709 | | #endif |
710 | | {NULL, NULL} |
711 | | }; |
712 | | |
713 | | |
714 | | static struct PyModuleDef _localemodule = { |
715 | | PyModuleDef_HEAD_INIT, |
716 | | "_locale", |
717 | | locale__doc__, |
718 | | -1, |
719 | | PyLocale_Methods, |
720 | | NULL, |
721 | | NULL, |
722 | | NULL, |
723 | | NULL |
724 | | }; |
725 | | |
726 | | PyMODINIT_FUNC |
727 | | PyInit__locale(void) |
728 | 1 | { |
729 | 1 | PyObject *m; |
730 | 1 | #ifdef HAVE_LANGINFO_H |
731 | 1 | int i; |
732 | 1 | #endif |
733 | | |
734 | 1 | m = PyModule_Create(&_localemodule); |
735 | 1 | if (m == NULL) |
736 | 0 | return NULL; |
737 | | |
738 | 1 | PyModule_AddIntMacro(m, LC_CTYPE); |
739 | 1 | PyModule_AddIntMacro(m, LC_TIME); |
740 | 1 | PyModule_AddIntMacro(m, LC_COLLATE); |
741 | 1 | PyModule_AddIntMacro(m, LC_MONETARY); |
742 | | |
743 | 1 | #ifdef LC_MESSAGES |
744 | 1 | PyModule_AddIntMacro(m, LC_MESSAGES); |
745 | 1 | #endif /* LC_MESSAGES */ |
746 | | |
747 | 1 | PyModule_AddIntMacro(m, LC_NUMERIC); |
748 | 1 | PyModule_AddIntMacro(m, LC_ALL); |
749 | 1 | PyModule_AddIntMacro(m, CHAR_MAX); |
750 | | |
751 | 1 | Error = PyErr_NewException("locale.Error", NULL, NULL); |
752 | 1 | if (Error == NULL) { |
753 | 0 | Py_DECREF(m); |
754 | 0 | return NULL; |
755 | 0 | } |
756 | 1 | PyModule_AddObject(m, "Error", Error); |
757 | | |
758 | 1 | #ifdef HAVE_LANGINFO_H |
759 | 57 | for (i = 0; langinfo_constants[i].name; i++) { |
760 | 56 | PyModule_AddIntConstant(m, langinfo_constants[i].name, |
761 | 56 | langinfo_constants[i].value); |
762 | 56 | } |
763 | 1 | #endif |
764 | | |
765 | 1 | if (PyErr_Occurred()) { |
766 | 0 | Py_DECREF(m); |
767 | 0 | return NULL; |
768 | 0 | } |
769 | 1 | return m; |
770 | 1 | } |
771 | | |
772 | | /* |
773 | | Local variables: |
774 | | c-basic-offset: 4 |
775 | | indent-tabs-mode: nil |
776 | | End: |
777 | | */ |