LCOV - code coverage report
Current view: top level - Modules - _localemodule.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 42 240 17.5 %
Date: 2023-03-20 08:15:36 Functions: 7 21 33.3 %
Branches: 20 198 10.1 %

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

Generated by: LCOV version 1.14