blob: 53ae678e7648ea955944792e46a84a3895ff068b [file] [log] [blame]
Guido van Rossum220ecc81997-11-18 21:03:39 +00001/***********************************************************
Guido van Rossum239a2181998-04-28 16:08:19 +00002Copyright (C) 1997 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
Fred Drake68933b92000-08-10 21:41:08 +000012#include "Python.h"
13
Guido van Rossum220ecc81997-11-18 21:03:39 +000014#include <stdio.h>
15#include <errno.h>
16#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
Fredrik Lundh8f017a02000-07-08 19:57:37 +000020#if defined(MS_WIN32)
21#define WINDOWS_LEAN_AND_MEAN
22#include <windows.h>
Guido van Rossum239a2181998-04-28 16:08:19 +000023#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +000024
Fredrik Lundh8f017a02000-07-08 19:57:37 +000025#ifdef macintosh
Jack Jansen307d7a42000-07-15 22:31:45 +000026#include "macglue.h"
Fredrik Lundh8f017a02000-07-08 19:57:37 +000027#endif
28
Guido van Rossum1ca8bb32001-03-02 06:28:17 +000029#ifdef RISCOS
30char *strdup(const char *);
31#endif
32
Fredrik Lundh8f017a02000-07-08 19:57:37 +000033static char locale__doc__[] = "Support for POSIX locales.";
Guido van Rossum220ecc81997-11-18 21:03:39 +000034
35static PyObject *Error;
36
37/* support functions for formatting floating point numbers */
38
Fredrik Lundh8f017a02000-07-08 19:57:37 +000039static char setlocale__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +000040"(integer,string=None) -> string. Activates/queries locale processing."
41;
42
43/* to record the LC_NUMERIC settings */
Fredrik Lundh8f017a02000-07-08 19:57:37 +000044static PyObject* grouping = NULL;
45static PyObject* thousands_sep = NULL;
46static PyObject* decimal_point = NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000047/* if non-null, indicates that LC_NUMERIC is different from "C" */
Fredrik Lundh8f017a02000-07-08 19:57:37 +000048static char* saved_numeric = NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000049
50/* the grouping is terminated by either 0 or CHAR_MAX */
51static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +000052copy_grouping(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
57 if (s[0] == '\0')
58 /* empty string: no grouping at all */
59 return PyList_New(0);
60
61 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
62 ; /* nothing */
63
64 result = PyList_New(i+1);
65 if (!result)
66 return NULL;
67
68 i = -1;
69 do {
70 i++;
71 val = PyInt_FromLong(s[i]);
72 if (!val)
73 break;
74 if (PyList_SetItem(result, i, val)) {
75 Py_DECREF(val);
Fredrik Lundh89610a42000-07-08 20:07:24 +000076 val = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000077 break;
78 }
79 } while (s[i] != '\0' && s[i] != CHAR_MAX);
80
81 if (!val) {
82 Py_DECREF(result);
83 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000084 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +000085
86 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +000087}
88
89static void
Fredrik Lundh8f017a02000-07-08 19:57:37 +000090fixup_ulcase(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +000091{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000092 PyObject *mods, *strop, *string, *ulo;
93 unsigned char ul[256];
94 int n, c;
Guido van Rossum220ecc81997-11-18 21:03:39 +000095
Fredrik Lundh8f017a02000-07-08 19:57:37 +000096 /* find the string and strop modules */
97 mods = PyImport_GetModuleDict();
98 if (!mods)
99 return;
100 string = PyDict_GetItemString(mods, "string");
101 if (string)
102 string = PyModule_GetDict(string);
103 strop=PyDict_GetItemString(mods, "strop");
104 if (strop)
105 strop = PyModule_GetDict(strop);
106 if (!string && !strop)
107 return;
108
109 /* create uppercase map string */
110 n = 0;
111 for (c = 0; c < 256; c++) {
112 if (isupper(c))
113 ul[n++] = c;
114 }
115 ulo = PyString_FromStringAndSize((const char *)ul, n);
Fredrik Lundh89610a42000-07-08 20:07:24 +0000116 if (!ulo)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000117 return;
118 if (string)
119 PyDict_SetItemString(string, "uppercase", ulo);
120 if (strop)
121 PyDict_SetItemString(strop, "uppercase", ulo);
122 Py_DECREF(ulo);
123
124 /* create lowercase string */
125 n = 0;
126 for (c = 0; c < 256; c++) {
127 if (islower(c))
128 ul[n++] = c;
129 }
130 ulo = PyString_FromStringAndSize((const char *)ul, n);
131 if (!ulo)
132 return;
133 if (string)
134 PyDict_SetItemString(string, "lowercase", ulo);
135 if (strop)
136 PyDict_SetItemString(strop, "lowercase", ulo);
137 Py_DECREF(ulo);
138
139 /* create letters string */
140 n = 0;
141 for (c = 0; c < 256; c++) {
142 if (isalpha(c))
143 ul[n++] = c;
144 }
145 ulo = PyString_FromStringAndSize((const char *)ul, n);
146 if (!ulo)
147 return;
148 if (string)
149 PyDict_SetItemString(string, "letters", ulo);
150 Py_DECREF(ulo);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000151}
152
153
154static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000155PyLocale_setlocale(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000156{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000157 int category;
158 char *locale = NULL, *result;
159 PyObject *result_object;
160 struct lconv *lc;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000161
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000162 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
Fredrik Lundh89610a42000-07-08 20:07:24 +0000163 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000164
165 if (locale) {
166 /* set locale */
167 result = setlocale(category, locale);
168 if (!result) {
169 /* operation failed, no setting was changed */
170 PyErr_SetString(Error, "locale setting not supported");
171 return NULL;
172 }
173 result_object = PyString_FromString(result);
174 if (!result)
175 return NULL;
176 /* record changes to LC_NUMERIC */
177 if (category == LC_NUMERIC || category == LC_ALL) {
178 if (strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0) {
179 /* user just asked for default numeric locale */
180 if (saved_numeric)
181 free(saved_numeric);
182 saved_numeric = NULL;
183 } else {
184 /* remember values */
185 lc = localeconv();
186 Py_XDECREF(grouping);
187 grouping = copy_grouping(lc->grouping);
188 Py_XDECREF(thousands_sep);
189 thousands_sep = PyString_FromString(lc->thousands_sep);
190 Py_XDECREF(decimal_point);
191 decimal_point = PyString_FromString(lc->decimal_point);
192 saved_numeric = strdup(locale);
193 /* restore to "C" */
194 setlocale(LC_NUMERIC, "C");
195 }
196 }
197 /* record changes to LC_CTYPE */
198 if (category == LC_CTYPE || category == LC_ALL)
199 fixup_ulcase();
200 /* things that got wrong up to here are ignored */
201 PyErr_Clear();
202 } else {
203 /* get locale */
204 /* restore LC_NUMERIC first, if appropriate */
205 if (saved_numeric)
206 setlocale(LC_NUMERIC, saved_numeric);
207 result = setlocale(category, NULL);
208 if (!result) {
209 PyErr_SetString(Error, "locale query failed");
210 return NULL;
211 }
212 result_object = PyString_FromString(result);
213 /* restore back to "C" */
214 if (saved_numeric)
215 setlocale(LC_NUMERIC, "C");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000216 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000217 return result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000218}
219
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000220static char localeconv__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000221"() -> dict. Returns numeric and monetary locale-specific parameters."
222;
223
224static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000225PyLocale_localeconv(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000226{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000227 PyObject* result;
228 struct lconv *l;
229 PyObject *x;
230
231 if (!PyArg_NoArgs(args))
Fredrik Lundh89610a42000-07-08 20:07:24 +0000232 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000233
234 result = PyDict_New();
Fredrik Lundh89610a42000-07-08 20:07:24 +0000235 if (!result)
236 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000237
238 /* if LC_NUMERIC is different in the C library, use saved value */
239 l = localeconv();
240
241 /* hopefully, the localeconv result survives the C library calls
242 involved herein */
243
244#define RESULT_STRING(s)\
245 x = PyString_FromString(l->s);\
246 if (!x) goto failed;\
247 PyDict_SetItemString(result, #s, x);\
248 Py_XDECREF(x)
249
250#define RESULT_INT(i)\
251 x = PyInt_FromLong(l->i);\
252 if (!x) goto failed;\
253 PyDict_SetItemString(result, #i, x);\
254 Py_XDECREF(x)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000255
256 /* Numeric information */
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000257 if (saved_numeric){
258 /* cannot use localeconv results */
259 PyDict_SetItemString(result, "decimal_point", decimal_point);
260 PyDict_SetItemString(result, "grouping", grouping);
261 PyDict_SetItemString(result, "thousands_sep", thousands_sep);
262 } else {
263 RESULT_STRING(decimal_point);
264 RESULT_STRING(thousands_sep);
265 x = copy_grouping(l->grouping);
266 if (!x)
267 goto failed;
268 PyDict_SetItemString(result, "grouping", x);
269 Py_XDECREF(x);
270 }
271
272 /* Monetary information */
273 RESULT_STRING(int_curr_symbol);
274 RESULT_STRING(currency_symbol);
275 RESULT_STRING(mon_decimal_point);
276 RESULT_STRING(mon_thousands_sep);
277 x = copy_grouping(l->mon_grouping);
278 if (!x)
279 goto failed;
280 PyDict_SetItemString(result, "mon_grouping", x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000281 Py_XDECREF(x);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000282 RESULT_STRING(positive_sign);
283 RESULT_STRING(negative_sign);
284 RESULT_INT(int_frac_digits);
285 RESULT_INT(frac_digits);
286 RESULT_INT(p_cs_precedes);
287 RESULT_INT(p_sep_by_space);
288 RESULT_INT(n_cs_precedes);
289 RESULT_INT(n_sep_by_space);
290 RESULT_INT(p_sign_posn);
291 RESULT_INT(n_sign_posn);
292 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000293
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000294 failed:
295 Py_XDECREF(result);
296 Py_XDECREF(x);
297 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000298}
299
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000300static char strcoll__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000301"string,string -> int. Compares two strings according to the locale."
302;
303
304static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000305PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000306{
307 char *s1,*s2;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000308
309 if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
310 return NULL;
311 return PyInt_FromLong(strcoll(s1, s2));
Guido van Rossum220ecc81997-11-18 21:03:39 +0000312}
313
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000314static char strxfrm__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000315"string -> string. Returns a string that behaves for cmp locale-aware."
316;
317
318static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000319PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000320{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000321 char *s, *buf;
322 size_t n1, n2;
323 PyObject *result;
324
Fredrik Lundh89610a42000-07-08 20:07:24 +0000325 if (!PyArg_ParseTuple(args, "s:strxfrm", &s))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000326 return NULL;
327
328 /* assume no change in size, first */
329 n1 = strlen(s) + 1;
330 buf = PyMem_Malloc(n1);
331 if (!buf)
332 return PyErr_NoMemory();
333 n2 = strxfrm(buf, s, n1);
334 if (n2 > n1) {
335 /* more space needed */
336 buf = PyMem_Realloc(buf, n2);
337 if (!buf)
338 return PyErr_NoMemory();
339 strxfrm(buf, s, n2);
340 }
341 result = PyString_FromString(buf);
342 PyMem_Free(buf);
343 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000344}
345
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000346#if defined(MS_WIN32)
347static PyObject*
348PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
349{
350 char encoding[100];
351 char locale[100];
352
Fredrik Lundh89610a42000-07-08 20:07:24 +0000353 if (!PyArg_NoArgs(args))
354 return NULL;
355
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000356 sprintf(encoding, "cp%d", GetACP());
357
358 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
359 LOCALE_SISO639LANGNAME,
360 locale, sizeof(locale))) {
361 int i = strlen(locale);
362 locale[i++] = '_';
363 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
364 LOCALE_SISO3166CTRYNAME,
365 locale+i, sizeof(locale)-i))
366 return Py_BuildValue("ss", locale, encoding);
367 }
368
369 /* If we end up here, this windows version didn't know about
370 ISO639/ISO3166 names (it's probably Windows 95). Return the
371 Windows language identifier instead (a hexadecimal number) */
372
373 locale[0] = '0';
374 locale[1] = 'x';
375 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
376 locale+2, sizeof(locale)-2)) {
377 return Py_BuildValue("ss", locale, encoding);
378 }
379
380 /* cannot determine the language code (very unlikely) */
381 Py_INCREF(Py_None);
382 return Py_BuildValue("Os", Py_None, encoding);
383}
384#endif
385
Jack Jansen307d7a42000-07-15 22:31:45 +0000386#if defined(macintosh)
387static PyObject*
388PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
389{
390 return Py_BuildValue("Os", Py_None, PyMac_getscript());
391}
392#endif
393
Guido van Rossum220ecc81997-11-18 21:03:39 +0000394static struct PyMethodDef PyLocale_Methods[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000395 {"setlocale", (PyCFunction) PyLocale_setlocale,
396 METH_VARARGS, setlocale__doc__},
397 {"localeconv", (PyCFunction) PyLocale_localeconv,
398 0, localeconv__doc__},
399 {"strcoll", (PyCFunction) PyLocale_strcoll,
400 METH_VARARGS, strcoll__doc__},
401 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
402 METH_VARARGS, strxfrm__doc__},
Jack Jansen307d7a42000-07-15 22:31:45 +0000403#if defined(MS_WIN32) || defined(macintosh)
Fredrik Lundh89610a42000-07-08 20:07:24 +0000404 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, 0},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000405#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000406 {NULL, NULL}
407};
408
Guido van Rossum3886bb61998-12-04 18:50:17 +0000409DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000410init_locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000411{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000412 PyObject *m, *d, *x;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000413
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000414 m = Py_InitModule("_locale", PyLocale_Methods);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000415
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000416 d = PyModule_GetDict(m);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000417
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000418 x = PyInt_FromLong(LC_CTYPE);
419 PyDict_SetItemString(d, "LC_CTYPE", x);
420 Py_XDECREF(x);
421
422 x = PyInt_FromLong(LC_TIME);
423 PyDict_SetItemString(d, "LC_TIME", x);
424 Py_XDECREF(x);
425
426 x = PyInt_FromLong(LC_COLLATE);
427 PyDict_SetItemString(d, "LC_COLLATE", x);
428 Py_XDECREF(x);
429
430 x = PyInt_FromLong(LC_MONETARY);
431 PyDict_SetItemString(d, "LC_MONETARY", x);
432 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000433
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000434#ifdef LC_MESSAGES
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000435 x = PyInt_FromLong(LC_MESSAGES);
436 PyDict_SetItemString(d, "LC_MESSAGES", x);
437 Py_XDECREF(x);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000438#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000439
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000440 x = PyInt_FromLong(LC_NUMERIC);
441 PyDict_SetItemString(d, "LC_NUMERIC", x);
442 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000443
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000444 x = PyInt_FromLong(LC_ALL);
445 PyDict_SetItemString(d, "LC_ALL", x);
446 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000447
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000448 x = PyInt_FromLong(CHAR_MAX);
449 PyDict_SetItemString(d, "CHAR_MAX", x);
450 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000451
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000452 Error = PyErr_NewException("locale.Error", NULL, NULL);
453 PyDict_SetItemString(d, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000454
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000455 x = PyString_FromString(locale__doc__);
456 PyDict_SetItemString(d, "__doc__", x);
457 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000458}