blob: 036bdb301f3203306aa010d461454d4884624ea8 [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]);
Zackery Spytz99d56b52018-12-08 07:16:55 -070074 if (val == NULL) {
75 Py_DECREF(result);
76 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000077 }
Zackery Spytz99d56b52018-12-08 07:16:55 -070078 PyList_SET_ITEM(result, i, val);
Fredrik Lundh8f017a02000-07-08 19:57:37 +000079 } while (s[i] != '\0' && s[i] != CHAR_MAX);
80
Fredrik Lundh8f017a02000-07-08 19:57:37 +000081 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +000082}
83
Guido van Rossum220ecc81997-11-18 21:03:39 +000084static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +000085PyLocale_setlocale(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +000086{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000087 int category;
88 char *locale = NULL, *result;
89 PyObject *result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +000090
Fredrik Lundh8f017a02000-07-08 19:57:37 +000091 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
Fredrik Lundh89610a42000-07-08 20:07:24 +000092 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000093
Amaury Forgeot d'Arc64f3ca42009-12-01 21:59:18 +000094#if defined(MS_WINDOWS)
95 if (category < LC_MIN || category > LC_MAX)
96 {
97 PyErr_SetString(Error, "invalid locale category");
98 return NULL;
99 }
100#endif
101
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000102 if (locale) {
103 /* set locale */
104 result = setlocale(category, locale);
105 if (!result) {
106 /* operation failed, no setting was changed */
Martin v. Löwis25f90d52003-09-03 04:50:13 +0000107 PyErr_SetString(Error, "unsupported locale setting");
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000108 return NULL;
109 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100110 result_object = PyUnicode_DecodeLocale(result, NULL);
Mark Hammond9a714752003-07-24 14:15:07 +0000111 if (!result_object)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000112 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000113 } else {
114 /* get locale */
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000115 result = setlocale(category, NULL);
116 if (!result) {
117 PyErr_SetString(Error, "locale query failed");
118 return NULL;
119 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100120 result_object = PyUnicode_DecodeLocale(result, NULL);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000121 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000122 return result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000123}
124
Victor Stinner02e6bf72018-11-20 16:20:16 +0100125static int
126locale_is_ascii(const char *str)
127{
128 return (strlen(str) == 1 && ((unsigned char)str[0]) <= 127);
129}
130
131static int
132locale_decode_monetary(PyObject *dict, struct lconv *lc)
133{
134 int change_locale;
135 change_locale = (!locale_is_ascii(lc->int_curr_symbol)
136 || !locale_is_ascii(lc->currency_symbol)
137 || !locale_is_ascii(lc->mon_decimal_point)
138 || !locale_is_ascii(lc->mon_thousands_sep));
139
140 /* Keep a copy of the LC_CTYPE locale */
141 char *oldloc = NULL, *loc = NULL;
142 if (change_locale) {
143 oldloc = setlocale(LC_CTYPE, NULL);
144 if (!oldloc) {
145 PyErr_SetString(PyExc_RuntimeWarning,
146 "failed to get LC_CTYPE locale");
147 return -1;
148 }
149
150 oldloc = _PyMem_Strdup(oldloc);
151 if (!oldloc) {
152 PyErr_NoMemory();
153 return -1;
154 }
155
156 loc = setlocale(LC_MONETARY, NULL);
157 if (loc != NULL && strcmp(loc, oldloc) == 0) {
158 loc = NULL;
159 }
160
161 if (loc != NULL) {
162 /* Only set the locale temporarily the LC_CTYPE locale
163 to the LC_MONETARY locale if the two locales are different and
164 at least one string is non-ASCII. */
165 setlocale(LC_CTYPE, loc);
166 }
167 }
168
169 int res = -1;
170
171#define RESULT_STRING(ATTR) \
172 do { \
173 PyObject *obj; \
174 obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
175 if (obj == NULL) { \
176 goto done; \
177 } \
178 if (PyDict_SetItemString(dict, Py_STRINGIFY(ATTR), obj) < 0) { \
179 Py_DECREF(obj); \
180 goto done; \
181 } \
182 Py_DECREF(obj); \
183 } while (0)
184
185 RESULT_STRING(int_curr_symbol);
186 RESULT_STRING(currency_symbol);
187 RESULT_STRING(mon_decimal_point);
188 RESULT_STRING(mon_thousands_sep);
189#undef RESULT_STRING
190
191 res = 0;
192
193done:
194 if (loc != NULL) {
195 setlocale(LC_CTYPE, oldloc);
196 }
197 PyMem_Free(oldloc);
198 return res;
199}
200
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000201PyDoc_STRVAR(localeconv__doc__,
202"() -> dict. Returns numeric and monetary locale-specific parameters.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000203
204static PyObject*
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530205PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
Guido van Rossum220ecc81997-11-18 21:03:39 +0000206{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000207 PyObject* result;
Victor Stinner02e6bf72018-11-20 16:20:16 +0100208 struct lconv *lc;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000209 PyObject *x;
210
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000211 result = PyDict_New();
Victor Stinnercb064fc2018-01-15 15:58:02 +0100212 if (!result) {
Fredrik Lundh89610a42000-07-08 20:07:24 +0000213 return NULL;
Victor Stinnercb064fc2018-01-15 15:58:02 +0100214 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000215
216 /* if LC_NUMERIC is different in the C library, use saved value */
Victor Stinner02e6bf72018-11-20 16:20:16 +0100217 lc = localeconv();
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000218
219 /* hopefully, the localeconv result survives the C library calls
220 involved herein */
221
Victor Stinnerd594f242013-07-17 00:55:57 +0200222#define RESULT(key, obj)\
223 do { \
224 if (obj == NULL) \
225 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100226 if (PyDict_SetItemString(result, key, obj) < 0) { \
227 Py_DECREF(obj); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200228 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100229 } \
Victor Stinnerd594f242013-07-17 00:55:57 +0200230 Py_DECREF(obj); \
231 } while (0)
232
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000233#define RESULT_STRING(s)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200234 do { \
Victor Stinner02e6bf72018-11-20 16:20:16 +0100235 x = PyUnicode_DecodeLocale(lc->s, NULL); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200236 RESULT(#s, x); \
237 } while (0)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000238
239#define RESULT_INT(i)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200240 do { \
Victor Stinner02e6bf72018-11-20 16:20:16 +0100241 x = PyLong_FromLong(lc->i); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200242 RESULT(#i, x); \
243 } while (0)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000244
Victor Stinner02e6bf72018-11-20 16:20:16 +0100245 /* Monetary information: LC_MONETARY encoding */
246 if (locale_decode_monetary(result, lc) < 0) {
247 goto failed;
248 }
249 x = copy_grouping(lc->mon_grouping);
Victor Stinnerd594f242013-07-17 00:55:57 +0200250 RESULT("mon_grouping", x);
251
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000252 RESULT_STRING(positive_sign);
253 RESULT_STRING(negative_sign);
254 RESULT_INT(int_frac_digits);
255 RESULT_INT(frac_digits);
256 RESULT_INT(p_cs_precedes);
257 RESULT_INT(p_sep_by_space);
258 RESULT_INT(n_cs_precedes);
259 RESULT_INT(n_sep_by_space);
260 RESULT_INT(p_sign_posn);
261 RESULT_INT(n_sign_posn);
Victor Stinnercb064fc2018-01-15 15:58:02 +0100262
Victor Stinner02e6bf72018-11-20 16:20:16 +0100263 /* Numeric information: LC_NUMERIC encoding */
Victor Stinnercb064fc2018-01-15 15:58:02 +0100264 PyObject *decimal_point, *thousands_sep;
Victor Stinner02e6bf72018-11-20 16:20:16 +0100265 if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) {
Victor Stinnercb064fc2018-01-15 15:58:02 +0100266 goto failed;
267 }
268
269 if (PyDict_SetItemString(result, "decimal_point", decimal_point) < 0) {
270 Py_DECREF(decimal_point);
271 Py_DECREF(thousands_sep);
272 goto failed;
273 }
274 Py_DECREF(decimal_point);
275
276 if (PyDict_SetItemString(result, "thousands_sep", thousands_sep) < 0) {
277 Py_DECREF(thousands_sep);
278 goto failed;
279 }
280 Py_DECREF(thousands_sep);
281
Victor Stinner02e6bf72018-11-20 16:20:16 +0100282 x = copy_grouping(lc->grouping);
Victor Stinnercb064fc2018-01-15 15:58:02 +0100283 RESULT("grouping", x);
284
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000285 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000286
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000287 failed:
Victor Stinnercb064fc2018-01-15 15:58:02 +0100288 Py_DECREF(result);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000289 return NULL;
Victor Stinner02e6bf72018-11-20 16:20:16 +0100290
291#undef RESULT
292#undef RESULT_STRING
293#undef RESULT_INT
Guido van Rossum220ecc81997-11-18 21:03:39 +0000294}
295
Martin v. Löwis92fab752008-03-08 10:40:41 +0000296#if defined(HAVE_WCSCOLL)
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000297PyDoc_STRVAR(strcoll__doc__,
298"string,string -> int. Compares two strings according to the locale.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000299
300static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000301PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000302{
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000303 PyObject *os1, *os2, *result = NULL;
304 wchar_t *ws1 = NULL, *ws2 = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305
Martin v. Löwis92fab752008-03-08 10:40:41 +0000306 if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2))
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000307 return NULL;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000308 /* Convert the unicode strings to wchar[]. */
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000309 ws1 = PyUnicode_AsWideCharString(os1, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000310 if (ws1 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000311 goto done;
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000312 ws2 = PyUnicode_AsWideCharString(os2, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000313 if (ws2 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000314 goto done;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000315 /* Collate the strings. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000316 result = PyLong_FromLong(wcscoll(ws1, ws2));
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000317 done:
318 /* Deallocate everything. */
319 if (ws1) PyMem_FREE(ws1);
320 if (ws2) PyMem_FREE(ws2);
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000321 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000322}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000323#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000324
Martin v. Löwis92fab752008-03-08 10:40:41 +0000325#ifdef HAVE_WCSXFRM
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000326PyDoc_STRVAR(strxfrm__doc__,
Mark Dickinson211c6252009-02-01 10:28:51 +0000327"strxfrm(string) -> string.\n\
328\n\
329Return a string that can be used as a key for locale-aware comparisons.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000330
331static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000332PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000333{
Victor Stinner63649272011-09-29 23:32:06 +0200334 PyObject *str;
335 Py_ssize_t n1;
336 wchar_t *s = NULL, *buf = NULL;
337 size_t n2;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000338 PyObject *result = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000339
Victor Stinner63649272011-09-29 23:32:06 +0200340 if (!PyArg_ParseTuple(args, "U:strxfrm", &str))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000341 return NULL;
342
Victor Stinner63649272011-09-29 23:32:06 +0200343 s = PyUnicode_AsWideCharString(str, &n1);
344 if (s == NULL)
345 goto exit;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300346 if (wcslen(s) != (size_t)n1) {
347 PyErr_SetString(PyExc_ValueError,
348 "embedded null character");
349 goto exit;
350 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000351
352 /* assume no change in size, first */
Victor Stinner63649272011-09-29 23:32:06 +0200353 n1 = n1 + 1;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200354 buf = PyMem_New(wchar_t, n1);
Martin v. Löwis92fab752008-03-08 10:40:41 +0000355 if (!buf) {
356 PyErr_NoMemory();
357 goto exit;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000358 }
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200359 errno = 0;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000360 n2 = wcsxfrm(buf, s, n1);
Benjamin Petersonad4a0cc2017-03-07 22:24:44 -0800361 if (errno && errno != ERANGE) {
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200362 PyErr_SetFromErrno(PyExc_OSError);
363 goto exit;
364 }
Victor Stinner2c5d3cb2011-10-11 22:35:52 +0200365 if (n2 >= (size_t)n1) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000366 /* more space needed */
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000367 wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t));
368 if (!new_buf) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000369 PyErr_NoMemory();
370 goto exit;
371 }
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000372 buf = new_buf;
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200373 errno = 0;
Martin v. Löwisdb1c3992009-05-23 10:38:26 +0000374 n2 = wcsxfrm(buf, s, n2+1);
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200375 if (errno) {
376 PyErr_SetFromErrno(PyExc_OSError);
377 goto exit;
378 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000379 }
380 result = PyUnicode_FromWideChar(buf, n2);
Victor Stinner63649272011-09-29 23:32:06 +0200381exit:
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200382 PyMem_Free(buf);
383 PyMem_Free(s);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000384 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000385}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000386#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000387
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000388#if defined(MS_WINDOWS)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000389static PyObject*
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530390PyLocale_getdefaultlocale(PyObject* self, PyObject *Py_UNUSED(ignored))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000391{
Victor Stinner9e4994d2018-08-28 23:26:33 +0200392 char encoding[20];
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000393 char locale[100];
394
Serhiy Storchakad53fe5f2019-03-13 22:59:55 +0200395 PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP());
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000396
397 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
398 LOCALE_SISO639LANGNAME,
399 locale, sizeof(locale))) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000400 Py_ssize_t i = strlen(locale);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000401 locale[i++] = '_';
402 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
403 LOCALE_SISO3166CTRYNAME,
Martin v. Löwis18e16552006-02-15 17:27:45 +0000404 locale+i, (int)(sizeof(locale)-i)))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000405 return Py_BuildValue("ss", locale, encoding);
406 }
407
408 /* If we end up here, this windows version didn't know about
409 ISO639/ISO3166 names (it's probably Windows 95). Return the
410 Windows language identifier instead (a hexadecimal number) */
411
412 locale[0] = '0';
413 locale[1] = 'x';
414 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
415 locale+2, sizeof(locale)-2)) {
416 return Py_BuildValue("ss", locale, encoding);
417 }
418
419 /* cannot determine the language code (very unlikely) */
420 Py_INCREF(Py_None);
421 return Py_BuildValue("Os", Py_None, encoding);
422}
423#endif
424
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000425#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000426#define LANGINFO(X) {#X, X}
Martin v. Löwis59683e82008-06-13 07:50:45 +0000427static struct langinfo_constant{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000428 char* name;
429 int value;
430} langinfo_constants[] =
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000431{
432 /* These constants should exist on any langinfo implementation */
433 LANGINFO(DAY_1),
434 LANGINFO(DAY_2),
435 LANGINFO(DAY_3),
436 LANGINFO(DAY_4),
437 LANGINFO(DAY_5),
438 LANGINFO(DAY_6),
439 LANGINFO(DAY_7),
440
441 LANGINFO(ABDAY_1),
442 LANGINFO(ABDAY_2),
443 LANGINFO(ABDAY_3),
444 LANGINFO(ABDAY_4),
445 LANGINFO(ABDAY_5),
446 LANGINFO(ABDAY_6),
447 LANGINFO(ABDAY_7),
448
449 LANGINFO(MON_1),
450 LANGINFO(MON_2),
451 LANGINFO(MON_3),
452 LANGINFO(MON_4),
453 LANGINFO(MON_5),
454 LANGINFO(MON_6),
455 LANGINFO(MON_7),
456 LANGINFO(MON_8),
457 LANGINFO(MON_9),
458 LANGINFO(MON_10),
459 LANGINFO(MON_11),
460 LANGINFO(MON_12),
461
462 LANGINFO(ABMON_1),
463 LANGINFO(ABMON_2),
464 LANGINFO(ABMON_3),
465 LANGINFO(ABMON_4),
466 LANGINFO(ABMON_5),
467 LANGINFO(ABMON_6),
468 LANGINFO(ABMON_7),
469 LANGINFO(ABMON_8),
470 LANGINFO(ABMON_9),
471 LANGINFO(ABMON_10),
472 LANGINFO(ABMON_11),
473 LANGINFO(ABMON_12),
474
475#ifdef RADIXCHAR
476 /* The following are not available with glibc 2.0 */
477 LANGINFO(RADIXCHAR),
478 LANGINFO(THOUSEP),
479 /* YESSTR and NOSTR are deprecated in glibc, since they are
480 a special case of message translation, which should be rather
481 done using gettext. So we don't expose it to Python in the
482 first place.
483 LANGINFO(YESSTR),
484 LANGINFO(NOSTR),
485 */
486 LANGINFO(CRNCYSTR),
487#endif
488
489 LANGINFO(D_T_FMT),
490 LANGINFO(D_FMT),
491 LANGINFO(T_FMT),
492 LANGINFO(AM_STR),
493 LANGINFO(PM_STR),
494
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000495 /* The following constants are available only with XPG4, but...
496 AIX 3.2. only has CODESET.
497 OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have
498 a few of the others.
499 Solution: ifdef-test them all. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000500#ifdef CODESET
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000501 LANGINFO(CODESET),
Martin v. Löwis496f9e42002-03-27 12:15:57 +0000502#endif
503#ifdef T_FMT_AMPM
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000504 LANGINFO(T_FMT_AMPM),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000505#endif
506#ifdef ERA
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000507 LANGINFO(ERA),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000508#endif
509#ifdef ERA_D_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000510 LANGINFO(ERA_D_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000511#endif
512#ifdef ERA_D_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000513 LANGINFO(ERA_D_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000514#endif
515#ifdef ERA_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000516 LANGINFO(ERA_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000517#endif
518#ifdef ALT_DIGITS
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000519 LANGINFO(ALT_DIGITS),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000520#endif
521#ifdef YESEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000522 LANGINFO(YESEXPR),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000523#endif
524#ifdef NOEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000525 LANGINFO(NOEXPR),
526#endif
527#ifdef _DATE_FMT
528 /* This is not available in all glibc versions that have CODESET. */
529 LANGINFO(_DATE_FMT),
530#endif
531 {0, 0}
532};
533
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000534PyDoc_STRVAR(nl_langinfo__doc__,
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000535"nl_langinfo(key) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000536"Return the value for the locale information associated with key.");
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000537
538static PyObject*
539PyLocale_nl_langinfo(PyObject* self, PyObject* args)
540{
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000541 int item, i;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000542 if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item))
543 return NULL;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000544 /* Check whether this is a supported constant. GNU libc sometimes
545 returns numeric values in the char* return value, which would
Neal Norwitz7f9d29c2007-08-26 07:21:45 +0000546 crash PyUnicode_FromString. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000547 for (i = 0; langinfo_constants[i].name; i++)
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000548 if (langinfo_constants[i].value == item) {
549 /* Check NULL as a workaround for GNU libc's returning NULL
550 instead of an empty string for nl_langinfo(ERA). */
551 const char *result = nl_langinfo(item);
Neal Norwitz3d7a90d2007-10-27 05:40:06 +0000552 result = result != NULL ? result : "";
Victor Stinnera9c895d2012-02-14 02:33:38 +0100553 return PyUnicode_DecodeLocale(result, NULL);
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000554 }
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000555 PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
556 return NULL;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000557}
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000558#endif /* HAVE_LANGINFO_H */
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000559
560#ifdef HAVE_LIBINTL_H
561
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000562PyDoc_STRVAR(gettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000563"gettext(msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000564"Return translation of msg.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000565
566static PyObject*
567PyIntl_gettext(PyObject* self, PyObject *args)
568{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 char *in;
570 if (!PyArg_ParseTuple(args, "s", &in))
571 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100572 return PyUnicode_DecodeLocale(gettext(in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000573}
574
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000575PyDoc_STRVAR(dgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000576"dgettext(domain, msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000577"Return translation of msg in domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000578
579static PyObject*
580PyIntl_dgettext(PyObject* self, PyObject *args)
581{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 char *domain, *in;
583 if (!PyArg_ParseTuple(args, "zs", &domain, &in))
584 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100585 return PyUnicode_DecodeLocale(dgettext(domain, in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000586}
587
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000588PyDoc_STRVAR(dcgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000589"dcgettext(domain, msg, category) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000590"Return translation of msg in domain and category.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000591
592static PyObject*
593PyIntl_dcgettext(PyObject *self, PyObject *args)
594{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 char *domain, *msgid;
596 int category;
597 if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category))
598 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100599 return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000600}
601
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000602PyDoc_STRVAR(textdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000603"textdomain(domain) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000604"Set the C library's textdmain to domain, returning the new domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000605
606static PyObject*
607PyIntl_textdomain(PyObject* self, PyObject* args)
608{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 char *domain;
610 if (!PyArg_ParseTuple(args, "z", &domain))
611 return 0;
612 domain = textdomain(domain);
613 if (!domain) {
614 PyErr_SetFromErrno(PyExc_OSError);
615 return NULL;
616 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100617 return PyUnicode_DecodeLocale(domain, NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000618}
619
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000620PyDoc_STRVAR(bindtextdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000621"bindtextdomain(domain, dir) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000622"Bind the C library's domain to dir.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000623
624static PyObject*
625PyIntl_bindtextdomain(PyObject* self,PyObject*args)
626{
Victor Stinner9e19ca42010-06-11 22:09:51 +0000627 char *domain, *dirname, *current_dirname;
628 PyObject *dirname_obj, *dirname_bytes = NULL, *result;
629 if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 return 0;
631 if (!strlen(domain)) {
632 PyErr_SetString(Error, "domain must be a non-empty string");
633 return 0;
634 }
Victor Stinner9e19ca42010-06-11 22:09:51 +0000635 if (dirname_obj != Py_None) {
636 if (!PyUnicode_FSConverter(dirname_obj, &dirname_bytes))
637 return NULL;
638 dirname = PyBytes_AsString(dirname_bytes);
639 } else {
640 dirname_bytes = NULL;
641 dirname = NULL;
642 }
643 current_dirname = bindtextdomain(domain, dirname);
644 if (current_dirname == NULL) {
645 Py_XDECREF(dirname_bytes);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 PyErr_SetFromErrno(PyExc_OSError);
647 return NULL;
648 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100649 result = PyUnicode_DecodeLocale(current_dirname, NULL);
Victor Stinner9e19ca42010-06-11 22:09:51 +0000650 Py_XDECREF(dirname_bytes);
651 return result;
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000652}
653
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000654#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
655PyDoc_STRVAR(bind_textdomain_codeset__doc__,
656"bind_textdomain_codeset(domain, codeset) -> string\n"
657"Bind the C library's domain to codeset.");
658
659static PyObject*
660PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args)
661{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 char *domain,*codeset;
663 if (!PyArg_ParseTuple(args, "sz", &domain, &codeset))
664 return NULL;
665 codeset = bind_textdomain_codeset(domain, codeset);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100666 if (codeset) {
Victor Stinnera9c895d2012-02-14 02:33:38 +0100667 return PyUnicode_DecodeLocale(codeset, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100668 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 Py_RETURN_NONE;
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000670}
671#endif
672
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000673#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000674
Guido van Rossum220ecc81997-11-18 21:03:39 +0000675static struct PyMethodDef PyLocale_Methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 {"setlocale", (PyCFunction) PyLocale_setlocale,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000677 METH_VARARGS, setlocale__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530678 {"localeconv", PyLocale_localeconv, METH_NOARGS, localeconv__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000679#ifdef HAVE_WCSCOLL
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 {"strcoll", (PyCFunction) PyLocale_strcoll,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000681 METH_VARARGS, strcoll__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000682#endif
683#ifdef HAVE_WCSXFRM
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000685 METH_VARARGS, strxfrm__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000686#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687#if defined(MS_WINDOWS)
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530688 {"_getdefaultlocale", PyLocale_getdefaultlocale, METH_NOARGS},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000689#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000690#ifdef HAVE_LANGINFO_H
691 {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo,
692 METH_VARARGS, nl_langinfo__doc__},
693#endif
Martin v. Löwisc6a7d7e2002-05-02 12:16:29 +0000694#ifdef HAVE_LIBINTL_H
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000695 {"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS,
696 gettext__doc__},
697 {"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS,
698 dgettext__doc__},
699 {"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS,
700 dcgettext__doc__},
701 {"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS,
702 textdomain__doc__},
703 {"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS,
704 bindtextdomain__doc__},
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000705#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
706 {"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset,
707 METH_VARARGS, bind_textdomain_codeset__doc__},
708#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000710 {NULL, NULL}
711};
712
Martin v. Löwis1a214512008-06-11 05:26:20 +0000713
714static struct PyModuleDef _localemodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 PyModuleDef_HEAD_INIT,
716 "_locale",
717 locale__doc__,
718 -1,
719 PyLocale_Methods,
720 NULL,
721 NULL,
722 NULL,
723 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000724};
725
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000726PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000727PyInit__locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000728{
Christian Heimesff4fddd2016-09-09 00:24:12 +0200729 PyObject *m;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000730#ifdef HAVE_LANGINFO_H
731 int i;
732#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000733
Martin v. Löwis1a214512008-06-11 05:26:20 +0000734 m = PyModule_Create(&_localemodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000735 if (m == NULL)
Christian Heimesff4fddd2016-09-09 00:24:12 +0200736 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000737
Christian Heimesff4fddd2016-09-09 00:24:12 +0200738 PyModule_AddIntMacro(m, LC_CTYPE);
739 PyModule_AddIntMacro(m, LC_TIME);
740 PyModule_AddIntMacro(m, LC_COLLATE);
741 PyModule_AddIntMacro(m, LC_MONETARY);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000742
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000743#ifdef LC_MESSAGES
Christian Heimesff4fddd2016-09-09 00:24:12 +0200744 PyModule_AddIntMacro(m, LC_MESSAGES);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000745#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000746
Christian Heimesff4fddd2016-09-09 00:24:12 +0200747 PyModule_AddIntMacro(m, LC_NUMERIC);
748 PyModule_AddIntMacro(m, LC_ALL);
749 PyModule_AddIntMacro(m, CHAR_MAX);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000750
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000751 Error = PyErr_NewException("locale.Error", NULL, NULL);
Christian Heimesff4fddd2016-09-09 00:24:12 +0200752 if (Error == NULL) {
753 Py_DECREF(m);
754 return NULL;
755 }
756 PyModule_AddObject(m, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000757
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000758#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000759 for (i = 0; langinfo_constants[i].name; i++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760 PyModule_AddIntConstant(m, langinfo_constants[i].name,
761 langinfo_constants[i].value);
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000762 }
Martin v. Löwisf95dd0a2001-08-15 17:14:33 +0000763#endif
Christian Heimesff4fddd2016-09-09 00:24:12 +0200764
765 if (PyErr_Occurred()) {
766 Py_DECREF(m);
767 return NULL;
768 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000769 return m;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000770}
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000772/*
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000773Local variables:
774c-basic-offset: 4
775indent-tabs-mode: nil
776End:
777*/