blob: 8efda35dd4e52a8068dc2e2910e1daf829fa17c2 [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"
14
Guido van Rossum220ecc81997-11-18 21:03:39 +000015#include <stdio.h>
Guido van Rossum220ecc81997-11-18 21:03:39 +000016#include <locale.h>
17#include <string.h>
Guido van Rossum5cd70f41998-06-19 04:33:30 +000018#include <ctype.h>
Fredrik Lundh8f017a02000-07-08 19:57:37 +000019
Thomas Wouters0e3f5912006-08-11 14:57:12 +000020#ifdef HAVE_ERRNO_H
Thomas Wouters477c8d52006-05-27 19:21:47 +000021#include <errno.h>
22#endif
23
Martin v. Löwis9b75dca2001-08-10 13:58:50 +000024#ifdef HAVE_LANGINFO_H
25#include <langinfo.h>
26#endif
27
Martin v. Löwis2e64c342002-03-27 18:49:02 +000028#ifdef HAVE_LIBINTL_H
29#include <libintl.h>
30#endif
31
Martin v. Löwis9c36c292002-12-21 18:34:06 +000032#ifdef HAVE_WCHAR_H
33#include <wchar.h>
34#endif
35
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000036#if defined(MS_WINDOWS)
Tim Peters7a1f9172002-07-14 22:14:19 +000037#define WIN32_LEAN_AND_MEAN
Fredrik Lundh8f017a02000-07-08 19:57:37 +000038#include <windows.h>
Guido van Rossum239a2181998-04-28 16:08:19 +000039#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +000040
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000041PyDoc_STRVAR(locale__doc__, "Support for POSIX locales.");
Guido van Rossum220ecc81997-11-18 21:03:39 +000042
43static PyObject *Error;
44
45/* support functions for formatting floating point numbers */
46
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000047PyDoc_STRVAR(setlocale__doc__,
48"(integer,string=None) -> string. Activates/queries locale processing.");
Guido van Rossum220ecc81997-11-18 21:03:39 +000049
Guido van Rossum220ecc81997-11-18 21:03:39 +000050/* the grouping is terminated by either 0 or CHAR_MAX */
51static PyObject*
Serhiy Storchakaef1585e2015-12-25 20:01:53 +020052copy_grouping(const char* s)
Guido van Rossum220ecc81997-11-18 21:03:39 +000053{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000054 int i;
55 PyObject *result, *val = NULL;
56
Martin Panter6d57fe12016-09-17 03:26:16 +000057 if (s[0] == '\0') {
Fredrik Lundh8f017a02000-07-08 19:57:37 +000058 /* empty string: no grouping at all */
59 return PyList_New(0);
Martin Panter6d57fe12016-09-17 03:26:16 +000060 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +000061
62 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
63 ; /* nothing */
64
65 result = PyList_New(i+1);
66 if (!result)
67 return NULL;
68
69 i = -1;
70 do {
71 i++;
Christian Heimes217cfd12007-12-02 14:31:20 +000072 val = PyLong_FromLong(s[i]);
Miss Islington (bot)8b7d8ac2018-12-08 06:34:49 -080073 if (val == NULL) {
74 Py_DECREF(result);
75 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000076 }
Miss Islington (bot)8b7d8ac2018-12-08 06:34:49 -080077 PyList_SET_ITEM(result, i, val);
Fredrik Lundh8f017a02000-07-08 19:57:37 +000078 } while (s[i] != '\0' && s[i] != CHAR_MAX);
79
Fredrik Lundh8f017a02000-07-08 19:57:37 +000080 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +000081}
82
Guido van Rossum220ecc81997-11-18 21:03:39 +000083static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +000084PyLocale_setlocale(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +000085{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000086 int category;
87 char *locale = NULL, *result;
88 PyObject *result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +000089
Fredrik Lundh8f017a02000-07-08 19:57:37 +000090 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
Fredrik Lundh89610a42000-07-08 20:07:24 +000091 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000092
Amaury Forgeot d'Arc64f3ca42009-12-01 21:59:18 +000093#if defined(MS_WINDOWS)
94 if (category < LC_MIN || category > LC_MAX)
95 {
96 PyErr_SetString(Error, "invalid locale category");
97 return NULL;
98 }
99#endif
100
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000101 if (locale) {
102 /* set locale */
103 result = setlocale(category, locale);
104 if (!result) {
105 /* operation failed, no setting was changed */
Martin v. Löwis25f90d52003-09-03 04:50:13 +0000106 PyErr_SetString(Error, "unsupported locale setting");
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000107 return NULL;
108 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100109 result_object = PyUnicode_DecodeLocale(result, NULL);
Mark Hammond9a714752003-07-24 14:15:07 +0000110 if (!result_object)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000111 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000112 } else {
113 /* get locale */
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000114 result = setlocale(category, NULL);
115 if (!result) {
116 PyErr_SetString(Error, "locale query failed");
117 return NULL;
118 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100119 result_object = PyUnicode_DecodeLocale(result, NULL);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000120 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000121 return result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000122}
123
Victor Stinner6eff6b82018-11-20 22:06:21 +0100124static int
125locale_is_ascii(const char *str)
126{
127 return (strlen(str) == 1 && ((unsigned char)str[0]) <= 127);
128}
129
130static int
131locale_decode_monetary(PyObject *dict, struct lconv *lc)
132{
133 int change_locale;
134 change_locale = (!locale_is_ascii(lc->int_curr_symbol)
135 || !locale_is_ascii(lc->currency_symbol)
136 || !locale_is_ascii(lc->mon_decimal_point)
137 || !locale_is_ascii(lc->mon_thousands_sep));
138
139 /* Keep a copy of the LC_CTYPE locale */
140 char *oldloc = NULL, *loc = NULL;
141 if (change_locale) {
142 oldloc = setlocale(LC_CTYPE, NULL);
143 if (!oldloc) {
144 PyErr_SetString(PyExc_RuntimeWarning,
145 "failed to get LC_CTYPE locale");
146 return -1;
147 }
148
149 oldloc = _PyMem_Strdup(oldloc);
150 if (!oldloc) {
151 PyErr_NoMemory();
152 return -1;
153 }
154
155 loc = setlocale(LC_MONETARY, NULL);
156 if (loc != NULL && strcmp(loc, oldloc) == 0) {
157 loc = NULL;
158 }
159
160 if (loc != NULL) {
161 /* Only set the locale temporarily the LC_CTYPE locale
162 to the LC_MONETARY locale if the two locales are different and
163 at least one string is non-ASCII. */
164 setlocale(LC_CTYPE, loc);
165 }
166 }
167
168 int res = -1;
169
170#define RESULT_STRING(ATTR) \
171 do { \
172 PyObject *obj; \
173 obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
174 if (obj == NULL) { \
175 goto done; \
176 } \
177 if (PyDict_SetItemString(dict, Py_STRINGIFY(ATTR), obj) < 0) { \
178 Py_DECREF(obj); \
179 goto done; \
180 } \
181 Py_DECREF(obj); \
182 } while (0)
183
184 RESULT_STRING(int_curr_symbol);
185 RESULT_STRING(currency_symbol);
186 RESULT_STRING(mon_decimal_point);
187 RESULT_STRING(mon_thousands_sep);
188#undef RESULT_STRING
189
190 res = 0;
191
192done:
193 if (loc != NULL) {
194 setlocale(LC_CTYPE, oldloc);
195 }
196 PyMem_Free(oldloc);
197 return res;
198}
199
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000200PyDoc_STRVAR(localeconv__doc__,
201"() -> dict. Returns numeric and monetary locale-specific parameters.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000202
203static PyObject*
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000204PyLocale_localeconv(PyObject* self)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000205{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000206 PyObject* result;
207 struct lconv *l;
208 PyObject *x;
209
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000210 result = PyDict_New();
Victor Stinnercb064fc2018-01-15 15:58:02 +0100211 if (!result) {
Fredrik Lundh89610a42000-07-08 20:07:24 +0000212 return NULL;
Victor Stinnercb064fc2018-01-15 15:58:02 +0100213 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000214
215 /* if LC_NUMERIC is different in the C library, use saved value */
216 l = localeconv();
217
218 /* hopefully, the localeconv result survives the C library calls
219 involved herein */
220
Victor Stinnerd594f242013-07-17 00:55:57 +0200221#define RESULT(key, obj)\
222 do { \
223 if (obj == NULL) \
224 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100225 if (PyDict_SetItemString(result, key, obj) < 0) { \
226 Py_DECREF(obj); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200227 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100228 } \
Victor Stinnerd594f242013-07-17 00:55:57 +0200229 Py_DECREF(obj); \
230 } while (0)
231
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000232#define RESULT_STRING(s)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200233 do { \
234 x = PyUnicode_DecodeLocale(l->s, NULL); \
235 RESULT(#s, x); \
236 } while (0)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000237
238#define RESULT_INT(i)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200239 do { \
240 x = PyLong_FromLong(l->i); \
241 RESULT(#i, x); \
242 } while (0)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000243
Victor Stinner6eff6b82018-11-20 22:06:21 +0100244 /* Monetary information: LC_MONETARY encoding */
245 if (locale_decode_monetary(result, l) < 0) {
246 goto failed;
247 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000248 x = copy_grouping(l->mon_grouping);
Victor Stinnerd594f242013-07-17 00:55:57 +0200249 RESULT("mon_grouping", x);
250
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000251 RESULT_STRING(positive_sign);
252 RESULT_STRING(negative_sign);
253 RESULT_INT(int_frac_digits);
254 RESULT_INT(frac_digits);
255 RESULT_INT(p_cs_precedes);
256 RESULT_INT(p_sep_by_space);
257 RESULT_INT(n_cs_precedes);
258 RESULT_INT(n_sep_by_space);
259 RESULT_INT(p_sign_posn);
260 RESULT_INT(n_sign_posn);
Victor Stinnercb064fc2018-01-15 15:58:02 +0100261
Victor Stinner6eff6b82018-11-20 22:06:21 +0100262 /* Numeric information: LC_NUMERIC encoding */
Victor Stinnercb064fc2018-01-15 15:58:02 +0100263 PyObject *decimal_point, *thousands_sep;
264 const char *grouping;
265 if (_Py_GetLocaleconvNumeric(&decimal_point,
266 &thousands_sep,
267 &grouping) < 0) {
268 goto failed;
269 }
270
271 if (PyDict_SetItemString(result, "decimal_point", decimal_point) < 0) {
272 Py_DECREF(decimal_point);
273 Py_DECREF(thousands_sep);
274 goto failed;
275 }
276 Py_DECREF(decimal_point);
277
278 if (PyDict_SetItemString(result, "thousands_sep", thousands_sep) < 0) {
279 Py_DECREF(thousands_sep);
280 goto failed;
281 }
282 Py_DECREF(thousands_sep);
283
284 x = copy_grouping(grouping);
285 RESULT("grouping", x);
286
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000287 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000288
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000289 failed:
Victor Stinnercb064fc2018-01-15 15:58:02 +0100290 Py_DECREF(result);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000291 return NULL;
Victor Stinner6eff6b82018-11-20 22:06:21 +0100292
293#undef RESULT
294#undef RESULT_STRING
295#undef RESULT_INT
Guido van Rossum220ecc81997-11-18 21:03:39 +0000296}
297
Martin v. Löwis92fab752008-03-08 10:40:41 +0000298#if defined(HAVE_WCSCOLL)
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000299PyDoc_STRVAR(strcoll__doc__,
300"string,string -> int. Compares two strings according to the locale.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000301
302static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000303PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000304{
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000305 PyObject *os1, *os2, *result = NULL;
306 wchar_t *ws1 = NULL, *ws2 = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000307
Martin v. Löwis92fab752008-03-08 10:40:41 +0000308 if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2))
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000309 return NULL;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000310 /* Convert the unicode strings to wchar[]. */
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000311 ws1 = PyUnicode_AsWideCharString(os1, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000312 if (ws1 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000313 goto done;
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000314 ws2 = PyUnicode_AsWideCharString(os2, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000315 if (ws2 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000316 goto done;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000317 /* Collate the strings. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000318 result = PyLong_FromLong(wcscoll(ws1, ws2));
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000319 done:
320 /* Deallocate everything. */
321 if (ws1) PyMem_FREE(ws1);
322 if (ws2) PyMem_FREE(ws2);
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000323 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000324}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000325#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000326
Martin v. Löwis92fab752008-03-08 10:40:41 +0000327#ifdef HAVE_WCSXFRM
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000328PyDoc_STRVAR(strxfrm__doc__,
Mark Dickinson211c6252009-02-01 10:28:51 +0000329"strxfrm(string) -> string.\n\
330\n\
331Return a string that can be used as a key for locale-aware comparisons.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000332
333static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000334PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000335{
Victor Stinner63649272011-09-29 23:32:06 +0200336 PyObject *str;
337 Py_ssize_t n1;
338 wchar_t *s = NULL, *buf = NULL;
339 size_t n2;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000340 PyObject *result = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000341
Victor Stinner63649272011-09-29 23:32:06 +0200342 if (!PyArg_ParseTuple(args, "U:strxfrm", &str))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000343 return NULL;
344
Victor Stinner63649272011-09-29 23:32:06 +0200345 s = PyUnicode_AsWideCharString(str, &n1);
346 if (s == NULL)
347 goto exit;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300348 if (wcslen(s) != (size_t)n1) {
349 PyErr_SetString(PyExc_ValueError,
350 "embedded null character");
351 goto exit;
352 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000353
354 /* assume no change in size, first */
Victor Stinner63649272011-09-29 23:32:06 +0200355 n1 = n1 + 1;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200356 buf = PyMem_New(wchar_t, n1);
Martin v. Löwis92fab752008-03-08 10:40:41 +0000357 if (!buf) {
358 PyErr_NoMemory();
359 goto exit;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000360 }
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200361 errno = 0;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000362 n2 = wcsxfrm(buf, s, n1);
Benjamin Petersonad4a0cc2017-03-07 22:24:44 -0800363 if (errno && errno != ERANGE) {
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200364 PyErr_SetFromErrno(PyExc_OSError);
365 goto exit;
366 }
Victor Stinner2c5d3cb2011-10-11 22:35:52 +0200367 if (n2 >= (size_t)n1) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000368 /* more space needed */
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000369 wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t));
370 if (!new_buf) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000371 PyErr_NoMemory();
372 goto exit;
373 }
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000374 buf = new_buf;
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200375 errno = 0;
Martin v. Löwisdb1c3992009-05-23 10:38:26 +0000376 n2 = wcsxfrm(buf, s, n2+1);
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200377 if (errno) {
378 PyErr_SetFromErrno(PyExc_OSError);
379 goto exit;
380 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000381 }
382 result = PyUnicode_FromWideChar(buf, n2);
Victor Stinner63649272011-09-29 23:32:06 +0200383exit:
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200384 PyMem_Free(buf);
385 PyMem_Free(s);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000386 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000387}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000388#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000389
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000390#if defined(MS_WINDOWS)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000391static PyObject*
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000392PyLocale_getdefaultlocale(PyObject* self)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000393{
394 char encoding[100];
395 char locale[100];
396
Tim Peters885d4572001-11-28 20:27:42 +0000397 PyOS_snprintf(encoding, sizeof(encoding), "cp%d", GetACP());
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000398
399 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
400 LOCALE_SISO639LANGNAME,
401 locale, sizeof(locale))) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000402 Py_ssize_t i = strlen(locale);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000403 locale[i++] = '_';
404 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
405 LOCALE_SISO3166CTRYNAME,
Martin v. Löwis18e16552006-02-15 17:27:45 +0000406 locale+i, (int)(sizeof(locale)-i)))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000407 return Py_BuildValue("ss", locale, encoding);
408 }
409
410 /* If we end up here, this windows version didn't know about
411 ISO639/ISO3166 names (it's probably Windows 95). Return the
412 Windows language identifier instead (a hexadecimal number) */
413
414 locale[0] = '0';
415 locale[1] = 'x';
416 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
417 locale+2, sizeof(locale)-2)) {
418 return Py_BuildValue("ss", locale, encoding);
419 }
420
421 /* cannot determine the language code (very unlikely) */
422 Py_INCREF(Py_None);
423 return Py_BuildValue("Os", Py_None, encoding);
424}
425#endif
426
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000427#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000428#define LANGINFO(X) {#X, X}
Martin v. Löwis59683e82008-06-13 07:50:45 +0000429static struct langinfo_constant{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 char* name;
431 int value;
432} langinfo_constants[] =
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000433{
434 /* These constants should exist on any langinfo implementation */
435 LANGINFO(DAY_1),
436 LANGINFO(DAY_2),
437 LANGINFO(DAY_3),
438 LANGINFO(DAY_4),
439 LANGINFO(DAY_5),
440 LANGINFO(DAY_6),
441 LANGINFO(DAY_7),
442
443 LANGINFO(ABDAY_1),
444 LANGINFO(ABDAY_2),
445 LANGINFO(ABDAY_3),
446 LANGINFO(ABDAY_4),
447 LANGINFO(ABDAY_5),
448 LANGINFO(ABDAY_6),
449 LANGINFO(ABDAY_7),
450
451 LANGINFO(MON_1),
452 LANGINFO(MON_2),
453 LANGINFO(MON_3),
454 LANGINFO(MON_4),
455 LANGINFO(MON_5),
456 LANGINFO(MON_6),
457 LANGINFO(MON_7),
458 LANGINFO(MON_8),
459 LANGINFO(MON_9),
460 LANGINFO(MON_10),
461 LANGINFO(MON_11),
462 LANGINFO(MON_12),
463
464 LANGINFO(ABMON_1),
465 LANGINFO(ABMON_2),
466 LANGINFO(ABMON_3),
467 LANGINFO(ABMON_4),
468 LANGINFO(ABMON_5),
469 LANGINFO(ABMON_6),
470 LANGINFO(ABMON_7),
471 LANGINFO(ABMON_8),
472 LANGINFO(ABMON_9),
473 LANGINFO(ABMON_10),
474 LANGINFO(ABMON_11),
475 LANGINFO(ABMON_12),
476
477#ifdef RADIXCHAR
478 /* The following are not available with glibc 2.0 */
479 LANGINFO(RADIXCHAR),
480 LANGINFO(THOUSEP),
481 /* YESSTR and NOSTR are deprecated in glibc, since they are
482 a special case of message translation, which should be rather
483 done using gettext. So we don't expose it to Python in the
484 first place.
485 LANGINFO(YESSTR),
486 LANGINFO(NOSTR),
487 */
488 LANGINFO(CRNCYSTR),
489#endif
490
491 LANGINFO(D_T_FMT),
492 LANGINFO(D_FMT),
493 LANGINFO(T_FMT),
494 LANGINFO(AM_STR),
495 LANGINFO(PM_STR),
496
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000497 /* The following constants are available only with XPG4, but...
498 AIX 3.2. only has CODESET.
499 OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have
500 a few of the others.
501 Solution: ifdef-test them all. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000502#ifdef CODESET
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000503 LANGINFO(CODESET),
Martin v. Löwis496f9e42002-03-27 12:15:57 +0000504#endif
505#ifdef T_FMT_AMPM
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000506 LANGINFO(T_FMT_AMPM),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000507#endif
508#ifdef ERA
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000509 LANGINFO(ERA),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000510#endif
511#ifdef ERA_D_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000512 LANGINFO(ERA_D_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000513#endif
514#ifdef ERA_D_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000515 LANGINFO(ERA_D_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000516#endif
517#ifdef ERA_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000518 LANGINFO(ERA_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000519#endif
520#ifdef ALT_DIGITS
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000521 LANGINFO(ALT_DIGITS),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000522#endif
523#ifdef YESEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000524 LANGINFO(YESEXPR),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000525#endif
526#ifdef NOEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000527 LANGINFO(NOEXPR),
528#endif
529#ifdef _DATE_FMT
530 /* This is not available in all glibc versions that have CODESET. */
531 LANGINFO(_DATE_FMT),
532#endif
533 {0, 0}
534};
535
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000536PyDoc_STRVAR(nl_langinfo__doc__,
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000537"nl_langinfo(key) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000538"Return the value for the locale information associated with key.");
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000539
540static PyObject*
541PyLocale_nl_langinfo(PyObject* self, PyObject* args)
542{
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000543 int item, i;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000544 if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item))
545 return NULL;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000546 /* Check whether this is a supported constant. GNU libc sometimes
547 returns numeric values in the char* return value, which would
Neal Norwitz7f9d29c2007-08-26 07:21:45 +0000548 crash PyUnicode_FromString. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000549 for (i = 0; langinfo_constants[i].name; i++)
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000550 if (langinfo_constants[i].value == item) {
551 /* Check NULL as a workaround for GNU libc's returning NULL
552 instead of an empty string for nl_langinfo(ERA). */
553 const char *result = nl_langinfo(item);
Neal Norwitz3d7a90d2007-10-27 05:40:06 +0000554 result = result != NULL ? result : "";
Victor Stinnera9c895d2012-02-14 02:33:38 +0100555 return PyUnicode_DecodeLocale(result, NULL);
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000556 }
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000557 PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
558 return NULL;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000559}
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000560#endif /* HAVE_LANGINFO_H */
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000561
562#ifdef HAVE_LIBINTL_H
563
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000564PyDoc_STRVAR(gettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000565"gettext(msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000566"Return translation of msg.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000567
568static PyObject*
569PyIntl_gettext(PyObject* self, PyObject *args)
570{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 char *in;
572 if (!PyArg_ParseTuple(args, "s", &in))
573 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100574 return PyUnicode_DecodeLocale(gettext(in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000575}
576
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000577PyDoc_STRVAR(dgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000578"dgettext(domain, msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000579"Return translation of msg in domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000580
581static PyObject*
582PyIntl_dgettext(PyObject* self, PyObject *args)
583{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 char *domain, *in;
585 if (!PyArg_ParseTuple(args, "zs", &domain, &in))
586 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100587 return PyUnicode_DecodeLocale(dgettext(domain, in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000588}
589
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000590PyDoc_STRVAR(dcgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000591"dcgettext(domain, msg, category) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000592"Return translation of msg in domain and category.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000593
594static PyObject*
595PyIntl_dcgettext(PyObject *self, PyObject *args)
596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 char *domain, *msgid;
598 int category;
599 if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category))
600 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100601 return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000602}
603
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000604PyDoc_STRVAR(textdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000605"textdomain(domain) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000606"Set the C library's textdmain to domain, returning the new domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000607
608static PyObject*
609PyIntl_textdomain(PyObject* self, PyObject* args)
610{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 char *domain;
612 if (!PyArg_ParseTuple(args, "z", &domain))
613 return 0;
614 domain = textdomain(domain);
615 if (!domain) {
616 PyErr_SetFromErrno(PyExc_OSError);
617 return NULL;
618 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100619 return PyUnicode_DecodeLocale(domain, NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000620}
621
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000622PyDoc_STRVAR(bindtextdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000623"bindtextdomain(domain, dir) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000624"Bind the C library's domain to dir.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000625
626static PyObject*
627PyIntl_bindtextdomain(PyObject* self,PyObject*args)
628{
Victor Stinner9e19ca42010-06-11 22:09:51 +0000629 char *domain, *dirname, *current_dirname;
630 PyObject *dirname_obj, *dirname_bytes = NULL, *result;
631 if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 return 0;
633 if (!strlen(domain)) {
634 PyErr_SetString(Error, "domain must be a non-empty string");
635 return 0;
636 }
Victor Stinner9e19ca42010-06-11 22:09:51 +0000637 if (dirname_obj != Py_None) {
638 if (!PyUnicode_FSConverter(dirname_obj, &dirname_bytes))
639 return NULL;
640 dirname = PyBytes_AsString(dirname_bytes);
641 } else {
642 dirname_bytes = NULL;
643 dirname = NULL;
644 }
645 current_dirname = bindtextdomain(domain, dirname);
646 if (current_dirname == NULL) {
647 Py_XDECREF(dirname_bytes);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 PyErr_SetFromErrno(PyExc_OSError);
649 return NULL;
650 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100651 result = PyUnicode_DecodeLocale(current_dirname, NULL);
Victor Stinner9e19ca42010-06-11 22:09:51 +0000652 Py_XDECREF(dirname_bytes);
653 return result;
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000654}
655
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000656#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
657PyDoc_STRVAR(bind_textdomain_codeset__doc__,
658"bind_textdomain_codeset(domain, codeset) -> string\n"
659"Bind the C library's domain to codeset.");
660
661static PyObject*
662PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args)
663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 char *domain,*codeset;
665 if (!PyArg_ParseTuple(args, "sz", &domain, &codeset))
666 return NULL;
667 codeset = bind_textdomain_codeset(domain, codeset);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100668 if (codeset) {
Victor Stinnera9c895d2012-02-14 02:33:38 +0100669 return PyUnicode_DecodeLocale(codeset, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100670 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 Py_RETURN_NONE;
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000672}
673#endif
674
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000675#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000676
Guido van Rossum220ecc81997-11-18 21:03:39 +0000677static struct PyMethodDef PyLocale_Methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 {"setlocale", (PyCFunction) PyLocale_setlocale,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000679 METH_VARARGS, setlocale__doc__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 {"localeconv", (PyCFunction) PyLocale_localeconv,
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000681 METH_NOARGS, localeconv__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000682#ifdef HAVE_WCSCOLL
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 {"strcoll", (PyCFunction) PyLocale_strcoll,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000684 METH_VARARGS, strcoll__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000685#endif
686#ifdef HAVE_WCSXFRM
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000688 METH_VARARGS, strxfrm__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000689#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690#if defined(MS_WINDOWS)
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000691 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, METH_NOARGS},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000692#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000693#ifdef HAVE_LANGINFO_H
694 {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo,
695 METH_VARARGS, nl_langinfo__doc__},
696#endif
Martin v. Löwisc6a7d7e2002-05-02 12:16:29 +0000697#ifdef HAVE_LIBINTL_H
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000698 {"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS,
699 gettext__doc__},
700 {"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS,
701 dgettext__doc__},
702 {"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS,
703 dcgettext__doc__},
704 {"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS,
705 textdomain__doc__},
706 {"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS,
707 bindtextdomain__doc__},
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000708#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
709 {"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset,
710 METH_VARARGS, bind_textdomain_codeset__doc__},
711#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000713 {NULL, NULL}
714};
715
Martin v. Löwis1a214512008-06-11 05:26:20 +0000716
717static struct PyModuleDef _localemodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 PyModuleDef_HEAD_INIT,
719 "_locale",
720 locale__doc__,
721 -1,
722 PyLocale_Methods,
723 NULL,
724 NULL,
725 NULL,
726 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000727};
728
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000729PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000730PyInit__locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000731{
Christian Heimesff4fddd2016-09-09 00:24:12 +0200732 PyObject *m;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000733#ifdef HAVE_LANGINFO_H
734 int i;
735#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000736
Martin v. Löwis1a214512008-06-11 05:26:20 +0000737 m = PyModule_Create(&_localemodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000738 if (m == NULL)
Christian Heimesff4fddd2016-09-09 00:24:12 +0200739 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000740
Christian Heimesff4fddd2016-09-09 00:24:12 +0200741 PyModule_AddIntMacro(m, LC_CTYPE);
742 PyModule_AddIntMacro(m, LC_TIME);
743 PyModule_AddIntMacro(m, LC_COLLATE);
744 PyModule_AddIntMacro(m, LC_MONETARY);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000745
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000746#ifdef LC_MESSAGES
Christian Heimesff4fddd2016-09-09 00:24:12 +0200747 PyModule_AddIntMacro(m, LC_MESSAGES);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000748#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000749
Christian Heimesff4fddd2016-09-09 00:24:12 +0200750 PyModule_AddIntMacro(m, LC_NUMERIC);
751 PyModule_AddIntMacro(m, LC_ALL);
752 PyModule_AddIntMacro(m, CHAR_MAX);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000753
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000754 Error = PyErr_NewException("locale.Error", NULL, NULL);
Christian Heimesff4fddd2016-09-09 00:24:12 +0200755 if (Error == NULL) {
756 Py_DECREF(m);
757 return NULL;
758 }
759 PyModule_AddObject(m, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000760
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000761#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000762 for (i = 0; langinfo_constants[i].name; i++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 PyModule_AddIntConstant(m, langinfo_constants[i].name,
764 langinfo_constants[i].value);
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000765 }
Martin v. Löwisf95dd0a2001-08-15 17:14:33 +0000766#endif
Christian Heimesff4fddd2016-09-09 00:24:12 +0200767
768 if (PyErr_Occurred()) {
769 Py_DECREF(m);
770 return NULL;
771 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000772 return m;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000773}
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000774
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775/*
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000776Local variables:
777c-basic-offset: 4
778indent-tabs-mode: nil
779End:
780*/