blob: 716a7306d3dcd33fe566fadfa7477c8e4b4ddd06 [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]);
Fredrik Lundh8f017a02000-07-08 19:57:37 +000073 if (!val)
74 break;
75 if (PyList_SetItem(result, i, val)) {
76 Py_DECREF(val);
Fredrik Lundh89610a42000-07-08 20:07:24 +000077 val = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000078 break;
79 }
80 } while (s[i] != '\0' && s[i] != CHAR_MAX);
81
82 if (!val) {
83 Py_DECREF(result);
84 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000085 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +000086
87 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +000088}
89
Guido van Rossum220ecc81997-11-18 21:03:39 +000090static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +000091PyLocale_setlocale(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +000092{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000093 int category;
94 char *locale = NULL, *result;
95 PyObject *result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +000096
Fredrik Lundh8f017a02000-07-08 19:57:37 +000097 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
Fredrik Lundh89610a42000-07-08 20:07:24 +000098 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000099
Amaury Forgeot d'Arc64f3ca42009-12-01 21:59:18 +0000100#if defined(MS_WINDOWS)
101 if (category < LC_MIN || category > LC_MAX)
102 {
103 PyErr_SetString(Error, "invalid locale category");
104 return NULL;
105 }
106#endif
107
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000108 if (locale) {
109 /* set locale */
110 result = setlocale(category, locale);
111 if (!result) {
112 /* operation failed, no setting was changed */
Martin v. Löwis25f90d52003-09-03 04:50:13 +0000113 PyErr_SetString(Error, "unsupported locale setting");
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000114 return NULL;
115 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100116 result_object = PyUnicode_DecodeLocale(result, NULL);
Mark Hammond9a714752003-07-24 14:15:07 +0000117 if (!result_object)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000118 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000119 } else {
120 /* get locale */
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000121 result = setlocale(category, NULL);
122 if (!result) {
123 PyErr_SetString(Error, "locale query failed");
124 return NULL;
125 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100126 result_object = PyUnicode_DecodeLocale(result, NULL);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000127 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000128 return result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000129}
130
Victor Stinner6eff6b82018-11-20 22:06:21 +0100131static int
132locale_is_ascii(const char *str)
133{
134 return (strlen(str) == 1 && ((unsigned char)str[0]) <= 127);
135}
136
137static int
138locale_decode_monetary(PyObject *dict, struct lconv *lc)
139{
140 int change_locale;
141 change_locale = (!locale_is_ascii(lc->int_curr_symbol)
142 || !locale_is_ascii(lc->currency_symbol)
143 || !locale_is_ascii(lc->mon_decimal_point)
144 || !locale_is_ascii(lc->mon_thousands_sep));
145
146 /* Keep a copy of the LC_CTYPE locale */
147 char *oldloc = NULL, *loc = NULL;
148 if (change_locale) {
149 oldloc = setlocale(LC_CTYPE, NULL);
150 if (!oldloc) {
151 PyErr_SetString(PyExc_RuntimeWarning,
152 "failed to get LC_CTYPE locale");
153 return -1;
154 }
155
156 oldloc = _PyMem_Strdup(oldloc);
157 if (!oldloc) {
158 PyErr_NoMemory();
159 return -1;
160 }
161
162 loc = setlocale(LC_MONETARY, NULL);
163 if (loc != NULL && strcmp(loc, oldloc) == 0) {
164 loc = NULL;
165 }
166
167 if (loc != NULL) {
168 /* Only set the locale temporarily the LC_CTYPE locale
169 to the LC_MONETARY locale if the two locales are different and
170 at least one string is non-ASCII. */
171 setlocale(LC_CTYPE, loc);
172 }
173 }
174
175 int res = -1;
176
177#define RESULT_STRING(ATTR) \
178 do { \
179 PyObject *obj; \
180 obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
181 if (obj == NULL) { \
182 goto done; \
183 } \
184 if (PyDict_SetItemString(dict, Py_STRINGIFY(ATTR), obj) < 0) { \
185 Py_DECREF(obj); \
186 goto done; \
187 } \
188 Py_DECREF(obj); \
189 } while (0)
190
191 RESULT_STRING(int_curr_symbol);
192 RESULT_STRING(currency_symbol);
193 RESULT_STRING(mon_decimal_point);
194 RESULT_STRING(mon_thousands_sep);
195#undef RESULT_STRING
196
197 res = 0;
198
199done:
200 if (loc != NULL) {
201 setlocale(LC_CTYPE, oldloc);
202 }
203 PyMem_Free(oldloc);
204 return res;
205}
206
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000207PyDoc_STRVAR(localeconv__doc__,
208"() -> dict. Returns numeric and monetary locale-specific parameters.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000209
210static PyObject*
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000211PyLocale_localeconv(PyObject* self)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000212{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000213 PyObject* result;
214 struct lconv *l;
215 PyObject *x;
216
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000217 result = PyDict_New();
Victor Stinnercb064fc2018-01-15 15:58:02 +0100218 if (!result) {
Fredrik Lundh89610a42000-07-08 20:07:24 +0000219 return NULL;
Victor Stinnercb064fc2018-01-15 15:58:02 +0100220 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000221
222 /* if LC_NUMERIC is different in the C library, use saved value */
223 l = localeconv();
224
225 /* hopefully, the localeconv result survives the C library calls
226 involved herein */
227
Victor Stinnerd594f242013-07-17 00:55:57 +0200228#define RESULT(key, obj)\
229 do { \
230 if (obj == NULL) \
231 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100232 if (PyDict_SetItemString(result, key, obj) < 0) { \
233 Py_DECREF(obj); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200234 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100235 } \
Victor Stinnerd594f242013-07-17 00:55:57 +0200236 Py_DECREF(obj); \
237 } while (0)
238
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000239#define RESULT_STRING(s)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200240 do { \
241 x = PyUnicode_DecodeLocale(l->s, NULL); \
242 RESULT(#s, x); \
243 } while (0)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000244
245#define RESULT_INT(i)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200246 do { \
247 x = PyLong_FromLong(l->i); \
248 RESULT(#i, x); \
249 } while (0)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000250
Victor Stinner6eff6b82018-11-20 22:06:21 +0100251 /* Monetary information: LC_MONETARY encoding */
252 if (locale_decode_monetary(result, l) < 0) {
253 goto failed;
254 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000255 x = copy_grouping(l->mon_grouping);
Victor Stinnerd594f242013-07-17 00:55:57 +0200256 RESULT("mon_grouping", x);
257
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000258 RESULT_STRING(positive_sign);
259 RESULT_STRING(negative_sign);
260 RESULT_INT(int_frac_digits);
261 RESULT_INT(frac_digits);
262 RESULT_INT(p_cs_precedes);
263 RESULT_INT(p_sep_by_space);
264 RESULT_INT(n_cs_precedes);
265 RESULT_INT(n_sep_by_space);
266 RESULT_INT(p_sign_posn);
267 RESULT_INT(n_sign_posn);
Victor Stinnercb064fc2018-01-15 15:58:02 +0100268
Victor Stinner6eff6b82018-11-20 22:06:21 +0100269 /* Numeric information: LC_NUMERIC encoding */
Victor Stinnercb064fc2018-01-15 15:58:02 +0100270 PyObject *decimal_point, *thousands_sep;
271 const char *grouping;
272 if (_Py_GetLocaleconvNumeric(&decimal_point,
273 &thousands_sep,
274 &grouping) < 0) {
275 goto failed;
276 }
277
278 if (PyDict_SetItemString(result, "decimal_point", decimal_point) < 0) {
279 Py_DECREF(decimal_point);
280 Py_DECREF(thousands_sep);
281 goto failed;
282 }
283 Py_DECREF(decimal_point);
284
285 if (PyDict_SetItemString(result, "thousands_sep", thousands_sep) < 0) {
286 Py_DECREF(thousands_sep);
287 goto failed;
288 }
289 Py_DECREF(thousands_sep);
290
291 x = copy_grouping(grouping);
292 RESULT("grouping", x);
293
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000294 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000295
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000296 failed:
Victor Stinnercb064fc2018-01-15 15:58:02 +0100297 Py_DECREF(result);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000298 return NULL;
Victor Stinner6eff6b82018-11-20 22:06:21 +0100299
300#undef RESULT
301#undef RESULT_STRING
302#undef RESULT_INT
Guido van Rossum220ecc81997-11-18 21:03:39 +0000303}
304
Martin v. Löwis92fab752008-03-08 10:40:41 +0000305#if defined(HAVE_WCSCOLL)
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000306PyDoc_STRVAR(strcoll__doc__,
307"string,string -> int. Compares two strings according to the locale.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000308
309static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000310PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000311{
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000312 PyObject *os1, *os2, *result = NULL;
313 wchar_t *ws1 = NULL, *ws2 = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000314
Martin v. Löwis92fab752008-03-08 10:40:41 +0000315 if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2))
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000316 return NULL;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000317 /* Convert the unicode strings to wchar[]. */
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000318 ws1 = PyUnicode_AsWideCharString(os1, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000319 if (ws1 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000320 goto done;
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000321 ws2 = PyUnicode_AsWideCharString(os2, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000322 if (ws2 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000323 goto done;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000324 /* Collate the strings. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000325 result = PyLong_FromLong(wcscoll(ws1, ws2));
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000326 done:
327 /* Deallocate everything. */
328 if (ws1) PyMem_FREE(ws1);
329 if (ws2) PyMem_FREE(ws2);
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000330 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000331}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000332#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000333
Martin v. Löwis92fab752008-03-08 10:40:41 +0000334#ifdef HAVE_WCSXFRM
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000335PyDoc_STRVAR(strxfrm__doc__,
Mark Dickinson211c6252009-02-01 10:28:51 +0000336"strxfrm(string) -> string.\n\
337\n\
338Return a string that can be used as a key for locale-aware comparisons.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000339
340static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000341PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000342{
Victor Stinner63649272011-09-29 23:32:06 +0200343 PyObject *str;
344 Py_ssize_t n1;
345 wchar_t *s = NULL, *buf = NULL;
346 size_t n2;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000347 PyObject *result = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000348
Victor Stinner63649272011-09-29 23:32:06 +0200349 if (!PyArg_ParseTuple(args, "U:strxfrm", &str))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000350 return NULL;
351
Victor Stinner63649272011-09-29 23:32:06 +0200352 s = PyUnicode_AsWideCharString(str, &n1);
353 if (s == NULL)
354 goto exit;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300355 if (wcslen(s) != (size_t)n1) {
356 PyErr_SetString(PyExc_ValueError,
357 "embedded null character");
358 goto exit;
359 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000360
361 /* assume no change in size, first */
Victor Stinner63649272011-09-29 23:32:06 +0200362 n1 = n1 + 1;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200363 buf = PyMem_New(wchar_t, n1);
Martin v. Löwis92fab752008-03-08 10:40:41 +0000364 if (!buf) {
365 PyErr_NoMemory();
366 goto exit;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000367 }
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200368 errno = 0;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000369 n2 = wcsxfrm(buf, s, n1);
Benjamin Petersonad4a0cc2017-03-07 22:24:44 -0800370 if (errno && errno != ERANGE) {
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200371 PyErr_SetFromErrno(PyExc_OSError);
372 goto exit;
373 }
Victor Stinner2c5d3cb2011-10-11 22:35:52 +0200374 if (n2 >= (size_t)n1) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000375 /* more space needed */
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000376 wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t));
377 if (!new_buf) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000378 PyErr_NoMemory();
379 goto exit;
380 }
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000381 buf = new_buf;
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200382 errno = 0;
Martin v. Löwisdb1c3992009-05-23 10:38:26 +0000383 n2 = wcsxfrm(buf, s, n2+1);
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200384 if (errno) {
385 PyErr_SetFromErrno(PyExc_OSError);
386 goto exit;
387 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000388 }
389 result = PyUnicode_FromWideChar(buf, n2);
Victor Stinner63649272011-09-29 23:32:06 +0200390exit:
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200391 PyMem_Free(buf);
392 PyMem_Free(s);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000393 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000394}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000395#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000396
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000397#if defined(MS_WINDOWS)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000398static PyObject*
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000399PyLocale_getdefaultlocale(PyObject* self)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000400{
401 char encoding[100];
402 char locale[100];
403
Tim Peters885d4572001-11-28 20:27:42 +0000404 PyOS_snprintf(encoding, sizeof(encoding), "cp%d", GetACP());
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000405
406 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
407 LOCALE_SISO639LANGNAME,
408 locale, sizeof(locale))) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000409 Py_ssize_t i = strlen(locale);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000410 locale[i++] = '_';
411 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
412 LOCALE_SISO3166CTRYNAME,
Martin v. Löwis18e16552006-02-15 17:27:45 +0000413 locale+i, (int)(sizeof(locale)-i)))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000414 return Py_BuildValue("ss", locale, encoding);
415 }
416
417 /* If we end up here, this windows version didn't know about
418 ISO639/ISO3166 names (it's probably Windows 95). Return the
419 Windows language identifier instead (a hexadecimal number) */
420
421 locale[0] = '0';
422 locale[1] = 'x';
423 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
424 locale+2, sizeof(locale)-2)) {
425 return Py_BuildValue("ss", locale, encoding);
426 }
427
428 /* cannot determine the language code (very unlikely) */
429 Py_INCREF(Py_None);
430 return Py_BuildValue("Os", Py_None, encoding);
431}
432#endif
433
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000434#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000435#define LANGINFO(X) {#X, X}
Martin v. Löwis59683e82008-06-13 07:50:45 +0000436static struct langinfo_constant{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 char* name;
438 int value;
439} langinfo_constants[] =
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000440{
441 /* These constants should exist on any langinfo implementation */
442 LANGINFO(DAY_1),
443 LANGINFO(DAY_2),
444 LANGINFO(DAY_3),
445 LANGINFO(DAY_4),
446 LANGINFO(DAY_5),
447 LANGINFO(DAY_6),
448 LANGINFO(DAY_7),
449
450 LANGINFO(ABDAY_1),
451 LANGINFO(ABDAY_2),
452 LANGINFO(ABDAY_3),
453 LANGINFO(ABDAY_4),
454 LANGINFO(ABDAY_5),
455 LANGINFO(ABDAY_6),
456 LANGINFO(ABDAY_7),
457
458 LANGINFO(MON_1),
459 LANGINFO(MON_2),
460 LANGINFO(MON_3),
461 LANGINFO(MON_4),
462 LANGINFO(MON_5),
463 LANGINFO(MON_6),
464 LANGINFO(MON_7),
465 LANGINFO(MON_8),
466 LANGINFO(MON_9),
467 LANGINFO(MON_10),
468 LANGINFO(MON_11),
469 LANGINFO(MON_12),
470
471 LANGINFO(ABMON_1),
472 LANGINFO(ABMON_2),
473 LANGINFO(ABMON_3),
474 LANGINFO(ABMON_4),
475 LANGINFO(ABMON_5),
476 LANGINFO(ABMON_6),
477 LANGINFO(ABMON_7),
478 LANGINFO(ABMON_8),
479 LANGINFO(ABMON_9),
480 LANGINFO(ABMON_10),
481 LANGINFO(ABMON_11),
482 LANGINFO(ABMON_12),
483
484#ifdef RADIXCHAR
485 /* The following are not available with glibc 2.0 */
486 LANGINFO(RADIXCHAR),
487 LANGINFO(THOUSEP),
488 /* YESSTR and NOSTR are deprecated in glibc, since they are
489 a special case of message translation, which should be rather
490 done using gettext. So we don't expose it to Python in the
491 first place.
492 LANGINFO(YESSTR),
493 LANGINFO(NOSTR),
494 */
495 LANGINFO(CRNCYSTR),
496#endif
497
498 LANGINFO(D_T_FMT),
499 LANGINFO(D_FMT),
500 LANGINFO(T_FMT),
501 LANGINFO(AM_STR),
502 LANGINFO(PM_STR),
503
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000504 /* The following constants are available only with XPG4, but...
505 AIX 3.2. only has CODESET.
506 OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have
507 a few of the others.
508 Solution: ifdef-test them all. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000509#ifdef CODESET
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000510 LANGINFO(CODESET),
Martin v. Löwis496f9e42002-03-27 12:15:57 +0000511#endif
512#ifdef T_FMT_AMPM
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000513 LANGINFO(T_FMT_AMPM),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000514#endif
515#ifdef ERA
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000516 LANGINFO(ERA),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000517#endif
518#ifdef ERA_D_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000519 LANGINFO(ERA_D_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000520#endif
521#ifdef ERA_D_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000522 LANGINFO(ERA_D_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000523#endif
524#ifdef ERA_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000525 LANGINFO(ERA_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000526#endif
527#ifdef ALT_DIGITS
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000528 LANGINFO(ALT_DIGITS),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000529#endif
530#ifdef YESEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000531 LANGINFO(YESEXPR),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000532#endif
533#ifdef NOEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000534 LANGINFO(NOEXPR),
535#endif
536#ifdef _DATE_FMT
537 /* This is not available in all glibc versions that have CODESET. */
538 LANGINFO(_DATE_FMT),
539#endif
540 {0, 0}
541};
542
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000543PyDoc_STRVAR(nl_langinfo__doc__,
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000544"nl_langinfo(key) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000545"Return the value for the locale information associated with key.");
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000546
547static PyObject*
548PyLocale_nl_langinfo(PyObject* self, PyObject* args)
549{
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000550 int item, i;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000551 if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item))
552 return NULL;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000553 /* Check whether this is a supported constant. GNU libc sometimes
554 returns numeric values in the char* return value, which would
Neal Norwitz7f9d29c2007-08-26 07:21:45 +0000555 crash PyUnicode_FromString. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000556 for (i = 0; langinfo_constants[i].name; i++)
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000557 if (langinfo_constants[i].value == item) {
558 /* Check NULL as a workaround for GNU libc's returning NULL
559 instead of an empty string for nl_langinfo(ERA). */
560 const char *result = nl_langinfo(item);
Neal Norwitz3d7a90d2007-10-27 05:40:06 +0000561 result = result != NULL ? result : "";
Victor Stinnera9c895d2012-02-14 02:33:38 +0100562 return PyUnicode_DecodeLocale(result, NULL);
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000563 }
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000564 PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
565 return NULL;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000566}
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000567#endif /* HAVE_LANGINFO_H */
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000568
569#ifdef HAVE_LIBINTL_H
570
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000571PyDoc_STRVAR(gettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000572"gettext(msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000573"Return translation of msg.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000574
575static PyObject*
576PyIntl_gettext(PyObject* self, PyObject *args)
577{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 char *in;
579 if (!PyArg_ParseTuple(args, "s", &in))
580 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100581 return PyUnicode_DecodeLocale(gettext(in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000582}
583
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000584PyDoc_STRVAR(dgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000585"dgettext(domain, msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000586"Return translation of msg in domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000587
588static PyObject*
589PyIntl_dgettext(PyObject* self, PyObject *args)
590{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 char *domain, *in;
592 if (!PyArg_ParseTuple(args, "zs", &domain, &in))
593 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100594 return PyUnicode_DecodeLocale(dgettext(domain, in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000595}
596
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000597PyDoc_STRVAR(dcgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000598"dcgettext(domain, msg, category) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000599"Return translation of msg in domain and category.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000600
601static PyObject*
602PyIntl_dcgettext(PyObject *self, PyObject *args)
603{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000604 char *domain, *msgid;
605 int category;
606 if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category))
607 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100608 return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000609}
610
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000611PyDoc_STRVAR(textdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000612"textdomain(domain) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000613"Set the C library's textdmain to domain, returning the new domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000614
615static PyObject*
616PyIntl_textdomain(PyObject* self, PyObject* args)
617{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 char *domain;
619 if (!PyArg_ParseTuple(args, "z", &domain))
620 return 0;
621 domain = textdomain(domain);
622 if (!domain) {
623 PyErr_SetFromErrno(PyExc_OSError);
624 return NULL;
625 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100626 return PyUnicode_DecodeLocale(domain, NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000627}
628
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000629PyDoc_STRVAR(bindtextdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000630"bindtextdomain(domain, dir) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000631"Bind the C library's domain to dir.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000632
633static PyObject*
634PyIntl_bindtextdomain(PyObject* self,PyObject*args)
635{
Victor Stinner9e19ca42010-06-11 22:09:51 +0000636 char *domain, *dirname, *current_dirname;
637 PyObject *dirname_obj, *dirname_bytes = NULL, *result;
638 if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 return 0;
640 if (!strlen(domain)) {
641 PyErr_SetString(Error, "domain must be a non-empty string");
642 return 0;
643 }
Victor Stinner9e19ca42010-06-11 22:09:51 +0000644 if (dirname_obj != Py_None) {
645 if (!PyUnicode_FSConverter(dirname_obj, &dirname_bytes))
646 return NULL;
647 dirname = PyBytes_AsString(dirname_bytes);
648 } else {
649 dirname_bytes = NULL;
650 dirname = NULL;
651 }
652 current_dirname = bindtextdomain(domain, dirname);
653 if (current_dirname == NULL) {
654 Py_XDECREF(dirname_bytes);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 PyErr_SetFromErrno(PyExc_OSError);
656 return NULL;
657 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100658 result = PyUnicode_DecodeLocale(current_dirname, NULL);
Victor Stinner9e19ca42010-06-11 22:09:51 +0000659 Py_XDECREF(dirname_bytes);
660 return result;
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000661}
662
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000663#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
664PyDoc_STRVAR(bind_textdomain_codeset__doc__,
665"bind_textdomain_codeset(domain, codeset) -> string\n"
666"Bind the C library's domain to codeset.");
667
668static PyObject*
669PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args)
670{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 char *domain,*codeset;
672 if (!PyArg_ParseTuple(args, "sz", &domain, &codeset))
673 return NULL;
674 codeset = bind_textdomain_codeset(domain, codeset);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100675 if (codeset) {
Victor Stinnera9c895d2012-02-14 02:33:38 +0100676 return PyUnicode_DecodeLocale(codeset, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100677 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 Py_RETURN_NONE;
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000679}
680#endif
681
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000682#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000683
Guido van Rossum220ecc81997-11-18 21:03:39 +0000684static struct PyMethodDef PyLocale_Methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 {"setlocale", (PyCFunction) PyLocale_setlocale,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000686 METH_VARARGS, setlocale__doc__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 {"localeconv", (PyCFunction) PyLocale_localeconv,
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000688 METH_NOARGS, localeconv__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000689#ifdef HAVE_WCSCOLL
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 {"strcoll", (PyCFunction) PyLocale_strcoll,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000691 METH_VARARGS, strcoll__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000692#endif
693#ifdef HAVE_WCSXFRM
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000695 METH_VARARGS, strxfrm__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000696#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697#if defined(MS_WINDOWS)
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000698 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, METH_NOARGS},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000699#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000700#ifdef HAVE_LANGINFO_H
701 {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo,
702 METH_VARARGS, nl_langinfo__doc__},
703#endif
Martin v. Löwisc6a7d7e2002-05-02 12:16:29 +0000704#ifdef HAVE_LIBINTL_H
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000705 {"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS,
706 gettext__doc__},
707 {"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS,
708 dgettext__doc__},
709 {"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS,
710 dcgettext__doc__},
711 {"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS,
712 textdomain__doc__},
713 {"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS,
714 bindtextdomain__doc__},
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000715#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
716 {"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset,
717 METH_VARARGS, bind_textdomain_codeset__doc__},
718#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000720 {NULL, NULL}
721};
722
Martin v. Löwis1a214512008-06-11 05:26:20 +0000723
724static struct PyModuleDef _localemodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 PyModuleDef_HEAD_INIT,
726 "_locale",
727 locale__doc__,
728 -1,
729 PyLocale_Methods,
730 NULL,
731 NULL,
732 NULL,
733 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000734};
735
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000736PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000737PyInit__locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000738{
Christian Heimesff4fddd2016-09-09 00:24:12 +0200739 PyObject *m;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000740#ifdef HAVE_LANGINFO_H
741 int i;
742#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000743
Martin v. Löwis1a214512008-06-11 05:26:20 +0000744 m = PyModule_Create(&_localemodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000745 if (m == NULL)
Christian Heimesff4fddd2016-09-09 00:24:12 +0200746 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000747
Christian Heimesff4fddd2016-09-09 00:24:12 +0200748 PyModule_AddIntMacro(m, LC_CTYPE);
749 PyModule_AddIntMacro(m, LC_TIME);
750 PyModule_AddIntMacro(m, LC_COLLATE);
751 PyModule_AddIntMacro(m, LC_MONETARY);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000752
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000753#ifdef LC_MESSAGES
Christian Heimesff4fddd2016-09-09 00:24:12 +0200754 PyModule_AddIntMacro(m, LC_MESSAGES);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000755#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000756
Christian Heimesff4fddd2016-09-09 00:24:12 +0200757 PyModule_AddIntMacro(m, LC_NUMERIC);
758 PyModule_AddIntMacro(m, LC_ALL);
759 PyModule_AddIntMacro(m, CHAR_MAX);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000760
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000761 Error = PyErr_NewException("locale.Error", NULL, NULL);
Christian Heimesff4fddd2016-09-09 00:24:12 +0200762 if (Error == NULL) {
763 Py_DECREF(m);
764 return NULL;
765 }
766 PyModule_AddObject(m, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000767
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000768#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000769 for (i = 0; langinfo_constants[i].name; i++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 PyModule_AddIntConstant(m, langinfo_constants[i].name,
771 langinfo_constants[i].value);
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000772 }
Martin v. Löwisf95dd0a2001-08-15 17:14:33 +0000773#endif
Christian Heimesff4fddd2016-09-09 00:24:12 +0200774
775 if (PyErr_Occurred()) {
776 Py_DECREF(m);
777 return NULL;
778 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000779 return m;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000780}
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782/*
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000783Local variables:
784c-basic-offset: 4
785indent-tabs-mode: nil
786End:
787*/