blob: 2588b8e913d2f0731d621cde89e72a8d3d699d73 [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>
18#include <limits.h>
Guido van Rossum5cd70f41998-06-19 04:33:30 +000019#include <ctype.h>
Fredrik Lundh8f017a02000-07-08 19:57:37 +000020
Fredrik Lundh8f017a02000-07-08 19:57:37 +000021#if defined(MS_WIN32)
22#define WINDOWS_LEAN_AND_MEAN
23#include <windows.h>
Guido van Rossum239a2181998-04-28 16:08:19 +000024#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +000025
Fredrik Lundh8f017a02000-07-08 19:57:37 +000026#ifdef macintosh
Jack Jansen307d7a42000-07-15 22:31:45 +000027#include "macglue.h"
Fredrik Lundh8f017a02000-07-08 19:57:37 +000028#endif
29
30static char locale__doc__[] = "Support for POSIX locales.";
Guido van Rossum220ecc81997-11-18 21:03:39 +000031
32static PyObject *Error;
33
34/* support functions for formatting floating point numbers */
35
Fredrik Lundh8f017a02000-07-08 19:57:37 +000036static char setlocale__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +000037"(integer,string=None) -> string. Activates/queries locale processing."
38;
39
40/* to record the LC_NUMERIC settings */
Fredrik Lundh8f017a02000-07-08 19:57:37 +000041static PyObject* grouping = NULL;
42static PyObject* thousands_sep = NULL;
43static PyObject* decimal_point = NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000044/* if non-null, indicates that LC_NUMERIC is different from "C" */
Fredrik Lundh8f017a02000-07-08 19:57:37 +000045static char* saved_numeric = NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000046
47/* the grouping is terminated by either 0 or CHAR_MAX */
48static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +000049copy_grouping(char* s)
Guido van Rossum220ecc81997-11-18 21:03:39 +000050{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000051 int i;
52 PyObject *result, *val = NULL;
53
54 if (s[0] == '\0')
55 /* empty string: no grouping at all */
56 return PyList_New(0);
57
58 for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
59 ; /* nothing */
60
61 result = PyList_New(i+1);
62 if (!result)
63 return NULL;
64
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);
Fredrik Lundh89610a42000-07-08 20:07:24 +000073 val = NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +000074 break;
75 }
76 } while (s[i] != '\0' && s[i] != CHAR_MAX);
77
78 if (!val) {
79 Py_DECREF(result);
80 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +000081 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +000082
83 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +000084}
85
86static void
Fredrik Lundh8f017a02000-07-08 19:57:37 +000087fixup_ulcase(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +000088{
Fredrik Lundh8f017a02000-07-08 19:57:37 +000089 PyObject *mods, *strop, *string, *ulo;
90 unsigned char ul[256];
91 int n, c;
Guido van Rossum220ecc81997-11-18 21:03:39 +000092
Fredrik Lundh8f017a02000-07-08 19:57:37 +000093 /* 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;
105
106 /* create uppercase map string */
107 n = 0;
108 for (c = 0; c < 256; c++) {
109 if (isupper(c))
110 ul[n++] = c;
111 }
112 ulo = PyString_FromStringAndSize((const char *)ul, n);
Fredrik Lundh89610a42000-07-08 20:07:24 +0000113 if (!ulo)
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000114 return;
115 if (string)
116 PyDict_SetItemString(string, "uppercase", ulo);
117 if (strop)
118 PyDict_SetItemString(strop, "uppercase", ulo);
119 Py_DECREF(ulo);
120
121 /* create lowercase string */
122 n = 0;
123 for (c = 0; c < 256; c++) {
124 if (islower(c))
125 ul[n++] = c;
126 }
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);
135
136 /* create letters string */
137 n = 0;
138 for (c = 0; c < 256; c++) {
139 if (isalpha(c))
140 ul[n++] = c;
141 }
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);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000148}
149
150
151static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000152PyLocale_setlocale(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000153{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000154 int category;
155 char *locale = NULL, *result;
156 PyObject *result_object;
157 struct lconv *lc;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000158
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000159 if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
Fredrik Lundh89610a42000-07-08 20:07:24 +0000160 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000161
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;
169 }
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");
192 }
193 }
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;
208 }
209 result_object = PyString_FromString(result);
210 /* restore back to "C" */
211 if (saved_numeric)
212 setlocale(LC_NUMERIC, "C");
Guido van Rossum220ecc81997-11-18 21:03:39 +0000213 }
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000214 return result_object;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000215}
216
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000217static char localeconv__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000218"() -> dict. Returns numeric and monetary locale-specific parameters."
219;
220
221static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000222PyLocale_localeconv(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000223{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000224 PyObject* result;
225 struct lconv *l;
226 PyObject *x;
227
228 if (!PyArg_NoArgs(args))
Fredrik Lundh89610a42000-07-08 20:07:24 +0000229 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000230
231 result = PyDict_New();
Fredrik Lundh89610a42000-07-08 20:07:24 +0000232 if (!result)
233 return NULL;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000234
235 /* if LC_NUMERIC is different in the C library, use saved value */
236 l = localeconv();
237
238 /* hopefully, the localeconv result survives the C library calls
239 involved herein */
240
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)
246
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)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000252
253 /* Numeric information */
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000254 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);
267 }
268
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);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000278 Py_XDECREF(x);
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000279 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;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000290
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000291 failed:
292 Py_XDECREF(result);
293 Py_XDECREF(x);
294 return NULL;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000295}
296
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000297static char strcoll__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000298"string,string -> int. Compares two strings according to the locale."
299;
300
301static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000302PyLocale_strcoll(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000303{
304 char *s1,*s2;
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000305
306 if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
307 return NULL;
308 return PyInt_FromLong(strcoll(s1, s2));
Guido van Rossum220ecc81997-11-18 21:03:39 +0000309}
310
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000311static char strxfrm__doc__[] =
Guido van Rossum220ecc81997-11-18 21:03:39 +0000312"string -> string. Returns a string that behaves for cmp locale-aware."
313;
314
315static PyObject*
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000316PyLocale_strxfrm(PyObject* self, PyObject* args)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000317{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000318 char *s, *buf;
319 size_t n1, n2;
320 PyObject *result;
321
Fredrik Lundh89610a42000-07-08 20:07:24 +0000322 if (!PyArg_ParseTuple(args, "s:strxfrm", &s))
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000323 return NULL;
324
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);
337 }
338 result = PyString_FromString(buf);
339 PyMem_Free(buf);
340 return result;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000341}
342
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000343#if defined(MS_WIN32)
344static PyObject*
345PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
346{
347 char encoding[100];
348 char locale[100];
349
Fredrik Lundh89610a42000-07-08 20:07:24 +0000350 if (!PyArg_NoArgs(args))
351 return NULL;
352
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000353 sprintf(encoding, "cp%d", GetACP());
354
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);
364 }
365
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) */
369
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);
375 }
376
377 /* cannot determine the language code (very unlikely) */
378 Py_INCREF(Py_None);
379 return Py_BuildValue("Os", Py_None, encoding);
380}
381#endif
382
Jack Jansen307d7a42000-07-15 22:31:45 +0000383#if defined(macintosh)
384static PyObject*
385PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
386{
387 return Py_BuildValue("Os", Py_None, PyMac_getscript());
388}
389#endif
390
Guido van Rossum220ecc81997-11-18 21:03:39 +0000391static struct PyMethodDef PyLocale_Methods[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000392 {"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__},
Jack Jansen307d7a42000-07-15 22:31:45 +0000400#if defined(MS_WIN32) || defined(macintosh)
Fredrik Lundh89610a42000-07-08 20:07:24 +0000401 {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, 0},
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000402#endif
Guido van Rossum220ecc81997-11-18 21:03:39 +0000403 {NULL, NULL}
404};
405
Guido van Rossum3886bb61998-12-04 18:50:17 +0000406DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000407init_locale(void)
Guido van Rossum220ecc81997-11-18 21:03:39 +0000408{
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000409 PyObject *m, *d, *x;
Guido van Rossum220ecc81997-11-18 21:03:39 +0000410
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000411 m = Py_InitModule("_locale", PyLocale_Methods);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000412
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000413 d = PyModule_GetDict(m);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000414
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000415 x = PyInt_FromLong(LC_CTYPE);
416 PyDict_SetItemString(d, "LC_CTYPE", x);
417 Py_XDECREF(x);
418
419 x = PyInt_FromLong(LC_TIME);
420 PyDict_SetItemString(d, "LC_TIME", x);
421 Py_XDECREF(x);
422
423 x = PyInt_FromLong(LC_COLLATE);
424 PyDict_SetItemString(d, "LC_COLLATE", x);
425 Py_XDECREF(x);
426
427 x = PyInt_FromLong(LC_MONETARY);
428 PyDict_SetItemString(d, "LC_MONETARY", x);
429 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000430
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000431#ifdef LC_MESSAGES
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000432 x = PyInt_FromLong(LC_MESSAGES);
433 PyDict_SetItemString(d, "LC_MESSAGES", x);
434 Py_XDECREF(x);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000435#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000436
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000437 x = PyInt_FromLong(LC_NUMERIC);
438 PyDict_SetItemString(d, "LC_NUMERIC", x);
439 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000440
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000441 x = PyInt_FromLong(LC_ALL);
442 PyDict_SetItemString(d, "LC_ALL", x);
443 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000444
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000445 x = PyInt_FromLong(CHAR_MAX);
446 PyDict_SetItemString(d, "CHAR_MAX", x);
447 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000448
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000449 Error = PyErr_NewException("locale.Error", NULL, NULL);
450 PyDict_SetItemString(d, "Error", Error);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000451
Fredrik Lundh8f017a02000-07-08 19:57:37 +0000452 x = PyString_FromString(locale__doc__);
453 PyDict_SetItemString(d, "__doc__", x);
454 Py_XDECREF(x);
Guido van Rossum220ecc81997-11-18 21:03:39 +0000455}