LCOV - code coverage report
Current view: top level - Modules - _localemodule.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 165 237 69.6 %
Date: 2022-07-20 13:12:14 Functions: 15 21 71.4 %
Branches: 106 198 53.5 %

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

Generated by: LCOV version 1.14