17db96d56Sopenharmony_ci/***********************************************************
27db96d56Sopenharmony_ciCopyright (C) 1997, 2002, 2003, 2007, 2008 Martin von Loewis
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ciPermission to use, copy, modify, and distribute this software and its
57db96d56Sopenharmony_cidocumentation for any purpose and without fee is hereby granted,
67db96d56Sopenharmony_ciprovided that the above copyright notice appear in all copies.
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ciThis software comes with no warranty. Use at your own risk.
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci******************************************************************/
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN
137db96d56Sopenharmony_ci#include "Python.h"
147db96d56Sopenharmony_ci#include "pycore_fileutils.h"
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci#include <stdio.h>
177db96d56Sopenharmony_ci#include <locale.h>
187db96d56Sopenharmony_ci#include <string.h>
197db96d56Sopenharmony_ci#include <ctype.h>
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci#ifdef HAVE_ERRNO_H
227db96d56Sopenharmony_ci#include <errno.h>
237db96d56Sopenharmony_ci#endif
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci#ifdef HAVE_LANGINFO_H
267db96d56Sopenharmony_ci#include <langinfo.h>
277db96d56Sopenharmony_ci#endif
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci#ifdef HAVE_LIBINTL_H
307db96d56Sopenharmony_ci#include <libintl.h>
317db96d56Sopenharmony_ci#endif
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci#ifdef HAVE_WCHAR_H
347db96d56Sopenharmony_ci#include <wchar.h>
357db96d56Sopenharmony_ci#endif
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci#if defined(MS_WINDOWS)
387db96d56Sopenharmony_ci#define WIN32_LEAN_AND_MEAN
397db96d56Sopenharmony_ci#include <windows.h>
407db96d56Sopenharmony_ci#endif
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ciPyDoc_STRVAR(locale__doc__, "Support for POSIX locales.");
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_citypedef struct _locale_state {
457db96d56Sopenharmony_ci    PyObject *Error;
467db96d56Sopenharmony_ci} _locale_state;
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_cistatic inline _locale_state*
497db96d56Sopenharmony_ciget_locale_state(PyObject *m)
507db96d56Sopenharmony_ci{
517db96d56Sopenharmony_ci    void *state = PyModule_GetState(m);
527db96d56Sopenharmony_ci    assert(state != NULL);
537db96d56Sopenharmony_ci    return (_locale_state *)state;
547db96d56Sopenharmony_ci}
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci#include "clinic/_localemodule.c.h"
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci/*[clinic input]
597db96d56Sopenharmony_cimodule _locale
607db96d56Sopenharmony_ci[clinic start generated code]*/
617db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ed98569b726feada]*/
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci/* support functions for formatting floating point numbers */
647db96d56Sopenharmony_ci
657db96d56Sopenharmony_ci/* the grouping is terminated by either 0 or CHAR_MAX */
667db96d56Sopenharmony_cistatic PyObject*
677db96d56Sopenharmony_cicopy_grouping(const char* s)
687db96d56Sopenharmony_ci{
697db96d56Sopenharmony_ci    int i;
707db96d56Sopenharmony_ci    PyObject *result, *val = NULL;
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci    if (s[0] == '\0') {
737db96d56Sopenharmony_ci        /* empty string: no grouping at all */
747db96d56Sopenharmony_ci        return PyList_New(0);
757db96d56Sopenharmony_ci    }
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci    for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
787db96d56Sopenharmony_ci        ; /* nothing */
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci    result = PyList_New(i+1);
817db96d56Sopenharmony_ci    if (!result)
827db96d56Sopenharmony_ci        return NULL;
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci    i = -1;
857db96d56Sopenharmony_ci    do {
867db96d56Sopenharmony_ci        i++;
877db96d56Sopenharmony_ci        val = PyLong_FromLong(s[i]);
887db96d56Sopenharmony_ci        if (val == NULL) {
897db96d56Sopenharmony_ci            Py_DECREF(result);
907db96d56Sopenharmony_ci            return NULL;
917db96d56Sopenharmony_ci        }
927db96d56Sopenharmony_ci        PyList_SET_ITEM(result, i, val);
937db96d56Sopenharmony_ci    } while (s[i] != '\0' && s[i] != CHAR_MAX);
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci    return result;
967db96d56Sopenharmony_ci}
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ci/*[clinic input]
997db96d56Sopenharmony_ci_locale.setlocale
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci    category: int
1027db96d56Sopenharmony_ci    locale: str(accept={str, NoneType}) = NULL
1037db96d56Sopenharmony_ci    /
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ciActivates/queries locale processing.
1067db96d56Sopenharmony_ci[clinic start generated code]*/
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_cistatic PyObject *
1097db96d56Sopenharmony_ci_locale_setlocale_impl(PyObject *module, int category, const char *locale)
1107db96d56Sopenharmony_ci/*[clinic end generated code: output=a0e777ae5d2ff117 input=dbe18f1d66c57a6a]*/
1117db96d56Sopenharmony_ci{
1127db96d56Sopenharmony_ci    char *result;
1137db96d56Sopenharmony_ci    PyObject *result_object;
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci#if defined(MS_WINDOWS)
1167db96d56Sopenharmony_ci    if (category < LC_MIN || category > LC_MAX)
1177db96d56Sopenharmony_ci    {
1187db96d56Sopenharmony_ci        PyErr_SetString(get_locale_state(module)->Error,
1197db96d56Sopenharmony_ci                        "invalid locale category");
1207db96d56Sopenharmony_ci        return NULL;
1217db96d56Sopenharmony_ci    }
1227db96d56Sopenharmony_ci#endif
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_ci    if (locale) {
1257db96d56Sopenharmony_ci        /* set locale */
1267db96d56Sopenharmony_ci        result = setlocale(category, locale);
1277db96d56Sopenharmony_ci        if (!result) {
1287db96d56Sopenharmony_ci            /* operation failed, no setting was changed */
1297db96d56Sopenharmony_ci            PyErr_SetString(get_locale_state(module)->Error,
1307db96d56Sopenharmony_ci                            "unsupported locale setting");
1317db96d56Sopenharmony_ci            return NULL;
1327db96d56Sopenharmony_ci        }
1337db96d56Sopenharmony_ci        result_object = PyUnicode_DecodeLocale(result, NULL);
1347db96d56Sopenharmony_ci        if (!result_object)
1357db96d56Sopenharmony_ci            return NULL;
1367db96d56Sopenharmony_ci    } else {
1377db96d56Sopenharmony_ci        /* get locale */
1387db96d56Sopenharmony_ci        result = setlocale(category, NULL);
1397db96d56Sopenharmony_ci        if (!result) {
1407db96d56Sopenharmony_ci            PyErr_SetString(get_locale_state(module)->Error,
1417db96d56Sopenharmony_ci                            "locale query failed");
1427db96d56Sopenharmony_ci            return NULL;
1437db96d56Sopenharmony_ci        }
1447db96d56Sopenharmony_ci        result_object = PyUnicode_DecodeLocale(result, NULL);
1457db96d56Sopenharmony_ci    }
1467db96d56Sopenharmony_ci    return result_object;
1477db96d56Sopenharmony_ci}
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_cistatic int
1507db96d56Sopenharmony_cilocale_is_ascii(const char *str)
1517db96d56Sopenharmony_ci{
1527db96d56Sopenharmony_ci    return (strlen(str) == 1 && ((unsigned char)str[0]) <= 127);
1537db96d56Sopenharmony_ci}
1547db96d56Sopenharmony_ci
1557db96d56Sopenharmony_cistatic int
1567db96d56Sopenharmony_cilocale_decode_monetary(PyObject *dict, struct lconv *lc)
1577db96d56Sopenharmony_ci{
1587db96d56Sopenharmony_ci#ifndef MS_WINDOWS
1597db96d56Sopenharmony_ci    int change_locale;
1607db96d56Sopenharmony_ci    change_locale = (!locale_is_ascii(lc->int_curr_symbol)
1617db96d56Sopenharmony_ci                     || !locale_is_ascii(lc->currency_symbol)
1627db96d56Sopenharmony_ci                     || !locale_is_ascii(lc->mon_decimal_point)
1637db96d56Sopenharmony_ci                     || !locale_is_ascii(lc->mon_thousands_sep));
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci    /* Keep a copy of the LC_CTYPE locale */
1667db96d56Sopenharmony_ci    char *oldloc = NULL, *loc = NULL;
1677db96d56Sopenharmony_ci    if (change_locale) {
1687db96d56Sopenharmony_ci        oldloc = setlocale(LC_CTYPE, NULL);
1697db96d56Sopenharmony_ci        if (!oldloc) {
1707db96d56Sopenharmony_ci            PyErr_SetString(PyExc_RuntimeWarning,
1717db96d56Sopenharmony_ci                            "failed to get LC_CTYPE locale");
1727db96d56Sopenharmony_ci            return -1;
1737db96d56Sopenharmony_ci        }
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci        oldloc = _PyMem_Strdup(oldloc);
1767db96d56Sopenharmony_ci        if (!oldloc) {
1777db96d56Sopenharmony_ci            PyErr_NoMemory();
1787db96d56Sopenharmony_ci            return -1;
1797db96d56Sopenharmony_ci        }
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci        loc = setlocale(LC_MONETARY, NULL);
1827db96d56Sopenharmony_ci        if (loc != NULL && strcmp(loc, oldloc) == 0) {
1837db96d56Sopenharmony_ci            loc = NULL;
1847db96d56Sopenharmony_ci        }
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci        if (loc != NULL) {
1877db96d56Sopenharmony_ci            /* Only set the locale temporarily the LC_CTYPE locale
1887db96d56Sopenharmony_ci               to the LC_MONETARY locale if the two locales are different and
1897db96d56Sopenharmony_ci               at least one string is non-ASCII. */
1907db96d56Sopenharmony_ci            setlocale(LC_CTYPE, loc);
1917db96d56Sopenharmony_ci        }
1927db96d56Sopenharmony_ci    }
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_ci#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
1957db96d56Sopenharmony_ci#else  /* MS_WINDOWS */
1967db96d56Sopenharmony_ci/* Use _W_* fields of Windows struct lconv */
1977db96d56Sopenharmony_ci#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
1987db96d56Sopenharmony_ci#endif /* MS_WINDOWS */
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci    int res = -1;
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci#define RESULT_STRING(ATTR) \
2037db96d56Sopenharmony_ci    do { \
2047db96d56Sopenharmony_ci        PyObject *obj; \
2057db96d56Sopenharmony_ci        obj = GET_LOCALE_STRING(ATTR); \
2067db96d56Sopenharmony_ci        if (obj == NULL) { \
2077db96d56Sopenharmony_ci            goto done; \
2087db96d56Sopenharmony_ci        } \
2097db96d56Sopenharmony_ci        if (PyDict_SetItemString(dict, Py_STRINGIFY(ATTR), obj) < 0) { \
2107db96d56Sopenharmony_ci            Py_DECREF(obj); \
2117db96d56Sopenharmony_ci            goto done; \
2127db96d56Sopenharmony_ci        } \
2137db96d56Sopenharmony_ci        Py_DECREF(obj); \
2147db96d56Sopenharmony_ci    } while (0)
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci    RESULT_STRING(int_curr_symbol);
2177db96d56Sopenharmony_ci    RESULT_STRING(currency_symbol);
2187db96d56Sopenharmony_ci    RESULT_STRING(mon_decimal_point);
2197db96d56Sopenharmony_ci    RESULT_STRING(mon_thousands_sep);
2207db96d56Sopenharmony_ci#undef RESULT_STRING
2217db96d56Sopenharmony_ci#undef GET_LOCALE_STRING
2227db96d56Sopenharmony_ci
2237db96d56Sopenharmony_ci    res = 0;
2247db96d56Sopenharmony_ci
2257db96d56Sopenharmony_cidone:
2267db96d56Sopenharmony_ci#ifndef MS_WINDOWS
2277db96d56Sopenharmony_ci    if (loc != NULL) {
2287db96d56Sopenharmony_ci        setlocale(LC_CTYPE, oldloc);
2297db96d56Sopenharmony_ci    }
2307db96d56Sopenharmony_ci    PyMem_Free(oldloc);
2317db96d56Sopenharmony_ci#endif
2327db96d56Sopenharmony_ci    return res;
2337db96d56Sopenharmony_ci}
2347db96d56Sopenharmony_ci
2357db96d56Sopenharmony_ci/*[clinic input]
2367db96d56Sopenharmony_ci_locale.localeconv
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ciReturns numeric and monetary locale-specific parameters.
2397db96d56Sopenharmony_ci[clinic start generated code]*/
2407db96d56Sopenharmony_ci
2417db96d56Sopenharmony_cistatic PyObject *
2427db96d56Sopenharmony_ci_locale_localeconv_impl(PyObject *module)
2437db96d56Sopenharmony_ci/*[clinic end generated code: output=43a54515e0a2aef5 input=f1132d15accf4444]*/
2447db96d56Sopenharmony_ci{
2457db96d56Sopenharmony_ci    PyObject* result;
2467db96d56Sopenharmony_ci    struct lconv *lc;
2477db96d56Sopenharmony_ci    PyObject *x;
2487db96d56Sopenharmony_ci
2497db96d56Sopenharmony_ci    result = PyDict_New();
2507db96d56Sopenharmony_ci    if (!result) {
2517db96d56Sopenharmony_ci        return NULL;
2527db96d56Sopenharmony_ci    }
2537db96d56Sopenharmony_ci
2547db96d56Sopenharmony_ci    /* if LC_NUMERIC is different in the C library, use saved value */
2557db96d56Sopenharmony_ci    lc = localeconv();
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci    /* hopefully, the localeconv result survives the C library calls
2587db96d56Sopenharmony_ci       involved herein */
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ci#define RESULT(key, obj)\
2617db96d56Sopenharmony_ci    do { \
2627db96d56Sopenharmony_ci        if (obj == NULL) \
2637db96d56Sopenharmony_ci            goto failed; \
2647db96d56Sopenharmony_ci        if (PyDict_SetItemString(result, key, obj) < 0) { \
2657db96d56Sopenharmony_ci            Py_DECREF(obj); \
2667db96d56Sopenharmony_ci            goto failed; \
2677db96d56Sopenharmony_ci        } \
2687db96d56Sopenharmony_ci        Py_DECREF(obj); \
2697db96d56Sopenharmony_ci    } while (0)
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ci#ifdef MS_WINDOWS
2727db96d56Sopenharmony_ci/* Use _W_* fields of Windows struct lconv */
2737db96d56Sopenharmony_ci#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
2747db96d56Sopenharmony_ci#else
2757db96d56Sopenharmony_ci#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
2767db96d56Sopenharmony_ci#endif
2777db96d56Sopenharmony_ci#define RESULT_STRING(s)\
2787db96d56Sopenharmony_ci    do { \
2797db96d56Sopenharmony_ci        x = GET_LOCALE_STRING(s); \
2807db96d56Sopenharmony_ci        RESULT(#s, x); \
2817db96d56Sopenharmony_ci    } while (0)
2827db96d56Sopenharmony_ci
2837db96d56Sopenharmony_ci#define RESULT_INT(i)\
2847db96d56Sopenharmony_ci    do { \
2857db96d56Sopenharmony_ci        x = PyLong_FromLong(lc->i); \
2867db96d56Sopenharmony_ci        RESULT(#i, x); \
2877db96d56Sopenharmony_ci    } while (0)
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci    /* Monetary information: LC_MONETARY encoding */
2907db96d56Sopenharmony_ci    if (locale_decode_monetary(result, lc) < 0) {
2917db96d56Sopenharmony_ci        goto failed;
2927db96d56Sopenharmony_ci    }
2937db96d56Sopenharmony_ci    x = copy_grouping(lc->mon_grouping);
2947db96d56Sopenharmony_ci    RESULT("mon_grouping", x);
2957db96d56Sopenharmony_ci
2967db96d56Sopenharmony_ci    RESULT_STRING(positive_sign);
2977db96d56Sopenharmony_ci    RESULT_STRING(negative_sign);
2987db96d56Sopenharmony_ci    RESULT_INT(int_frac_digits);
2997db96d56Sopenharmony_ci    RESULT_INT(frac_digits);
3007db96d56Sopenharmony_ci    RESULT_INT(p_cs_precedes);
3017db96d56Sopenharmony_ci    RESULT_INT(p_sep_by_space);
3027db96d56Sopenharmony_ci    RESULT_INT(n_cs_precedes);
3037db96d56Sopenharmony_ci    RESULT_INT(n_sep_by_space);
3047db96d56Sopenharmony_ci    RESULT_INT(p_sign_posn);
3057db96d56Sopenharmony_ci    RESULT_INT(n_sign_posn);
3067db96d56Sopenharmony_ci
3077db96d56Sopenharmony_ci    /* Numeric information: LC_NUMERIC encoding */
3087db96d56Sopenharmony_ci    PyObject *decimal_point = NULL, *thousands_sep = NULL;
3097db96d56Sopenharmony_ci    if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) {
3107db96d56Sopenharmony_ci        Py_XDECREF(decimal_point);
3117db96d56Sopenharmony_ci        Py_XDECREF(thousands_sep);
3127db96d56Sopenharmony_ci        goto failed;
3137db96d56Sopenharmony_ci    }
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ci    if (PyDict_SetItemString(result, "decimal_point", decimal_point) < 0) {
3167db96d56Sopenharmony_ci        Py_DECREF(decimal_point);
3177db96d56Sopenharmony_ci        Py_DECREF(thousands_sep);
3187db96d56Sopenharmony_ci        goto failed;
3197db96d56Sopenharmony_ci    }
3207db96d56Sopenharmony_ci    Py_DECREF(decimal_point);
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci    if (PyDict_SetItemString(result, "thousands_sep", thousands_sep) < 0) {
3237db96d56Sopenharmony_ci        Py_DECREF(thousands_sep);
3247db96d56Sopenharmony_ci        goto failed;
3257db96d56Sopenharmony_ci    }
3267db96d56Sopenharmony_ci    Py_DECREF(thousands_sep);
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ci    x = copy_grouping(lc->grouping);
3297db96d56Sopenharmony_ci    RESULT("grouping", x);
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ci    return result;
3327db96d56Sopenharmony_ci
3337db96d56Sopenharmony_ci  failed:
3347db96d56Sopenharmony_ci    Py_DECREF(result);
3357db96d56Sopenharmony_ci    return NULL;
3367db96d56Sopenharmony_ci
3377db96d56Sopenharmony_ci#undef RESULT
3387db96d56Sopenharmony_ci#undef RESULT_STRING
3397db96d56Sopenharmony_ci#undef RESULT_INT
3407db96d56Sopenharmony_ci#undef GET_LOCALE_STRING
3417db96d56Sopenharmony_ci}
3427db96d56Sopenharmony_ci
3437db96d56Sopenharmony_ci#if defined(HAVE_WCSCOLL)
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ci/*[clinic input]
3467db96d56Sopenharmony_ci_locale.strcoll
3477db96d56Sopenharmony_ci
3487db96d56Sopenharmony_ci    os1: unicode
3497db96d56Sopenharmony_ci    os2: unicode
3507db96d56Sopenharmony_ci    /
3517db96d56Sopenharmony_ci
3527db96d56Sopenharmony_ciCompares two strings according to the locale.
3537db96d56Sopenharmony_ci[clinic start generated code]*/
3547db96d56Sopenharmony_ci
3557db96d56Sopenharmony_cistatic PyObject *
3567db96d56Sopenharmony_ci_locale_strcoll_impl(PyObject *module, PyObject *os1, PyObject *os2)
3577db96d56Sopenharmony_ci/*[clinic end generated code: output=82ddc6d62c76d618 input=693cd02bcbf38dd8]*/
3587db96d56Sopenharmony_ci{
3597db96d56Sopenharmony_ci    PyObject *result = NULL;
3607db96d56Sopenharmony_ci    wchar_t *ws1 = NULL, *ws2 = NULL;
3617db96d56Sopenharmony_ci
3627db96d56Sopenharmony_ci    /* Convert the unicode strings to wchar[]. */
3637db96d56Sopenharmony_ci    ws1 = PyUnicode_AsWideCharString(os1, NULL);
3647db96d56Sopenharmony_ci    if (ws1 == NULL)
3657db96d56Sopenharmony_ci        goto done;
3667db96d56Sopenharmony_ci    ws2 = PyUnicode_AsWideCharString(os2, NULL);
3677db96d56Sopenharmony_ci    if (ws2 == NULL)
3687db96d56Sopenharmony_ci        goto done;
3697db96d56Sopenharmony_ci    /* Collate the strings. */
3707db96d56Sopenharmony_ci    result = PyLong_FromLong(wcscoll(ws1, ws2));
3717db96d56Sopenharmony_ci  done:
3727db96d56Sopenharmony_ci    /* Deallocate everything. */
3737db96d56Sopenharmony_ci    if (ws1) PyMem_Free(ws1);
3747db96d56Sopenharmony_ci    if (ws2) PyMem_Free(ws2);
3757db96d56Sopenharmony_ci    return result;
3767db96d56Sopenharmony_ci}
3777db96d56Sopenharmony_ci#endif
3787db96d56Sopenharmony_ci
3797db96d56Sopenharmony_ci#ifdef HAVE_WCSXFRM
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ci/*[clinic input]
3827db96d56Sopenharmony_ci_locale.strxfrm
3837db96d56Sopenharmony_ci
3847db96d56Sopenharmony_ci    string as str: unicode
3857db96d56Sopenharmony_ci    /
3867db96d56Sopenharmony_ci
3877db96d56Sopenharmony_ciReturn a string that can be used as a key for locale-aware comparisons.
3887db96d56Sopenharmony_ci[clinic start generated code]*/
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_cistatic PyObject *
3917db96d56Sopenharmony_ci_locale_strxfrm_impl(PyObject *module, PyObject *str)
3927db96d56Sopenharmony_ci/*[clinic end generated code: output=3081866ebffc01af input=1378bbe6a88b4780]*/
3937db96d56Sopenharmony_ci{
3947db96d56Sopenharmony_ci    Py_ssize_t n1;
3957db96d56Sopenharmony_ci    wchar_t *s = NULL, *buf = NULL;
3967db96d56Sopenharmony_ci    size_t n2;
3977db96d56Sopenharmony_ci    PyObject *result = NULL;
3987db96d56Sopenharmony_ci
3997db96d56Sopenharmony_ci    s = PyUnicode_AsWideCharString(str, &n1);
4007db96d56Sopenharmony_ci    if (s == NULL)
4017db96d56Sopenharmony_ci        goto exit;
4027db96d56Sopenharmony_ci    if (wcslen(s) != (size_t)n1) {
4037db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError,
4047db96d56Sopenharmony_ci                        "embedded null character");
4057db96d56Sopenharmony_ci        goto exit;
4067db96d56Sopenharmony_ci    }
4077db96d56Sopenharmony_ci
4087db96d56Sopenharmony_ci    /* assume no change in size, first */
4097db96d56Sopenharmony_ci    n1 = n1 + 1;
4107db96d56Sopenharmony_ci    buf = PyMem_New(wchar_t, n1);
4117db96d56Sopenharmony_ci    if (!buf) {
4127db96d56Sopenharmony_ci        PyErr_NoMemory();
4137db96d56Sopenharmony_ci        goto exit;
4147db96d56Sopenharmony_ci    }
4157db96d56Sopenharmony_ci    errno = 0;
4167db96d56Sopenharmony_ci    n2 = wcsxfrm(buf, s, n1);
4177db96d56Sopenharmony_ci    if (errno && errno != ERANGE) {
4187db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
4197db96d56Sopenharmony_ci        goto exit;
4207db96d56Sopenharmony_ci    }
4217db96d56Sopenharmony_ci    if (n2 >= (size_t)n1) {
4227db96d56Sopenharmony_ci        /* more space needed */
4237db96d56Sopenharmony_ci        wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t));
4247db96d56Sopenharmony_ci        if (!new_buf) {
4257db96d56Sopenharmony_ci            PyErr_NoMemory();
4267db96d56Sopenharmony_ci            goto exit;
4277db96d56Sopenharmony_ci        }
4287db96d56Sopenharmony_ci        buf = new_buf;
4297db96d56Sopenharmony_ci        errno = 0;
4307db96d56Sopenharmony_ci        n2 = wcsxfrm(buf, s, n2+1);
4317db96d56Sopenharmony_ci        if (errno) {
4327db96d56Sopenharmony_ci            PyErr_SetFromErrno(PyExc_OSError);
4337db96d56Sopenharmony_ci            goto exit;
4347db96d56Sopenharmony_ci        }
4357db96d56Sopenharmony_ci    }
4367db96d56Sopenharmony_ci    result = PyUnicode_FromWideChar(buf, n2);
4377db96d56Sopenharmony_ciexit:
4387db96d56Sopenharmony_ci    PyMem_Free(buf);
4397db96d56Sopenharmony_ci    PyMem_Free(s);
4407db96d56Sopenharmony_ci    return result;
4417db96d56Sopenharmony_ci}
4427db96d56Sopenharmony_ci#endif
4437db96d56Sopenharmony_ci
4447db96d56Sopenharmony_ci#if defined(MS_WINDOWS)
4457db96d56Sopenharmony_ci
4467db96d56Sopenharmony_ci/*[clinic input]
4477db96d56Sopenharmony_ci_locale._getdefaultlocale
4487db96d56Sopenharmony_ci
4497db96d56Sopenharmony_ci[clinic start generated code]*/
4507db96d56Sopenharmony_ci
4517db96d56Sopenharmony_cistatic PyObject *
4527db96d56Sopenharmony_ci_locale__getdefaultlocale_impl(PyObject *module)
4537db96d56Sopenharmony_ci/*[clinic end generated code: output=e6254088579534c2 input=003ea41acd17f7c7]*/
4547db96d56Sopenharmony_ci{
4557db96d56Sopenharmony_ci    char encoding[20];
4567db96d56Sopenharmony_ci    char locale[100];
4577db96d56Sopenharmony_ci
4587db96d56Sopenharmony_ci    PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP());
4597db96d56Sopenharmony_ci
4607db96d56Sopenharmony_ci    if (GetLocaleInfo(LOCALE_USER_DEFAULT,
4617db96d56Sopenharmony_ci                      LOCALE_SISO639LANGNAME,
4627db96d56Sopenharmony_ci                      locale, sizeof(locale))) {
4637db96d56Sopenharmony_ci        Py_ssize_t i = strlen(locale);
4647db96d56Sopenharmony_ci        locale[i++] = '_';
4657db96d56Sopenharmony_ci        if (GetLocaleInfo(LOCALE_USER_DEFAULT,
4667db96d56Sopenharmony_ci                          LOCALE_SISO3166CTRYNAME,
4677db96d56Sopenharmony_ci                          locale+i, (int)(sizeof(locale)-i)))
4687db96d56Sopenharmony_ci            return Py_BuildValue("ss", locale, encoding);
4697db96d56Sopenharmony_ci    }
4707db96d56Sopenharmony_ci
4717db96d56Sopenharmony_ci    /* If we end up here, this windows version didn't know about
4727db96d56Sopenharmony_ci       ISO639/ISO3166 names (it's probably Windows 95).  Return the
4737db96d56Sopenharmony_ci       Windows language identifier instead (a hexadecimal number) */
4747db96d56Sopenharmony_ci
4757db96d56Sopenharmony_ci    locale[0] = '0';
4767db96d56Sopenharmony_ci    locale[1] = 'x';
4777db96d56Sopenharmony_ci    if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
4787db96d56Sopenharmony_ci                      locale+2, sizeof(locale)-2)) {
4797db96d56Sopenharmony_ci        return Py_BuildValue("ss", locale, encoding);
4807db96d56Sopenharmony_ci    }
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_ci    /* cannot determine the language code (very unlikely) */
4837db96d56Sopenharmony_ci    Py_INCREF(Py_None);
4847db96d56Sopenharmony_ci    return Py_BuildValue("Os", Py_None, encoding);
4857db96d56Sopenharmony_ci}
4867db96d56Sopenharmony_ci#endif
4877db96d56Sopenharmony_ci
4887db96d56Sopenharmony_ci#ifdef HAVE_LANGINFO_H
4897db96d56Sopenharmony_ci#define LANGINFO(X) {#X, X}
4907db96d56Sopenharmony_cistatic struct langinfo_constant{
4917db96d56Sopenharmony_ci    char* name;
4927db96d56Sopenharmony_ci    int value;
4937db96d56Sopenharmony_ci} langinfo_constants[] =
4947db96d56Sopenharmony_ci{
4957db96d56Sopenharmony_ci    /* These constants should exist on any langinfo implementation */
4967db96d56Sopenharmony_ci    LANGINFO(DAY_1),
4977db96d56Sopenharmony_ci    LANGINFO(DAY_2),
4987db96d56Sopenharmony_ci    LANGINFO(DAY_3),
4997db96d56Sopenharmony_ci    LANGINFO(DAY_4),
5007db96d56Sopenharmony_ci    LANGINFO(DAY_5),
5017db96d56Sopenharmony_ci    LANGINFO(DAY_6),
5027db96d56Sopenharmony_ci    LANGINFO(DAY_7),
5037db96d56Sopenharmony_ci
5047db96d56Sopenharmony_ci    LANGINFO(ABDAY_1),
5057db96d56Sopenharmony_ci    LANGINFO(ABDAY_2),
5067db96d56Sopenharmony_ci    LANGINFO(ABDAY_3),
5077db96d56Sopenharmony_ci    LANGINFO(ABDAY_4),
5087db96d56Sopenharmony_ci    LANGINFO(ABDAY_5),
5097db96d56Sopenharmony_ci    LANGINFO(ABDAY_6),
5107db96d56Sopenharmony_ci    LANGINFO(ABDAY_7),
5117db96d56Sopenharmony_ci
5127db96d56Sopenharmony_ci    LANGINFO(MON_1),
5137db96d56Sopenharmony_ci    LANGINFO(MON_2),
5147db96d56Sopenharmony_ci    LANGINFO(MON_3),
5157db96d56Sopenharmony_ci    LANGINFO(MON_4),
5167db96d56Sopenharmony_ci    LANGINFO(MON_5),
5177db96d56Sopenharmony_ci    LANGINFO(MON_6),
5187db96d56Sopenharmony_ci    LANGINFO(MON_7),
5197db96d56Sopenharmony_ci    LANGINFO(MON_8),
5207db96d56Sopenharmony_ci    LANGINFO(MON_9),
5217db96d56Sopenharmony_ci    LANGINFO(MON_10),
5227db96d56Sopenharmony_ci    LANGINFO(MON_11),
5237db96d56Sopenharmony_ci    LANGINFO(MON_12),
5247db96d56Sopenharmony_ci
5257db96d56Sopenharmony_ci    LANGINFO(ABMON_1),
5267db96d56Sopenharmony_ci    LANGINFO(ABMON_2),
5277db96d56Sopenharmony_ci    LANGINFO(ABMON_3),
5287db96d56Sopenharmony_ci    LANGINFO(ABMON_4),
5297db96d56Sopenharmony_ci    LANGINFO(ABMON_5),
5307db96d56Sopenharmony_ci    LANGINFO(ABMON_6),
5317db96d56Sopenharmony_ci    LANGINFO(ABMON_7),
5327db96d56Sopenharmony_ci    LANGINFO(ABMON_8),
5337db96d56Sopenharmony_ci    LANGINFO(ABMON_9),
5347db96d56Sopenharmony_ci    LANGINFO(ABMON_10),
5357db96d56Sopenharmony_ci    LANGINFO(ABMON_11),
5367db96d56Sopenharmony_ci    LANGINFO(ABMON_12),
5377db96d56Sopenharmony_ci
5387db96d56Sopenharmony_ci#ifdef RADIXCHAR
5397db96d56Sopenharmony_ci    /* The following are not available with glibc 2.0 */
5407db96d56Sopenharmony_ci    LANGINFO(RADIXCHAR),
5417db96d56Sopenharmony_ci    LANGINFO(THOUSEP),
5427db96d56Sopenharmony_ci    /* YESSTR and NOSTR are deprecated in glibc, since they are
5437db96d56Sopenharmony_ci       a special case of message translation, which should be rather
5447db96d56Sopenharmony_ci       done using gettext. So we don't expose it to Python in the
5457db96d56Sopenharmony_ci       first place.
5467db96d56Sopenharmony_ci    LANGINFO(YESSTR),
5477db96d56Sopenharmony_ci    LANGINFO(NOSTR),
5487db96d56Sopenharmony_ci    */
5497db96d56Sopenharmony_ci    LANGINFO(CRNCYSTR),
5507db96d56Sopenharmony_ci#endif
5517db96d56Sopenharmony_ci
5527db96d56Sopenharmony_ci    LANGINFO(D_T_FMT),
5537db96d56Sopenharmony_ci    LANGINFO(D_FMT),
5547db96d56Sopenharmony_ci    LANGINFO(T_FMT),
5557db96d56Sopenharmony_ci    LANGINFO(AM_STR),
5567db96d56Sopenharmony_ci    LANGINFO(PM_STR),
5577db96d56Sopenharmony_ci
5587db96d56Sopenharmony_ci    /* The following constants are available only with XPG4, but...
5597db96d56Sopenharmony_ci       OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have
5607db96d56Sopenharmony_ci       a few of the others.
5617db96d56Sopenharmony_ci       Solution: ifdef-test them all. */
5627db96d56Sopenharmony_ci#ifdef CODESET
5637db96d56Sopenharmony_ci    LANGINFO(CODESET),
5647db96d56Sopenharmony_ci#endif
5657db96d56Sopenharmony_ci#ifdef T_FMT_AMPM
5667db96d56Sopenharmony_ci    LANGINFO(T_FMT_AMPM),
5677db96d56Sopenharmony_ci#endif
5687db96d56Sopenharmony_ci#ifdef ERA
5697db96d56Sopenharmony_ci    LANGINFO(ERA),
5707db96d56Sopenharmony_ci#endif
5717db96d56Sopenharmony_ci#ifdef ERA_D_FMT
5727db96d56Sopenharmony_ci    LANGINFO(ERA_D_FMT),
5737db96d56Sopenharmony_ci#endif
5747db96d56Sopenharmony_ci#ifdef ERA_D_T_FMT
5757db96d56Sopenharmony_ci    LANGINFO(ERA_D_T_FMT),
5767db96d56Sopenharmony_ci#endif
5777db96d56Sopenharmony_ci#ifdef ERA_T_FMT
5787db96d56Sopenharmony_ci    LANGINFO(ERA_T_FMT),
5797db96d56Sopenharmony_ci#endif
5807db96d56Sopenharmony_ci#ifdef ALT_DIGITS
5817db96d56Sopenharmony_ci    LANGINFO(ALT_DIGITS),
5827db96d56Sopenharmony_ci#endif
5837db96d56Sopenharmony_ci#ifdef YESEXPR
5847db96d56Sopenharmony_ci    LANGINFO(YESEXPR),
5857db96d56Sopenharmony_ci#endif
5867db96d56Sopenharmony_ci#ifdef NOEXPR
5877db96d56Sopenharmony_ci    LANGINFO(NOEXPR),
5887db96d56Sopenharmony_ci#endif
5897db96d56Sopenharmony_ci#ifdef _DATE_FMT
5907db96d56Sopenharmony_ci    /* This is not available in all glibc versions that have CODESET. */
5917db96d56Sopenharmony_ci    LANGINFO(_DATE_FMT),
5927db96d56Sopenharmony_ci#endif
5937db96d56Sopenharmony_ci    {0, 0}
5947db96d56Sopenharmony_ci};
5957db96d56Sopenharmony_ci
5967db96d56Sopenharmony_ci/*[clinic input]
5977db96d56Sopenharmony_ci_locale.nl_langinfo
5987db96d56Sopenharmony_ci
5997db96d56Sopenharmony_ci    key as item: int
6007db96d56Sopenharmony_ci    /
6017db96d56Sopenharmony_ci
6027db96d56Sopenharmony_ciReturn the value for the locale information associated with key.
6037db96d56Sopenharmony_ci[clinic start generated code]*/
6047db96d56Sopenharmony_ci
6057db96d56Sopenharmony_cistatic PyObject *
6067db96d56Sopenharmony_ci_locale_nl_langinfo_impl(PyObject *module, int item)
6077db96d56Sopenharmony_ci/*[clinic end generated code: output=6aea457b47e077a3 input=00798143eecfeddc]*/
6087db96d56Sopenharmony_ci{
6097db96d56Sopenharmony_ci    int i;
6107db96d56Sopenharmony_ci    /* Check whether this is a supported constant. GNU libc sometimes
6117db96d56Sopenharmony_ci       returns numeric values in the char* return value, which would
6127db96d56Sopenharmony_ci       crash PyUnicode_FromString.  */
6137db96d56Sopenharmony_ci    for (i = 0; langinfo_constants[i].name; i++)
6147db96d56Sopenharmony_ci        if (langinfo_constants[i].value == item) {
6157db96d56Sopenharmony_ci            /* Check NULL as a workaround for GNU libc's returning NULL
6167db96d56Sopenharmony_ci               instead of an empty string for nl_langinfo(ERA).  */
6177db96d56Sopenharmony_ci            const char *result = nl_langinfo(item);
6187db96d56Sopenharmony_ci            result = result != NULL ? result : "";
6197db96d56Sopenharmony_ci            return PyUnicode_DecodeLocale(result, NULL);
6207db96d56Sopenharmony_ci        }
6217db96d56Sopenharmony_ci    PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
6227db96d56Sopenharmony_ci    return NULL;
6237db96d56Sopenharmony_ci}
6247db96d56Sopenharmony_ci#endif /* HAVE_LANGINFO_H */
6257db96d56Sopenharmony_ci
6267db96d56Sopenharmony_ci#ifdef HAVE_LIBINTL_H
6277db96d56Sopenharmony_ci
6287db96d56Sopenharmony_ci/*[clinic input]
6297db96d56Sopenharmony_ci_locale.gettext
6307db96d56Sopenharmony_ci
6317db96d56Sopenharmony_ci    msg as in: str
6327db96d56Sopenharmony_ci    /
6337db96d56Sopenharmony_ci
6347db96d56Sopenharmony_cigettext(msg) -> string
6357db96d56Sopenharmony_ci
6367db96d56Sopenharmony_ciReturn translation of msg.
6377db96d56Sopenharmony_ci[clinic start generated code]*/
6387db96d56Sopenharmony_ci
6397db96d56Sopenharmony_cistatic PyObject *
6407db96d56Sopenharmony_ci_locale_gettext_impl(PyObject *module, const char *in)
6417db96d56Sopenharmony_ci/*[clinic end generated code: output=493bb4b38a4704fe input=949fc8efc2bb3bc3]*/
6427db96d56Sopenharmony_ci{
6437db96d56Sopenharmony_ci    return PyUnicode_DecodeLocale(gettext(in), NULL);
6447db96d56Sopenharmony_ci}
6457db96d56Sopenharmony_ci
6467db96d56Sopenharmony_ci/*[clinic input]
6477db96d56Sopenharmony_ci_locale.dgettext
6487db96d56Sopenharmony_ci
6497db96d56Sopenharmony_ci    domain: str(accept={str, NoneType})
6507db96d56Sopenharmony_ci    msg as in: str
6517db96d56Sopenharmony_ci    /
6527db96d56Sopenharmony_ci
6537db96d56Sopenharmony_cidgettext(domain, msg) -> string
6547db96d56Sopenharmony_ci
6557db96d56Sopenharmony_ciReturn translation of msg in domain.
6567db96d56Sopenharmony_ci[clinic start generated code]*/
6577db96d56Sopenharmony_ci
6587db96d56Sopenharmony_cistatic PyObject *
6597db96d56Sopenharmony_ci_locale_dgettext_impl(PyObject *module, const char *domain, const char *in)
6607db96d56Sopenharmony_ci/*[clinic end generated code: output=3c0cd5287b972c8f input=a277388a635109d8]*/
6617db96d56Sopenharmony_ci{
6627db96d56Sopenharmony_ci    return PyUnicode_DecodeLocale(dgettext(domain, in), NULL);
6637db96d56Sopenharmony_ci}
6647db96d56Sopenharmony_ci
6657db96d56Sopenharmony_ci/*[clinic input]
6667db96d56Sopenharmony_ci_locale.dcgettext
6677db96d56Sopenharmony_ci
6687db96d56Sopenharmony_ci    domain: str(accept={str, NoneType})
6697db96d56Sopenharmony_ci    msg as msgid: str
6707db96d56Sopenharmony_ci    category: int
6717db96d56Sopenharmony_ci    /
6727db96d56Sopenharmony_ci
6737db96d56Sopenharmony_ciReturn translation of msg in domain and category.
6747db96d56Sopenharmony_ci[clinic start generated code]*/
6757db96d56Sopenharmony_ci
6767db96d56Sopenharmony_cistatic PyObject *
6777db96d56Sopenharmony_ci_locale_dcgettext_impl(PyObject *module, const char *domain,
6787db96d56Sopenharmony_ci                       const char *msgid, int category)
6797db96d56Sopenharmony_ci/*[clinic end generated code: output=0f4cc4fce0aa283f input=ec5f8fed4336de67]*/
6807db96d56Sopenharmony_ci{
6817db96d56Sopenharmony_ci    return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL);
6827db96d56Sopenharmony_ci}
6837db96d56Sopenharmony_ci
6847db96d56Sopenharmony_ci/*[clinic input]
6857db96d56Sopenharmony_ci_locale.textdomain
6867db96d56Sopenharmony_ci
6877db96d56Sopenharmony_ci    domain: str(accept={str, NoneType})
6887db96d56Sopenharmony_ci    /
6897db96d56Sopenharmony_ci
6907db96d56Sopenharmony_ciSet the C library's textdmain to domain, returning the new domain.
6917db96d56Sopenharmony_ci[clinic start generated code]*/
6927db96d56Sopenharmony_ci
6937db96d56Sopenharmony_cistatic PyObject *
6947db96d56Sopenharmony_ci_locale_textdomain_impl(PyObject *module, const char *domain)
6957db96d56Sopenharmony_ci/*[clinic end generated code: output=7992df06aadec313 input=66359716f5eb1d38]*/
6967db96d56Sopenharmony_ci{
6977db96d56Sopenharmony_ci    domain = textdomain(domain);
6987db96d56Sopenharmony_ci    if (!domain) {
6997db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
7007db96d56Sopenharmony_ci        return NULL;
7017db96d56Sopenharmony_ci    }
7027db96d56Sopenharmony_ci    return PyUnicode_DecodeLocale(domain, NULL);
7037db96d56Sopenharmony_ci}
7047db96d56Sopenharmony_ci
7057db96d56Sopenharmony_ci/*[clinic input]
7067db96d56Sopenharmony_ci_locale.bindtextdomain
7077db96d56Sopenharmony_ci
7087db96d56Sopenharmony_ci    domain: str
7097db96d56Sopenharmony_ci    dir as dirname_obj: object
7107db96d56Sopenharmony_ci    /
7117db96d56Sopenharmony_ci
7127db96d56Sopenharmony_ciBind the C library's domain to dir.
7137db96d56Sopenharmony_ci[clinic start generated code]*/
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_cistatic PyObject *
7167db96d56Sopenharmony_ci_locale_bindtextdomain_impl(PyObject *module, const char *domain,
7177db96d56Sopenharmony_ci                            PyObject *dirname_obj)
7187db96d56Sopenharmony_ci/*[clinic end generated code: output=6d6f3c7b345d785c input=c0dff085acfe272b]*/
7197db96d56Sopenharmony_ci{
7207db96d56Sopenharmony_ci    const char *dirname, *current_dirname;
7217db96d56Sopenharmony_ci    PyObject *dirname_bytes = NULL, *result;
7227db96d56Sopenharmony_ci
7237db96d56Sopenharmony_ci    if (!strlen(domain)) {
7247db96d56Sopenharmony_ci        PyErr_SetString(get_locale_state(module)->Error,
7257db96d56Sopenharmony_ci                        "domain must be a non-empty string");
7267db96d56Sopenharmony_ci        return 0;
7277db96d56Sopenharmony_ci    }
7287db96d56Sopenharmony_ci    if (dirname_obj != Py_None) {
7297db96d56Sopenharmony_ci        if (!PyUnicode_FSConverter(dirname_obj, &dirname_bytes))
7307db96d56Sopenharmony_ci            return NULL;
7317db96d56Sopenharmony_ci        dirname = PyBytes_AsString(dirname_bytes);
7327db96d56Sopenharmony_ci    } else {
7337db96d56Sopenharmony_ci        dirname_bytes = NULL;
7347db96d56Sopenharmony_ci        dirname = NULL;
7357db96d56Sopenharmony_ci    }
7367db96d56Sopenharmony_ci    current_dirname = bindtextdomain(domain, dirname);
7377db96d56Sopenharmony_ci    if (current_dirname == NULL) {
7387db96d56Sopenharmony_ci        Py_XDECREF(dirname_bytes);
7397db96d56Sopenharmony_ci        PyErr_SetFromErrno(PyExc_OSError);
7407db96d56Sopenharmony_ci        return NULL;
7417db96d56Sopenharmony_ci    }
7427db96d56Sopenharmony_ci    result = PyUnicode_DecodeLocale(current_dirname, NULL);
7437db96d56Sopenharmony_ci    Py_XDECREF(dirname_bytes);
7447db96d56Sopenharmony_ci    return result;
7457db96d56Sopenharmony_ci}
7467db96d56Sopenharmony_ci
7477db96d56Sopenharmony_ci#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
7487db96d56Sopenharmony_ci
7497db96d56Sopenharmony_ci/*[clinic input]
7507db96d56Sopenharmony_ci_locale.bind_textdomain_codeset
7517db96d56Sopenharmony_ci
7527db96d56Sopenharmony_ci    domain: str
7537db96d56Sopenharmony_ci    codeset: str(accept={str, NoneType})
7547db96d56Sopenharmony_ci    /
7557db96d56Sopenharmony_ci
7567db96d56Sopenharmony_ciBind the C library's domain to codeset.
7577db96d56Sopenharmony_ci[clinic start generated code]*/
7587db96d56Sopenharmony_ci
7597db96d56Sopenharmony_cistatic PyObject *
7607db96d56Sopenharmony_ci_locale_bind_textdomain_codeset_impl(PyObject *module, const char *domain,
7617db96d56Sopenharmony_ci                                     const char *codeset)
7627db96d56Sopenharmony_ci/*[clinic end generated code: output=fa452f9c8b1b9e89 input=23fbe3540400f259]*/
7637db96d56Sopenharmony_ci{
7647db96d56Sopenharmony_ci    codeset = bind_textdomain_codeset(domain, codeset);
7657db96d56Sopenharmony_ci    if (codeset) {
7667db96d56Sopenharmony_ci        return PyUnicode_DecodeLocale(codeset, NULL);
7677db96d56Sopenharmony_ci    }
7687db96d56Sopenharmony_ci    Py_RETURN_NONE;
7697db96d56Sopenharmony_ci}
7707db96d56Sopenharmony_ci#endif  // HAVE_BIND_TEXTDOMAIN_CODESET
7717db96d56Sopenharmony_ci
7727db96d56Sopenharmony_ci#endif  // HAVE_LIBINTL_H
7737db96d56Sopenharmony_ci
7747db96d56Sopenharmony_ci
7757db96d56Sopenharmony_ci/*[clinic input]
7767db96d56Sopenharmony_ci_locale.getencoding
7777db96d56Sopenharmony_ci
7787db96d56Sopenharmony_ciGet the current locale encoding.
7797db96d56Sopenharmony_ci[clinic start generated code]*/
7807db96d56Sopenharmony_ci
7817db96d56Sopenharmony_cistatic PyObject *
7827db96d56Sopenharmony_ci_locale_getencoding_impl(PyObject *module)
7837db96d56Sopenharmony_ci/*[clinic end generated code: output=86b326b971872e46 input=6503d11e5958b360]*/
7847db96d56Sopenharmony_ci{
7857db96d56Sopenharmony_ci    return _Py_GetLocaleEncodingObject();
7867db96d56Sopenharmony_ci}
7877db96d56Sopenharmony_ci
7887db96d56Sopenharmony_ci
7897db96d56Sopenharmony_cistatic struct PyMethodDef PyLocale_Methods[] = {
7907db96d56Sopenharmony_ci    _LOCALE_SETLOCALE_METHODDEF
7917db96d56Sopenharmony_ci    _LOCALE_LOCALECONV_METHODDEF
7927db96d56Sopenharmony_ci#ifdef HAVE_WCSCOLL
7937db96d56Sopenharmony_ci    _LOCALE_STRCOLL_METHODDEF
7947db96d56Sopenharmony_ci#endif
7957db96d56Sopenharmony_ci#ifdef HAVE_WCSXFRM
7967db96d56Sopenharmony_ci    _LOCALE_STRXFRM_METHODDEF
7977db96d56Sopenharmony_ci#endif
7987db96d56Sopenharmony_ci#if defined(MS_WINDOWS)
7997db96d56Sopenharmony_ci    _LOCALE__GETDEFAULTLOCALE_METHODDEF
8007db96d56Sopenharmony_ci#endif
8017db96d56Sopenharmony_ci#ifdef HAVE_LANGINFO_H
8027db96d56Sopenharmony_ci    _LOCALE_NL_LANGINFO_METHODDEF
8037db96d56Sopenharmony_ci#endif
8047db96d56Sopenharmony_ci#ifdef HAVE_LIBINTL_H
8057db96d56Sopenharmony_ci    _LOCALE_GETTEXT_METHODDEF
8067db96d56Sopenharmony_ci    _LOCALE_DGETTEXT_METHODDEF
8077db96d56Sopenharmony_ci    _LOCALE_DCGETTEXT_METHODDEF
8087db96d56Sopenharmony_ci    _LOCALE_TEXTDOMAIN_METHODDEF
8097db96d56Sopenharmony_ci    _LOCALE_BINDTEXTDOMAIN_METHODDEF
8107db96d56Sopenharmony_ci#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
8117db96d56Sopenharmony_ci    _LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF
8127db96d56Sopenharmony_ci#endif
8137db96d56Sopenharmony_ci#endif
8147db96d56Sopenharmony_ci    _LOCALE_GETENCODING_METHODDEF
8157db96d56Sopenharmony_ci  {NULL, NULL}
8167db96d56Sopenharmony_ci};
8177db96d56Sopenharmony_ci
8187db96d56Sopenharmony_cistatic int
8197db96d56Sopenharmony_ci_locale_exec(PyObject *module)
8207db96d56Sopenharmony_ci{
8217db96d56Sopenharmony_ci#ifdef HAVE_LANGINFO_H
8227db96d56Sopenharmony_ci    int i;
8237db96d56Sopenharmony_ci#endif
8247db96d56Sopenharmony_ci#define ADD_INT(module, value)                                    \
8257db96d56Sopenharmony_ci    do {                                                          \
8267db96d56Sopenharmony_ci        if (PyModule_AddIntConstant(module, #value, value) < 0) { \
8277db96d56Sopenharmony_ci            return -1;                                            \
8287db96d56Sopenharmony_ci        }                                                         \
8297db96d56Sopenharmony_ci    } while (0)
8307db96d56Sopenharmony_ci
8317db96d56Sopenharmony_ci    ADD_INT(module, LC_CTYPE);
8327db96d56Sopenharmony_ci    ADD_INT(module, LC_TIME);
8337db96d56Sopenharmony_ci    ADD_INT(module, LC_COLLATE);
8347db96d56Sopenharmony_ci    ADD_INT(module, LC_MONETARY);
8357db96d56Sopenharmony_ci
8367db96d56Sopenharmony_ci#ifdef LC_MESSAGES
8377db96d56Sopenharmony_ci    ADD_INT(module, LC_MESSAGES);
8387db96d56Sopenharmony_ci#endif /* LC_MESSAGES */
8397db96d56Sopenharmony_ci
8407db96d56Sopenharmony_ci    ADD_INT(module, LC_NUMERIC);
8417db96d56Sopenharmony_ci    ADD_INT(module, LC_ALL);
8427db96d56Sopenharmony_ci    ADD_INT(module, CHAR_MAX);
8437db96d56Sopenharmony_ci
8447db96d56Sopenharmony_ci    _locale_state *state = get_locale_state(module);
8457db96d56Sopenharmony_ci    state->Error = PyErr_NewException("locale.Error", NULL, NULL);
8467db96d56Sopenharmony_ci    if (state->Error == NULL) {
8477db96d56Sopenharmony_ci        return -1;
8487db96d56Sopenharmony_ci    }
8497db96d56Sopenharmony_ci    Py_INCREF(get_locale_state(module)->Error);
8507db96d56Sopenharmony_ci    if (PyModule_AddObject(module, "Error", get_locale_state(module)->Error) < 0) {
8517db96d56Sopenharmony_ci        Py_DECREF(get_locale_state(module)->Error);
8527db96d56Sopenharmony_ci        return -1;
8537db96d56Sopenharmony_ci    }
8547db96d56Sopenharmony_ci
8557db96d56Sopenharmony_ci#ifdef HAVE_LANGINFO_H
8567db96d56Sopenharmony_ci    for (i = 0; langinfo_constants[i].name; i++) {
8577db96d56Sopenharmony_ci        if (PyModule_AddIntConstant(module,
8587db96d56Sopenharmony_ci                                    langinfo_constants[i].name,
8597db96d56Sopenharmony_ci                                    langinfo_constants[i].value) < 0) {
8607db96d56Sopenharmony_ci            return -1;
8617db96d56Sopenharmony_ci        }
8627db96d56Sopenharmony_ci    }
8637db96d56Sopenharmony_ci#endif
8647db96d56Sopenharmony_ci
8657db96d56Sopenharmony_ci    if (PyErr_Occurred()) {
8667db96d56Sopenharmony_ci        return -1;
8677db96d56Sopenharmony_ci    }
8687db96d56Sopenharmony_ci    return 0;
8697db96d56Sopenharmony_ci
8707db96d56Sopenharmony_ci#undef ADD_INT
8717db96d56Sopenharmony_ci}
8727db96d56Sopenharmony_ci
8737db96d56Sopenharmony_cistatic struct PyModuleDef_Slot _locale_slots[] = {
8747db96d56Sopenharmony_ci    {Py_mod_exec, _locale_exec},
8757db96d56Sopenharmony_ci    {0, NULL}
8767db96d56Sopenharmony_ci};
8777db96d56Sopenharmony_ci
8787db96d56Sopenharmony_cistatic int
8797db96d56Sopenharmony_cilocale_traverse(PyObject *module, visitproc visit, void *arg)
8807db96d56Sopenharmony_ci{
8817db96d56Sopenharmony_ci    _locale_state *state = get_locale_state(module);
8827db96d56Sopenharmony_ci    Py_VISIT(state->Error);
8837db96d56Sopenharmony_ci    return 0;
8847db96d56Sopenharmony_ci}
8857db96d56Sopenharmony_ci
8867db96d56Sopenharmony_cistatic int
8877db96d56Sopenharmony_cilocale_clear(PyObject *module)
8887db96d56Sopenharmony_ci{
8897db96d56Sopenharmony_ci    _locale_state *state = get_locale_state(module);
8907db96d56Sopenharmony_ci    Py_CLEAR(state->Error);
8917db96d56Sopenharmony_ci    return 0;
8927db96d56Sopenharmony_ci}
8937db96d56Sopenharmony_ci
8947db96d56Sopenharmony_cistatic void
8957db96d56Sopenharmony_cilocale_free(PyObject *module)
8967db96d56Sopenharmony_ci{
8977db96d56Sopenharmony_ci    locale_clear(module);
8987db96d56Sopenharmony_ci}
8997db96d56Sopenharmony_ci
9007db96d56Sopenharmony_cistatic struct PyModuleDef _localemodule = {
9017db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
9027db96d56Sopenharmony_ci    "_locale",
9037db96d56Sopenharmony_ci    locale__doc__,
9047db96d56Sopenharmony_ci    sizeof(_locale_state),
9057db96d56Sopenharmony_ci    PyLocale_Methods,
9067db96d56Sopenharmony_ci    _locale_slots,
9077db96d56Sopenharmony_ci    locale_traverse,
9087db96d56Sopenharmony_ci    locale_clear,
9097db96d56Sopenharmony_ci    (freefunc)locale_free,
9107db96d56Sopenharmony_ci};
9117db96d56Sopenharmony_ci
9127db96d56Sopenharmony_ciPyMODINIT_FUNC
9137db96d56Sopenharmony_ciPyInit__locale(void)
9147db96d56Sopenharmony_ci{
9157db96d56Sopenharmony_ci    return PyModuleDef_Init(&_localemodule);
9167db96d56Sopenharmony_ci}
9177db96d56Sopenharmony_ci
9187db96d56Sopenharmony_ci/*
9197db96d56Sopenharmony_ciLocal variables:
9207db96d56Sopenharmony_cic-basic-offset: 4
9217db96d56Sopenharmony_ciindent-tabs-mode: nil
9227db96d56Sopenharmony_ciEnd:
9237db96d56Sopenharmony_ci*/
924