blob: 11b776039b3ba91a39a9ff481f72eaf7d5a79617 [file] [log] [blame]
Guido van Rossum220ecc81997-11-18 21:03:39 +00001/***********************************************************
2Copyright (C) 1997 Martin von Löwis
3
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.
9******************************************************************/
10
11#include <stdio.h>
12#include <errno.h>
13#include <locale.h>
14#include <string.h>
15#include <limits.h>
16#include "Python.h"
17
18static char locale__doc__[]="Support for POSIX locales.";
19
20static PyObject *Error;
21
22/* support functions for formatting floating point numbers */
23
24static char setlocale__doc__[]=
25"(integer,string=None) -> string. Activates/queries locale processing."
26;
27
28/* to record the LC_NUMERIC settings */
29static PyObject* grouping=0;
30static PyObject* thousands_sep=0;
31static PyObject* decimal_point=0;
32/* if non-null, indicates that LC_NUMERIC is different from "C" */
33static char* saved_numeric=0;
34
35/* the grouping is terminated by either 0 or CHAR_MAX */
36static PyObject*
37copy_grouping(s)
38 char* s;
39{
40 int i;
41 PyObject *result,*val=0;
42 if(s[0]=='\0')
43 /* empty string: no grouping at all */
44 return PyList_New(0);
45 for(i=0;s[i]!='\0' && s[i]!=CHAR_MAX;i++)
46 /* nothing */;
47 result = PyList_New(i+1);
48 if(!result)return NULL;
49 i=-1;
50 do{
51 i++;
52 val=PyInt_FromLong(s[i]);
53 if(!val)break;
54 if(PyList_SetItem(result,i,val)){
55 Py_DECREF(val);
56 val=0;
57 break;
58 }
59 }while(s[i]!='\0' && s[i]!=CHAR_MAX);
60 if(!val){
61 Py_DECREF(result);
62 return NULL;
63 }
64 return result;
65}
66
67static void
68fixup_ulcase()
69{
70 PyObject *mods,*strop,*string,*ulo;
71 unsigned char ul[256];
72 int n,c;
73
74 /* finding sys.modules */
75 mods=PyImport_GetModuleDict();
76 if(!mods)return;
77 /* finding the module */
78 string=PyDict_GetItemString(mods,"string");
79 if(string)
80 string=PyModule_GetDict(string);
81 strop=PyDict_GetItemString(mods,"strop");
82 if(strop)
83 strop=PyModule_GetDict(strop);
84 if(!string && !strop)return;
85 /* create uppercase */
86 n = 0;
87 for (c = 0; c < 256; c++) {
88 if (isupper(c))
89 ul[n++] = c;
90 }
91 ulo=PyString_FromStringAndSize(ul,n);
92 if(!ulo)return;
93 if(string)
94 PyDict_SetItemString(string,"uppercase",ulo);
95 if(strop)
96 PyDict_SetItemString(strop,"uppercase",ulo);
97 Py_DECREF(ulo);
98 /* create lowercase */
99 n = 0;
100 for (c = 0; c < 256; c++) {
101 if (islower(c))
102 ul[n++] = c;
103 }
104 ulo=PyString_FromStringAndSize(ul,n);
105 if(!ulo)return;
106 if(string)
107 PyDict_SetItemString(string,"lowercase",ulo);
108 if(strop)
109 PyDict_SetItemString(strop,"lowercase",ulo);
110 Py_DECREF(ulo);
111 /* create letters */
112 n = 0;
113 for (c = 0; c < 256; c++) {
114 if (isalpha(c))
115 ul[n++] = c;
116 }
117 ulo=PyString_FromStringAndSize(ul,n);
118 if(!ulo)return;
119 if(string)
120 PyDict_SetItemString(string,"letters",ulo);
121 Py_DECREF(ulo);
122}
123
124
125static PyObject*
126PyLocale_setlocale(self,args)
127 PyObject *self;
128 PyObject *args;
129{
130 int category;
131 char *locale=0,*result;
132 PyObject *result_object;
133 struct lconv *lc;
134 if(!PyArg_ParseTuple(args,"i|z",&category,&locale))return 0;
135 if(locale){
136 /* set locale */
137 result=setlocale(category,locale);
138 if(!result){
139 /* operation failed, no setting was changed */
140 PyErr_SetString(Error,"locale setting not supported");
141 return NULL;
142 }
143 result_object=PyString_FromString(result);
144 if(!result)return NULL;
145 /* record changes to LC_NUMERIC */
146 if(category==LC_NUMERIC || category==LC_ALL){
147 if(strcmp(locale,"C")==0 || strcmp(locale,"POSIX")==0){
148 /* user just asked for default numeric locale */
149 if(saved_numeric)free(saved_numeric);
150 saved_numeric=0;
151 }else{
152 /* remember values */
153 lc=localeconv();
154 Py_XDECREF(grouping);
155 grouping=copy_grouping(lc->grouping);
156 Py_XDECREF(thousands_sep);
157 thousands_sep=PyString_FromString(lc->thousands_sep);
158 Py_XDECREF(decimal_point);
159 decimal_point=PyString_FromString(lc->decimal_point);
160 saved_numeric = strdup(locale);
161
162 /* restore to "C" */
163 setlocale(LC_NUMERIC,"C");
164 }
165 }
166 /* record changes to LC_CTYPE */
167 if(category==LC_CTYPE || category==LC_ALL)
168 fixup_ulcase();
169 /* things that got wrong up to here are ignored */
170 PyErr_Clear();
171 }else{
172 /* get locale */
173 /* restore LC_NUMERIC first, if appropriate */
174 if(saved_numeric)
175 setlocale(LC_NUMERIC,saved_numeric);
176 result=setlocale(category,NULL);
177 if(!result){
178 PyErr_SetString(Error,"locale query failed");
179 return NULL;
180 }
181 result_object=PyString_FromString(result);
182 /* restore back to "C" */
183 if(saved_numeric)
184 setlocale(LC_NUMERIC,"C");
185 }
186 return result_object;
187}
188
189static char localeconv__doc__[]=
190"() -> dict. Returns numeric and monetary locale-specific parameters."
191;
192
193static PyObject*
194PyLocale_localeconv(self,args)
195 PyObject *self;
196 PyObject *args;
197{
198 PyObject* result;
199 struct lconv *l;
200 PyObject *x;
201 if(!PyArg_NoArgs(args))return 0;
202 result = PyDict_New();
203 if(!result)return 0;
204 /* if LC_NUMERIC is different in the C library, use saved value */
205 l = localeconv();
206 /* hopefully, the localeconv result survives the C library calls
207 involved herein */
208#define RESULT_STRING(s) \
209 x=PyString_FromString(l->s);if(!x)goto failed;PyDict_SetItemString(result,#s,x);Py_XDECREF(x)
210#define RESULT_INT(i) \
211 x=PyInt_FromLong(l->i);if(!x)goto failed;PyDict_SetItemString(result,#i,x);Py_XDECREF(x)
212
213 /* Numeric information */
214 if(saved_numeric){
215 /* cannot use localeconv results */
216 PyDict_SetItemString(result,"decimal_point",decimal_point);
217 PyDict_SetItemString(result,"grouping",grouping);
218 PyDict_SetItemString(result,"thousands_sep",thousands_sep);
219 }else{
220 RESULT_STRING(decimal_point);
221 RESULT_STRING(thousands_sep);
222 x=copy_grouping(l->grouping);
223 if(!x)goto failed;
224 PyDict_SetItemString(result,"grouping",x);
225 Py_XDECREF(x);
226 }
227
228 /* Monetary information */
229 RESULT_STRING(int_curr_symbol);
230 RESULT_STRING(currency_symbol);
231 RESULT_STRING(mon_decimal_point);
232 RESULT_STRING(mon_thousands_sep);
233 x=copy_grouping(l->mon_grouping);
234 if(!x)goto failed;
235 PyDict_SetItemString(result,"mon_grouping",x);
236 Py_XDECREF(x);
237 RESULT_STRING(positive_sign);
238 RESULT_STRING(negative_sign);
239 RESULT_INT(int_frac_digits);
240 RESULT_INT(frac_digits);
241 RESULT_INT(p_cs_precedes);
242 RESULT_INT(p_sep_by_space);
243 RESULT_INT(n_cs_precedes);
244 RESULT_INT(n_sep_by_space);
245 RESULT_INT(p_sign_posn);
246 RESULT_INT(n_sign_posn);
247
248 return result;
249 failed:
250 Py_XDECREF(result);
251 Py_XDECREF(x);
252 return NULL;
253}
254
255static char strcoll__doc__[]=
256"string,string -> int. Compares two strings according to the locale."
257;
258
259static PyObject*
260PyLocale_strcoll(self,args)
261 PyObject *self;
262 PyObject *args;
263{
264 char *s1,*s2;
265 if(!PyArg_ParseTuple(args,"ss",&s1,&s2))
266 return NULL;
267 return PyInt_FromLong(strcoll(s1,s2));
268}
269
270static char strxfrm__doc__[]=
271"string -> string. Returns a string that behaves for cmp locale-aware."
272;
273
274static PyObject*
275PyLocale_strxfrm(self,args)
276 PyObject* self;
277 PyObject* args;
278{
279 char *s,*buf;
280 int n1,n2;
281 PyObject *result;
282 if(!PyArg_ParseTuple(args,"s",&s))
283 return NULL;
284 /* assume no change in size, first */
285 n1=strlen(s)+1;
286 buf=Py_Malloc(n1);
287 if(!buf)return NULL;
288 n2=strxfrm(buf,s,n1);
289 if(n2>n1){
290 /* more space needed */
291 buf=Py_Realloc(buf,n2);
292 if(!buf)return NULL;
293 strxfrm(buf,s,n2);
294 }
295 result=PyString_FromString(buf);
296 Py_Free(buf);
297 return result;
298}
299
300static struct PyMethodDef PyLocale_Methods[] = {
301 {"setlocale",(PyCFunction)PyLocale_setlocale,1,setlocale__doc__},
302 {"localeconv",(PyCFunction)PyLocale_localeconv,0,localeconv__doc__},
303 {"strcoll",(PyCFunction)PyLocale_strcoll,1,strcoll__doc__},
304 {"strxfrm",(PyCFunction)PyLocale_strxfrm,1,strxfrm__doc__},
305 {NULL, NULL}
306};
307
308void
309init_locale()
310{
311 PyObject *m,*d,*x;
312 m=Py_InitModule("_locale",PyLocale_Methods);
313 d = PyModule_GetDict(m);
314 x=PyInt_FromLong(LC_CTYPE);
315 PyDict_SetItemString(d,"LC_CTYPE",x);
316 Py_XDECREF(x);
317
318 x=PyInt_FromLong(LC_TIME);
319 PyDict_SetItemString(d,"LC_TIME",x);
320 Py_XDECREF(x);
321
322 x=PyInt_FromLong(LC_COLLATE);
323 PyDict_SetItemString(d,"LC_COLLATE",x);
324 Py_XDECREF(x);
325
326 x=PyInt_FromLong(LC_MONETARY);
327 PyDict_SetItemString(d,"LC_MONETARY",x);
328 Py_XDECREF(x);
329
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000330#ifdef LC_MESSAGES
Guido van Rossum220ecc81997-11-18 21:03:39 +0000331 x=PyInt_FromLong(LC_MESSAGES);
332 PyDict_SetItemString(d,"LC_MESSAGES",x);
333 Py_XDECREF(x);
Guido van Rossum8d9c2e31997-12-09 19:35:11 +0000334#endif /* LC_MESSAGES */
Guido van Rossum220ecc81997-11-18 21:03:39 +0000335
336 x=PyInt_FromLong(LC_NUMERIC);
337 PyDict_SetItemString(d,"LC_NUMERIC",x);
338 Py_XDECREF(x);
339
340 x=PyInt_FromLong(LC_ALL);
341 PyDict_SetItemString(d,"LC_ALL",x);
342 Py_XDECREF(x);
343
344 x=PyInt_FromLong(CHAR_MAX);
345 PyDict_SetItemString(d,"CHAR_MAX",x);
346 Py_XDECREF(x);
347
348 Error = PyErr_NewException("locale.Error", NULL, NULL);
349 PyDict_SetItemString(d, "Error", Error);
350
351 x=PyString_FromString(locale__doc__);
352 PyDict_SetItemString(d,"__doc__",x);
353 Py_XDECREF(x);
354
355 if(PyErr_Occurred())
356 Py_FatalError("Can't initialize module locale");
357}