struct.pack has become picky about h (short) and H (unsigned short).
[python/dscho.git] / Modules / _localemodule.c
blob80bfbb27296cea26ddbb50173ae6ab04ed107e6e
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 static char locale__doc__[] = "Support for POSIX locales.";
31 static PyObject *Error;
33 /* support functions for formatting floating point numbers */
35 static char setlocale__doc__[] =
36 "(integer,string=None) -> string. Activates/queries locale processing."
39 /* to record the LC_NUMERIC settings */
40 static PyObject* grouping = NULL;
41 static PyObject* thousands_sep = NULL;
42 static PyObject* decimal_point = NULL;
43 /* if non-null, indicates that LC_NUMERIC is different from "C" */
44 static char* saved_numeric = NULL;
46 /* the grouping is terminated by either 0 or CHAR_MAX */
47 static PyObject*
48 copy_grouping(char* s)
50 int i;
51 PyObject *result, *val = NULL;
53 if (s[0] == '\0')
54 /* empty string: no grouping at all */
55 return PyList_New(0);
57 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
58 ; /* nothing */
60 result = PyList_New(i+1);
61 if (!result)
62 return NULL;
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);
72 val = NULL;
73 break;
75 } while (s[i] != '\0' && s[i] != CHAR_MAX);
77 if (!val) {
78 Py_DECREF(result);
79 return NULL;
82 return result;
85 static void
86 fixup_ulcase(void)
88 PyObject *mods, *strop, *string, *ulo;
89 unsigned char ul[256];
90 int n, c;
92 /* 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;
105 /* create uppercase map string */
106 n = 0;
107 for (c = 0; c < 256; c++) {
108 if (isupper(c))
109 ul[n++] = c;
111 ulo = PyString_FromStringAndSize((const char *)ul, n);
112 if (!ulo)
113 return;
114 if (string)
115 PyDict_SetItemString(string, "uppercase", ulo);
116 if (strop)
117 PyDict_SetItemString(strop, "uppercase", ulo);
118 Py_DECREF(ulo);
120 /* create lowercase string */
121 n = 0;
122 for (c = 0; c < 256; c++) {
123 if (islower(c))
124 ul[n++] = c;
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);
135 /* create letters string */
136 n = 0;
137 for (c = 0; c < 256; c++) {
138 if (isalpha(c))
139 ul[n++] = c;
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);
150 static PyObject*
151 PyLocale_setlocale(PyObject* self, PyObject* args)
153 int category;
154 char *locale = NULL, *result;
155 PyObject *result_object;
156 struct lconv *lc;
158 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
159 return NULL;
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;
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");
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;
208 result_object = PyString_FromString(result);
209 /* restore back to "C" */
210 if (saved_numeric)
211 setlocale(LC_NUMERIC, "C");
213 return result_object;
216 static char localeconv__doc__[] =
217 "() -> dict. Returns numeric and monetary locale-specific parameters."
220 static PyObject*
221 PyLocale_localeconv(PyObject* self, PyObject* args)
223 PyObject* result;
224 struct lconv *l;
225 PyObject *x;
227 if (!PyArg_NoArgs(args))
228 return NULL;
230 result = PyDict_New();
231 if (!result)
232 return NULL;
234 /* if LC_NUMERIC is different in the C library, use saved value */
235 l = localeconv();
237 /* hopefully, the localeconv result survives the C library calls
238 involved herein */
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)
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)
252 /* Numeric information */
253 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);
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);
277 Py_XDECREF(x);
278 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;
290 failed:
291 Py_XDECREF(result);
292 Py_XDECREF(x);
293 return NULL;
296 static char strcoll__doc__[] =
297 "string,string -> int. Compares two strings according to the locale."
300 static PyObject*
301 PyLocale_strcoll(PyObject* self, PyObject* args)
303 char *s1,*s2;
305 if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
306 return NULL;
307 return PyInt_FromLong(strcoll(s1, s2));
310 static char strxfrm__doc__[] =
311 "string -> string. Returns a string that behaves for cmp locale-aware."
314 static PyObject*
315 PyLocale_strxfrm(PyObject* self, PyObject* args)
317 char *s, *buf;
318 size_t n1, n2;
319 PyObject *result;
321 if (!PyArg_ParseTuple(args, "s:strxfrm", &s))
322 return NULL;
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);
337 result = PyString_FromString(buf);
338 PyMem_Free(buf);
339 return result;
342 #if defined(MS_WIN32)
343 static PyObject*
344 PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
346 char encoding[100];
347 char locale[100];
349 if (!PyArg_NoArgs(args))
350 return NULL;
352 sprintf(encoding, "cp%d", GetACP());
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);
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) */
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);
376 /* cannot determine the language code (very unlikely) */
377 Py_INCREF(Py_None);
378 return Py_BuildValue("Os", Py_None, encoding);
380 #endif
382 #if defined(macintosh)
383 static PyObject*
384 PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
386 return Py_BuildValue("Os", Py_None, PyMac_getscript());
388 #endif
390 static struct PyMethodDef PyLocale_Methods[] = {
391 {"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__},
399 #if defined(MS_WIN32) || defined(macintosh)
400 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, 0},
401 #endif
402 {NULL, NULL}
405 DL_EXPORT(void)
406 init_locale(void)
408 PyObject *m, *d, *x;
410 m = Py_InitModule("_locale", PyLocale_Methods);
412 d = PyModule_GetDict(m);
414 x = PyInt_FromLong(LC_CTYPE);
415 PyDict_SetItemString(d, "LC_CTYPE", x);
416 Py_XDECREF(x);
418 x = PyInt_FromLong(LC_TIME);
419 PyDict_SetItemString(d, "LC_TIME", x);
420 Py_XDECREF(x);
422 x = PyInt_FromLong(LC_COLLATE);
423 PyDict_SetItemString(d, "LC_COLLATE", x);
424 Py_XDECREF(x);
426 x = PyInt_FromLong(LC_MONETARY);
427 PyDict_SetItemString(d, "LC_MONETARY", x);
428 Py_XDECREF(x);
430 #ifdef LC_MESSAGES
431 x = PyInt_FromLong(LC_MESSAGES);
432 PyDict_SetItemString(d, "LC_MESSAGES", x);
433 Py_XDECREF(x);
434 #endif /* LC_MESSAGES */
436 x = PyInt_FromLong(LC_NUMERIC);
437 PyDict_SetItemString(d, "LC_NUMERIC", x);
438 Py_XDECREF(x);
440 x = PyInt_FromLong(LC_ALL);
441 PyDict_SetItemString(d, "LC_ALL", x);
442 Py_XDECREF(x);
444 x = PyInt_FromLong(CHAR_MAX);
445 PyDict_SetItemString(d, "CHAR_MAX", x);
446 Py_XDECREF(x);
448 Error = PyErr_NewException("locale.Error", NULL, NULL);
449 PyDict_SetItemString(d, "Error", Error);
451 x = PyString_FromString(locale__doc__);
452 PyDict_SetItemString(d, "__doc__", x);
453 Py_XDECREF(x);