- added _getdefaultlocale implementation for WIN32
- ansified, reindentified, spacified, nullified
diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
index 3e630bd..5a0883a 100644
--- a/Modules/_localemodule.c
+++ b/Modules/_localemodule.c
@@ -6,6 +6,7 @@
provided that the above copyright notice appear in all copies.
This software comes with no warranty. Use at your own risk.
+
******************************************************************/
#include <stdio.h>
@@ -14,348 +15,429 @@
#include <string.h>
#include <limits.h>
#include <ctype.h>
+
#include "Python.h"
-#ifdef macintosh
-char *strdup Py_PROTO((char *));
+
+#if defined(MS_WIN32)
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
#endif
-static char locale__doc__[]="Support for POSIX locales.";
+#ifdef macintosh
+char *strdup(char *);
+#endif
+
+static char locale__doc__[] = "Support for POSIX locales.";
static PyObject *Error;
/* support functions for formatting floating point numbers */
-static char setlocale__doc__[]=
+static char setlocale__doc__[] =
"(integer,string=None) -> string. Activates/queries locale processing."
;
/* to record the LC_NUMERIC settings */
-static PyObject* grouping=0;
-static PyObject* thousands_sep=0;
-static PyObject* decimal_point=0;
+static PyObject* grouping = NULL;
+static PyObject* thousands_sep = NULL;
+static PyObject* decimal_point = NULL;
/* if non-null, indicates that LC_NUMERIC is different from "C" */
-static char* saved_numeric=0;
+static char* saved_numeric = NULL;
/* the grouping is terminated by either 0 or CHAR_MAX */
static PyObject*
-copy_grouping(s)
- char* s;
+copy_grouping(char* s)
{
- int i;
- PyObject *result,*val=0;
- if(s[0]=='\0')
- /* empty string: no grouping at all */
- return PyList_New(0);
- for(i=0;s[i]!='\0' && s[i]!=CHAR_MAX;i++)
- /* nothing */;
- result = PyList_New(i+1);
- if(!result)return NULL;
- i=-1;
- do{
- i++;
- val=PyInt_FromLong(s[i]);
- if(!val)break;
- if(PyList_SetItem(result,i,val)){
- Py_DECREF(val);
- val=0;
- break;
+ int i;
+ PyObject *result, *val = NULL;
+
+ if (s[0] == '\0')
+ /* empty string: no grouping at all */
+ return PyList_New(0);
+
+ for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
+ ; /* nothing */
+
+ result = PyList_New(i+1);
+ if (!result)
+ return NULL;
+
+ i = -1;
+ do {
+ i++;
+ val = PyInt_FromLong(s[i]);
+ if (!val)
+ break;
+ if (PyList_SetItem(result, i, val)) {
+ Py_DECREF(val);
+ val = 0;
+ break;
+ }
+ } while (s[i] != '\0' && s[i] != CHAR_MAX);
+
+ if (!val) {
+ Py_DECREF(result);
+ return NULL;
}
- }while(s[i]!='\0' && s[i]!=CHAR_MAX);
- if(!val){
- Py_DECREF(result);
- return NULL;
- }
- return result;
+
+ return result;
}
static void
-fixup_ulcase()
+fixup_ulcase(void)
{
- PyObject *mods,*strop,*string,*ulo;
- unsigned char ul[256];
- int n,c;
+ PyObject *mods, *strop, *string, *ulo;
+ unsigned char ul[256];
+ int n, c;
- /* finding sys.modules */
- mods=PyImport_GetModuleDict();
- if(!mods)return;
- /* finding the module */
- string=PyDict_GetItemString(mods,"string");
- if(string)
- string=PyModule_GetDict(string);
- strop=PyDict_GetItemString(mods,"strop");
- if(strop)
- strop=PyModule_GetDict(strop);
- if(!string && !strop)return;
- /* create uppercase */
- n = 0;
- for (c = 0; c < 256; c++) {
- if (isupper(c))
- ul[n++] = c;
- }
- ulo=PyString_FromStringAndSize((const char *)ul,n);
- if(!ulo)return;
- if(string)
- PyDict_SetItemString(string,"uppercase",ulo);
- if(strop)
- PyDict_SetItemString(strop,"uppercase",ulo);
- Py_DECREF(ulo);
- /* create lowercase */
- n = 0;
- for (c = 0; c < 256; c++) {
- if (islower(c))
- ul[n++] = c;
- }
- ulo=PyString_FromStringAndSize((const char *)ul,n);
- if(!ulo)return;
- if(string)
- PyDict_SetItemString(string,"lowercase",ulo);
- if(strop)
- PyDict_SetItemString(strop,"lowercase",ulo);
- Py_DECREF(ulo);
- /* create letters */
- n = 0;
- for (c = 0; c < 256; c++) {
- if (isalpha(c))
- ul[n++] = c;
- }
- ulo=PyString_FromStringAndSize((const char *)ul,n);
- if(!ulo)return;
- if(string)
- PyDict_SetItemString(string,"letters",ulo);
- Py_DECREF(ulo);
+ /* find the string and strop modules */
+ mods = PyImport_GetModuleDict();
+ if (!mods)
+ return;
+ string = PyDict_GetItemString(mods, "string");
+ if (string)
+ string = PyModule_GetDict(string);
+ strop=PyDict_GetItemString(mods, "strop");
+ if (strop)
+ strop = PyModule_GetDict(strop);
+ if (!string && !strop)
+ return;
+
+ /* create uppercase map string */
+ n = 0;
+ for (c = 0; c < 256; c++) {
+ if (isupper(c))
+ ul[n++] = c;
+ }
+ ulo = PyString_FromStringAndSize((const char *)ul, n);
+ if(!ulo)
+ return;
+ if (string)
+ PyDict_SetItemString(string, "uppercase", ulo);
+ if (strop)
+ PyDict_SetItemString(strop, "uppercase", ulo);
+ Py_DECREF(ulo);
+
+ /* create lowercase string */
+ n = 0;
+ for (c = 0; c < 256; c++) {
+ if (islower(c))
+ ul[n++] = c;
+ }
+ ulo = PyString_FromStringAndSize((const char *)ul, n);
+ if (!ulo)
+ return;
+ if (string)
+ PyDict_SetItemString(string, "lowercase", ulo);
+ if (strop)
+ PyDict_SetItemString(strop, "lowercase", ulo);
+ Py_DECREF(ulo);
+
+ /* create letters string */
+ n = 0;
+ for (c = 0; c < 256; c++) {
+ if (isalpha(c))
+ ul[n++] = c;
+ }
+ ulo = PyString_FromStringAndSize((const char *)ul, n);
+ if (!ulo)
+ return;
+ if (string)
+ PyDict_SetItemString(string, "letters", ulo);
+ Py_DECREF(ulo);
}
static PyObject*
-PyLocale_setlocale(self,args)
- PyObject *self;
- PyObject *args;
+PyLocale_setlocale(PyObject* self, PyObject* args)
{
- int category;
- char *locale=0,*result;
- PyObject *result_object;
- struct lconv *lc;
- if(!PyArg_ParseTuple(args,"i|z:setlocale",&category,&locale))return 0;
- if(locale){
- /* set locale */
- result=setlocale(category,locale);
- if(!result){
- /* operation failed, no setting was changed */
- PyErr_SetString(Error,"locale setting not supported");
- return NULL;
- }
- result_object=PyString_FromString(result);
- if(!result)return NULL;
- /* record changes to LC_NUMERIC */
- if(category==LC_NUMERIC || category==LC_ALL){
- if(strcmp(locale,"C")==0 || strcmp(locale,"POSIX")==0){
- /* user just asked for default numeric locale */
- if(saved_numeric)free(saved_numeric);
- saved_numeric=0;
- }else{
- /* remember values */
- lc=localeconv();
- Py_XDECREF(grouping);
- grouping=copy_grouping(lc->grouping);
- Py_XDECREF(thousands_sep);
- thousands_sep=PyString_FromString(lc->thousands_sep);
- Py_XDECREF(decimal_point);
- decimal_point=PyString_FromString(lc->decimal_point);
- saved_numeric = strdup(locale);
+ int category;
+ char *locale = NULL, *result;
+ PyObject *result_object;
+ struct lconv *lc;
- /* restore to "C" */
- setlocale(LC_NUMERIC,"C");
- }
+ if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
+ return 0;
+
+ if (locale) {
+ /* set locale */
+ result = setlocale(category, locale);
+ if (!result) {
+ /* operation failed, no setting was changed */
+ PyErr_SetString(Error, "locale setting not supported");
+ return NULL;
+ }
+ result_object = PyString_FromString(result);
+ if (!result)
+ return NULL;
+ /* record changes to LC_NUMERIC */
+ if (category == LC_NUMERIC || category == LC_ALL) {
+ if (strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0) {
+ /* user just asked for default numeric locale */
+ if (saved_numeric)
+ free(saved_numeric);
+ saved_numeric = NULL;
+ } else {
+ /* remember values */
+ lc = localeconv();
+ Py_XDECREF(grouping);
+ grouping = copy_grouping(lc->grouping);
+ Py_XDECREF(thousands_sep);
+ thousands_sep = PyString_FromString(lc->thousands_sep);
+ Py_XDECREF(decimal_point);
+ decimal_point = PyString_FromString(lc->decimal_point);
+ saved_numeric = strdup(locale);
+ /* restore to "C" */
+ setlocale(LC_NUMERIC, "C");
+ }
+ }
+ /* record changes to LC_CTYPE */
+ if (category == LC_CTYPE || category == LC_ALL)
+ fixup_ulcase();
+ /* things that got wrong up to here are ignored */
+ PyErr_Clear();
+ } else {
+ /* get locale */
+ /* restore LC_NUMERIC first, if appropriate */
+ if (saved_numeric)
+ setlocale(LC_NUMERIC, saved_numeric);
+ result = setlocale(category, NULL);
+ if (!result) {
+ PyErr_SetString(Error, "locale query failed");
+ return NULL;
+ }
+ result_object = PyString_FromString(result);
+ /* restore back to "C" */
+ if (saved_numeric)
+ setlocale(LC_NUMERIC, "C");
}
- /* record changes to LC_CTYPE */
- if(category==LC_CTYPE || category==LC_ALL)
- fixup_ulcase();
- /* things that got wrong up to here are ignored */
- PyErr_Clear();
- }else{
- /* get locale */
- /* restore LC_NUMERIC first, if appropriate */
- if(saved_numeric)
- setlocale(LC_NUMERIC,saved_numeric);
- result=setlocale(category,NULL);
- if(!result){
- PyErr_SetString(Error,"locale query failed");
- return NULL;
- }
- result_object=PyString_FromString(result);
- /* restore back to "C" */
- if(saved_numeric)
- setlocale(LC_NUMERIC,"C");
- }
- return result_object;
+ return result_object;
}
-static char localeconv__doc__[]=
+static char localeconv__doc__[] =
"() -> dict. Returns numeric and monetary locale-specific parameters."
;
static PyObject*
-PyLocale_localeconv(self,args)
- PyObject *self;
- PyObject *args;
+PyLocale_localeconv(PyObject* self, PyObject* args)
{
- PyObject* result;
- struct lconv *l;
- PyObject *x;
- if(!PyArg_NoArgs(args))return 0;
- result = PyDict_New();
- if(!result)return 0;
- /* if LC_NUMERIC is different in the C library, use saved value */
- l = localeconv();
- /* hopefully, the localeconv result survives the C library calls
- involved herein */
-#define RESULT_STRING(s) \
- x=PyString_FromString(l->s);if(!x)goto failed;PyDict_SetItemString(result,#s,x);Py_XDECREF(x)
-#define RESULT_INT(i) \
- x=PyInt_FromLong(l->i);if(!x)goto failed;PyDict_SetItemString(result,#i,x);Py_XDECREF(x)
+ PyObject* result;
+ struct lconv *l;
+ PyObject *x;
+
+ if (!PyArg_NoArgs(args))
+ return 0;
+
+ result = PyDict_New();
+ if(!result)
+ return 0;
+
+ /* if LC_NUMERIC is different in the C library, use saved value */
+ l = localeconv();
+
+ /* hopefully, the localeconv result survives the C library calls
+ involved herein */
+
+#define RESULT_STRING(s)\
+ x = PyString_FromString(l->s);\
+ if (!x) goto failed;\
+ PyDict_SetItemString(result, #s, x);\
+ Py_XDECREF(x)
+
+#define RESULT_INT(i)\
+ x = PyInt_FromLong(l->i);\
+ if (!x) goto failed;\
+ PyDict_SetItemString(result, #i, x);\
+ Py_XDECREF(x)
/* Numeric information */
- if(saved_numeric){
- /* cannot use localeconv results */
- PyDict_SetItemString(result,"decimal_point",decimal_point);
- PyDict_SetItemString(result,"grouping",grouping);
- PyDict_SetItemString(result,"thousands_sep",thousands_sep);
- }else{
- RESULT_STRING(decimal_point);
- RESULT_STRING(thousands_sep);
- x=copy_grouping(l->grouping);
- if(!x)goto failed;
- PyDict_SetItemString(result,"grouping",x);
+ if (saved_numeric){
+ /* cannot use localeconv results */
+ PyDict_SetItemString(result, "decimal_point", decimal_point);
+ PyDict_SetItemString(result, "grouping", grouping);
+ PyDict_SetItemString(result, "thousands_sep", thousands_sep);
+ } else {
+ RESULT_STRING(decimal_point);
+ RESULT_STRING(thousands_sep);
+ x = copy_grouping(l->grouping);
+ if (!x)
+ goto failed;
+ PyDict_SetItemString(result, "grouping", x);
+ Py_XDECREF(x);
+ }
+
+ /* Monetary information */
+ RESULT_STRING(int_curr_symbol);
+ RESULT_STRING(currency_symbol);
+ RESULT_STRING(mon_decimal_point);
+ RESULT_STRING(mon_thousands_sep);
+ x = copy_grouping(l->mon_grouping);
+ if (!x)
+ goto failed;
+ PyDict_SetItemString(result, "mon_grouping", x);
Py_XDECREF(x);
- }
+ RESULT_STRING(positive_sign);
+ RESULT_STRING(negative_sign);
+ RESULT_INT(int_frac_digits);
+ RESULT_INT(frac_digits);
+ RESULT_INT(p_cs_precedes);
+ RESULT_INT(p_sep_by_space);
+ RESULT_INT(n_cs_precedes);
+ RESULT_INT(n_sep_by_space);
+ RESULT_INT(p_sign_posn);
+ RESULT_INT(n_sign_posn);
+ return result;
- /* Monetary information */
- RESULT_STRING(int_curr_symbol);
- RESULT_STRING(currency_symbol);
- RESULT_STRING(mon_decimal_point);
- RESULT_STRING(mon_thousands_sep);
- x=copy_grouping(l->mon_grouping);
- if(!x)goto failed;
- PyDict_SetItemString(result,"mon_grouping",x);
- Py_XDECREF(x);
- RESULT_STRING(positive_sign);
- RESULT_STRING(negative_sign);
- RESULT_INT(int_frac_digits);
- RESULT_INT(frac_digits);
- RESULT_INT(p_cs_precedes);
- RESULT_INT(p_sep_by_space);
- RESULT_INT(n_cs_precedes);
- RESULT_INT(n_sep_by_space);
- RESULT_INT(p_sign_posn);
- RESULT_INT(n_sign_posn);
-
- return result;
- failed:
- Py_XDECREF(result);
- Py_XDECREF(x);
- return NULL;
+ failed:
+ Py_XDECREF(result);
+ Py_XDECREF(x);
+ return NULL;
}
-static char strcoll__doc__[]=
+static char strcoll__doc__[] =
"string,string -> int. Compares two strings according to the locale."
;
static PyObject*
-PyLocale_strcoll(self,args)
- PyObject *self;
- PyObject *args;
+PyLocale_strcoll(PyObject* self, PyObject* args)
{
char *s1,*s2;
- if(!PyArg_ParseTuple(args,"ss:strcoll",&s1,&s2))
- return NULL;
- return PyInt_FromLong(strcoll(s1,s2));
+
+ if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
+ return NULL;
+ return PyInt_FromLong(strcoll(s1, s2));
}
-static char strxfrm__doc__[]=
+static char strxfrm__doc__[] =
"string -> string. Returns a string that behaves for cmp locale-aware."
;
static PyObject*
-PyLocale_strxfrm(self,args)
- PyObject* self;
- PyObject* args;
+PyLocale_strxfrm(PyObject* self, PyObject* args)
{
- char *s,*buf;
- size_t n1,n2;
- PyObject *result;
- if(!PyArg_ParseTuple(args,"s:strxfrm",&s))
- return NULL;
- /* assume no change in size, first */
- n1=strlen(s)+1;
- buf=PyMem_Malloc(n1);
- if(!buf)return PyErr_NoMemory();
- n2=strxfrm(buf,s,n1);
- if(n2>n1){
- /* more space needed */
- buf=PyMem_Realloc(buf,n2);
- if(!buf)return PyErr_NoMemory();
- strxfrm(buf,s,n2);
- }
- result=PyString_FromString(buf);
- PyMem_Free(buf);
- return result;
+ char *s, *buf;
+ size_t n1, n2;
+ PyObject *result;
+
+ if(!PyArg_ParseTuple(args, "s:strxfrm", &s))
+ return NULL;
+
+ /* assume no change in size, first */
+ n1 = strlen(s) + 1;
+ buf = PyMem_Malloc(n1);
+ if (!buf)
+ return PyErr_NoMemory();
+ n2 = strxfrm(buf, s, n1);
+ if (n2 > n1) {
+ /* more space needed */
+ buf = PyMem_Realloc(buf, n2);
+ if (!buf)
+ return PyErr_NoMemory();
+ strxfrm(buf, s, n2);
+ }
+ result = PyString_FromString(buf);
+ PyMem_Free(buf);
+ return result;
}
+#if defined(MS_WIN32)
+static PyObject*
+PyLocale_getdefaultlocale(PyObject* self, PyObject* args)
+{
+ char encoding[100];
+ char locale[100];
+
+ sprintf(encoding, "cp%d", GetACP());
+
+ if (GetLocaleInfo(LOCALE_USER_DEFAULT,
+ LOCALE_SISO639LANGNAME,
+ locale, sizeof(locale))) {
+ int i = strlen(locale);
+ locale[i++] = '_';
+ if (GetLocaleInfo(LOCALE_USER_DEFAULT,
+ LOCALE_SISO3166CTRYNAME,
+ locale+i, sizeof(locale)-i))
+ return Py_BuildValue("ss", locale, encoding);
+ }
+
+ /* If we end up here, this windows version didn't know about
+ ISO639/ISO3166 names (it's probably Windows 95). Return the
+ Windows language identifier instead (a hexadecimal number) */
+
+ locale[0] = '0';
+ locale[1] = 'x';
+ if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
+ locale+2, sizeof(locale)-2)) {
+ return Py_BuildValue("ss", locale, encoding);
+ }
+
+ /* cannot determine the language code (very unlikely) */
+ Py_INCREF(Py_None);
+ return Py_BuildValue("Os", Py_None, encoding);
+}
+#endif
+
static struct PyMethodDef PyLocale_Methods[] = {
- {"setlocale",(PyCFunction)PyLocale_setlocale,1,setlocale__doc__},
- {"localeconv",(PyCFunction)PyLocale_localeconv,0,localeconv__doc__},
- {"strcoll",(PyCFunction)PyLocale_strcoll,1,strcoll__doc__},
- {"strxfrm",(PyCFunction)PyLocale_strxfrm,1,strxfrm__doc__},
+ {"setlocale", (PyCFunction) PyLocale_setlocale, 1, setlocale__doc__},
+ {"localeconv", (PyCFunction) PyLocale_localeconv, 0, localeconv__doc__},
+ {"strcoll", (PyCFunction) PyLocale_strcoll, 1, strcoll__doc__},
+ {"strxfrm", (PyCFunction) PyLocale_strxfrm, 1, strxfrm__doc__},
+#if defined(MS_WIN32)
+ {"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, 1},
+#endif
{NULL, NULL}
};
DL_EXPORT(void)
init_locale()
{
- PyObject *m,*d,*x;
- m=Py_InitModule("_locale",PyLocale_Methods);
- d = PyModule_GetDict(m);
- x=PyInt_FromLong(LC_CTYPE);
- PyDict_SetItemString(d,"LC_CTYPE",x);
- Py_XDECREF(x);
+ PyObject *m, *d, *x;
- x=PyInt_FromLong(LC_TIME);
- PyDict_SetItemString(d,"LC_TIME",x);
- Py_XDECREF(x);
+ m = Py_InitModule("_locale", PyLocale_Methods);
- x=PyInt_FromLong(LC_COLLATE);
- PyDict_SetItemString(d,"LC_COLLATE",x);
- Py_XDECREF(x);
+ d = PyModule_GetDict(m);
- x=PyInt_FromLong(LC_MONETARY);
- PyDict_SetItemString(d,"LC_MONETARY",x);
- Py_XDECREF(x);
+ x = PyInt_FromLong(LC_CTYPE);
+ PyDict_SetItemString(d, "LC_CTYPE", x);
+ Py_XDECREF(x);
+
+ x = PyInt_FromLong(LC_TIME);
+ PyDict_SetItemString(d, "LC_TIME", x);
+ Py_XDECREF(x);
+
+ x = PyInt_FromLong(LC_COLLATE);
+ PyDict_SetItemString(d, "LC_COLLATE", x);
+ Py_XDECREF(x);
+
+ x = PyInt_FromLong(LC_MONETARY);
+ PyDict_SetItemString(d, "LC_MONETARY", x);
+ Py_XDECREF(x);
#ifdef LC_MESSAGES
- x=PyInt_FromLong(LC_MESSAGES);
- PyDict_SetItemString(d,"LC_MESSAGES",x);
- Py_XDECREF(x);
+ x = PyInt_FromLong(LC_MESSAGES);
+ PyDict_SetItemString(d, "LC_MESSAGES", x);
+ Py_XDECREF(x);
#endif /* LC_MESSAGES */
- x=PyInt_FromLong(LC_NUMERIC);
- PyDict_SetItemString(d,"LC_NUMERIC",x);
- Py_XDECREF(x);
+ x = PyInt_FromLong(LC_NUMERIC);
+ PyDict_SetItemString(d, "LC_NUMERIC", x);
+ Py_XDECREF(x);
- x=PyInt_FromLong(LC_ALL);
- PyDict_SetItemString(d,"LC_ALL",x);
- Py_XDECREF(x);
+ x = PyInt_FromLong(LC_ALL);
+ PyDict_SetItemString(d, "LC_ALL", x);
+ Py_XDECREF(x);
- x=PyInt_FromLong(CHAR_MAX);
- PyDict_SetItemString(d,"CHAR_MAX",x);
- Py_XDECREF(x);
+ x = PyInt_FromLong(CHAR_MAX);
+ PyDict_SetItemString(d, "CHAR_MAX", x);
+ Py_XDECREF(x);
- Error = PyErr_NewException("locale.Error", NULL, NULL);
- PyDict_SetItemString(d, "Error", Error);
+ Error = PyErr_NewException("locale.Error", NULL, NULL);
+ PyDict_SetItemString(d, "Error", Error);
- x=PyString_FromString(locale__doc__);
- PyDict_SetItemString(d,"__doc__",x);
- Py_XDECREF(x);
+ x = PyString_FromString(locale__doc__);
+ PyDict_SetItemString(d, "__doc__", x);
+ Py_XDECREF(x);
- if(PyErr_Occurred())
- Py_FatalError("Can't initialize module locale");
+ if (PyErr_Occurred())
+ Py_FatalError("Can't initialize module locale");
}