blob: 4202cc401414241032fbcfdb924670a8326f2726 [file] [log] [blame]
Guido van Rossum220ecc81997-11-18 21:03:39 +00001/***********************************************************
Martin v. Löwis92fab752008-03-08 10:40:41 +00002Copyright (C) 1997, 2002, 2003, 2007, 2008 Martin von Loewis
Guido van Rossum220ecc81997-11-18 21:03:39 +00003
4Permission to use, copy, modify, and distribute this software and its
5documentation for any purpose and without fee is hereby granted,
6provided that the above copyright notice appear in all copies.
7
8This software comes with no warranty. Use at your own risk.
Fredrik Lundh8f017a02000-07-08 19:57:37 +00009
Guido van Rossum220ecc81997-11-18 21:03:39 +000010******************************************************************/
11
Antoine Pitrou6a448d42009-10-19 19:43:09 +000012#define PY_SSIZE_T_CLEAN
Fred Drake68933b92000-08-10 21:41:08 +000013#include "Python.h"
Victor Stinner02e6bf72018-11-20 16:20:16 +010014#include "pycore_fileutils.h"
Fred Drake68933b92000-08-10 21:41:08 +000015
Guido van Rossum220ecc81997-11-18 21:03:39 +000016#include <stdio.h>
Guido van Rossum220ecc81997-11-18 21:03:39 +000017#include <locale.h>
18#include <string.h>
Guido van Rossum5cd70f41998-06-19 04:33:30 +000019#include <ctype.h>
Fredrik Lundh8f017a02000-07-08 19:57:37 +000020
Thomas Wouters0e3f5912006-08-11 14:57:12 +000021#ifdef HAVE_ERRNO_H
Thomas Wouters477c8d52006-05-27 19:21:47 +000022#include <errno.h>
23#endif
24
Martin v. Löwis9b75dca2001-08-10 13:58:50 +000025#ifdef HAVE_LANGINFO_H
26#include <langinfo.h>
27#endif
28
Martin v. Löwis2e64c342002-03-27 18:49:02 +000029#ifdef HAVE_LIBINTL_H
30#include <libintl.h>
31#endif
32
Martin v. Löwis9c36c292002-12-21 18:34:06 +000033#ifdef HAVE_WCHAR_H
34#include <wchar.h>
35#endif
36
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000037#if defined(MS_WINDOWS)
Tim Peters7a1f9172002-07-14 22:14:19 +000038#define WIN32_LEAN_AND_MEAN
Fredrik Lundh8f017a02000-07-08 19:57:37 +000039#include <windows.h>
Guido van Rossum239a2181998-04-28 16:08:19 +000040#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +000041
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000042PyDoc_STRVAR(locale__doc__, "Support for POSIX locales.");
Guido van Rossum220ecc81997-11-18 21:03:39 +000043
44static PyObject *Error;
45
46/* support functions for formatting floating point numbers */
47
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000048PyDoc_STRVAR(setlocale__doc__,
49"(integer,string=None) -> string. Activates/queries locale processing.");
Guido van Rossum220ecc81997-11-18 21:03:39 +000050
Guido van Rossum220ecc81997-11-18 21:03:39 +000051/* the grouping is terminated by either 0 or CHAR_MAX */
52static PyObject*
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020053copy_grouping(const char* s)
Guido van Rossum220ecc81997-11-18 21:03:39 +000054{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000055 int i;
56 PyObject *result, *val = NULL;
57
Martin Panter6d57fe12016-09-17 03:26:16 +000058 if (s[0] == '\0') {
Fredrik Lundh8f017a02000-07-08 19:57:37 +000059 /* empty string: no grouping at all */
60 return PyList_New(0);
Martin Panter6d57fe12016-09-17 03:26:16 +000061 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +000062
63 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
64 ; /* nothing */
65
66 result = PyList_New(i+1);
67 if (!result)
68 return NULL;
69
70 i = -1;
71 do {
72 i++;
Christian Heimes217cfd12007-12-02 14:31:20 +000073 val = PyLong_FromLong(s[i]);
Fredrik Lundh8f017a02000-07-08 19:57:37 +000074 if (!val)
75 break;
76 if (PyList_SetItem(result, i, val)) {
77 Py_DECREF(val);
Fredrik Lundh89610a42000-07-08 20:07:24 +000078 val = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000079 break;
80 }
81 } while (s[i] != '\0' && s[i] != CHAR_MAX);
82
83 if (!val) {
84 Py_DECREF(result);
85 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000086 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +000087
88 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +000089}
90
Guido van Rossum220ecc81997-11-18 21:03:39 +000091static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +000092PyLocale_setlocale(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +000093{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000094 int category;
95 char *locale = NULL, *result;
96 PyObject *result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +000097
Fredrik Lundh8f017a02000-07-08 19:57:37 +000098 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
Fredrik Lundh89610a42000-07-08 20:07:24 +000099 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000100
Amaury Forgeot d'Arc64f3ca42009-12-01 21:59:18 +0000101#if defined(MS_WINDOWS)
102 if (category < LC_MIN || category > LC_MAX)
103 {
104 PyErr_SetString(Error, "invalid locale category");
105 return NULL;
106 }
107#endif
108
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000109 if (locale) {
110 /* set locale */
111 result = setlocale(category, locale);
112 if (!result) {
113 /* operation failed, no setting was changed */
Martin v. Löwis25f90d52003-09-03 04:50:13 +0000114 PyErr_SetString(Error, "unsupported locale setting");
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000115 return NULL;
116 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100117 result_object = PyUnicode_DecodeLocale(result, NULL);
Mark Hammond9a714752003-07-24 14:15:07 +0000118 if (!result_object)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000119 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000120 } else {
121 /* get locale */
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000122 result = setlocale(category, NULL);
123 if (!result) {
124 PyErr_SetString(Error, "locale query failed");
125 return NULL;
126 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100127 result_object = PyUnicode_DecodeLocale(result, NULL);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000128 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000129 return result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000130}
131
Victor Stinner02e6bf72018-11-20 16:20:16 +0100132static int
133locale_is_ascii(const char *str)
134{
135 return (strlen(str) == 1 && ((unsigned char)str[0]) <= 127);
136}
137
138static int
139locale_decode_monetary(PyObject *dict, struct lconv *lc)
140{
141 int change_locale;
142 change_locale = (!locale_is_ascii(lc->int_curr_symbol)
143 || !locale_is_ascii(lc->currency_symbol)
144 || !locale_is_ascii(lc->mon_decimal_point)
145 || !locale_is_ascii(lc->mon_thousands_sep));
146
147 /* Keep a copy of the LC_CTYPE locale */
148 char *oldloc = NULL, *loc = NULL;
149 if (change_locale) {
150 oldloc = setlocale(LC_CTYPE, NULL);
151 if (!oldloc) {
152 PyErr_SetString(PyExc_RuntimeWarning,
153 "failed to get LC_CTYPE locale");
154 return -1;
155 }
156
157 oldloc = _PyMem_Strdup(oldloc);
158 if (!oldloc) {
159 PyErr_NoMemory();
160 return -1;
161 }
162
163 loc = setlocale(LC_MONETARY, NULL);
164 if (loc != NULL && strcmp(loc, oldloc) == 0) {
165 loc = NULL;
166 }
167
168 if (loc != NULL) {
169 /* Only set the locale temporarily the LC_CTYPE locale
170 to the LC_MONETARY locale if the two locales are different and
171 at least one string is non-ASCII. */
172 setlocale(LC_CTYPE, loc);
173 }
174 }
175
176 int res = -1;
177
178#define RESULT_STRING(ATTR) \
179 do { \
180 PyObject *obj; \
181 obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
182 if (obj == NULL) { \
183 goto done; \
184 } \
185 if (PyDict_SetItemString(dict, Py_STRINGIFY(ATTR), obj) < 0) { \
186 Py_DECREF(obj); \
187 goto done; \
188 } \
189 Py_DECREF(obj); \
190 } while (0)
191
192 RESULT_STRING(int_curr_symbol);
193 RESULT_STRING(currency_symbol);
194 RESULT_STRING(mon_decimal_point);
195 RESULT_STRING(mon_thousands_sep);
196#undef RESULT_STRING
197
198 res = 0;
199
200done:
201 if (loc != NULL) {
202 setlocale(LC_CTYPE, oldloc);
203 }
204 PyMem_Free(oldloc);
205 return res;
206}
207
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000208PyDoc_STRVAR(localeconv__doc__,
209"() -> dict. Returns numeric and monetary locale-specific parameters.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000210
211static PyObject*
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530212PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
Guido van Rossum220ecc81997-11-18 21:03:39 +0000213{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000214 PyObject* result;
Victor Stinner02e6bf72018-11-20 16:20:16 +0100215 struct lconv *lc;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000216 PyObject *x;
217
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000218 result = PyDict_New();
Victor Stinnercb064fc2018-01-15 15:58:02 +0100219 if (!result) {
Fredrik Lundh89610a42000-07-08 20:07:24 +0000220 return NULL;
Victor Stinnercb064fc2018-01-15 15:58:02 +0100221 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000222
223 /* if LC_NUMERIC is different in the C library, use saved value */
Victor Stinner02e6bf72018-11-20 16:20:16 +0100224 lc = localeconv();
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000225
226 /* hopefully, the localeconv result survives the C library calls
227 involved herein */
228
Victor Stinnerd594f242013-07-17 00:55:57 +0200229#define RESULT(key, obj)\
230 do { \
231 if (obj == NULL) \
232 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100233 if (PyDict_SetItemString(result, key, obj) < 0) { \
234 Py_DECREF(obj); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200235 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100236 } \
Victor Stinnerd594f242013-07-17 00:55:57 +0200237 Py_DECREF(obj); \
238 } while (0)
239
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000240#define RESULT_STRING(s)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200241 do { \
Victor Stinner02e6bf72018-11-20 16:20:16 +0100242 x = PyUnicode_DecodeLocale(lc->s, NULL); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200243 RESULT(#s, x); \
244 } while (0)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000245
246#define RESULT_INT(i)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200247 do { \
Victor Stinner02e6bf72018-11-20 16:20:16 +0100248 x = PyLong_FromLong(lc->i); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200249 RESULT(#i, x); \
250 } while (0)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000251
Victor Stinner02e6bf72018-11-20 16:20:16 +0100252 /* Monetary information: LC_MONETARY encoding */
253 if (locale_decode_monetary(result, lc) < 0) {
254 goto failed;
255 }
256 x = copy_grouping(lc->mon_grouping);
Victor Stinnerd594f242013-07-17 00:55:57 +0200257 RESULT("mon_grouping", x);
258
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000259 RESULT_STRING(positive_sign);
260 RESULT_STRING(negative_sign);
261 RESULT_INT(int_frac_digits);
262 RESULT_INT(frac_digits);
263 RESULT_INT(p_cs_precedes);
264 RESULT_INT(p_sep_by_space);
265 RESULT_INT(n_cs_precedes);
266 RESULT_INT(n_sep_by_space);
267 RESULT_INT(p_sign_posn);
268 RESULT_INT(n_sign_posn);
Victor Stinnercb064fc2018-01-15 15:58:02 +0100269
Victor Stinner02e6bf72018-11-20 16:20:16 +0100270 /* Numeric information: LC_NUMERIC encoding */
Victor Stinnercb064fc2018-01-15 15:58:02 +0100271 PyObject *decimal_point, *thousands_sep;
Victor Stinner02e6bf72018-11-20 16:20:16 +0100272 if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) {
Victor Stinnercb064fc2018-01-15 15:58:02 +0100273 goto failed;
274 }
275
276 if (PyDict_SetItemString(result, "decimal_point", decimal_point) < 0) {
277 Py_DECREF(decimal_point);
278 Py_DECREF(thousands_sep);
279 goto failed;
280 }
281 Py_DECREF(decimal_point);
282
283 if (PyDict_SetItemString(result, "thousands_sep", thousands_sep) < 0) {
284 Py_DECREF(thousands_sep);
285 goto failed;
286 }
287 Py_DECREF(thousands_sep);
288
Victor Stinner02e6bf72018-11-20 16:20:16 +0100289 x = copy_grouping(lc->grouping);
Victor Stinnercb064fc2018-01-15 15:58:02 +0100290 RESULT("grouping", x);
291
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000292 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000293
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000294 failed:
Victor Stinnercb064fc2018-01-15 15:58:02 +0100295 Py_DECREF(result);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000296 return NULL;
Victor Stinner02e6bf72018-11-20 16:20:16 +0100297
298#undef RESULT
299#undef RESULT_STRING
300#undef RESULT_INT
Guido van Rossum220ecc81997-11-18 21:03:39 +0000301}
302
Martin v. Löwis92fab752008-03-08 10:40:41 +0000303#if defined(HAVE_WCSCOLL)
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000304PyDoc_STRVAR(strcoll__doc__,
305"string,string -> int. Compares two strings according to the locale.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000306
307static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000308PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000309{
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000310 PyObject *os1, *os2, *result = NULL;
311 wchar_t *ws1 = NULL, *ws2 = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312
Martin v. Löwis92fab752008-03-08 10:40:41 +0000313 if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2))
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000314 return NULL;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000315 /* Convert the unicode strings to wchar[]. */
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000316 ws1 = PyUnicode_AsWideCharString(os1, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000317 if (ws1 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000318 goto done;
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000319 ws2 = PyUnicode_AsWideCharString(os2, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000320 if (ws2 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000321 goto done;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000322 /* Collate the strings. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000323 result = PyLong_FromLong(wcscoll(ws1, ws2));
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000324 done:
325 /* Deallocate everything. */
326 if (ws1) PyMem_FREE(ws1);
327 if (ws2) PyMem_FREE(ws2);
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000328 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000329}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000330#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000331
Martin v. Löwis92fab752008-03-08 10:40:41 +0000332#ifdef HAVE_WCSXFRM
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000333PyDoc_STRVAR(strxfrm__doc__,
Mark Dickinson211c6252009-02-01 10:28:51 +0000334"strxfrm(string) -> string.\n\
335\n\
336Return a string that can be used as a key for locale-aware comparisons.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000337
338static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000339PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000340{
Victor Stinner63649272011-09-29 23:32:06 +0200341 PyObject *str;
342 Py_ssize_t n1;
343 wchar_t *s = NULL, *buf = NULL;
344 size_t n2;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000345 PyObject *result = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000346
Victor Stinner63649272011-09-29 23:32:06 +0200347 if (!PyArg_ParseTuple(args, "U:strxfrm", &str))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000348 return NULL;
349
Victor Stinner63649272011-09-29 23:32:06 +0200350 s = PyUnicode_AsWideCharString(str, &n1);
351 if (s == NULL)
352 goto exit;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300353 if (wcslen(s) != (size_t)n1) {
354 PyErr_SetString(PyExc_ValueError,
355 "embedded null character");
356 goto exit;
357 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000358
359 /* assume no change in size, first */
Victor Stinner63649272011-09-29 23:32:06 +0200360 n1 = n1 + 1;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200361 buf = PyMem_New(wchar_t, n1);
Martin v. Löwis92fab752008-03-08 10:40:41 +0000362 if (!buf) {
363 PyErr_NoMemory();
364 goto exit;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000365 }
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200366 errno = 0;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000367 n2 = wcsxfrm(buf, s, n1);
Benjamin Petersonad4a0cc2017-03-07 22:24:44 -0800368 if (errno && errno != ERANGE) {
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200369 PyErr_SetFromErrno(PyExc_OSError);
370 goto exit;
371 }
Victor Stinner2c5d3cb2011-10-11 22:35:52 +0200372 if (n2 >= (size_t)n1) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000373 /* more space needed */
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000374 wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t));
375 if (!new_buf) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000376 PyErr_NoMemory();
377 goto exit;
378 }
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000379 buf = new_buf;
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200380 errno = 0;
Martin v. Löwisdb1c3992009-05-23 10:38:26 +0000381 n2 = wcsxfrm(buf, s, n2+1);
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200382 if (errno) {
383 PyErr_SetFromErrno(PyExc_OSError);
384 goto exit;
385 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000386 }
387 result = PyUnicode_FromWideChar(buf, n2);
Victor Stinner63649272011-09-29 23:32:06 +0200388exit:
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200389 PyMem_Free(buf);
390 PyMem_Free(s);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000391 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000392}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000393#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000394
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000395#if defined(MS_WINDOWS)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000396static PyObject*
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530397PyLocale_getdefaultlocale(PyObject* self, PyObject *Py_UNUSED(ignored))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000398{
Victor Stinner9e4994d2018-08-28 23:26:33 +0200399 char encoding[20];
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000400 char locale[100];
401
Tim Peters885d4572001-11-28 20:27:42 +0000402 PyOS_snprintf(encoding, sizeof(encoding), "cp%d", GetACP());
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000403
404 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
405 LOCALE_SISO639LANGNAME,
406 locale, sizeof(locale))) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000407 Py_ssize_t i = strlen(locale);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000408 locale[i++] = '_';
409 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
410 LOCALE_SISO3166CTRYNAME,
Martin v. Löwis18e16552006-02-15 17:27:45 +0000411 locale+i, (int)(sizeof(locale)-i)))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000412 return Py_BuildValue("ss", locale, encoding);
413 }
414
415 /* If we end up here, this windows version didn't know about
416 ISO639/ISO3166 names (it's probably Windows 95). Return the
417 Windows language identifier instead (a hexadecimal number) */
418
419 locale[0] = '0';
420 locale[1] = 'x';
421 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
422 locale+2, sizeof(locale)-2)) {
423 return Py_BuildValue("ss", locale, encoding);
424 }
425
426 /* cannot determine the language code (very unlikely) */
427 Py_INCREF(Py_None);
428 return Py_BuildValue("Os", Py_None, encoding);
429}
430#endif
431
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000432#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000433#define LANGINFO(X) {#X, X}
Martin v. Löwis59683e82008-06-13 07:50:45 +0000434static struct langinfo_constant{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000435 char* name;
436 int value;
437} langinfo_constants[] =
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000438{
439 /* These constants should exist on any langinfo implementation */
440 LANGINFO(DAY_1),
441 LANGINFO(DAY_2),
442 LANGINFO(DAY_3),
443 LANGINFO(DAY_4),
444 LANGINFO(DAY_5),
445 LANGINFO(DAY_6),
446 LANGINFO(DAY_7),
447
448 LANGINFO(ABDAY_1),
449 LANGINFO(ABDAY_2),
450 LANGINFO(ABDAY_3),
451 LANGINFO(ABDAY_4),
452 LANGINFO(ABDAY_5),
453 LANGINFO(ABDAY_6),
454 LANGINFO(ABDAY_7),
455
456 LANGINFO(MON_1),
457 LANGINFO(MON_2),
458 LANGINFO(MON_3),
459 LANGINFO(MON_4),
460 LANGINFO(MON_5),
461 LANGINFO(MON_6),
462 LANGINFO(MON_7),
463 LANGINFO(MON_8),
464 LANGINFO(MON_9),
465 LANGINFO(MON_10),
466 LANGINFO(MON_11),
467 LANGINFO(MON_12),
468
469 LANGINFO(ABMON_1),
470 LANGINFO(ABMON_2),
471 LANGINFO(ABMON_3),
472 LANGINFO(ABMON_4),
473 LANGINFO(ABMON_5),
474 LANGINFO(ABMON_6),
475 LANGINFO(ABMON_7),
476 LANGINFO(ABMON_8),
477 LANGINFO(ABMON_9),
478 LANGINFO(ABMON_10),
479 LANGINFO(ABMON_11),
480 LANGINFO(ABMON_12),
481
482#ifdef RADIXCHAR
483 /* The following are not available with glibc 2.0 */
484 LANGINFO(RADIXCHAR),
485 LANGINFO(THOUSEP),
486 /* YESSTR and NOSTR are deprecated in glibc, since they are
487 a special case of message translation, which should be rather
488 done using gettext. So we don't expose it to Python in the
489 first place.
490 LANGINFO(YESSTR),
491 LANGINFO(NOSTR),
492 */
493 LANGINFO(CRNCYSTR),
494#endif
495
496 LANGINFO(D_T_FMT),
497 LANGINFO(D_FMT),
498 LANGINFO(T_FMT),
499 LANGINFO(AM_STR),
500 LANGINFO(PM_STR),
501
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000502 /* The following constants are available only with XPG4, but...
503 AIX 3.2. only has CODESET.
504 OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have
505 a few of the others.
506 Solution: ifdef-test them all. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000507#ifdef CODESET
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000508 LANGINFO(CODESET),
Martin v. Löwis496f9e42002-03-27 12:15:57 +0000509#endif
510#ifdef T_FMT_AMPM
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000511 LANGINFO(T_FMT_AMPM),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000512#endif
513#ifdef ERA
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000514 LANGINFO(ERA),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000515#endif
516#ifdef ERA_D_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000517 LANGINFO(ERA_D_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000518#endif
519#ifdef ERA_D_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000520 LANGINFO(ERA_D_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000521#endif
522#ifdef ERA_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000523 LANGINFO(ERA_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000524#endif
525#ifdef ALT_DIGITS
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000526 LANGINFO(ALT_DIGITS),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000527#endif
528#ifdef YESEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000529 LANGINFO(YESEXPR),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000530#endif
531#ifdef NOEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000532 LANGINFO(NOEXPR),
533#endif
534#ifdef _DATE_FMT
535 /* This is not available in all glibc versions that have CODESET. */
536 LANGINFO(_DATE_FMT),
537#endif
538 {0, 0}
539};
540
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000541PyDoc_STRVAR(nl_langinfo__doc__,
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000542"nl_langinfo(key) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000543"Return the value for the locale information associated with key.");
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000544
545static PyObject*
546PyLocale_nl_langinfo(PyObject* self, PyObject* args)
547{
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000548 int item, i;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000549 if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item))
550 return NULL;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000551 /* Check whether this is a supported constant. GNU libc sometimes
552 returns numeric values in the char* return value, which would
Neal Norwitz7f9d29c2007-08-26 07:21:45 +0000553 crash PyUnicode_FromString. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000554 for (i = 0; langinfo_constants[i].name; i++)
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000555 if (langinfo_constants[i].value == item) {
556 /* Check NULL as a workaround for GNU libc's returning NULL
557 instead of an empty string for nl_langinfo(ERA). */
558 const char *result = nl_langinfo(item);
Neal Norwitz3d7a90d2007-10-27 05:40:06 +0000559 result = result != NULL ? result : "";
Victor Stinnera9c895d2012-02-14 02:33:38 +0100560 return PyUnicode_DecodeLocale(result, NULL);
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000561 }
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000562 PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
563 return NULL;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000564}
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000565#endif /* HAVE_LANGINFO_H */
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000566
567#ifdef HAVE_LIBINTL_H
568
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000569PyDoc_STRVAR(gettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000570"gettext(msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000571"Return translation of msg.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000572
573static PyObject*
574PyIntl_gettext(PyObject* self, PyObject *args)
575{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 char *in;
577 if (!PyArg_ParseTuple(args, "s", &in))
578 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100579 return PyUnicode_DecodeLocale(gettext(in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000580}
581
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000582PyDoc_STRVAR(dgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000583"dgettext(domain, msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000584"Return translation of msg in domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000585
586static PyObject*
587PyIntl_dgettext(PyObject* self, PyObject *args)
588{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 char *domain, *in;
590 if (!PyArg_ParseTuple(args, "zs", &domain, &in))
591 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100592 return PyUnicode_DecodeLocale(dgettext(domain, in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000593}
594
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000595PyDoc_STRVAR(dcgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000596"dcgettext(domain, msg, category) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000597"Return translation of msg in domain and category.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000598
599static PyObject*
600PyIntl_dcgettext(PyObject *self, PyObject *args)
601{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 char *domain, *msgid;
603 int category;
604 if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category))
605 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100606 return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000607}
608
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000609PyDoc_STRVAR(textdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000610"textdomain(domain) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000611"Set the C library's textdmain to domain, returning the new domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000612
613static PyObject*
614PyIntl_textdomain(PyObject* self, PyObject* args)
615{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 char *domain;
617 if (!PyArg_ParseTuple(args, "z", &domain))
618 return 0;
619 domain = textdomain(domain);
620 if (!domain) {
621 PyErr_SetFromErrno(PyExc_OSError);
622 return NULL;
623 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100624 return PyUnicode_DecodeLocale(domain, NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000625}
626
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000627PyDoc_STRVAR(bindtextdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000628"bindtextdomain(domain, dir) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000629"Bind the C library's domain to dir.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000630
631static PyObject*
632PyIntl_bindtextdomain(PyObject* self,PyObject*args)
633{
Victor Stinner9e19ca42010-06-11 22:09:51 +0000634 char *domain, *dirname, *current_dirname;
635 PyObject *dirname_obj, *dirname_bytes = NULL, *result;
636 if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 return 0;
638 if (!strlen(domain)) {
639 PyErr_SetString(Error, "domain must be a non-empty string");
640 return 0;
641 }
Victor Stinner9e19ca42010-06-11 22:09:51 +0000642 if (dirname_obj != Py_None) {
643 if (!PyUnicode_FSConverter(dirname_obj, &dirname_bytes))
644 return NULL;
645 dirname = PyBytes_AsString(dirname_bytes);
646 } else {
647 dirname_bytes = NULL;
648 dirname = NULL;
649 }
650 current_dirname = bindtextdomain(domain, dirname);
651 if (current_dirname == NULL) {
652 Py_XDECREF(dirname_bytes);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 PyErr_SetFromErrno(PyExc_OSError);
654 return NULL;
655 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100656 result = PyUnicode_DecodeLocale(current_dirname, NULL);
Victor Stinner9e19ca42010-06-11 22:09:51 +0000657 Py_XDECREF(dirname_bytes);
658 return result;
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000659}
660
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000661#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
662PyDoc_STRVAR(bind_textdomain_codeset__doc__,
663"bind_textdomain_codeset(domain, codeset) -> string\n"
664"Bind the C library's domain to codeset.");
665
666static PyObject*
667PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args)
668{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 char *domain,*codeset;
670 if (!PyArg_ParseTuple(args, "sz", &domain, &codeset))
671 return NULL;
672 codeset = bind_textdomain_codeset(domain, codeset);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100673 if (codeset) {
Victor Stinnera9c895d2012-02-14 02:33:38 +0100674 return PyUnicode_DecodeLocale(codeset, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100675 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 Py_RETURN_NONE;
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000677}
678#endif
679
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000680#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000681
Guido van Rossum220ecc81997-11-18 21:03:39 +0000682static struct PyMethodDef PyLocale_Methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 {"setlocale", (PyCFunction) PyLocale_setlocale,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000684 METH_VARARGS, setlocale__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530685 {"localeconv", PyLocale_localeconv, METH_NOARGS, localeconv__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000686#ifdef HAVE_WCSCOLL
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 {"strcoll", (PyCFunction) PyLocale_strcoll,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000688 METH_VARARGS, strcoll__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000689#endif
690#ifdef HAVE_WCSXFRM
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000692 METH_VARARGS, strxfrm__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000693#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694#if defined(MS_WINDOWS)
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530695 {"_getdefaultlocale", PyLocale_getdefaultlocale, METH_NOARGS},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000696#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000697#ifdef HAVE_LANGINFO_H
698 {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo,
699 METH_VARARGS, nl_langinfo__doc__},
700#endif
Martin v. Löwisc6a7d7e2002-05-02 12:16:29 +0000701#ifdef HAVE_LIBINTL_H
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000702 {"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS,
703 gettext__doc__},
704 {"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS,
705 dgettext__doc__},
706 {"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS,
707 dcgettext__doc__},
708 {"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS,
709 textdomain__doc__},
710 {"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS,
711 bindtextdomain__doc__},
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000712#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
713 {"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset,
714 METH_VARARGS, bind_textdomain_codeset__doc__},
715#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000717 {NULL, NULL}
718};
719
Martin v. Löwis1a214512008-06-11 05:26:20 +0000720
721static struct PyModuleDef _localemodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 PyModuleDef_HEAD_INIT,
723 "_locale",
724 locale__doc__,
725 -1,
726 PyLocale_Methods,
727 NULL,
728 NULL,
729 NULL,
730 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000731};
732
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000733PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000734PyInit__locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000735{
Christian Heimesff4fddd2016-09-09 00:24:12 +0200736 PyObject *m;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000737#ifdef HAVE_LANGINFO_H
738 int i;
739#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000740
Martin v. Löwis1a214512008-06-11 05:26:20 +0000741 m = PyModule_Create(&_localemodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000742 if (m == NULL)
Christian Heimesff4fddd2016-09-09 00:24:12 +0200743 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000744
Christian Heimesff4fddd2016-09-09 00:24:12 +0200745 PyModule_AddIntMacro(m, LC_CTYPE);
746 PyModule_AddIntMacro(m, LC_TIME);
747 PyModule_AddIntMacro(m, LC_COLLATE);
748 PyModule_AddIntMacro(m, LC_MONETARY);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000749
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000750#ifdef LC_MESSAGES
Christian Heimesff4fddd2016-09-09 00:24:12 +0200751 PyModule_AddIntMacro(m, LC_MESSAGES);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000752#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000753
Christian Heimesff4fddd2016-09-09 00:24:12 +0200754 PyModule_AddIntMacro(m, LC_NUMERIC);
755 PyModule_AddIntMacro(m, LC_ALL);
756 PyModule_AddIntMacro(m, CHAR_MAX);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000757
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000758 Error = PyErr_NewException("locale.Error", NULL, NULL);
Christian Heimesff4fddd2016-09-09 00:24:12 +0200759 if (Error == NULL) {
760 Py_DECREF(m);
761 return NULL;
762 }
763 PyModule_AddObject(m, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000764
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000765#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000766 for (i = 0; langinfo_constants[i].name; i++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767 PyModule_AddIntConstant(m, langinfo_constants[i].name,
768 langinfo_constants[i].value);
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000769 }
Martin v. Löwisf95dd0a2001-08-15 17:14:33 +0000770#endif
Christian Heimesff4fddd2016-09-09 00:24:12 +0200771
772 if (PyErr_Occurred()) {
773 Py_DECREF(m);
774 return NULL;
775 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000776 return m;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000777}
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000778
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779/*
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000780Local variables:
781c-basic-offset: 4
782indent-tabs-mode: nil
783End:
784*/