blob: 80bfbb27296cea26ddbb50173ae6ab04ed107e6e [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
29static char locale__doc__[] = "Support for POSIX locales.";
Guido van Rossum220ecc81997-11-18 21:03:39 +000030
31static PyObject *Error;
32
33/* support functions for formatting floating point numbers */
34
Fredrik Lundh8f017a02000-07-08 19:57:37 +000035static char setlocale__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +000036"(integer,string=None) -> string. Activates/queries locale processing."
37;
38
39/* to record the LC_NUMERIC settings */
Fredrik Lundh8f017a02000-07-08 19:57:37 +000040static PyObject* grouping = NULL;
41static PyObject* thousands_sep = NULL;
42static PyObject* decimal_point = NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000043/* if non-null, indicates that LC_NUMERIC is different from "C" */
Fredrik Lundh8f017a02000-07-08 19:57:37 +000044static char* saved_numeric = NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000045
46/* the grouping is terminated by either 0 or CHAR_MAX */
47static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +000048copy_grouping(char* s)
Guido van Rossum220ecc81997-11-18 21:03:39 +000049{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000050 int i;
51 PyObject *result, *val = NULL;
52
53 if (s[0] == '\0')
54 /* empty string: no grouping at all */
55 return PyList_New(0);
56
57 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
58 ; /* nothing */
59
60 result = PyList_New(i+1);
61 if (!result)
62 return NULL;
63
64 i = -1;
65 do {
66 i++;
67 val = PyInt_FromLong(s[i]);
68 if (!val)
69 break;
70 if (PyList_SetItem(result, i, val)) {
71 Py_DECREF(val);
Fredrik Lundh89610a42000-07-08 20:07:24 +000072 val = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000073 break;
74 }
75 } while (s[i] != '\0' && s[i] != CHAR_MAX);
76
77 if (!val) {
78 Py_DECREF(result);
79 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000080 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +000081
82 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +000083}
84
85static void
Fredrik Lundh8f017a02000-07-08 19:57:37 +000086fixup_ulcase(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +000087{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000088 PyObject *mods, *strop, *string, *ulo;
89 unsigned char ul[256];
90 int n, c;
Guido van Rossum220ecc81997-11-18 21:03:39 +000091
Fredrik Lundh8f017a02000-07-08 19:57:37 +000092 /* find the string and strop modules */
93 mods = PyImport_GetModuleDict();
94 if (!mods)
95 return;
96 string = PyDict_GetItemString(mods, "string");
97 if (string)
98 string = PyModule_GetDict(string);
99 strop=PyDict_GetItemString(mods, "strop");
100 if (strop)
101 strop = PyModule_GetDict(strop);
102 if (!string && !strop)
103 return;
104
105 /* create uppercase map string */
106 n = 0;
107 for (c = 0; c < 256; c++) {
108 if (isupper(c))
109 ul[n++] = c;
110 }
111 ulo = PyString_FromStringAndSize((const char *)ul, n);
Fredrik Lundh89610a42000-07-08 20:07:24 +0000112 if (!ulo)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000113 return;
114 if (string)
115 PyDict_SetItemString(string, "uppercase", ulo);
116 if (strop)
117 PyDict_SetItemString(strop, "uppercase", ulo);
118 Py_DECREF(ulo);
119
120 /* create lowercase string */
121 n = 0;
122 for (c = 0; c < 256; c++) {
123 if (islower(c))
124 ul[n++] = c;
125 }
126 ulo = PyString_FromStringAndSize((const char *)ul, n);
127 if (!ulo)
128 return;
129 if (string)
130 PyDict_SetItemString(string, "lowercase", ulo);
131 if (strop)
132 PyDict_SetItemString(strop, "lowercase", ulo);
133 Py_DECREF(ulo);
134
135 /* create letters string */
136 n = 0;
137 for (c = 0; c < 256; c++) {
138 if (isalpha(c))
139 ul[n++] = c;
140 }
141 ulo = PyString_FromStringAndSize((const char *)ul, n);
142 if (!ulo)
143 return;
144 if (string)
145 PyDict_SetItemString(string, "letters", ulo);
146 Py_DECREF(ulo);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000147}
148
149
150static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000151PyLocale_setlocale(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000152{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000153 int category;
154 char *locale = NULL, *result;
155 PyObject *result_object;
156 struct lconv *lc;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000157
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000158 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
Fredrik Lundh89610a42000-07-08 20:07:24 +0000159 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000160
161 if (locale) {
162 /* set locale */
163 result = setlocale(category, locale);
164 if (!result) {
165 /* operation failed, no setting was changed */
166 PyErr_SetString(Error, "locale setting not supported");
167 return NULL;
168 }
169 result_object = PyString_FromString(result);
170 if (!result)
171 return NULL;
172 /* record changes to LC_NUMERIC */
173 if (category == LC_NUMERIC || category == LC_ALL) {
174 if (strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0) {
175 /* user just asked for default numeric locale */
176 if (saved_numeric)
177 free(saved_numeric);
178 saved_numeric = NULL;
179 } else {
180 /* remember values */
181 lc = localeconv();
182 Py_XDECREF(grouping);
183 grouping = copy_grouping(lc->grouping);
184 Py_XDECREF(thousands_sep);
185 thousands_sep = PyString_FromString(lc->thousands_sep);
186 Py_XDECREF(decimal_point);
187 decimal_point = PyString_FromString(lc->decimal_point);
188 saved_numeric = strdup(locale);
189 /* restore to "C" */
190 setlocale(LC_NUMERIC, "C");
191 }
192 }
193 /* record changes to LC_CTYPE */
194 if (category == LC_CTYPE || category == LC_ALL)
195 fixup_ulcase();
196 /* things that got wrong up to here are ignored */
197 PyErr_Clear();
198 } else {
199 /* get locale */
200 /* restore LC_NUMERIC first, if appropriate */
201 if (saved_numeric)
202 setlocale(LC_NUMERIC, saved_numeric);
203 result = setlocale(category, NULL);
204 if (!result) {
205 PyErr_SetString(Error, "locale query failed");
206 return NULL;
207 }
208 result_object = PyString_FromString(result);
209 /* restore back to "C" */
210 if (saved_numeric)
211 setlocale(LC_NUMERIC, "C");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000212 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000213 return result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000214}
215
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000216static char localeconv__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000217"() -> dict. Returns numeric and monetary locale-specific parameters."
218;
219
220static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000221PyLocale_localeconv(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000222{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000223 PyObject* result;
224 struct lconv *l;
225 PyObject *x;
226
227 if (!PyArg_NoArgs(args))
Fredrik Lundh89610a42000-07-08 20:07:24 +0000228 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000229
230 result = PyDict_New();
Fredrik Lundh89610a42000-07-08 20:07:24 +0000231 if (!result)
232 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000233
234 /* if LC_NUMERIC is different in the C library, use saved value */
235 l = localeconv();
236
237 /* hopefully, the localeconv result survives the C library calls
238 involved herein */
239
240#define RESULT_STRING(s)\
241 x = PyString_FromString(l->s);\
242 if (!x) goto failed;\
243 PyDict_SetItemString(result, #s, x);\
244 Py_XDECREF(x)
245
246#define RESULT_INT(i)\
247 x = PyInt_FromLong(l->i);\
248 if (!x) goto failed;\
249 PyDict_SetItemString(result, #i, x);\
250 Py_XDECREF(x)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000251
252 /* Numeric information */
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000253 if (saved_numeric){
254 /* cannot use localeconv results */
255 PyDict_SetItemString(result, "decimal_point", decimal_point);
256 PyDict_SetItemString(result, "grouping", grouping);
257 PyDict_SetItemString(result, "thousands_sep", thousands_sep);
258 } else {
259 RESULT_STRING(decimal_point);
260 RESULT_STRING(thousands_sep);
261 x = copy_grouping(l->grouping);
262 if (!x)
263 goto failed;
264 PyDict_SetItemString(result, "grouping", x);
265 Py_XDECREF(x);
266 }
267
268 /* Monetary information */
269 RESULT_STRING(int_curr_symbol);
270 RESULT_STRING(currency_symbol);
271 RESULT_STRING(mon_decimal_point);
272 RESULT_STRING(mon_thousands_sep);
273 x = copy_grouping(l->mon_grouping);
274 if (!x)
275 goto failed;
276 PyDict_SetItemString(result, "mon_grouping", x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000277 Py_XDECREF(x);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000278 RESULT_STRING(positive_sign);
279 RESULT_STRING(negative_sign);
280 RESULT_INT(int_frac_digits);
281 RESULT_INT(frac_digits);
282 RESULT_INT(p_cs_precedes);
283 RESULT_INT(p_sep_by_space);
284 RESULT_INT(n_cs_precedes);
285 RESULT_INT(n_sep_by_space);
286 RESULT_INT(p_sign_posn);
287 RESULT_INT(n_sign_posn);
288 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000289
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000290 failed:
291 Py_XDECREF(result);
292 Py_XDECREF(x);
293 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000294}
295
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000296static char strcoll__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000297"string,string -> int. Compares two strings according to the locale."
298;
299
300static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000301PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000302{
303 char *s1,*s2;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000304
305 if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
306 return NULL;
307 return PyInt_FromLong(strcoll(s1, s2));
Guido van Rossum220ecc81997-11-18 21:03:39 +0000308}
309
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000310static char strxfrm__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000311"string -> string. Returns a string that behaves for cmp locale-aware."
312;
313
314static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000315PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000316{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000317 char *s, *buf;
318 size_t n1, n2;
319 PyObject *result;
320
Fredrik Lundh89610a42000-07-08 20:07:24 +0000321 if (!PyArg_ParseTuple(args, "s:strxfrm", &s))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000322 return NULL;
323
324 /* assume no change in size, first */
325 n1 = strlen(s) + 1;
326 buf = PyMem_Malloc(n1);
327 if (!buf)
328 return PyErr_NoMemory();
329 n2 = strxfrm(buf, s, n1);
330 if (n2 > n1) {
331 /* more space needed */
332 buf = PyMem_Realloc(buf, n2);
333 if (!buf)
334 return PyErr_NoMemory();
335 strxfrm(buf, s, n2);
336 }
337 result = PyString_FromString(buf);
338 PyMem_Free(buf);
339 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000340}
341
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000342#if defined(MS_WIN32)
343static PyObject*
344PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
345{
346 char encoding[100];
347 char locale[100];
348
Fredrik Lundh89610a42000-07-08 20:07:24 +0000349 if (!PyArg_NoArgs(args))
350 return NULL;
351
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000352 sprintf(encoding, "cp%d", GetACP());
353
354 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
355 LOCALE_SISO639LANGNAME,
356 locale, sizeof(locale))) {
357 int i = strlen(locale);
358 locale[i++] = '_';
359 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
360 LOCALE_SISO3166CTRYNAME,
361 locale+i, sizeof(locale)-i))
362 return Py_BuildValue("ss", locale, encoding);
363 }
364
365 /* If we end up here, this windows version didn't know about
366 ISO639/ISO3166 names (it's probably Windows 95). Return the
367 Windows language identifier instead (a hexadecimal number) */
368
369 locale[0] = '0';
370 locale[1] = 'x';
371 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
372 locale+2, sizeof(locale)-2)) {
373 return Py_BuildValue("ss", locale, encoding);
374 }
375
376 /* cannot determine the language code (very unlikely) */
377 Py_INCREF(Py_None);
378 return Py_BuildValue("Os", Py_None, encoding);
379}
380#endif
381
Jack Jansen307d7a42000-07-15 22:31:45 +0000382#if defined(macintosh)
383static PyObject*
384PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
385{
386 return Py_BuildValue("Os", Py_None, PyMac_getscript());
387}
388#endif
389
Guido van Rossum220ecc81997-11-18 21:03:39 +0000390static struct PyMethodDef PyLocale_Methods[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000391 {"setlocale", (PyCFunction) PyLocale_setlocale,
392 METH_VARARGS, setlocale__doc__},
393 {"localeconv", (PyCFunction) PyLocale_localeconv,
394 0, localeconv__doc__},
395 {"strcoll", (PyCFunction) PyLocale_strcoll,
396 METH_VARARGS, strcoll__doc__},
397 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
398 METH_VARARGS, strxfrm__doc__},
Jack Jansen307d7a42000-07-15 22:31:45 +0000399#if defined(MS_WIN32) || defined(macintosh)
Fredrik Lundh89610a42000-07-08 20:07:24 +0000400 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, 0},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000401#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000402 {NULL, NULL}
403};
404
Guido van Rossum3886bb61998-12-04 18:50:17 +0000405DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000406init_locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000407{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000408 PyObject *m, *d, *x;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000409
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000410 m = Py_InitModule("_locale", PyLocale_Methods);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000411
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000412 d = PyModule_GetDict(m);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000413
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000414 x = PyInt_FromLong(LC_CTYPE);
415 PyDict_SetItemString(d, "LC_CTYPE", x);
416 Py_XDECREF(x);
417
418 x = PyInt_FromLong(LC_TIME);
419 PyDict_SetItemString(d, "LC_TIME", x);
420 Py_XDECREF(x);
421
422 x = PyInt_FromLong(LC_COLLATE);
423 PyDict_SetItemString(d, "LC_COLLATE", x);
424 Py_XDECREF(x);
425
426 x = PyInt_FromLong(LC_MONETARY);
427 PyDict_SetItemString(d, "LC_MONETARY", x);
428 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000429
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000430#ifdef LC_MESSAGES
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000431 x = PyInt_FromLong(LC_MESSAGES);
432 PyDict_SetItemString(d, "LC_MESSAGES", x);
433 Py_XDECREF(x);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000434#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000435
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000436 x = PyInt_FromLong(LC_NUMERIC);
437 PyDict_SetItemString(d, "LC_NUMERIC", x);
438 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000439
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000440 x = PyInt_FromLong(LC_ALL);
441 PyDict_SetItemString(d, "LC_ALL", 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(CHAR_MAX);
445 PyDict_SetItemString(d, "CHAR_MAX", x);
446 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000447
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000448 Error = PyErr_NewException("locale.Error", NULL, NULL);
449 PyDict_SetItemString(d, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000450
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000451 x = PyString_FromString(locale__doc__);
452 PyDict_SetItemString(d, "__doc__", x);
453 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000454}