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