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