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