blob: 3fdbc5ea8122b3df99afbbc8e2f1e6fd7ee6be44 [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
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000131PyDoc_STRVAR(localeconv__doc__,
132"() -> dict. Returns numeric and monetary locale-specific parameters.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000133
134static PyObject*
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530135PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored))
Guido van Rossum220ecc81997-11-18 21:03:39 +0000136{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000137 PyObject* result;
138 struct lconv *l;
139 PyObject *x;
140
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000141 result = PyDict_New();
Victor Stinnercb064fc2018-01-15 15:58:02 +0100142 if (!result) {
Fredrik Lundh89610a42000-07-08 20:07:24 +0000143 return NULL;
Victor Stinnercb064fc2018-01-15 15:58:02 +0100144 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000145
146 /* if LC_NUMERIC is different in the C library, use saved value */
147 l = localeconv();
148
149 /* hopefully, the localeconv result survives the C library calls
150 involved herein */
151
Victor Stinnerd594f242013-07-17 00:55:57 +0200152#define RESULT(key, obj)\
153 do { \
154 if (obj == NULL) \
155 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100156 if (PyDict_SetItemString(result, key, obj) < 0) { \
157 Py_DECREF(obj); \
Victor Stinnerd594f242013-07-17 00:55:57 +0200158 goto failed; \
Victor Stinnerf38a5c22013-10-29 19:28:20 +0100159 } \
Victor Stinnerd594f242013-07-17 00:55:57 +0200160 Py_DECREF(obj); \
161 } while (0)
162
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000163#define RESULT_STRING(s)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200164 do { \
165 x = PyUnicode_DecodeLocale(l->s, NULL); \
166 RESULT(#s, x); \
167 } while (0)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000168
169#define RESULT_INT(i)\
Victor Stinnerd594f242013-07-17 00:55:57 +0200170 do { \
171 x = PyLong_FromLong(l->i); \
172 RESULT(#i, x); \
173 } while (0)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000174
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000175 /* Monetary information */
176 RESULT_STRING(int_curr_symbol);
177 RESULT_STRING(currency_symbol);
178 RESULT_STRING(mon_decimal_point);
179 RESULT_STRING(mon_thousands_sep);
180 x = copy_grouping(l->mon_grouping);
Victor Stinnerd594f242013-07-17 00:55:57 +0200181 RESULT("mon_grouping", x);
182
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000183 RESULT_STRING(positive_sign);
184 RESULT_STRING(negative_sign);
185 RESULT_INT(int_frac_digits);
186 RESULT_INT(frac_digits);
187 RESULT_INT(p_cs_precedes);
188 RESULT_INT(p_sep_by_space);
189 RESULT_INT(n_cs_precedes);
190 RESULT_INT(n_sep_by_space);
191 RESULT_INT(p_sign_posn);
192 RESULT_INT(n_sign_posn);
Victor Stinnercb064fc2018-01-15 15:58:02 +0100193
194 /* Numeric information */
195 PyObject *decimal_point, *thousands_sep;
196 const char *grouping;
197 if (_Py_GetLocaleconvNumeric(&decimal_point,
198 &thousands_sep,
199 &grouping) < 0) {
200 goto failed;
201 }
202
203 if (PyDict_SetItemString(result, "decimal_point", decimal_point) < 0) {
204 Py_DECREF(decimal_point);
205 Py_DECREF(thousands_sep);
206 goto failed;
207 }
208 Py_DECREF(decimal_point);
209
210 if (PyDict_SetItemString(result, "thousands_sep", thousands_sep) < 0) {
211 Py_DECREF(thousands_sep);
212 goto failed;
213 }
214 Py_DECREF(thousands_sep);
215
216 x = copy_grouping(grouping);
217 RESULT("grouping", x);
218
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000219 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000220
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000221 failed:
Victor Stinnercb064fc2018-01-15 15:58:02 +0100222 Py_DECREF(result);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000223 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000224}
225
Martin v. Löwis92fab752008-03-08 10:40:41 +0000226#if defined(HAVE_WCSCOLL)
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000227PyDoc_STRVAR(strcoll__doc__,
228"string,string -> int. Compares two strings according to the locale.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000229
230static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000231PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000232{
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000233 PyObject *os1, *os2, *result = NULL;
234 wchar_t *ws1 = NULL, *ws2 = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000235
Martin v. Löwis92fab752008-03-08 10:40:41 +0000236 if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2))
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000237 return NULL;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000238 /* Convert the unicode strings to wchar[]. */
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000239 ws1 = PyUnicode_AsWideCharString(os1, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000240 if (ws1 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000241 goto done;
Victor Stinnerbeb4135b2010-10-07 01:02:42 +0000242 ws2 = PyUnicode_AsWideCharString(os2, NULL);
Victor Stinner449057f2010-09-29 10:30:43 +0000243 if (ws2 == NULL)
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000244 goto done;
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000245 /* Collate the strings. */
Christian Heimes217cfd12007-12-02 14:31:20 +0000246 result = PyLong_FromLong(wcscoll(ws1, ws2));
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000247 done:
248 /* Deallocate everything. */
249 if (ws1) PyMem_FREE(ws1);
250 if (ws2) PyMem_FREE(ws2);
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000251 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000252}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000253#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000254
Martin v. Löwis92fab752008-03-08 10:40:41 +0000255#ifdef HAVE_WCSXFRM
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000256PyDoc_STRVAR(strxfrm__doc__,
Mark Dickinson211c6252009-02-01 10:28:51 +0000257"strxfrm(string) -> string.\n\
258\n\
259Return a string that can be used as a key for locale-aware comparisons.");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000260
261static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000262PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000263{
Victor Stinner63649272011-09-29 23:32:06 +0200264 PyObject *str;
265 Py_ssize_t n1;
266 wchar_t *s = NULL, *buf = NULL;
267 size_t n2;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000268 PyObject *result = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000269
Victor Stinner63649272011-09-29 23:32:06 +0200270 if (!PyArg_ParseTuple(args, "U:strxfrm", &str))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000271 return NULL;
272
Victor Stinner63649272011-09-29 23:32:06 +0200273 s = PyUnicode_AsWideCharString(str, &n1);
274 if (s == NULL)
275 goto exit;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300276 if (wcslen(s) != (size_t)n1) {
277 PyErr_SetString(PyExc_ValueError,
278 "embedded null character");
279 goto exit;
280 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000281
282 /* assume no change in size, first */
Victor Stinner63649272011-09-29 23:32:06 +0200283 n1 = n1 + 1;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200284 buf = PyMem_New(wchar_t, n1);
Martin v. Löwis92fab752008-03-08 10:40:41 +0000285 if (!buf) {
286 PyErr_NoMemory();
287 goto exit;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000288 }
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200289 errno = 0;
Martin v. Löwis92fab752008-03-08 10:40:41 +0000290 n2 = wcsxfrm(buf, s, n1);
Benjamin Petersonad4a0cc2017-03-07 22:24:44 -0800291 if (errno && errno != ERANGE) {
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200292 PyErr_SetFromErrno(PyExc_OSError);
293 goto exit;
294 }
Victor Stinner2c5d3cb2011-10-11 22:35:52 +0200295 if (n2 >= (size_t)n1) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000296 /* more space needed */
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000297 wchar_t * new_buf = PyMem_Realloc(buf, (n2+1)*sizeof(wchar_t));
298 if (!new_buf) {
Martin v. Löwis92fab752008-03-08 10:40:41 +0000299 PyErr_NoMemory();
300 goto exit;
301 }
Kristjan Valur Jonsson85634d72012-05-31 09:37:31 +0000302 buf = new_buf;
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200303 errno = 0;
Martin v. Löwisdb1c3992009-05-23 10:38:26 +0000304 n2 = wcsxfrm(buf, s, n2+1);
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200305 if (errno) {
306 PyErr_SetFromErrno(PyExc_OSError);
307 goto exit;
308 }
Martin v. Löwis92fab752008-03-08 10:40:41 +0000309 }
310 result = PyUnicode_FromWideChar(buf, n2);
Victor Stinner63649272011-09-29 23:32:06 +0200311exit:
Serhiy Storchakabe487a62017-03-06 21:21:41 +0200312 PyMem_Free(buf);
313 PyMem_Free(s);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000314 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000315}
Martin v. Löwis92fab752008-03-08 10:40:41 +0000316#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000317
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000318#if defined(MS_WINDOWS)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000319static PyObject*
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530320PyLocale_getdefaultlocale(PyObject* self, PyObject *Py_UNUSED(ignored))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000321{
Victor Stinner9e4994d2018-08-28 23:26:33 +0200322 char encoding[20];
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000323 char locale[100];
324
Tim Peters885d4572001-11-28 20:27:42 +0000325 PyOS_snprintf(encoding, sizeof(encoding), "cp%d", GetACP());
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000326
327 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
328 LOCALE_SISO639LANGNAME,
329 locale, sizeof(locale))) {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000330 Py_ssize_t i = strlen(locale);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000331 locale[i++] = '_';
332 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
333 LOCALE_SISO3166CTRYNAME,
Martin v. Löwis18e16552006-02-15 17:27:45 +0000334 locale+i, (int)(sizeof(locale)-i)))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000335 return Py_BuildValue("ss", locale, encoding);
336 }
337
338 /* If we end up here, this windows version didn't know about
339 ISO639/ISO3166 names (it's probably Windows 95). Return the
340 Windows language identifier instead (a hexadecimal number) */
341
342 locale[0] = '0';
343 locale[1] = 'x';
344 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
345 locale+2, sizeof(locale)-2)) {
346 return Py_BuildValue("ss", locale, encoding);
347 }
348
349 /* cannot determine the language code (very unlikely) */
350 Py_INCREF(Py_None);
351 return Py_BuildValue("Os", Py_None, encoding);
352}
353#endif
354
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000355#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000356#define LANGINFO(X) {#X, X}
Martin v. Löwis59683e82008-06-13 07:50:45 +0000357static struct langinfo_constant{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 char* name;
359 int value;
360} langinfo_constants[] =
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000361{
362 /* These constants should exist on any langinfo implementation */
363 LANGINFO(DAY_1),
364 LANGINFO(DAY_2),
365 LANGINFO(DAY_3),
366 LANGINFO(DAY_4),
367 LANGINFO(DAY_5),
368 LANGINFO(DAY_6),
369 LANGINFO(DAY_7),
370
371 LANGINFO(ABDAY_1),
372 LANGINFO(ABDAY_2),
373 LANGINFO(ABDAY_3),
374 LANGINFO(ABDAY_4),
375 LANGINFO(ABDAY_5),
376 LANGINFO(ABDAY_6),
377 LANGINFO(ABDAY_7),
378
379 LANGINFO(MON_1),
380 LANGINFO(MON_2),
381 LANGINFO(MON_3),
382 LANGINFO(MON_4),
383 LANGINFO(MON_5),
384 LANGINFO(MON_6),
385 LANGINFO(MON_7),
386 LANGINFO(MON_8),
387 LANGINFO(MON_9),
388 LANGINFO(MON_10),
389 LANGINFO(MON_11),
390 LANGINFO(MON_12),
391
392 LANGINFO(ABMON_1),
393 LANGINFO(ABMON_2),
394 LANGINFO(ABMON_3),
395 LANGINFO(ABMON_4),
396 LANGINFO(ABMON_5),
397 LANGINFO(ABMON_6),
398 LANGINFO(ABMON_7),
399 LANGINFO(ABMON_8),
400 LANGINFO(ABMON_9),
401 LANGINFO(ABMON_10),
402 LANGINFO(ABMON_11),
403 LANGINFO(ABMON_12),
404
405#ifdef RADIXCHAR
406 /* The following are not available with glibc 2.0 */
407 LANGINFO(RADIXCHAR),
408 LANGINFO(THOUSEP),
409 /* YESSTR and NOSTR are deprecated in glibc, since they are
410 a special case of message translation, which should be rather
411 done using gettext. So we don't expose it to Python in the
412 first place.
413 LANGINFO(YESSTR),
414 LANGINFO(NOSTR),
415 */
416 LANGINFO(CRNCYSTR),
417#endif
418
419 LANGINFO(D_T_FMT),
420 LANGINFO(D_FMT),
421 LANGINFO(T_FMT),
422 LANGINFO(AM_STR),
423 LANGINFO(PM_STR),
424
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000425 /* The following constants are available only with XPG4, but...
426 AIX 3.2. only has CODESET.
427 OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have
428 a few of the others.
429 Solution: ifdef-test them all. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000430#ifdef CODESET
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000431 LANGINFO(CODESET),
Martin v. Löwis496f9e42002-03-27 12:15:57 +0000432#endif
433#ifdef T_FMT_AMPM
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000434 LANGINFO(T_FMT_AMPM),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000435#endif
436#ifdef ERA
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000437 LANGINFO(ERA),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000438#endif
439#ifdef ERA_D_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000440 LANGINFO(ERA_D_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000441#endif
442#ifdef ERA_D_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000443 LANGINFO(ERA_D_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000444#endif
445#ifdef ERA_T_FMT
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000446 LANGINFO(ERA_T_FMT),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000447#endif
448#ifdef ALT_DIGITS
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000449 LANGINFO(ALT_DIGITS),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000450#endif
451#ifdef YESEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000452 LANGINFO(YESEXPR),
Martin v. Löwis2ea2c9d2002-04-19 21:04:41 +0000453#endif
454#ifdef NOEXPR
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000455 LANGINFO(NOEXPR),
456#endif
457#ifdef _DATE_FMT
458 /* This is not available in all glibc versions that have CODESET. */
459 LANGINFO(_DATE_FMT),
460#endif
461 {0, 0}
462};
463
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000464PyDoc_STRVAR(nl_langinfo__doc__,
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000465"nl_langinfo(key) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000466"Return the value for the locale information associated with key.");
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000467
468static PyObject*
469PyLocale_nl_langinfo(PyObject* self, PyObject* args)
470{
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000471 int item, i;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000472 if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item))
473 return NULL;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000474 /* Check whether this is a supported constant. GNU libc sometimes
475 returns numeric values in the char* return value, which would
Neal Norwitz7f9d29c2007-08-26 07:21:45 +0000476 crash PyUnicode_FromString. */
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000477 for (i = 0; langinfo_constants[i].name; i++)
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000478 if (langinfo_constants[i].value == item) {
479 /* Check NULL as a workaround for GNU libc's returning NULL
480 instead of an empty string for nl_langinfo(ERA). */
481 const char *result = nl_langinfo(item);
Neal Norwitz3d7a90d2007-10-27 05:40:06 +0000482 result = result != NULL ? result : "";
Victor Stinnera9c895d2012-02-14 02:33:38 +0100483 return PyUnicode_DecodeLocale(result, NULL);
Hye-Shik Changc3a87b82004-03-21 19:34:30 +0000484 }
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000485 PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
486 return NULL;
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000487}
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000488#endif /* HAVE_LANGINFO_H */
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000489
490#ifdef HAVE_LIBINTL_H
491
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000492PyDoc_STRVAR(gettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000493"gettext(msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000494"Return translation of msg.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000495
496static PyObject*
497PyIntl_gettext(PyObject* self, PyObject *args)
498{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000499 char *in;
500 if (!PyArg_ParseTuple(args, "s", &in))
501 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100502 return PyUnicode_DecodeLocale(gettext(in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000503}
504
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000505PyDoc_STRVAR(dgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000506"dgettext(domain, msg) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000507"Return translation of msg in domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000508
509static PyObject*
510PyIntl_dgettext(PyObject* self, PyObject *args)
511{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000512 char *domain, *in;
513 if (!PyArg_ParseTuple(args, "zs", &domain, &in))
514 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100515 return PyUnicode_DecodeLocale(dgettext(domain, in), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000516}
517
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000518PyDoc_STRVAR(dcgettext__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000519"dcgettext(domain, msg, category) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000520"Return translation of msg in domain and category.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000521
522static PyObject*
523PyIntl_dcgettext(PyObject *self, PyObject *args)
524{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 char *domain, *msgid;
526 int category;
527 if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category))
528 return 0;
Victor Stinnera9c895d2012-02-14 02:33:38 +0100529 return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000530}
531
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000532PyDoc_STRVAR(textdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000533"textdomain(domain) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000534"Set the C library's textdmain to domain, returning the new domain.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000535
536static PyObject*
537PyIntl_textdomain(PyObject* self, PyObject* args)
538{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 char *domain;
540 if (!PyArg_ParseTuple(args, "z", &domain))
541 return 0;
542 domain = textdomain(domain);
543 if (!domain) {
544 PyErr_SetFromErrno(PyExc_OSError);
545 return NULL;
546 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100547 return PyUnicode_DecodeLocale(domain, NULL);
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000548}
549
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000550PyDoc_STRVAR(bindtextdomain__doc__,
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000551"bindtextdomain(domain, dir) -> string\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000552"Bind the C library's domain to dir.");
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000553
554static PyObject*
555PyIntl_bindtextdomain(PyObject* self,PyObject*args)
556{
Victor Stinner9e19ca42010-06-11 22:09:51 +0000557 char *domain, *dirname, *current_dirname;
558 PyObject *dirname_obj, *dirname_bytes = NULL, *result;
559 if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 return 0;
561 if (!strlen(domain)) {
562 PyErr_SetString(Error, "domain must be a non-empty string");
563 return 0;
564 }
Victor Stinner9e19ca42010-06-11 22:09:51 +0000565 if (dirname_obj != Py_None) {
566 if (!PyUnicode_FSConverter(dirname_obj, &dirname_bytes))
567 return NULL;
568 dirname = PyBytes_AsString(dirname_bytes);
569 } else {
570 dirname_bytes = NULL;
571 dirname = NULL;
572 }
573 current_dirname = bindtextdomain(domain, dirname);
574 if (current_dirname == NULL) {
575 Py_XDECREF(dirname_bytes);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 PyErr_SetFromErrno(PyExc_OSError);
577 return NULL;
578 }
Victor Stinnera9c895d2012-02-14 02:33:38 +0100579 result = PyUnicode_DecodeLocale(current_dirname, NULL);
Victor Stinner9e19ca42010-06-11 22:09:51 +0000580 Py_XDECREF(dirname_bytes);
581 return result;
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000582}
583
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000584#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
585PyDoc_STRVAR(bind_textdomain_codeset__doc__,
586"bind_textdomain_codeset(domain, codeset) -> string\n"
587"Bind the C library's domain to codeset.");
588
589static PyObject*
590PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args)
591{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 char *domain,*codeset;
593 if (!PyArg_ParseTuple(args, "sz", &domain, &codeset))
594 return NULL;
595 codeset = bind_textdomain_codeset(domain, codeset);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100596 if (codeset) {
Victor Stinnera9c895d2012-02-14 02:33:38 +0100597 return PyUnicode_DecodeLocale(codeset, NULL);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100598 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 Py_RETURN_NONE;
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000600}
601#endif
602
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000603#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000604
Guido van Rossum220ecc81997-11-18 21:03:39 +0000605static struct PyMethodDef PyLocale_Methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 {"setlocale", (PyCFunction) PyLocale_setlocale,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000607 METH_VARARGS, setlocale__doc__},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530608 {"localeconv", PyLocale_localeconv, METH_NOARGS, localeconv__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000609#ifdef HAVE_WCSCOLL
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 {"strcoll", (PyCFunction) PyLocale_strcoll,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000611 METH_VARARGS, strcoll__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000612#endif
613#ifdef HAVE_WCSXFRM
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000615 METH_VARARGS, strxfrm__doc__},
Martin v. Löwis92fab752008-03-08 10:40:41 +0000616#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000617#if defined(MS_WINDOWS)
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530618 {"_getdefaultlocale", PyLocale_getdefaultlocale, METH_NOARGS},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000619#endif
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000620#ifdef HAVE_LANGINFO_H
621 {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo,
622 METH_VARARGS, nl_langinfo__doc__},
623#endif
Martin v. Löwisc6a7d7e2002-05-02 12:16:29 +0000624#ifdef HAVE_LIBINTL_H
Martin v. Löwis2e64c342002-03-27 18:49:02 +0000625 {"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS,
626 gettext__doc__},
627 {"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS,
628 dgettext__doc__},
629 {"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS,
630 dcgettext__doc__},
631 {"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS,
632 textdomain__doc__},
633 {"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS,
634 bindtextdomain__doc__},
Gustavo Niemeyer7bd33c52004-07-22 18:44:01 +0000635#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
636 {"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset,
637 METH_VARARGS, bind_textdomain_codeset__doc__},
638#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000640 {NULL, NULL}
641};
642
Martin v. Löwis1a214512008-06-11 05:26:20 +0000643
644static struct PyModuleDef _localemodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 PyModuleDef_HEAD_INIT,
646 "_locale",
647 locale__doc__,
648 -1,
649 PyLocale_Methods,
650 NULL,
651 NULL,
652 NULL,
653 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000654};
655
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000656PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000657PyInit__locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000658{
Christian Heimesff4fddd2016-09-09 00:24:12 +0200659 PyObject *m;
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000660#ifdef HAVE_LANGINFO_H
661 int i;
662#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000663
Martin v. Löwis1a214512008-06-11 05:26:20 +0000664 m = PyModule_Create(&_localemodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000665 if (m == NULL)
Christian Heimesff4fddd2016-09-09 00:24:12 +0200666 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000667
Christian Heimesff4fddd2016-09-09 00:24:12 +0200668 PyModule_AddIntMacro(m, LC_CTYPE);
669 PyModule_AddIntMacro(m, LC_TIME);
670 PyModule_AddIntMacro(m, LC_COLLATE);
671 PyModule_AddIntMacro(m, LC_MONETARY);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000672
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000673#ifdef LC_MESSAGES
Christian Heimesff4fddd2016-09-09 00:24:12 +0200674 PyModule_AddIntMacro(m, LC_MESSAGES);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000675#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000676
Christian Heimesff4fddd2016-09-09 00:24:12 +0200677 PyModule_AddIntMacro(m, LC_NUMERIC);
678 PyModule_AddIntMacro(m, LC_ALL);
679 PyModule_AddIntMacro(m, CHAR_MAX);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000680
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000681 Error = PyErr_NewException("locale.Error", NULL, NULL);
Christian Heimesff4fddd2016-09-09 00:24:12 +0200682 if (Error == NULL) {
683 Py_DECREF(m);
684 return NULL;
685 }
686 PyModule_AddObject(m, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000687
Martin v. Löwis9b75dca2001-08-10 13:58:50 +0000688#ifdef HAVE_LANGINFO_H
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000689 for (i = 0; langinfo_constants[i].name; i++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 PyModule_AddIntConstant(m, langinfo_constants[i].name,
691 langinfo_constants[i].value);
Martin v. Löwisdc0b61d2002-03-12 22:05:02 +0000692 }
Martin v. Löwisf95dd0a2001-08-15 17:14:33 +0000693#endif
Christian Heimesff4fddd2016-09-09 00:24:12 +0200694
695 if (PyErr_Occurred()) {
696 Py_DECREF(m);
697 return NULL;
698 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000699 return m;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000700}
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702/*
Martin v. Löwis9c36c292002-12-21 18:34:06 +0000703Local variables:
704c-basic-offset: 4
705indent-tabs-mode: nil
706End:
707*/