py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Modules / _localemodule.c
blob53ae678e7648ea955944792e46a84a3895ff068b
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 <ctype.h>
20 #if defined(MS_WIN32)
21 #define WINDOWS_LEAN_AND_MEAN
22 #include <windows.h>
23 #endif
25 #ifdef macintosh
26 #include "macglue.h"
27 #endif
29 #ifdef RISCOS
30 char *strdup(const char *);
31 #endif
33 static char locale__doc__[] = "Support for POSIX locales.";
35 static PyObject *Error;
37 /* support functions for formatting floating point numbers */
39 static char setlocale__doc__[] =
40 "(integer,string=None) -> string. Activates/queries locale processing."
43 /* to record the LC_NUMERIC settings */
44 static PyObject* grouping = NULL;
45 static PyObject* thousands_sep = NULL;
46 static PyObject* decimal_point = NULL;
47 /* if non-null, indicates that LC_NUMERIC is different from "C" */
48 static char* saved_numeric = NULL;
50 /* the grouping is terminated by either 0 or CHAR_MAX */
51 static PyObject*
52 copy_grouping(char* s)
54 int i;
55 PyObject *result, *val = NULL;
57 if (s[0] == '\0')
58 /* empty string: no grouping at all */
59 return PyList_New(0);
61 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
62 ; /* nothing */
64 result = PyList_New(i+1);
65 if (!result)
66 return NULL;
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);
76 val = NULL;
77 break;
79 } while (s[i] != '\0' && s[i] != CHAR_MAX);
81 if (!val) {
82 Py_DECREF(result);
83 return NULL;
86 return result;
89 static void
90 fixup_ulcase(void)
92 PyObject *mods, *strop, *string, *ulo;
93 unsigned char ul[256];
94 int n, c;
96 /* 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;
109 /* create uppercase map string */
110 n = 0;
111 for (c = 0; c < 256; c++) {
112 if (isupper(c))
113 ul[n++] = c;
115 ulo = PyString_FromStringAndSize((const char *)ul, n);
116 if (!ulo)
117 return;
118 if (string)
119 PyDict_SetItemString(string, "uppercase", ulo);
120 if (strop)
121 PyDict_SetItemString(strop, "uppercase", ulo);
122 Py_DECREF(ulo);
124 /* create lowercase string */
125 n = 0;
126 for (c = 0; c < 256; c++) {
127 if (islower(c))
128 ul[n++] = c;
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);
139 /* create letters string */
140 n = 0;
141 for (c = 0; c < 256; c++) {
142 if (isalpha(c))
143 ul[n++] = c;
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);
154 static PyObject*
155 PyLocale_setlocale(PyObject* self, PyObject* args)
157 int category;
158 char *locale = NULL, *result;
159 PyObject *result_object;
160 struct lconv *lc;
162 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
163 return NULL;
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;
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");
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;
212 result_object = PyString_FromString(result);
213 /* restore back to "C" */
214 if (saved_numeric)
215 setlocale(LC_NUMERIC, "C");
217 return result_object;
220 static char localeconv__doc__[] =
221 "() -> dict. Returns numeric and monetary locale-specific parameters."
224 static PyObject*
225 PyLocale_localeconv(PyObject* self, PyObject* args)
227 PyObject* result;
228 struct lconv *l;
229 PyObject *x;
231 if (!PyArg_NoArgs(args))
232 return NULL;
234 result = PyDict_New();
235 if (!result)
236 return NULL;
238 /* if LC_NUMERIC is different in the C library, use saved value */
239 l = localeconv();
241 /* hopefully, the localeconv result survives the C library calls
242 involved herein */
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)
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)
256 /* Numeric information */
257 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);
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);
281 Py_XDECREF(x);
282 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;
294 failed:
295 Py_XDECREF(result);
296 Py_XDECREF(x);
297 return NULL;
300 static char strcoll__doc__[] =
301 "string,string -> int. Compares two strings according to the locale."
304 static PyObject*
305 PyLocale_strcoll(PyObject* self, PyObject* args)
307 char *s1,*s2;
309 if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
310 return NULL;
311 return PyInt_FromLong(strcoll(s1, s2));
314 static char strxfrm__doc__[] =
315 "string -> string. Returns a string that behaves for cmp locale-aware."
318 static PyObject*
319 PyLocale_strxfrm(PyObject* self, PyObject* args)
321 char *s, *buf;
322 size_t n1, n2;
323 PyObject *result;
325 if (!PyArg_ParseTuple(args, "s:strxfrm", &s))
326 return NULL;
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);
341 result = PyString_FromString(buf);
342 PyMem_Free(buf);
343 return result;
346 #if defined(MS_WIN32)
347 static PyObject*
348 PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
350 char encoding[100];
351 char locale[100];
353 if (!PyArg_NoArgs(args))
354 return NULL;
356 sprintf(encoding, "cp%d", GetACP());
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);
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) */
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);
380 /* cannot determine the language code (very unlikely) */
381 Py_INCREF(Py_None);
382 return Py_BuildValue("Os", Py_None, encoding);
384 #endif
386 #if defined(macintosh)
387 static PyObject*
388 PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
390 return Py_BuildValue("Os", Py_None, PyMac_getscript());
392 #endif
394 static struct PyMethodDef PyLocale_Methods[] = {
395 {"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__},
403 #if defined(MS_WIN32) || defined(macintosh)
404 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, 0},
405 #endif
406 {NULL, NULL}
409 DL_EXPORT(void)
410 init_locale(void)
412 PyObject *m, *d, *x;
414 m = Py_InitModule("_locale", PyLocale_Methods);
416 d = PyModule_GetDict(m);
418 x = PyInt_FromLong(LC_CTYPE);
419 PyDict_SetItemString(d, "LC_CTYPE", x);
420 Py_XDECREF(x);
422 x = PyInt_FromLong(LC_TIME);
423 PyDict_SetItemString(d, "LC_TIME", x);
424 Py_XDECREF(x);
426 x = PyInt_FromLong(LC_COLLATE);
427 PyDict_SetItemString(d, "LC_COLLATE", x);
428 Py_XDECREF(x);
430 x = PyInt_FromLong(LC_MONETARY);
431 PyDict_SetItemString(d, "LC_MONETARY", x);
432 Py_XDECREF(x);
434 #ifdef LC_MESSAGES
435 x = PyInt_FromLong(LC_MESSAGES);
436 PyDict_SetItemString(d, "LC_MESSAGES", x);
437 Py_XDECREF(x);
438 #endif /* LC_MESSAGES */
440 x = PyInt_FromLong(LC_NUMERIC);
441 PyDict_SetItemString(d, "LC_NUMERIC", x);
442 Py_XDECREF(x);
444 x = PyInt_FromLong(LC_ALL);
445 PyDict_SetItemString(d, "LC_ALL", x);
446 Py_XDECREF(x);
448 x = PyInt_FromLong(CHAR_MAX);
449 PyDict_SetItemString(d, "CHAR_MAX", x);
450 Py_XDECREF(x);
452 Error = PyErr_NewException("locale.Error", NULL, NULL);
453 PyDict_SetItemString(d, "Error", Error);
455 x = PyString_FromString(locale__doc__);
456 PyDict_SetItemString(d, "__doc__", x);
457 Py_XDECREF(x);