Bump version to 0.9.1.
[python/dscho.git] / Modules / _localemodule.c
blob030f9d6e593f0cd539bafcb4b37177889ce7a796
1 /***********************************************************
2 Copyright (C) 1997 Martin von Loewis
4 Permission to use, copy, modify, and distribute this software and its
5 documentation for any purpose and without fee is hereby granted,
6 provided that the above copyright notice appear in all copies.
8 This software comes with no warranty. Use at your own risk.
10 ******************************************************************/
12 #include "Python.h"
14 #include <stdio.h>
15 #include <errno.h>
16 #include <locale.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <ctype.h>
21 #if defined(MS_WIN32)
22 #define WINDOWS_LEAN_AND_MEAN
23 #include <windows.h>
24 #endif
26 #ifdef macintosh
27 #include "macglue.h"
28 #endif
30 static char locale__doc__[] = "Support for POSIX locales.";
32 static PyObject *Error;
34 /* support functions for formatting floating point numbers */
36 static char setlocale__doc__[] =
37 "(integer,string=None) -> string. Activates/queries locale processing."
40 /* to record the LC_NUMERIC settings */
41 static PyObject* grouping = NULL;
42 static PyObject* thousands_sep = NULL;
43 static PyObject* decimal_point = NULL;
44 /* if non-null, indicates that LC_NUMERIC is different from "C" */
45 static char* saved_numeric = NULL;
47 /* the grouping is terminated by either 0 or CHAR_MAX */
48 static PyObject*
49 copy_grouping(char* s)
51 int i;
52 PyObject *result, *val = NULL;
54 if (s[0] == '\0')
55 /* empty string: no grouping at all */
56 return PyList_New(0);
58 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
59 ; /* nothing */
61 result = PyList_New(i+1);
62 if (!result)
63 return NULL;
65 i = -1;
66 do {
67 i++;
68 val = PyInt_FromLong(s[i]);
69 if (!val)
70 break;
71 if (PyList_SetItem(result, i, val)) {
72 Py_DECREF(val);
73 val = NULL;
74 break;
76 } while (s[i] != '\0' && s[i] != CHAR_MAX);
78 if (!val) {
79 Py_DECREF(result);
80 return NULL;
83 return result;
86 static void
87 fixup_ulcase(void)
89 PyObject *mods, *strop, *string, *ulo;
90 unsigned char ul[256];
91 int n, c;
93 /* find the string and strop modules */
94 mods = PyImport_GetModuleDict();
95 if (!mods)
96 return;
97 string = PyDict_GetItemString(mods, "string");
98 if (string)
99 string = PyModule_GetDict(string);
100 strop=PyDict_GetItemString(mods, "strop");
101 if (strop)
102 strop = PyModule_GetDict(strop);
103 if (!string && !strop)
104 return;
106 /* create uppercase map string */
107 n = 0;
108 for (c = 0; c < 256; c++) {
109 if (isupper(c))
110 ul[n++] = c;
112 ulo = PyString_FromStringAndSize((const char *)ul, n);
113 if (!ulo)
114 return;
115 if (string)
116 PyDict_SetItemString(string, "uppercase", ulo);
117 if (strop)
118 PyDict_SetItemString(strop, "uppercase", ulo);
119 Py_DECREF(ulo);
121 /* create lowercase string */
122 n = 0;
123 for (c = 0; c < 256; c++) {
124 if (islower(c))
125 ul[n++] = c;
127 ulo = PyString_FromStringAndSize((const char *)ul, n);
128 if (!ulo)
129 return;
130 if (string)
131 PyDict_SetItemString(string, "lowercase", ulo);
132 if (strop)
133 PyDict_SetItemString(strop, "lowercase", ulo);
134 Py_DECREF(ulo);
136 /* create letters string */
137 n = 0;
138 for (c = 0; c < 256; c++) {
139 if (isalpha(c))
140 ul[n++] = c;
142 ulo = PyString_FromStringAndSize((const char *)ul, n);
143 if (!ulo)
144 return;
145 if (string)
146 PyDict_SetItemString(string, "letters", ulo);
147 Py_DECREF(ulo);
151 static PyObject*
152 PyLocale_setlocale(PyObject* self, PyObject* args)
154 int category;
155 char *locale = NULL, *result;
156 PyObject *result_object;
157 struct lconv *lc;
159 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
160 return NULL;
162 if (locale) {
163 /* set locale */
164 result = setlocale(category, locale);
165 if (!result) {
166 /* operation failed, no setting was changed */
167 PyErr_SetString(Error, "locale setting not supported");
168 return NULL;
170 result_object = PyString_FromString(result);
171 if (!result)
172 return NULL;
173 /* record changes to LC_NUMERIC */
174 if (category == LC_NUMERIC || category == LC_ALL) {
175 if (strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0) {
176 /* user just asked for default numeric locale */
177 if (saved_numeric)
178 free(saved_numeric);
179 saved_numeric = NULL;
180 } else {
181 /* remember values */
182 lc = localeconv();
183 Py_XDECREF(grouping);
184 grouping = copy_grouping(lc->grouping);
185 Py_XDECREF(thousands_sep);
186 thousands_sep = PyString_FromString(lc->thousands_sep);
187 Py_XDECREF(decimal_point);
188 decimal_point = PyString_FromString(lc->decimal_point);
189 saved_numeric = strdup(locale);
190 /* restore to "C" */
191 setlocale(LC_NUMERIC, "C");
194 /* record changes to LC_CTYPE */
195 if (category == LC_CTYPE || category == LC_ALL)
196 fixup_ulcase();
197 /* things that got wrong up to here are ignored */
198 PyErr_Clear();
199 } else {
200 /* get locale */
201 /* restore LC_NUMERIC first, if appropriate */
202 if (saved_numeric)
203 setlocale(LC_NUMERIC, saved_numeric);
204 result = setlocale(category, NULL);
205 if (!result) {
206 PyErr_SetString(Error, "locale query failed");
207 return NULL;
209 result_object = PyString_FromString(result);
210 /* restore back to "C" */
211 if (saved_numeric)
212 setlocale(LC_NUMERIC, "C");
214 return result_object;
217 static char localeconv__doc__[] =
218 "() -> dict. Returns numeric and monetary locale-specific parameters."
221 static PyObject*
222 PyLocale_localeconv(PyObject* self, PyObject* args)
224 PyObject* result;
225 struct lconv *l;
226 PyObject *x;
228 if (!PyArg_NoArgs(args))
229 return NULL;
231 result = PyDict_New();
232 if (!result)
233 return NULL;
235 /* if LC_NUMERIC is different in the C library, use saved value */
236 l = localeconv();
238 /* hopefully, the localeconv result survives the C library calls
239 involved herein */
241 #define RESULT_STRING(s)\
242 x = PyString_FromString(l->s);\
243 if (!x) goto failed;\
244 PyDict_SetItemString(result, #s, x);\
245 Py_XDECREF(x)
247 #define RESULT_INT(i)\
248 x = PyInt_FromLong(l->i);\
249 if (!x) goto failed;\
250 PyDict_SetItemString(result, #i, x);\
251 Py_XDECREF(x)
253 /* Numeric information */
254 if (saved_numeric){
255 /* cannot use localeconv results */
256 PyDict_SetItemString(result, "decimal_point", decimal_point);
257 PyDict_SetItemString(result, "grouping", grouping);
258 PyDict_SetItemString(result, "thousands_sep", thousands_sep);
259 } else {
260 RESULT_STRING(decimal_point);
261 RESULT_STRING(thousands_sep);
262 x = copy_grouping(l->grouping);
263 if (!x)
264 goto failed;
265 PyDict_SetItemString(result, "grouping", x);
266 Py_XDECREF(x);
269 /* Monetary information */
270 RESULT_STRING(int_curr_symbol);
271 RESULT_STRING(currency_symbol);
272 RESULT_STRING(mon_decimal_point);
273 RESULT_STRING(mon_thousands_sep);
274 x = copy_grouping(l->mon_grouping);
275 if (!x)
276 goto failed;
277 PyDict_SetItemString(result, "mon_grouping", x);
278 Py_XDECREF(x);
279 RESULT_STRING(positive_sign);
280 RESULT_STRING(negative_sign);
281 RESULT_INT(int_frac_digits);
282 RESULT_INT(frac_digits);
283 RESULT_INT(p_cs_precedes);
284 RESULT_INT(p_sep_by_space);
285 RESULT_INT(n_cs_precedes);
286 RESULT_INT(n_sep_by_space);
287 RESULT_INT(p_sign_posn);
288 RESULT_INT(n_sign_posn);
289 return result;
291 failed:
292 Py_XDECREF(result);
293 Py_XDECREF(x);
294 return NULL;
297 static char strcoll__doc__[] =
298 "string,string -> int. Compares two strings according to the locale."
301 static PyObject*
302 PyLocale_strcoll(PyObject* self, PyObject* args)
304 char *s1,*s2;
306 if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
307 return NULL;
308 return PyInt_FromLong(strcoll(s1, s2));
311 static char strxfrm__doc__[] =
312 "string -> string. Returns a string that behaves for cmp locale-aware."
315 static PyObject*
316 PyLocale_strxfrm(PyObject* self, PyObject* args)
318 char *s, *buf;
319 size_t n1, n2;
320 PyObject *result;
322 if (!PyArg_ParseTuple(args, "s:strxfrm", &s))
323 return NULL;
325 /* assume no change in size, first */
326 n1 = strlen(s) + 1;
327 buf = PyMem_Malloc(n1);
328 if (!buf)
329 return PyErr_NoMemory();
330 n2 = strxfrm(buf, s, n1);
331 if (n2 > n1) {
332 /* more space needed */
333 buf = PyMem_Realloc(buf, n2);
334 if (!buf)
335 return PyErr_NoMemory();
336 strxfrm(buf, s, n2);
338 result = PyString_FromString(buf);
339 PyMem_Free(buf);
340 return result;
343 #if defined(MS_WIN32)
344 static PyObject*
345 PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
347 char encoding[100];
348 char locale[100];
350 if (!PyArg_NoArgs(args))
351 return NULL;
353 sprintf(encoding, "cp%d", GetACP());
355 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
356 LOCALE_SISO639LANGNAME,
357 locale, sizeof(locale))) {
358 int i = strlen(locale);
359 locale[i++] = '_';
360 if (GetLocaleInfo(LOCALE_USER_DEFAULT,
361 LOCALE_SISO3166CTRYNAME,
362 locale+i, sizeof(locale)-i))
363 return Py_BuildValue("ss", locale, encoding);
366 /* If we end up here, this windows version didn't know about
367 ISO639/ISO3166 names (it's probably Windows 95). Return the
368 Windows language identifier instead (a hexadecimal number) */
370 locale[0] = '0';
371 locale[1] = 'x';
372 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
373 locale+2, sizeof(locale)-2)) {
374 return Py_BuildValue("ss", locale, encoding);
377 /* cannot determine the language code (very unlikely) */
378 Py_INCREF(Py_None);
379 return Py_BuildValue("Os", Py_None, encoding);
381 #endif
383 #if defined(macintosh)
384 static PyObject*
385 PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
387 return Py_BuildValue("Os", Py_None, PyMac_getscript());
389 #endif
391 static struct PyMethodDef PyLocale_Methods[] = {
392 {"setlocale", (PyCFunction) PyLocale_setlocale,
393 METH_VARARGS, setlocale__doc__},
394 {"localeconv", (PyCFunction) PyLocale_localeconv,
395 0, localeconv__doc__},
396 {"strcoll", (PyCFunction) PyLocale_strcoll,
397 METH_VARARGS, strcoll__doc__},
398 {"strxfrm", (PyCFunction) PyLocale_strxfrm,
399 METH_VARARGS, strxfrm__doc__},
400 #if defined(MS_WIN32) || defined(macintosh)
401 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, 0},
402 #endif
403 {NULL, NULL}
406 DL_EXPORT(void)
407 init_locale(void)
409 PyObject *m, *d, *x;
411 m = Py_InitModule("_locale", PyLocale_Methods);
413 d = PyModule_GetDict(m);
415 x = PyInt_FromLong(LC_CTYPE);
416 PyDict_SetItemString(d, "LC_CTYPE", x);
417 Py_XDECREF(x);
419 x = PyInt_FromLong(LC_TIME);
420 PyDict_SetItemString(d, "LC_TIME", x);
421 Py_XDECREF(x);
423 x = PyInt_FromLong(LC_COLLATE);
424 PyDict_SetItemString(d, "LC_COLLATE", x);
425 Py_XDECREF(x);
427 x = PyInt_FromLong(LC_MONETARY);
428 PyDict_SetItemString(d, "LC_MONETARY", x);
429 Py_XDECREF(x);
431 #ifdef LC_MESSAGES
432 x = PyInt_FromLong(LC_MESSAGES);
433 PyDict_SetItemString(d, "LC_MESSAGES", x);
434 Py_XDECREF(x);
435 #endif /* LC_MESSAGES */
437 x = PyInt_FromLong(LC_NUMERIC);
438 PyDict_SetItemString(d, "LC_NUMERIC", x);
439 Py_XDECREF(x);
441 x = PyInt_FromLong(LC_ALL);
442 PyDict_SetItemString(d, "LC_ALL", x);
443 Py_XDECREF(x);
445 x = PyInt_FromLong(CHAR_MAX);
446 PyDict_SetItemString(d, "CHAR_MAX", x);
447 Py_XDECREF(x);
449 Error = PyErr_NewException("locale.Error", NULL, NULL);
450 PyDict_SetItemString(d, "Error", Error);
452 x = PyString_FromString(locale__doc__);
453 PyDict_SetItemString(d, "__doc__", x);
454 Py_XDECREF(x);
456 if (PyErr_Occurred())
457 Py_FatalError("Can't initialize module locale");