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