[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
new module 'duplocale'
From: |
Bruno Haible |
Subject: |
new module 'duplocale' |
Date: |
Mon, 23 Nov 2009 01:54:10 +0100 |
User-agent: |
KMail/1.9.9 |
glibc unfortunately has a big bug in its duplocale function:
<http://sourceware.org/bugzilla/show_bug.cgi?id=10969>
This module provides a workaround for it. Tested on glibc and MacOS X systems,
which are AFAIK the only systems so far with a duplocale function.
2009-11-22 Bruno Haible <address@hidden>
New module 'duplocale'.
* m4/duplocale.m4: New file.
* lib/locale.in.h (duplocale): New declaration.
* lib/duplocale.c: New file.
* m4/locale_h.m4 (gl_REPLACE_LOCALE_H, gl_LOCALE_MODULE_INDICATOR,
gl_LOCALE_H_DEFAULTS): New macros.
(gl_LOCALE_H): Require gl_LOCALE_H_DEFAULTS. Invoke
gl_CHECK_NEXT_HEADERS unconditionally. Invoke gl_REPLACE_LOCALE_H.
* modules/locale (Makefile.am): Substitute also GNULIB_DUPLOCALE,
REPLACE_DUPLOCALE.
* modules/duplocale: New file.
* doc/posix-functions/duplocale.texi: Mention the glibc bug.
=============================== m4/duplocale.m4 ===============================
# duplocale.m4 serial 1
dnl Copyright (C) 2009 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_DUPLOCALE],
[
AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
AC_REQUIRE([AC_CANONICAL_HOST])
AC_CHECK_FUNCS_ONCE([duplocale])
if test $ac_cv_func_duplocale = yes; then
dnl Check against glibc bug where duplocale crashes.
dnl See <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>.
AC_REQUIRE([gl_LOCALE_H])
AC_CACHE_CHECK([whether duplocale(LC_GLOBAL_LOCALE) works],
[gl_cv_func_duplocale_works],
[AC_TRY_RUN([
#include <locale.h>
#if HAVE_XLOCALE_H
# include <xlocale.h>
#endif
int main ()
{
(void) duplocale (LC_GLOBAL_LOCALE);
return 0;
}], [gl_cv_func_duplocale_works=yes], [gl_cv_func_duplocale_works=no],
[dnl Guess it works except on glibc < 2.12.
AC_EGREP_CPP([Unlucky GNU user], [
#include <features.h>
#ifdef __GNU_LIBRARY__
#if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 12)
Unlucky GNU user
#endif
#endif
],
[gl_cv_func_duplocale_works="guessing no"],
[gl_cv_func_duplocale_works="guessing yes"])
])
])
case "$gl_cv_func_duplocale_works" in
*no) REPLACE_DUPLOCALE=1 ;;
esac
fi
if test $REPLACE_DUPLOCALE = 1; then
gl_REPLACE_LOCALE_H
AC_LIBOBJ([duplocale])
gl_PREREQ_DUPLOCALE
fi
])
# Prerequisites of lib/duplocale.c.
AC_DEFUN([gl_PREREQ_DUPLOCALE],
[
:
])
=============================== lib/duplocale.c ===============================
/* Duplicate a locale object.
Copyright (C) 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <address@hidden>, 2007. */
#include <config.h>
/* Specification. */
#include <locale.h>
#include <errno.h>
#include <langinfo.h>
#include <string.h>
/* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
glibc < 2.12.
See <http://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
#undef _NL_LOCALE_NAME
#define _NL_LOCALE_NAME(category) _NL_ITEM ((category), _NL_ITEM_INDEX (-1))
#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
#undef duplocale
locale_t
rpl_duplocale (locale_t locale)
{
/* Work around crash in the duplocale function in glibc < 2.12.
See <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>. */
if (locale == LC_GLOBAL_LOCALE)
{
/* Create a copy of the locale by fetching the name of each locale
category, starting with LC_CTYPE. */
static struct { int cat; int mask; } categories[] =
{
{ LC_NUMERIC, LC_NUMERIC_MASK },
{ LC_TIME, LC_TIME_MASK },
{ LC_COLLATE, LC_COLLATE_MASK },
{ LC_MONETARY, LC_MONETARY_MASK },
{ LC_MESSAGES, LC_MESSAGES_MASK }
#ifdef LC_PAPER
, { LC_PAPER, LC_PAPER_MASK }
#endif
#ifdef LC_NAME
, { LC_NAME, LC_NAME_MASK }
#endif
#ifdef LC_ADDRESS
, { LC_ADDRESS, LC_ADDRESS_MASK }
#endif
#ifdef LC_TELEPHONE
, { LC_TELEPHONE, LC_TELEPHONE_MASK }
#endif
#ifdef LC_MEASUREMENT
, { LC_MEASUREMENT, LC_MEASUREMENT_MASK }
#endif
#ifdef LC_IDENTIFICATION
, { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK }
#endif
};
const char *base_name = nl_langinfo (_NL_LOCALE_NAME (LC_CTYPE));
locale_t base_copy = newlocale (LC_ALL_MASK, base_name, NULL);
unsigned int i;
if (base_copy == NULL)
return NULL;
for (i = 0; i < SIZEOF (categories); i++)
{
int category = categories[i].cat;
int category_mask = categories[i].mask;
const char *name = nl_langinfo (_NL_LOCALE_NAME (category));
if (strcmp (name, base_name) != 0)
{
locale_t copy = newlocale (category_mask, name, base_copy);
if (copy == NULL)
{
int saved_errno = errno;
freelocale (base_copy);
errno = saved_errno;
return NULL;
}
/* No need to call freelocale (base_copy) if copy != base_copy;
the newlocale function already takes care of doing it. */
base_copy = copy;
}
}
return base_copy;
}
return duplocale (locale);
}
============================== modules/duplocale ==============================
Description:
duplocale() function: duplicate a locale object.
Files:
lib/duplocale.c
m4/duplocale.m4
Depends-on:
locale
configure.ac:
gl_FUNC_DUPLOCALE
gl_LOCALE_MODULE_INDICATOR([duplocale])
Makefile.am:
Include:
<locale.h>
License:
LGPL
Maintainer:
Bruno Haible
===============================================================================
*** lib/locale.in.h.orig 2009-11-23 01:42:27.000000000 +0100
--- lib/locale.in.h 2009-11-23 01:05:28.000000000 +0100
***************
*** 40,44 ****
--- 40,58 ----
# define LC_MESSAGES 1729
#endif
+ #if @GNULIB_DUPLOCALE@
+ # if @REPLACE_DUPLOCALE@
+ # undef duplocale
+ # define duplocale rpl_duplocale
+ extern locale_t duplocale (locale_t locale);
+ # endif
+ #elif defined GNULIB_POSIXCHECK
+ # undef duplocale
+ # define duplocale(l) \
+ (GL_LINK_WARNING ("duplocale is buggy on some glibc systems - " \
+ "use gnulib module duplocale for portability"), \
+ duplocale (l))
+ #endif
+
#endif /* _GL_LOCALE_H */
#endif /* _GL_LOCALE_H */
*** m4/locale_h.m4.orig 2009-11-23 01:42:27.000000000 +0100
--- m4/locale_h.m4 2009-11-23 01:05:28.000000000 +0100
***************
*** 1,4 ****
! # locale_h.m4 serial 4
dnl Copyright (C) 2007, 2009 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
--- 1,4 ----
! # locale_h.m4 serial 5
dnl Copyright (C) 2007, 2009 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
***************
*** 6,11 ****
--- 6,15 ----
AC_DEFUN([gl_LOCALE_H],
[
+ dnl Use AC_REQUIRE here, so that the default behavior below is expanded
+ dnl once only, before all statements that occur in other macros.
+ AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
+
dnl Persuade glibc <locale.h> to define locale_t.
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
***************
*** 44,56 ****
fi
AC_SUBST([HAVE_XLOCALE_H])
! if test -z "$STDDEF_H" \
! && test $gl_cv_header_locale_h_posix2001 = yes \
! && test $gl_cv_header_locale_h_needs_xlocale_h = no; then
! LOCALE_H=
! else
! gl_CHECK_NEXT_HEADERS([locale.h])
! LOCALE_H=locale.h
fi
! AC_SUBST([LOCALE_H])
])
--- 48,82 ----
fi
AC_SUBST([HAVE_XLOCALE_H])
! dnl Execute this unconditionally, because LOCALE_H may be set by other
! dnl modules, after this code is executed.
! gl_CHECK_NEXT_HEADERS([locale.h])
!
! if test -n "$STDDEF_H" \
! || test $gl_cv_header_locale_h_posix2001 = no \
! || test $gl_cv_header_locale_h_needs_xlocale_h = yes; then
! gl_REPLACE_LOCALE_H
fi
! ])
!
! dnl Unconditionally enables the replacement of <locale.h>.
! AC_DEFUN([gl_REPLACE_LOCALE_H],
! [
! AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
! LOCALE_H=locale.h
! ])
!
! AC_DEFUN([gl_LOCALE_MODULE_INDICATOR],
! [
! dnl Use AC_REQUIRE here, so that the default settings are expanded once
only.
! AC_REQUIRE([gl_LOCALE_H_DEFAULTS])
!
GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
! ])
!
! AC_DEFUN([gl_LOCALE_H_DEFAULTS],
! [
! GNULIB_DUPLOCALE=0; AC_SUBST([GNULIB_DUPLOCALE])
! dnl Assume proper GNU behavior unless another module says otherwise.
! REPLACE_DUPLOCALE=0; AC_SUBST([REPLACE_DUPLOCALE])
! LOCALE_H=''; AC_SUBST([LOCALE_H])
])
*** modules/locale.orig 2009-11-23 01:42:27.000000000 +0100
--- modules/locale 2009-11-23 01:05:28.000000000 +0100
***************
*** 24,30 ****
--- 24,32 ----
sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
-e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \
+ -e 's|@''GNULIB_DUPLOCALE''@|$(GNULIB_DUPLOCALE)|g' \
-e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \
+ -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \
< $(srcdir)/locale.in.h; \
} > address@hidden && \
mv address@hidden $@
*** doc/posix-functions/duplocale.texi.orig 2009-11-23 01:42:27.000000000
+0100
--- doc/posix-functions/duplocale.texi 2009-11-23 01:05:28.000000000 +0100
***************
*** 4,13 ****
POSIX specification:
@url{http://www.opengroup.org/onlinepubs/9699919799/functions/duplocale.html}
! Gnulib module: ---
Portability problems fixed by Gnulib:
@itemize
@end itemize
Portability problems not fixed by Gnulib:
--- 4,16 ----
POSIX specification:
@url{http://www.opengroup.org/onlinepubs/9699919799/functions/duplocale.html}
! Gnulib module: duplocale
Portability problems fixed by Gnulib:
@itemize
+ @item
+ The argument @code{LC_GLOBAL_LOCALE} is not supported on some platforms:
+ glibc 2.11.
@end itemize
Portability problems not fixed by Gnulib:
- new module 'duplocale',
Bruno Haible <=