From 79ab294f6f75042e12cbf96ed5dded0ae622a650 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Fri, 1 Aug 2008 08:27:18 +0000 Subject: big patch from Roumen Petrov finishing xsl:sort lang support with many * libxslt/xsltconfig.h.in libxslt/xslt.c libxslt/extensions.c libxslt/xsltlocale.c libxslt/preproc.c libxslt/xsltutils.c libxslt/xsltlocale.h libxslt/win32config.h configure.in config.h.in win32/configure.js: big patch from Roumen Petrov finishing xsl:sort lang support with many portability issues fixed and feedback from Nick Wellnhofer and Rob Richards Daniel svn path=/trunk/; revision=1488 --- ChangeLog | 12 +- config.h.in | 3 + configure.in | 44 ++++-- libxslt/extensions.c | 2 + libxslt/preproc.c | 6 +- libxslt/win32config.h | 2 + libxslt/xslt.c | 6 + libxslt/xsltconfig.h.in | 6 +- libxslt/xsltlocale.c | 347 ++++++++++++++++++++++++++---------------------- libxslt/xsltlocale.h | 12 +- libxslt/xsltutils.c | 8 +- win32/configure.js | 6 +- 12 files changed, 263 insertions(+), 191 deletions(-) diff --git a/ChangeLog b/ChangeLog index d3236ea0..cbdaa498 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Fri Aug 1 10:16:48 CEST 2008 Daniel Veillard + + * libxslt/xsltconfig.h.in libxslt/xslt.c libxslt/extensions.c + libxslt/xsltlocale.c libxslt/preproc.c libxslt/xsltutils.c + libxslt/xsltlocale.h libxslt/win32config.h configure.in + config.h.in win32/configure.js: big patch from Roumen Petrov + finishing xsl:sort lang support with many portability issues + fixed and feedback from Nick Wellnhofer and Rob Richards + Fri Aug 1 07:54:02 CEST 2008 Daniel Veillard * libexslt/crypto.c: fix for CVE-2008-2935 libexslt RC4 @@ -39,7 +48,8 @@ Tue Jun 24 23:55:48 PST 2008 William Brack Fri Jun 13 10:58:52 CEST 2008 Daniel Veillard * libxslt/libxslt.h libexslt/libexslt.h libexslt/exslt.h: patch - from Roumen Petrov fixing include path when compiling with MinGW + from Roumen Petrov fixing include path when compiling outside + source tree Thu Jun 12 11:23:23 CEST 2008 Daniel Veillard diff --git a/config.h.in b/config.h.in index 83448e39..7b8783da 100644 --- a/config.h.in +++ b/config.h.in @@ -42,6 +42,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + /* Define to 1 if you have the `localtime' function. */ #undef HAVE_LOCALTIME diff --git a/configure.in b/configure.in index 28fb1ffc..6439edc2 100644 --- a/configure.in +++ b/configure.in @@ -107,31 +107,48 @@ AC_STDC_HEADERS AM_PROG_LIBTOOL +AC_CHECK_HEADERS(sys/types.h sys/time.h stdlib.h unistd.h string.h) + dnl dnl Detect supported locale dnl XSLT_LOCALE_XLOCALE=0 -XSLT_LOCALE_MSVCRT=0 +XSLT_LOCALE_WINAPI=0 -AC_CHECK_HEADERS([xlocale.h]) +AC_CHECK_HEADERS([locale.h xlocale.h]) if test $ac_cv_header_xlocale_h = yes; then -AC_MSG_CHECKING([for working xlocale]) -AC_RUN_IFELSE(AC_LANG_PROGRAM([[ +dnl +dnl Check for generic locale_t declaration +dnl +AC_MSG_CHECKING([if xlocale program link]) +AC_LINK_IFELSE(AC_LANG_PROGRAM([[ +#ifdef HAVE_LOCALE_H #include +#endif +#ifdef HAVE_XLOCALE_H #include +#endif +#ifdef HAVE_STRING_H #include +#endif +#ifdef HAVE_STDLIB_H #include +#endif +#ifdef __GLIBC__ +typedef __locale_t xsltLocale; +#else +typedef locale_t xsltLocale; +#endif #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2 -#define locale_t __locale_t #define newlocale __newlocale #define freelocale __freelocale #define strxfrm_l __strxfrm_l #define LC_COLLATE_MASK (1 << LC_COLLATE) #endif ]],[[ - locale_t locale; + xsltLocale locale; const char *src[[2]] = { "\xc3\x84rger", "Zeppelin" }; char *dst[[2]]; size_t len, r; @@ -152,24 +169,23 @@ AC_RUN_IFELSE(AC_LANG_PROGRAM([[ return(0); ]]), [AC_MSG_RESULT(yes); XSLT_LOCALE_XLOCALE=1], - [AC_MSG_RESULT(no)], - [AC_MSG_WARN([cross compiling: assuming no])] + [AC_MSG_RESULT(no)] ) else - dnl defined in msvcrt - AC_CHECK_FUNC(_create_locale, - [XSLT_LOCALE_MSVCRT=1] - ) + case "$host" in + *-*-mingw*) + AC_MSG_NOTICE([using winapi locale]) + XSLT_LOCALE_WINAPI=1;; + esac fi AC_SUBST(XSLT_LOCALE_XLOCALE) -AC_SUBST(XSLT_LOCALE_MSVCRT) +AC_SUBST(XSLT_LOCALE_WINAPI) dnl dnl Math detection dnl -AC_CHECK_HEADERS(sys/types.h sys/time.h stdlib.h unistd.h string.h) AC_CHECK_HEADERS(ieeefp.h nan.h math.h fp_class.h float.h ansidecl.h) AC_CHECK_HEADERS(sys/timeb.h time.h sys/stat.h sys/select.h stdarg.h) AC_CHECK_FUNCS(stat _stat) diff --git a/libxslt/extensions.c b/libxslt/extensions.c index 2c1b239d..87eefb45 100644 --- a/libxslt/extensions.c +++ b/libxslt/extensions.c @@ -34,8 +34,10 @@ #ifdef _WIN32 #include /* for _MAX_PATH */ +#ifndef PATH_MAX #define PATH_MAX _MAX_PATH #endif +#endif #ifdef WITH_XSLT_DEBUG #define WITH_XSLT_DEBUG_EXTENSIONS diff --git a/libxslt/preproc.c b/libxslt/preproc.c index 42908384..9a5e9d69 100644 --- a/libxslt/preproc.c +++ b/libxslt/preproc.c @@ -391,7 +391,7 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) { break; case XSLT_FUNC_SORT: { xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp; - if (item->locale != NULL) + if (item->locale != (xsltLocale)0) xsltFreeLocale(item->locale); if (item->comp != NULL) xmlXPathFreeCompExpr(item->comp); @@ -489,7 +489,7 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) { break; } #else - if (comp->locale != NULL) + if (comp->locale != (xsltLocale)0) xsltFreeLocale(comp->locale); if (comp->comp != NULL) xmlXPathFreeCompExpr(comp->comp); @@ -736,7 +736,7 @@ xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) { comp->locale = xsltNewLocale(comp->lang); } else { - comp->locale = NULL; + comp->locale = (xsltLocale)0; } comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE); diff --git a/libxslt/win32config.h b/libxslt/win32config.h index 169b03d1..00ba2a0e 100644 --- a/libxslt/win32config.h +++ b/libxslt/win32config.h @@ -95,5 +95,7 @@ static int isnan (double d) { #define ATTRIBUTE_UNUSED #endif +#define _WINSOCKAPI_ + #endif /* __LIBXSLT_WIN32_CONFIG__ */ diff --git a/libxslt/xslt.c b/libxslt/xslt.c index 071658b4..f35ad237 100644 --- a/libxslt/xslt.c +++ b/libxslt/xslt.c @@ -83,6 +83,9 @@ const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr"; #endif +#ifdef XSLT_LOCALE_WINAPI +extern xmlRMutexPtr xsltLocaleMutex; +#endif /* * Harmless but avoiding a problem when compiling against a * libxml <= 2.3.11 without LIBXML_DEBUG_ENABLED @@ -222,6 +225,9 @@ void xsltInit (void) { if (initialized == 0) { initialized = 1; +#ifdef XSLT_LOCALE_WINAPI + xsltLocaleMutex = xmlNewRMutex(); +#endif xsltRegisterAllExtras(); } } diff --git a/libxslt/xsltconfig.h.in b/libxslt/xsltconfig.h.in index e9a3c56c..b4cac6d3 100644 --- a/libxslt/xsltconfig.h.in +++ b/libxslt/xsltconfig.h.in @@ -130,9 +130,9 @@ extern "C" { #ifndef XSLT_LOCALE_XLOCALE #define XSLT_LOCALE_XLOCALE #endif -#elif @XSLT_LOCALE_MSVCRT@ -#ifndef XSLT_LOCALE_MSVCRT -#define XSLT_LOCALE_MSVCRT +#elif @XSLT_LOCALE_WINAPI@ +#ifndef XSLT_LOCALE_WINAPI +#define XSLT_LOCALE_WINAPI #endif #endif diff --git a/libxslt/xsltlocale.c b/libxslt/xsltlocale.c index 0b76ec09..9c57805f 100644 --- a/libxslt/xsltlocale.c +++ b/libxslt/xsltlocale.c @@ -7,6 +7,7 @@ * ISO 639-1, ISO 3166-1 * * Author: Nick Wellnhofer + * winapi port: Roumen Petrov */ #define IN_LIBXSLT @@ -29,6 +30,42 @@ #define TOUPPER(c) (c & ~0x20) #define TOLOWER(c) (c | 0x20) +/*without terminating null character*/ +#define XSLTMAX_ISO639LANGLEN 8 +#define XSLTMAX_ISO3166CNTRYLEN 8 + /* - */ +#define XSLTMAX_LANGTAGLEN (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166CNTRYLEN) + +static const xmlChar* xsltDefaultRegion(const xmlChar *localeName); + +#ifdef XSLT_LOCALE_WINAPI +xmlRMutexPtr xsltLocaleMutex = NULL; + +struct xsltRFC1766Info_s { + /*note typedef unsigned char xmlChar !*/ + xmlChar tag[XSLTMAX_LANGTAGLEN+1]; + /*note typedef LCID xsltLocale !*/ + xsltLocale lcid; +}; +typedef struct xsltRFC1766Info_s xsltRFC1766Info; + +static int xsltLocaleListSize = 0; +static xsltRFC1766Info *xsltLocaleList = NULL; + + +static xsltLocale +xslt_locale_WINAPI(const xmlChar *languageTag) { + int k; + xsltRFC1766Info *p = xsltLocaleList; + + for (k=0; ktag, languageTag) == 0) return p->lcid; + return((xsltLocale)0); +} + +static void xsltEnumSupportedLocales(void); +#endif + /** * xsltNewLocale: * @languageTag: RFC 3066 language tag @@ -43,7 +80,7 @@ xsltLocale xsltNewLocale(const xmlChar *languageTag) { #ifdef XSLT_LOCALE_XLOCALE xsltLocale locale; - char localeName[23]; /* 8*lang + "-" + 8*region + ".utf8\0" */ + char localeName[XSLTMAX_LANGTAGLEN+6]; /* 8*lang + "-" + 8*region + ".utf8\0" */ const xmlChar *p = languageTag; const char *region = NULL; char *q = localeName; @@ -54,7 +91,7 @@ xsltNewLocale(const xmlChar *languageTag) { if (languageTag == NULL) return(NULL); - for (i=0; i<8 && ISALPHA(*p); ++i) + for (i=0; i= xstrlen) { xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n"); xmlFree(xstr); @@ -431,6 +393,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string) /** * xsltLocaleStrcmp: + * @locale: a locale identifier * @str1: a string transformed with xsltStrxfrm * @str2: a string transformed with xsltStrxfrm * @@ -441,13 +404,79 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string) * 0 if str1 and str2 are equal wrt sorting */ int -xsltLocaleStrcmp(const xsltLocaleChar *str1, const xsltLocaleChar *str2) { -#ifdef XSLT_LOCALE_MSVCRT +xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2) { + (void)locale; +#ifdef XSLT_LOCALE_WINAPI +{ + int ret; if (str1 == str2) return(0); if (str1 == NULL) return(-1); if (str2 == NULL) return(1); - return(wcscmp(str1, str2)); + ret = CompareStringW(locale, 0, str1, -1, str2, -1); + if (ret == 0) { + xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n"); + return(0); + } + return(ret - 2); +} #else return(xmlStrcmp(str1, str2)); #endif } + +#ifdef XSLT_LOCALE_WINAPI +BOOL CALLBACK +xsltCountSupportedLocales(LPSTR lcid) { + (void) lcid; + ++xsltLocaleListSize; + return(TRUE); +} + +BOOL CALLBACK +xsltIterateSupportedLocales(LPSTR lcid) { + static int count = 0; + xmlChar iso639lang [XSLTMAX_ISO639LANGLEN +1]; + xmlChar iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1]; + int k, l; + xsltRFC1766Info *p = xsltLocaleList + count; + + k = sscanf(lcid, "%lx", (long*)&p->lcid); + if (k < 1) goto end; + /*don't count terminating null character*/ + k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME , iso639lang , sizeof(iso639lang )); + if (--k < 1) goto end; + l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, iso3136ctry, sizeof(iso3136ctry)); + if (--l < 1) goto end; + + { /*fill results*/ + xmlChar *q = p->tag; + memcpy(q, iso639lang, k); + q += k; + *q++ = '-'; + memcpy(q, iso3136ctry, l); + q += l; + *q = '\0'; + } + ++count; +end: + return((count < xsltLocaleListSize) ? TRUE : FALSE); +} + + +static void +xsltEnumSupportedLocales(void) { + xmlRMutexLock(xsltLocaleMutex); + if (xsltLocaleListSize <= 0) { + size_t len; + + EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED); + + len = xsltLocaleListSize * sizeof(xsltRFC1766Info); + xsltLocaleList = xmlMalloc(len); + memset(xsltLocaleList, 0, len); + EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED); + } + xmlRMutexUnlock(xsltLocaleMutex); +} + +#endif /*def XSLT_LOCALE_WINAPI*/ diff --git a/libxslt/xsltlocale.h b/libxslt/xsltlocale.h index c700df4e..2f20d630 100644 --- a/libxslt/xsltlocale.h +++ b/libxslt/xsltlocale.h @@ -18,18 +18,20 @@ #include #include -#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2 +#ifdef __GLIBC__ +/*locale_t is defined only if _GNU_SOURCE is defined*/ typedef __locale_t xsltLocale; #else typedef locale_t xsltLocale; #endif typedef xmlChar xsltLocaleChar; -#elif defined(XSLT_LOCALE_MSVCRT) +#elif defined(XSLT_LOCALE_WINAPI) -#include +#include +#include -typedef _locale_t xsltLocale; +typedef LCID xsltLocale; typedef wchar_t xsltLocaleChar; #else @@ -46,6 +48,6 @@ typedef xmlChar xsltLocaleChar; xsltLocale xsltNewLocale(const xmlChar *langName); void xsltFreeLocale(xsltLocale locale); xsltLocaleChar *xsltStrxfrm(xsltLocale locale, const xmlChar *string); -int xsltLocaleStrcmp(const xsltLocaleChar *str1, const xsltLocaleChar *str2); +int xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2); #endif /* __XML_XSLTLOCALE_H__ */ diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c index 4650215b..9565e152 100644 --- a/libxslt/xsltutils.c +++ b/libxslt/xsltutils.c @@ -1039,7 +1039,7 @@ xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) { } } else { if (res->type == XPATH_STRING) { - if (comp->locale != NULL) { + if (comp->locale != (xsltLocale)0) { xmlChar *str = res->stringval; res->stringval = (xmlChar *) xsltStrxfrm(comp->locale, str); xmlFree(str); @@ -1197,8 +1197,9 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, results[j + incr]->floatval) tst = 1; else tst = -1; - } else if(comp->locale != NULL) { + } else if(comp->locale != (xsltLocale)0) { tst = xsltLocaleStrcmp( + comp->locale, (xsltLocaleChar *) results[j]->stringval, (xsltLocaleChar *) results[j + incr]->stringval); } else { @@ -1255,8 +1256,9 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, res[j + incr]->floatval) tst = 1; else tst = -1; - } else if(comp->locale != NULL) { + } else if(comp->locale != (xsltLocale)0) { tst = xsltLocaleStrcmp( + comp->locale, (xsltLocaleChar *) res[j]->stringval, (xsltLocaleChar *) res[j + incr]->stringval); } else { diff --git a/win32/configure.js b/win32/configure.js index 4feb4b27..7f2f8548 100644 --- a/win32/configure.js +++ b/win32/configure.js @@ -107,7 +107,7 @@ function usage() txt += " zlib: Use zlib library (" + (withZlib? "yes" : "no") + ")\n"; txt += " crypto: Enable Crypto support (" + (withCrypto? "yes" : "no") + ")\n"; txt += " modules: Enable Module support (" + (withModules? "yes" : "no") + ")\n"; - txt += " locale: Enable Locale support, requires msvcr80.dll (" + (withLocale? "yes" : "no") + ")\n"; + txt += " locale: Enable Locale support, requires unicode OS support (" + (withLocale? "yes" : "no") + ")\n"; txt += "\nWin32 build options, default value given in parentheses:\n\n"; txt += " compiler: Compiler to be used [msvc|mingw] (" + compiler + ")\n"; txt += " cruntime: C-runtime compiler option (only msvc) (" + cruntime + ")\n"; @@ -244,8 +244,8 @@ function configureXslt() of.WriteLine(s.replace(/\@WITH_MODULES\@/, withModules? "1" : "0")); } else if (s.search(/\@XSLT_LOCALE_XLOCALE\@/) != -1) { of.WriteLine(s.replace(/\@XSLT_LOCALE_XLOCALE\@/, "0")); - } else if (s.search(/\@XSLT_LOCALE_MSVCRT\@/) != -1) { - of.WriteLine(s.replace(/\@XSLT_LOCALE_MSVCRT\@/, withLocale? "1" : "0")); + } else if (s.search(/\@XSLT_LOCALE_WINAPI\@/) != -1) { + of.WriteLine(s.replace(/\@XSLT_LOCALE_WINAPI\@/, withLocale? "1" : "0")); } else if (s.search(/\@LIBXSLT_DEFAULT_PLUGINS_PATH\@/) != -1) { of.WriteLine(s.replace(/\@LIBXSLT_DEFAULT_PLUGINS_PATH\@/, "NULL")); } else -- cgit v1.2.1