Added 'description' class attribute to every command class (to help the
[python/dscho.git] / Modules / _localemodule.c
blob3b8472954bb2961797ab07603ce91fcadabb7cd8
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.
9 ******************************************************************/
11 #include <stdio.h>
12 #include <errno.h>
13 #include <locale.h>
14 #include <string.h>
15 #include <limits.h>
16 #include <ctype.h>
17 #include "Python.h"
18 #ifdef macintosh
19 char *strdup Py_PROTO((char *));
20 #endif
22 static char locale__doc__[]="Support for POSIX locales.";
24 static PyObject *Error;
26 /* support functions for formatting floating point numbers */
28 static char setlocale__doc__[]=
29 "(integer,string=None) -> string. Activates/queries locale processing."
32 /* to record the LC_NUMERIC settings */
33 static PyObject* grouping=0;
34 static PyObject* thousands_sep=0;
35 static PyObject* decimal_point=0;
36 /* if non-null, indicates that LC_NUMERIC is different from "C" */
37 static char* saved_numeric=0;
39 /* the grouping is terminated by either 0 or CHAR_MAX */
40 static PyObject*
41 copy_grouping(s)
42 char* s;
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;
63 }while(s[i]!='\0' && s[i]!=CHAR_MAX);
64 if(!val){
65 Py_DECREF(result);
66 return NULL;
68 return result;
71 static void
72 fixup_ulcase()
74 PyObject *mods,*strop,*string,*ulo;
75 unsigned char ul[256];
76 int n,c;
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;
95 ulo=PyString_FromStringAndSize((const char *)ul,n);
96 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;
108 ulo=PyString_FromStringAndSize((const char *)ul,n);
109 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;
121 ulo=PyString_FromStringAndSize((const char *)ul,n);
122 if(!ulo)return;
123 if(string)
124 PyDict_SetItemString(string,"letters",ulo);
125 Py_DECREF(ulo);
129 static PyObject*
130 PyLocale_setlocale(self,args)
131 PyObject *self;
132 PyObject *args;
134 int category;
135 char *locale=0,*result;
136 PyObject *result_object;
137 struct lconv *lc;
138 if(!PyArg_ParseTuple(args,"i|z",&category,&locale))return 0;
139 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;
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);
166 /* restore to "C" */
167 setlocale(LC_NUMERIC,"C");
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;
185 result_object=PyString_FromString(result);
186 /* restore back to "C" */
187 if(saved_numeric)
188 setlocale(LC_NUMERIC,"C");
190 return result_object;
193 static char localeconv__doc__[]=
194 "() -> dict. Returns numeric and monetary locale-specific parameters."
197 static PyObject*
198 PyLocale_localeconv(self,args)
199 PyObject *self;
200 PyObject *args;
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)
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);
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);
252 return result;
253 failed:
254 Py_XDECREF(result);
255 Py_XDECREF(x);
256 return NULL;
259 static char strcoll__doc__[]=
260 "string,string -> int. Compares two strings according to the locale."
263 static PyObject*
264 PyLocale_strcoll(self,args)
265 PyObject *self;
266 PyObject *args;
268 char *s1,*s2;
269 if(!PyArg_ParseTuple(args,"ss",&s1,&s2))
270 return NULL;
271 return PyInt_FromLong(strcoll(s1,s2));
274 static char strxfrm__doc__[]=
275 "string -> string. Returns a string that behaves for cmp locale-aware."
278 static PyObject*
279 PyLocale_strxfrm(self,args)
280 PyObject* self;
281 PyObject* args;
283 char *s,*buf;
284 int n1,n2;
285 PyObject *result;
286 if(!PyArg_ParseTuple(args,"s",&s))
287 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);
299 result=PyString_FromString(buf);
300 Py_Free(buf);
301 return result;
304 static 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}
312 DL_EXPORT(void)
313 init_locale()
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);
322 x=PyInt_FromLong(LC_TIME);
323 PyDict_SetItemString(d,"LC_TIME",x);
324 Py_XDECREF(x);
326 x=PyInt_FromLong(LC_COLLATE);
327 PyDict_SetItemString(d,"LC_COLLATE",x);
328 Py_XDECREF(x);
330 x=PyInt_FromLong(LC_MONETARY);
331 PyDict_SetItemString(d,"LC_MONETARY",x);
332 Py_XDECREF(x);
334 #ifdef LC_MESSAGES
335 x=PyInt_FromLong(LC_MESSAGES);
336 PyDict_SetItemString(d,"LC_MESSAGES",x);
337 Py_XDECREF(x);
338 #endif /* LC_MESSAGES */
340 x=PyInt_FromLong(LC_NUMERIC);
341 PyDict_SetItemString(d,"LC_NUMERIC",x);
342 Py_XDECREF(x);
344 x=PyInt_FromLong(LC_ALL);
345 PyDict_SetItemString(d,"LC_ALL",x);
346 Py_XDECREF(x);
348 x=PyInt_FromLong(CHAR_MAX);
349 PyDict_SetItemString(d,"CHAR_MAX",x);
350 Py_XDECREF(x);
352 Error = PyErr_NewException("locale.Error", NULL, NULL);
353 PyDict_SetItemString(d, "Error", Error);
355 x=PyString_FromString(locale__doc__);
356 PyDict_SetItemString(d,"__doc__",x);
357 Py_XDECREF(x);
359 if(PyErr_Occurred())
360 Py_FatalError("Can't initialize module locale");