Coverage Report

Created: 2025-07-11 06:59

/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
*/