/src/Python-3.8.3/Modules/_localemodule.c
Line  | Count  | Source  | 
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  |  | */  |