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