>From 567591f3b194927a4d7eefa71007be2709796c4e Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 15 Dec 2019 21:39:55 +0100 Subject: [PATCH 1/2] setlocale-null: New module. * lib/locale.in.h (SETLOCALE_NULL_MAX, SETLOCALE_NULL_ALL_MAX, setlocale_null): New declarations. * lib/setlocale_null.c: New file. * lib/setlocale-lock.c: New file. * m4/threadlib.m4 (gl_PTHREADLIB_BODY): Define C macro HAVE_PTHREAD_API. * m4/setlocale_null.m4: New file. * m4/locale_h.m4 (gl_LOCALE_H_DEFAULTS): Initialize GNULIB_SETLOCALE_NULL. * modules/locale (Makefile.am): Substitute GNULIB_SETLOCALE_NULL. * modules/setlocale-null: New file. * doc/posix-functions/setlocale.texi: Mention the new module. --- ChangeLog | 15 +++ doc/posix-functions/setlocale.texi | 14 ++- lib/locale.in.h | 39 +++++++ lib/setlocale-lock.c | 124 ++++++++++++++++++++++ lib/setlocale_null.c | 204 +++++++++++++++++++++++++++++++++++++ m4/locale_h.m4 | 11 +- m4/setlocale_null.m4 | 84 +++++++++++++++ m4/threadlib.m4 | 8 +- modules/locale | 1 + modules/setlocale-null | 34 +++++++ 10 files changed, 526 insertions(+), 8 deletions(-) create mode 100644 lib/setlocale-lock.c create mode 100644 lib/setlocale_null.c create mode 100644 m4/setlocale_null.m4 create mode 100644 modules/setlocale-null diff --git a/ChangeLog b/ChangeLog index 39ba464..51f367c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2019-12-15 Bruno Haible + setlocale-null: New module. + * lib/locale.in.h (SETLOCALE_NULL_MAX, SETLOCALE_NULL_ALL_MAX, + setlocale_null): New declarations. + * lib/setlocale_null.c: New file. + * lib/setlocale-lock.c: New file. + * m4/threadlib.m4 (gl_PTHREADLIB_BODY): Define C macro HAVE_PTHREAD_API. + * m4/setlocale_null.m4: New file. + * m4/locale_h.m4 (gl_LOCALE_H_DEFAULTS): Initialize + GNULIB_SETLOCALE_NULL. + * modules/locale (Makefile.am): Substitute GNULIB_SETLOCALE_NULL. + * modules/setlocale-null: New file. + * doc/posix-functions/setlocale.texi: Mention the new module. + +2019-12-15 Bruno Haible + lock tests: Skip test when no multithreading is enabled. * tests/test-rwlock1.c: Skip the test when no multithreading is enabled. diff --git a/doc/posix-functions/setlocale.texi b/doc/posix-functions/setlocale.texi index 0678ac9..cd172c0 100644 --- a/doc/posix-functions/setlocale.texi +++ b/doc/posix-functions/setlocale.texi @@ -4,9 +4,9 @@ POSIX specification:@* @url{https://pubs.opengroup.org/onlinepubs/9699919799/functions/setlocale.html} -Gnulib module: setlocale +Gnulib module: setlocale, setlocale-null -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{setlocale}: @itemize @item On Windows platforms (excluding Cygwin), @code{setlocale(@var{category},NULL)} @@ -26,6 +26,16 @@ always fails. The replacement, however, supports only the locale names @code{"C"} and @code{"POSIX"}. @end itemize +Portability problems fixed by Gnulib module @code{setlocale-null}: +@itemize +@item +Invocations of @code{setlocale (..., NULL)} are not multithread-safe on some +platforms: +musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin. +To make these invocations multithread-safe, you need to change the code to +invoke @code{setlocale_null} instead. +@end itemize + Portability problems not fixed by Gnulib: @itemize @item diff --git a/lib/locale.in.h b/lib/locale.in.h index 9e897a3..5986683 100644 --- a/lib/locale.in.h +++ b/lib/locale.in.h @@ -206,6 +206,45 @@ _GL_WARN_ON_USE (setlocale, "setlocale works differently on native Windows - " # endif #endif +#if @GNULIB_SETLOCALE_NULL@ +/* Recommended size of a buffer for a locale name for a single category. + On glibc systems, you can have locale names that are relative file names; + assume a maximum length 256. + In native Windows, in 2018 the longest locale name was of length 58 + ("FYRO Macedonian_Former Yugoslav Republic of Macedonia.1251"). */ +# define SETLOCALE_NULL_MAX (256+1) +/* Recommended size of a buffer for a locale name with all categories. + On glibc systems, you can have locale names that are relative file names; + assume maximum length 256 for each. There are 12 categories; so, the + maximum total length is 148+12*256. + In native Windows, there are 5 categories, and the maximum total length is + 55+5*58. */ +# define SETLOCALE_NULL_ALL_MAX (148+12*256+1) +/* setlocale_null (CATEGORY, BUF, BUFSIZE) is like setlocale (CATEGORY, NULL), + except that + - it is guaranteed to be multithread-safe, + - it returns the resulting locale category name or locale name in the + user-supplied buffer BUF, which must be BUFSIZE bytes long. + The recommended minimum buffer size is + - SETLOCALE_NULL_MAX for CATEGORY != LC_ALL, and + - SETLOCALE_NULL_ALL_MAX for CATEGORY == LC_ALL. + The return value is an error code: 0 if the call is successful, ERANGE if + BUFSIZE is smaller than the length needed size (including the trailing NUL + byte). In the latter case, a truncated result is returned in BUF, but + still NUL-terminated if BUFSIZE > 0. + For this call to be multithread-safe, *all* calls to + setlocale (CATEGORY, NULL) in all other threads must have been converted + to use setlocale_null as well, and the other threads must not make other + setlocale invocations (since changing the global locale has side effects + on all threads). */ +_GL_FUNCDECL_SYS (setlocale_null, int, + (int category, char *buf, size_t bufsize) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_SYS (setlocale_null, int, + (int category, char *buf, size_t bufsize)); +_GL_CXXALIASWARN (setlocale_null); +#endif + #if /*@GNULIB_NEWLOCALE@ ||*/ (@GNULIB_LOCALENAME@ && @HAVE_NEWLOCALE@) # if @REPLACE_NEWLOCALE@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) diff --git a/lib/setlocale-lock.c b/lib/setlocale-lock.c new file mode 100644 index 0000000..ed6ab9f --- /dev/null +++ b/lib/setlocale-lock.c @@ -0,0 +1,124 @@ +/* Return the internal lock used by setlocale_null. + Copyright (C) 2019 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 . */ + +/* Written by Bruno Haible , 2019. */ + +#include + +/* This file defines the internal lock used by setlocale_null. + It is a separate compilation unit, so that only one copy of it is + present when linking statically. */ + +/* Prohibit renaming this symbol. */ +#undef gl_get_setlocale_null_lock + +#if defined _WIN32 && !defined __CYGWIN__ + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include + +# include "windows-initguard.h" + +/* The return type is a 'CRITICAL_SECTION *', not a 'glwthread_mutex_t *', + because the latter is not guaranteed to be a stable ABI in the future. */ + +/* Make sure the function gets exported from DLLs. */ +__declspec(dllexport) CRITICAL_SECTION *gl_get_setlocale_null_lock (void); + +static glwthread_initguard_t guard = GLWTHREAD_INITGUARD_INIT; +static CRITICAL_SECTION lock; + +/* Returns the internal lock used by setlocale_null. */ +CRITICAL_SECTION * +gl_get_setlocale_null_lock (void) +{ + if (!guard.done) + { + if (InterlockedIncrement (&guard.started) == 0) + { + /* This thread is the first one to need the lock. Initialize it. */ + InitializeCriticalSection (&lock); + guard.done = 1; + } + else + { + /* Don't let guard.started grow and wrap around. */ + InterlockedDecrement (&guard.started); + /* Yield the CPU while waiting for another thread to finish + initializing this mutex. */ + while (!guard.done) + Sleep (0); + } + } + return &lock; +} + +#elif HAVE_PTHREAD_API + +# include + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +# if defined _WIN32 || defined __CYGWIN__ +/* Make sure the function gets exported from DLLs. */ +__declspec(dllexport) pthread_mutex_t *gl_get_setlocale_null_lock (void); +# endif + +/* Returns the internal lock used by setlocale_null. */ +pthread_mutex_t * +gl_get_setlocale_null_lock (void) +{ + return &mutex; +} + +#elif HAVE_THREADS_H + +# include +# include + +static int volatile init_needed = 1; +static once_flag init_once = ONCE_FLAG_INIT; +static mtx_t mutex; + +static void +atomic_init (void) +{ + if (mtx_init (&mutex, mtx_plain) != thrd_success) + abort (); + init_needed = 0; +} + +/* Returns the internal lock used by setlocale_null. */ +mtx_t * +gl_get_setlocale_null_lock (void) +{ + if (init_needed) + call_once (&init_once, atomic_init); + return &mutex; +} + +#endif + +#if defined _WIN32 || defined __CYGWIN__ +/* Make sure the '__declspec(dllimport)' in setlocale_null.c does not cause + a link failure when no DLLs are involved. */ +# if defined _WIN64 || defined _LP64 +# define IMP(x) __imp_##x +# else +# define IMP(x) _imp__##x +# endif +void * IMP(gl_get_setlocale_null_lock) = &gl_get_setlocale_null_lock; +#endif diff --git a/lib/setlocale_null.c b/lib/setlocale_null.c new file mode 100644 index 0000000..b0506b9 --- /dev/null +++ b/lib/setlocale_null.c @@ -0,0 +1,204 @@ +/* Query the name of the current global locale. + Copyright (C) 2019 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 . */ + +/* Written by Bruno Haible , 2019. */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#if defined _WIN32 && !defined __CYGWIN__ +# include +#endif + +#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) +# if defined _WIN32 && !defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include +# elif HAVE_PTHREAD_API +# include +# elif HAVE_THREADS_H +# include +# endif +#endif + +/* Use the system's setlocale() function, not the gnulib override, here. */ +#undef setlocale + +static int +setlocale_null_unlocked (int category, char *buf, size_t bufsize) +{ +#if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER + /* On native Windows, nowadays, the setlocale() implementation is based + on _wsetlocale() and uses malloc() for the result. We are better off + using _wsetlocale() directly. */ + const wchar_t *result = _wsetlocale (category, NULL); + size_t length = wcslen (result); + if (length < bufsize) + { + size_t i; + + /* Convert wchar_t[] -> char[], assuming plain ASCII. */ + for (i = 0; i <= length; i++) + buf[i] = result[i]; + + return 0; + } + else + { + if (bufsize > 0) + { + /* Return a truncated result in BUF. + This is a convenience for callers that don't want to write + explicit code for handling ERANGE. */ + size_t i; + + /* Convert wchar_t[] -> char[], assuming plain ASCII. */ + for (i = 0; i < bufsize; i++) + buf[i] = result[i]; + buf[bufsize - 1] = '\0'; + } + return ERANGE; + } +#else + const char *result = setlocale (category, NULL); + size_t length = strlen (result); + if (length < bufsize) + { + memcpy (buf, result, length + 1); + return 0; + } + else + { + if (bufsize > 0) + { + /* Return a truncated result in BUF. + This is a convenience for callers that don't want to write + explicit code for handling ERANGE. */ + memcpy (buf, result, bufsize - 1); + buf[bufsize - 1] = '\0'; + } + return ERANGE; + } +#endif +} + +#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) + +/* Use a lock, so that no two threads can invoke setlocale_null_unlocked + at the same time. */ + +/* Prohibit renaming this symbol. */ +# undef gl_get_setlocale_null_lock + +# if defined _WIN32 && !defined __CYGWIN__ + +extern __declspec(dllimport) CRITICAL_SECTION *gl_get_setlocale_null_lock (void); + +static int +setlocale_null_with_lock (int category, char *buf, size_t bufsize) +{ + CRITICAL_SECTION *lock = gl_get_setlocale_null_lock (); + int ret; + + EnterCriticalSection (lock); + ret = setlocale_null_unlocked (category, buf, bufsize); + LeaveCriticalSection (lock); + + return ret; +} + +# elif HAVE_PTHREAD_API + +extern +# if defined _WIN32 || defined __CYGWIN__ + __declspec(dllimport) +# endif + pthread_mutex_t *gl_get_setlocale_null_lock (void); + +static int +setlocale_null_with_lock (int category, char *buf, size_t bufsize) +{ + pthread_mutex_t *lock = gl_get_setlocale_null_lock (); + int ret; + + if (pthread_mutex_lock (lock)) + abort (); + ret = setlocale_null_unlocked (category, buf, bufsize); + if (pthread_mutex_unlock (lock)) + abort (); + + return ret; +} + +# elif HAVE_THREADS_H + +extern mtx_t *gl_get_setlocale_null_lock (void); + +static int +setlocale_null_with_lock (int category, char *buf, size_t bufsize) +{ + mtx_t *lock = gl_get_setlocale_null_lock (); + int ret; + + if (mtx_lock (lock) != thrd_success) + abort (); + ret = setlocale_null_unlocked (category, buf, bufsize); + if (mtx_unlock (lock) != thrd_success) + abort (); + + return ret; +} + +# endif + +#endif + +int +setlocale_null (int category, char *buf, size_t bufsize) +{ +#if SETLOCALE_NULL_ALL_MTSAFE +# if SETLOCALE_NULL_ONE_MTSAFE + + return setlocale_null_unlocked (category, buf, bufsize); + +# else + + if (category == LC_ALL) + return setlocale_null_unlocked (category, buf, bufsize); + else + return setlocale_null_with_lock (category, buf, bufsize); + +# endif +#else +# if SETLOCALE_NULL_ONE_MTSAFE + + if (category == LC_ALL) + return setlocale_null_with_lock (category, buf, bufsize); + else + return setlocale_null_unlocked (category, buf, bufsize); + +# else + + return setlocale_null_with_lock (category, buf, bufsize); + +# endif +#endif +} diff --git a/m4/locale_h.m4 b/m4/locale_h.m4 index c0ec3fc..fd7de42 100644 --- a/m4/locale_h.m4 +++ b/m4/locale_h.m4 @@ -1,4 +1,4 @@ -# locale_h.m4 serial 23 +# locale_h.m4 serial 24 dnl Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -140,10 +140,11 @@ AC_DEFUN([gl_LOCALE_MODULE_INDICATOR], AC_DEFUN([gl_LOCALE_H_DEFAULTS], [ - GNULIB_LOCALECONV=0; AC_SUBST([GNULIB_LOCALECONV]) - GNULIB_SETLOCALE=0; AC_SUBST([GNULIB_SETLOCALE]) - GNULIB_DUPLOCALE=0; AC_SUBST([GNULIB_DUPLOCALE]) - GNULIB_LOCALENAME=0; AC_SUBST([GNULIB_LOCALENAME]) + GNULIB_LOCALECONV=0; AC_SUBST([GNULIB_LOCALECONV]) + GNULIB_SETLOCALE=0; AC_SUBST([GNULIB_SETLOCALE]) + GNULIB_SETLOCALE_NULL=0; AC_SUBST([GNULIB_SETLOCALE_NULL]) + GNULIB_DUPLOCALE=0; AC_SUBST([GNULIB_DUPLOCALE]) + GNULIB_LOCALENAME=0; AC_SUBST([GNULIB_LOCALENAME]) dnl Assume proper GNU behavior unless another module says otherwise. HAVE_NEWLOCALE=1; AC_SUBST([HAVE_NEWLOCALE]) HAVE_DUPLOCALE=1; AC_SUBST([HAVE_DUPLOCALE]) diff --git a/m4/setlocale_null.m4 b/m4/setlocale_null.m4 new file mode 100644 index 0000000..5c69a3f --- /dev/null +++ b/m4/setlocale_null.m4 @@ -0,0 +1,84 @@ +# setlocale_null.m4 serial 1 +dnl Copyright (C) 2019 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_SETLOCALE_NULL], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([gl_PTHREADLIB]) + AC_CHECK_HEADERS_ONCE([threads.h]) + + AC_CACHE_CHECK([whether setlocale (LC_ALL, NULL) is multithread-safe], + [gl_cv_func_setlocale_null_all_mtsafe], + [case "$host_os" in + # Guess no on musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin. + *-musl* | darwin* | freebsd* | netbsd* | openbsd* | aix* | haiku* | cygwin*) + gl_cv_func_setlocale_null_all_mtsafe=no ;; + # Guess yes on glibc, HP-UX, IRIX, Solaris, native Windows. + *-gnu* | gnu* | hpux* | irix* | solaris* | mingw*) + gl_cv_func_setlocale_null_all_mtsafe=yes ;; + # If we don't know, obey --enable-cross-guesses. + *) + gl_cv_func_setlocale_null_all_mtsafe="$gl_cross_guess_normal" ;; + esac + ]) + dnl On platforms without multithreading, there is no issue. + case "$host_os" in + mingw*) ;; + *) + if test $gl_pthread_api = no && test $ac_cv_header_threads_h = no; then + gl_cv_func_setlocale_null_all_mtsafe="trivially yes" + fi + ;; + esac + case "$gl_cv_func_setlocale_null_all_mtsafe" in + *yes) SETLOCALE_NULL_ALL_MTSAFE=1 ;; + *) SETLOCALE_NULL_ALL_MTSAFE=0 ;; + esac + AC_DEFINE_UNQUOTED([SETLOCALE_NULL_ALL_MTSAFE], [$SETLOCALE_NULL_ALL_MTSAFE], + [Define to 1 if setlocale (LC_ALL, NULL) is multithread-safe.]) + + dnl This is about a single category (not LC_ALL). + AC_CACHE_CHECK([whether setlocale (category, NULL) is multithread-safe], + [gl_cv_func_setlocale_null_one_mtsafe], + [case "$host_os" in + # Guess no on OpenBSD, AIX. + openbsd* | aix*) + gl_cv_func_setlocale_null_one_mtsafe=no ;; + # Guess yes on glibc, musl libc, macOS, FreeBSD, NetBSD, HP-UX, IRIX, Solaris, Haiku, Cygwin, native Windows. + *-gnu* | gnu* | *-musl* | darwin* | freebsd* | netbsd* | hpux* | irix* | solaris* | haiku* | cygwin* | mingw*) + gl_cv_func_setlocale_null_one_mtsafe=yes ;; + # If we don't know, obey --enable-cross-guesses. + *) + gl_cv_func_setlocale_null_one_mtsafe="$gl_cross_guess_normal" ;; + esac + ]) + dnl On platforms without multithreading, there is no issue. + case "$host_os" in + mingw*) ;; + *) + if test $gl_pthread_api = no && test $ac_cv_header_threads_h = no; then + gl_cv_func_setlocale_null_one_mtsafe="trivially yes" + fi + ;; + esac + case "$gl_cv_func_setlocale_null_one_mtsafe" in + *yes) SETLOCALE_NULL_ONE_MTSAFE=1 ;; + *) SETLOCALE_NULL_ONE_MTSAFE=0 ;; + esac + AC_DEFINE_UNQUOTED([SETLOCALE_NULL_ONE_MTSAFE], [$SETLOCALE_NULL_ONE_MTSAFE], + [Define to 1 if setlocale (category, NULL) is multithread-safe.]) + + dnl Determine link dependencies of lib/setlocale_null.c and lib/setlocale-lock.c. + if test $SETLOCALE_NULL_ALL_MTSAFE = 0 || test $SETLOCALE_NULL_ONE_MTSAFE = 0; then + case "$host_os" in + mingw*) LIB_SETLOCALE_NULL= ;; + *) LIB_SETLOCALE_NULL="$LIBPTHREAD" ;; + esac + else + LIB_SETLOCALE_NULL= + fi + AC_SUBST([LIB_SETLOCALE_NULL]) +]) diff --git a/m4/threadlib.m4 b/m4/threadlib.m4 index d22e0d6..d6e6bf9 100644 --- a/m4/threadlib.m4 +++ b/m4/threadlib.m4 @@ -1,4 +1,4 @@ -# threadlib.m4 serial 22 +# threadlib.m4 serial 23 dnl Copyright (C) 2005-2019 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,6 +18,8 @@ dnl LIBPMULTITHREAD is that on platforms supporting weak symbols, typically dnl LIBPTHREAD is empty whereas LIBPMULTITHREAD is not. dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for dnl multithread-safe programs. +dnl Defines the C macro HAVE_PTHREAD_API if (at least parts of) the POSIX +dnl threads API is available. dnl gl_THREADLIB dnl ------------ @@ -220,6 +222,10 @@ AC_DEFUN([gl_PTHREADLIB_BODY], AC_MSG_RESULT([$gl_pthread_api]) AC_SUBST([LIBPTHREAD]) AC_SUBST([LIBPMULTITHREAD]) + if test $gl_pthread_api = yes; then + AC_DEFINE([HAVE_PTHREAD_API], [1], + [Define if you have the header and the POSIX threads API.]) + fi gl_threadlib_body_done=done fi ]) diff --git a/modules/locale b/modules/locale index 488e437..aac463c 100644 --- a/modules/locale +++ b/modules/locale @@ -31,6 +31,7 @@ locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \ -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ + -e 's/@''GNULIB_SETLOCALE_NULL''@/$(GNULIB_SETLOCALE_NULL)/g' \ -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ -e 's/@''GNULIB_LOCALENAME''@/$(GNULIB_LOCALENAME)/g' \ -e 's|@''HAVE_NEWLOCALE''@|$(HAVE_NEWLOCALE)|g' \ diff --git a/modules/setlocale-null b/modules/setlocale-null new file mode 100644 index 0000000..17e8d9d --- /dev/null +++ b/modules/setlocale-null @@ -0,0 +1,34 @@ +Description: +setlocale_null() function: query the name of the current global locale. + +Files: +lib/setlocale_null.c +lib/setlocale-lock.c +lib/windows-initguard.h +m4/setlocale_null.m4 +m4/threadlib.m4 + +Depends-on: +locale + +configure.ac: +gl_FUNC_SETLOCALE_NULL +if test $SETLOCALE_NULL_ALL_MTSAFE = 0 || test $SETLOCALE_NULL_ONE_MTSAFE = 0; then + AC_LIBOBJ([setlocale-lock]) +fi +gl_LOCALE_MODULE_INDICATOR([setlocale_null]) + +Makefile.am: +lib_SOURCES += setlocale_null.c + +Include: + + +Link: +$(LIB_SETLOCALE_NULL) + +License: +LGPLv2+ + +Maintainer: +Bruno Haible -- 2.7.4