aboutsummaryrefslogtreecommitdiffstats
path: root/intl
diff options
context:
space:
mode:
Diffstat (limited to 'intl')
-rw-r--r--intl/export.h6
-rw-r--r--intl/hash-string.c51
-rw-r--r--intl/intl-exports.c36
-rw-r--r--intl/langprefs.c130
-rw-r--r--intl/lock.c924
-rw-r--r--intl/lock.h801
-rw-r--r--intl/version.c26
7 files changed, 1974 insertions, 0 deletions
diff --git a/intl/export.h b/intl/export.h
new file mode 100644
index 000000000..b5c47ad5b
--- /dev/null
+++ b/intl/export.h
@@ -0,0 +1,6 @@
+
+#if @HAVE_VISIBILITY@ && BUILDING_LIBINTL
+#define LIBINTL_DLL_EXPORTED __attribute__((__visibility__("default")))
+#else
+#define LIBINTL_DLL_EXPORTED
+#endif
diff --git a/intl/hash-string.c b/intl/hash-string.c
new file mode 100644
index 000000000..3c513f099
--- /dev/null
+++ b/intl/hash-string.c
@@ -0,0 +1,51 @@
+/* Implements a string hashing function.
+ Copyright (C) 1995, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "hash-string.h"
+
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+unsigned long int
+__hash_string (const char *str_param)
+{
+ unsigned long int hval, g;
+ const char *str = str_param;
+
+ /* Compute the hash value for the given string. */
+ hval = 0;
+ while (*str != '\0')
+ {
+ hval <<= 4;
+ hval += (unsigned char) *str++;
+ g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+ if (g != 0)
+ {
+ hval ^= g >> (HASHWORDBITS - 8);
+ hval ^= g;
+ }
+ }
+ return hval;
+}
diff --git a/intl/intl-exports.c b/intl/intl-exports.c
new file mode 100644
index 000000000..717658994
--- /dev/null
+++ b/intl/intl-exports.c
@@ -0,0 +1,36 @@
+/* List of exported symbols of libintl on Cygwin.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Bruno Haible <[email protected]>, 2006.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+ /* IMP(x) is a symbol that contains the address of x. */
+#define IMP(x) _imp__##x
+
+ /* Ensure that the variable x is exported from the library, and that a
+ pseudo-variable IMP(x) is available. */
+#define VARIABLE(x) \
+ /* Export x without redefining x. This code was found by compiling a \
+ snippet: \
+ extern __declspec(dllexport) int x; int x = 42; */ \
+ asm (".section .drectve\n"); \
+ asm (".ascii \" -export:" #x ",data\"\n"); \
+ asm (".data\n"); \
+ /* Allocate a pseudo-variable IMP(x). */ \
+ extern int x; \
+ void * IMP(x) = &x;
+
+VARIABLE(libintl_version)
diff --git a/intl/langprefs.c b/intl/langprefs.c
new file mode 100644
index 000000000..5436040f9
--- /dev/null
+++ b/intl/langprefs.c
@@ -0,0 +1,130 @@
+/* Determine the user's language preferences.
+ Copyright (C) 2004-2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <[email protected]>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#if HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <string.h>
+# include <CoreFoundation/CFPreferences.h>
+# include <CoreFoundation/CFPropertyList.h>
+# include <CoreFoundation/CFArray.h>
+# include <CoreFoundation/CFString.h>
+extern void _nl_locale_name_canonicalize (char *name);
+#endif
+
+/* Determine the user's language preferences, as a colon separated list of
+ locale names in XPG syntax
+ language[_territory[.codeset]][@modifier]
+ The result must not be freed; it is statically allocated.
+ The LANGUAGE environment variable does not need to be considered; it is
+ already taken into account by the caller. */
+
+const char *
+_nl_language_preferences_default (void)
+{
+#if HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.2 or newer */
+ {
+ /* Cache the preferences list, since CoreFoundation calls are expensive. */
+ static const char *cached_languages;
+ static int cache_initialized;
+
+ if (!cache_initialized)
+ {
+ CFTypeRef preferences =
+ CFPreferencesCopyAppValue (CFSTR ("AppleLanguages"),
+ kCFPreferencesCurrentApplication);
+ if (preferences != NULL
+ && CFGetTypeID (preferences) == CFArrayGetTypeID ())
+ {
+ CFArrayRef prefArray = (CFArrayRef)preferences;
+ int n = CFArrayGetCount (prefArray);
+ char buf[256];
+ size_t size = 0;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ CFTypeRef element = CFArrayGetValueAtIndex (prefArray, i);
+ if (element != NULL
+ && CFGetTypeID (element) == CFStringGetTypeID ()
+ && CFStringGetCString ((CFStringRef)element,
+ buf, sizeof (buf),
+ kCFStringEncodingASCII))
+ {
+ _nl_locale_name_canonicalize (buf);
+ size += strlen (buf) + 1;
+ /* Most GNU programs use msgids in English and don't ship
+ an en.mo message catalog. Therefore when we see "en"
+ in the preferences list, arrange for gettext() to
+ return the msgid, and ignore all further elements of
+ the preferences list. */
+ if (strcmp (buf, "en") == 0)
+ break;
+ }
+ else
+ break;
+ }
+ if (size > 0)
+ {
+ char *languages = (char *) malloc (size);
+
+ if (languages != NULL)
+ {
+ char *p = languages;
+
+ for (i = 0; i < n; i++)
+ {
+ CFTypeRef element =
+ CFArrayGetValueAtIndex (prefArray, i);
+ if (element != NULL
+ && CFGetTypeID (element) == CFStringGetTypeID ()
+ && CFStringGetCString ((CFStringRef)element,
+ buf, sizeof (buf),
+ kCFStringEncodingASCII))
+ {
+ _nl_locale_name_canonicalize (buf);
+ strcpy (p, buf);
+ p += strlen (buf);
+ *p++ = ':';
+ if (strcmp (buf, "en") == 0)
+ break;
+ }
+ else
+ break;
+ }
+ *--p = '\0';
+
+ cached_languages = languages;
+ }
+ }
+ }
+ cache_initialized = 1;
+ }
+ if (cached_languages != NULL)
+ return cached_languages;
+ }
+#endif
+
+ return NULL;
+}
diff --git a/intl/lock.c b/intl/lock.c
new file mode 100644
index 000000000..a860459d1
--- /dev/null
+++ b/intl/lock.c
@@ -0,0 +1,924 @@
+/* Locking in multithreaded situations.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <[email protected]>, 2005.
+ Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
+ gthr-win32.h. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "lock.h"
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# if PTHREAD_IN_USE_DETECTION_HARD
+
+/* The function to be executed by a dummy thread. */
+static void *
+dummy_thread_func (void *arg)
+{
+ return arg;
+}
+
+int
+glthread_in_use (void)
+{
+ static int tested;
+ static int result; /* 1: linked with -lpthread, 0: only with libc */
+
+ if (!tested)
+ {
+ pthread_t thread;
+
+ if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0)
+ /* Thread creation failed. */
+ result = 0;
+ else
+ {
+ /* Thread creation works. */
+ void *retval;
+ if (pthread_join (thread, &retval) != 0)
+ abort ();
+ result = 1;
+ }
+ tested = 1;
+ }
+ return result;
+}
+
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+# if HAVE_PTHREAD_RWLOCK
+
+# if !defined PTHREAD_RWLOCK_INITIALIZER
+
+void
+glthread_rwlock_init (gl_rwlock_t *lock)
+{
+ if (pthread_rwlock_init (&lock->rwlock, NULL) != 0)
+ abort ();
+ lock->initialized = 1;
+}
+
+void
+glthread_rwlock_rdlock (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ if (pthread_mutex_lock (&lock->guard) != 0)
+ abort ();
+ if (!lock->initialized)
+ glthread_rwlock_init (lock);
+ if (pthread_mutex_unlock (&lock->guard) != 0)
+ abort ();
+ }
+ if (pthread_rwlock_rdlock (&lock->rwlock) != 0)
+ abort ();
+}
+
+void
+glthread_rwlock_wrlock (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ if (pthread_mutex_lock (&lock->guard) != 0)
+ abort ();
+ if (!lock->initialized)
+ glthread_rwlock_init (lock);
+ if (pthread_mutex_unlock (&lock->guard) != 0)
+ abort ();
+ }
+ if (pthread_rwlock_wrlock (&lock->rwlock) != 0)
+ abort ();
+}
+
+void
+glthread_rwlock_unlock (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ abort ();
+ if (pthread_rwlock_unlock (&lock->rwlock) != 0)
+ abort ();
+}
+
+void
+glthread_rwlock_destroy (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ abort ();
+ if (pthread_rwlock_destroy (&lock->rwlock) != 0)
+ abort ();
+ lock->initialized = 0;
+}
+
+# endif
+
+# else
+
+void
+glthread_rwlock_init (gl_rwlock_t *lock)
+{
+ if (pthread_mutex_init (&lock->lock, NULL) != 0)
+ abort ();
+ if (pthread_cond_init (&lock->waiting_readers, NULL) != 0)
+ abort ();
+ if (pthread_cond_init (&lock->waiting_writers, NULL) != 0)
+ abort ();
+ lock->waiting_writers_count = 0;
+ lock->runcount = 0;
+}
+
+void
+glthread_rwlock_rdlock (gl_rwlock_t *lock)
+{
+ if (pthread_mutex_lock (&lock->lock) != 0)
+ abort ();
+ /* Test whether only readers are currently running, and whether the runcount
+ field will not overflow. */
+ /* POSIX says: "It is implementation-defined whether the calling thread
+ acquires the lock when a writer does not hold the lock and there are
+ writers blocked on the lock." Let's say, no: give the writers a higher
+ priority. */
+ while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_readers. */
+ if (pthread_cond_wait (&lock->waiting_readers, &lock->lock) != 0)
+ abort ();
+ }
+ lock->runcount++;
+ if (pthread_mutex_unlock (&lock->lock) != 0)
+ abort ();
+}
+
+void
+glthread_rwlock_wrlock (gl_rwlock_t *lock)
+{
+ if (pthread_mutex_lock (&lock->lock) != 0)
+ abort ();
+ /* Test whether no readers or writers are currently running. */
+ while (!(lock->runcount == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_writers. */
+ lock->waiting_writers_count++;
+ if (pthread_cond_wait (&lock->waiting_writers, &lock->lock) != 0)
+ abort ();
+ lock->waiting_writers_count--;
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ if (pthread_mutex_unlock (&lock->lock) != 0)
+ abort ();
+}
+
+void
+glthread_rwlock_unlock (gl_rwlock_t *lock)
+{
+ if (pthread_mutex_lock (&lock->lock) != 0)
+ abort ();
+ if (lock->runcount < 0)
+ {
+ /* Drop a writer lock. */
+ if (!(lock->runcount == -1))
+ abort ();
+ lock->runcount = 0;
+ }
+ else
+ {
+ /* Drop a reader lock. */
+ if (!(lock->runcount > 0))
+ abort ();
+ lock->runcount--;
+ }
+ if (lock->runcount == 0)
+ {
+ /* POSIX recommends that "write locks shall take precedence over read
+ locks", to avoid "writer starvation". */
+ if (lock->waiting_writers_count > 0)
+ {
+ /* Wake up one of the waiting writers. */
+ if (pthread_cond_signal (&lock->waiting_writers) != 0)
+ abort ();
+ }
+ else
+ {
+ /* Wake up all waiting readers. */
+ if (pthread_cond_broadcast (&lock->waiting_readers) != 0)
+ abort ();
+ }
+ }
+ if (pthread_mutex_unlock (&lock->lock) != 0)
+ abort ();
+}
+
+void
+glthread_rwlock_destroy (gl_rwlock_t *lock)
+{
+ if (pthread_mutex_destroy (&lock->lock) != 0)
+ abort ();
+ if (pthread_cond_destroy (&lock->waiting_readers) != 0)
+ abort ();
+ if (pthread_cond_destroy (&lock->waiting_writers) != 0)
+ abort ();
+}
+
+# endif
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+# if HAVE_PTHREAD_MUTEX_RECURSIVE
+
+# if !(defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
+
+void
+glthread_recursive_lock_init (gl_recursive_lock_t *lock)
+{
+ pthread_mutexattr_t attributes;
+
+ if (pthread_mutexattr_init (&attributes) != 0)
+ abort ();
+ if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0)
+ abort ();
+ if (pthread_mutex_init (&lock->recmutex, &attributes) != 0)
+ abort ();
+ if (pthread_mutexattr_destroy (&attributes) != 0)
+ abort ();
+ lock->initialized = 1;
+}
+
+void
+glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ if (pthread_mutex_lock (&lock->guard) != 0)
+ abort ();
+ if (!lock->initialized)
+ glthread_recursive_lock_init (lock);
+ if (pthread_mutex_unlock (&lock->guard) != 0)
+ abort ();
+ }
+ if (pthread_mutex_lock (&lock->recmutex) != 0)
+ abort ();
+}
+
+void
+glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
+{
+ if (!lock->initialized)
+ abort ();
+ if (pthread_mutex_unlock (&lock->recmutex) != 0)
+ abort ();
+}
+
+void
+glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
+{
+ if (!lock->initialized)
+ abort ();
+ if (pthread_mutex_destroy (&lock->recmutex) != 0)
+ abort ();
+ lock->initialized = 0;
+}
+
+# endif
+
+# else
+
+void
+glthread_recursive_lock_init (gl_recursive_lock_t *lock)
+{
+ if (pthread_mutex_init (&lock->mutex, NULL) != 0)
+ abort ();
+ lock->owner = (pthread_t) 0;
+ lock->depth = 0;
+}
+
+void
+glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
+{
+ pthread_t self = pthread_self ();
+ if (lock->owner != self)
+ {
+ if (pthread_mutex_lock (&lock->mutex) != 0)
+ abort ();
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ abort ();
+}
+
+void
+glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != pthread_self ())
+ abort ();
+ if (lock->depth == 0)
+ abort ();
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = (pthread_t) 0;
+ if (pthread_mutex_unlock (&lock->mutex) != 0)
+ abort ();
+ }
+}
+
+void
+glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != (pthread_t) 0)
+ abort ();
+ if (pthread_mutex_destroy (&lock->mutex) != 0)
+ abort ();
+}
+
+# endif
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
+
+int
+glthread_once_singlethreaded (pthread_once_t *once_control)
+{
+ /* We don't know whether pthread_once_t is an integer type, a floating-point
+ type, a pointer type, or a structure type. */
+ char *firstbyte = (char *)once_control;
+ if (*firstbyte == *(const char *)&fresh_once)
+ {
+ /* First time use of once_control. Invert the first byte. */
+ *firstbyte = ~ *(const char *)&fresh_once;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+void
+glthread_once_call (void *arg)
+{
+ void (**gl_once_temp_addr) (void) = (void (**) (void)) arg;
+ void (*initfunction) (void) = *gl_once_temp_addr;
+ initfunction ();
+}
+
+int
+glthread_once_singlethreaded (pth_once_t *once_control)
+{
+ /* We know that pth_once_t is an integer type. */
+ if (*once_control == PTH_ONCE_INIT)
+ {
+ /* First time use of once_control. Invert the marker. */
+ *once_control = ~ PTH_ONCE_INIT;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+void
+glthread_recursive_lock_init (gl_recursive_lock_t *lock)
+{
+ if (mutex_init (&lock->mutex, USYNC_THREAD, NULL) != 0)
+ abort ();
+ lock->owner = (thread_t) 0;
+ lock->depth = 0;
+}
+
+void
+glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
+{
+ thread_t self = thr_self ();
+ if (lock->owner != self)
+ {
+ if (mutex_lock (&lock->mutex) != 0)
+ abort ();
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ abort ();
+}
+
+void
+glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != thr_self ())
+ abort ();
+ if (lock->depth == 0)
+ abort ();
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = (thread_t) 0;
+ if (mutex_unlock (&lock->mutex) != 0)
+ abort ();
+ }
+}
+
+void
+glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != (thread_t) 0)
+ abort ();
+ if (mutex_destroy (&lock->mutex) != 0)
+ abort ();
+}
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+void
+glthread_once (gl_once_t *once_control, void (*initfunction) (void))
+{
+ if (!once_control->inited)
+ {
+ /* Use the mutex to guarantee that if another thread is already calling
+ the initfunction, this thread waits until it's finished. */
+ if (mutex_lock (&once_control->mutex) != 0)
+ abort ();
+ if (!once_control->inited)
+ {
+ once_control->inited = 1;
+ initfunction ();
+ }
+ if (mutex_unlock (&once_control->mutex) != 0)
+ abort ();
+ }
+}
+
+int
+glthread_once_singlethreaded (gl_once_t *once_control)
+{
+ /* We know that gl_once_t contains an integer type. */
+ if (!once_control->inited)
+ {
+ /* First time use of once_control. Invert the marker. */
+ once_control->inited = ~ 0;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+void
+glthread_lock_init (gl_lock_t *lock)
+{
+ InitializeCriticalSection (&lock->lock);
+ lock->guard.done = 1;
+}
+
+void
+glthread_lock_lock (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_lock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ EnterCriticalSection (&lock->lock);
+}
+
+void
+glthread_lock_unlock (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ abort ();
+ LeaveCriticalSection (&lock->lock);
+}
+
+void
+glthread_lock_destroy (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ abort ();
+ DeleteCriticalSection (&lock->lock);
+ lock->guard.done = 0;
+}
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+static inline void
+gl_waitqueue_init (gl_waitqueue_t *wq)
+{
+ wq->array = NULL;
+ wq->count = 0;
+ wq->alloc = 0;
+ wq->offset = 0;
+}
+
+/* Enqueues the current thread, represented by an event, in a wait queue.
+ Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */
+static HANDLE
+gl_waitqueue_add (gl_waitqueue_t *wq)
+{
+ HANDLE event;
+ unsigned int index;
+
+ if (wq->count == wq->alloc)
+ {
+ unsigned int new_alloc = 2 * wq->alloc + 1;
+ HANDLE *new_array =
+ (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
+ if (new_array == NULL)
+ /* No more memory. */
+ return INVALID_HANDLE_VALUE;
+ /* Now is a good opportunity to rotate the array so that its contents
+ starts at offset 0. */
+ if (wq->offset > 0)
+ {
+ unsigned int old_count = wq->count;
+ unsigned int old_alloc = wq->alloc;
+ unsigned int old_offset = wq->offset;
+ unsigned int i;
+ if (old_offset + old_count > old_alloc)
+ {
+ unsigned int limit = old_offset + old_count - old_alloc;
+ for (i = 0; i < limit; i++)
+ new_array[old_alloc + i] = new_array[i];
+ }
+ for (i = 0; i < old_count; i++)
+ new_array[i] = new_array[old_offset + i];
+ wq->offset = 0;
+ }
+ wq->array = new_array;
+ wq->alloc = new_alloc;
+ }
+ event = CreateEvent (NULL, TRUE, FALSE, NULL);
+ if (event == INVALID_HANDLE_VALUE)
+ /* No way to allocate an event. */
+ return INVALID_HANDLE_VALUE;
+ index = wq->offset + wq->count;
+ if (index >= wq->alloc)
+ index -= wq->alloc;
+ wq->array[index] = event;
+ wq->count++;
+ return event;
+}
+
+/* Notifies the first thread from a wait queue and dequeues it. */
+static inline void
+gl_waitqueue_notify_first (gl_waitqueue_t *wq)
+{
+ SetEvent (wq->array[wq->offset + 0]);
+ wq->offset++;
+ wq->count--;
+ if (wq->count == 0 || wq->offset == wq->alloc)
+ wq->offset = 0;
+}
+
+/* Notifies all threads from a wait queue and dequeues them all. */
+static inline void
+gl_waitqueue_notify_all (gl_waitqueue_t *wq)
+{
+ unsigned int i;
+
+ for (i = 0; i < wq->count; i++)
+ {
+ unsigned int index = wq->offset + i;
+ if (index >= wq->alloc)
+ index -= wq->alloc;
+ SetEvent (wq->array[index]);
+ }
+ wq->count = 0;
+ wq->offset = 0;
+}
+
+void
+glthread_rwlock_init (gl_rwlock_t *lock)
+{
+ InitializeCriticalSection (&lock->lock);
+ gl_waitqueue_init (&lock->waiting_readers);
+ gl_waitqueue_init (&lock->waiting_writers);
+ lock->runcount = 0;
+ lock->guard.done = 1;
+}
+
+void
+glthread_rwlock_rdlock (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_rwlock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ EnterCriticalSection (&lock->lock);
+ /* Test whether only readers are currently running, and whether the runcount
+ field will not overflow. */
+ if (!(lock->runcount + 1 > 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_readers. */
+ HANDLE event = gl_waitqueue_add (&lock->waiting_readers);
+ if (event != INVALID_HANDLE_VALUE)
+ {
+ DWORD result;
+ LeaveCriticalSection (&lock->lock);
+ /* Wait until another thread signals this event. */
+ result = WaitForSingleObject (event, INFINITE);
+ if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+ abort ();
+ CloseHandle (event);
+ /* The thread which signalled the event already did the bookkeeping:
+ removed us from the waiting_readers, incremented lock->runcount. */
+ if (!(lock->runcount > 0))
+ abort ();
+ return;
+ }
+ else
+ {
+ /* Allocation failure. Weird. */
+ do
+ {
+ LeaveCriticalSection (&lock->lock);
+ Sleep (1);
+ EnterCriticalSection (&lock->lock);
+ }
+ while (!(lock->runcount + 1 > 0));
+ }
+ }
+ lock->runcount++;
+ LeaveCriticalSection (&lock->lock);
+}
+
+void
+glthread_rwlock_wrlock (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_rwlock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ EnterCriticalSection (&lock->lock);
+ /* Test whether no readers or writers are currently running. */
+ if (!(lock->runcount == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_writers. */
+ HANDLE event = gl_waitqueue_add (&lock->waiting_writers);
+ if (event != INVALID_HANDLE_VALUE)
+ {
+ DWORD result;
+ LeaveCriticalSection (&lock->lock);
+ /* Wait until another thread signals this event. */
+ result = WaitForSingleObject (event, INFINITE);
+ if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+ abort ();
+ CloseHandle (event);
+ /* The thread which signalled the event already did the bookkeeping:
+ removed us from the waiting_writers, set lock->runcount = -1. */
+ if (!(lock->runcount == -1))
+ abort ();
+ return;
+ }
+ else
+ {
+ /* Allocation failure. Weird. */
+ do
+ {
+ LeaveCriticalSection (&lock->lock);
+ Sleep (1);
+ EnterCriticalSection (&lock->lock);
+ }
+ while (!(lock->runcount == 0));
+ }
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ LeaveCriticalSection (&lock->lock);
+}
+
+void
+glthread_rwlock_unlock (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ abort ();
+ EnterCriticalSection (&lock->lock);
+ if (lock->runcount < 0)
+ {
+ /* Drop a writer lock. */
+ if (!(lock->runcount == -1))
+ abort ();
+ lock->runcount = 0;
+ }
+ else
+ {
+ /* Drop a reader lock. */
+ if (!(lock->runcount > 0))
+ abort ();
+ lock->runcount--;
+ }
+ if (lock->runcount == 0)
+ {
+ /* POSIX recommends that "write locks shall take precedence over read
+ locks", to avoid "writer starvation". */
+ if (lock->waiting_writers.count > 0)
+ {
+ /* Wake up one of the waiting writers. */
+ lock->runcount--;
+ gl_waitqueue_notify_first (&lock->waiting_writers);
+ }
+ else
+ {
+ /* Wake up all waiting readers. */
+ lock->runcount += lock->waiting_readers.count;
+ gl_waitqueue_notify_all (&lock->waiting_readers);
+ }
+ }
+ LeaveCriticalSection (&lock->lock);
+}
+
+void
+glthread_rwlock_destroy (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ abort ();
+ if (lock->runcount != 0)
+ abort ();
+ DeleteCriticalSection (&lock->lock);
+ if (lock->waiting_readers.array != NULL)
+ free (lock->waiting_readers.array);
+ if (lock->waiting_writers.array != NULL)
+ free (lock->waiting_writers.array);
+ lock->guard.done = 0;
+}
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+void
+glthread_recursive_lock_init (gl_recursive_lock_t *lock)
+{
+ lock->owner = 0;
+ lock->depth = 0;
+ InitializeCriticalSection (&lock->lock);
+ lock->guard.done = 1;
+}
+
+void
+glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_recursive_lock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ {
+ DWORD self = GetCurrentThreadId ();
+ if (lock->owner != self)
+ {
+ EnterCriticalSection (&lock->lock);
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ abort ();
+ }
+}
+
+void
+glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != GetCurrentThreadId ())
+ abort ();
+ if (lock->depth == 0)
+ abort ();
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = 0;
+ LeaveCriticalSection (&lock->lock);
+ }
+}
+
+void
+glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != 0)
+ abort ();
+ DeleteCriticalSection (&lock->lock);
+ lock->guard.done = 0;
+}
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+void
+glthread_once (gl_once_t *once_control, void (*initfunction) (void))
+{
+ if (once_control->inited <= 0)
+ {
+ if (InterlockedIncrement (&once_control->started) == 0)
+ {
+ /* This thread is the first one to come to this once_control. */
+ InitializeCriticalSection (&once_control->lock);
+ EnterCriticalSection (&once_control->lock);
+ once_control->inited = 0;
+ initfunction ();
+ once_control->inited = 1;
+ LeaveCriticalSection (&once_control->lock);
+ }
+ else
+ {
+ /* Undo last operation. */
+ InterlockedDecrement (&once_control->started);
+ /* Some other thread has already started the initialization.
+ Yield the CPU while waiting for the other thread to finish
+ initializing and taking the lock. */
+ while (once_control->inited < 0)
+ Sleep (0);
+ if (once_control->inited <= 0)
+ {
+ /* Take the lock. This blocks until the other thread has
+ finished calling the initfunction. */
+ EnterCriticalSection (&once_control->lock);
+ LeaveCriticalSection (&once_control->lock);
+ if (!(once_control->inited > 0))
+ abort ();
+ }
+ }
+ }
+}
+
+#endif
+
+/* ========================================================================= */
diff --git a/intl/lock.h b/intl/lock.h
new file mode 100644
index 000000000..be99139dc
--- /dev/null
+++ b/intl/lock.h
@@ -0,0 +1,801 @@
+/* Locking in multithreaded situations.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <[email protected]>, 2005.
+ Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
+ gthr-win32.h. */
+
+/* This file contains locking primitives for use with a given thread library.
+ It does not contain primitives for creating threads or for other
+ synchronization primitives.
+
+ Normal (non-recursive) locks:
+ Type: gl_lock_t
+ Declaration: gl_lock_define(extern, name)
+ Initializer: gl_lock_define_initialized(, name)
+ Initialization: gl_lock_init (name);
+ Taking the lock: gl_lock_lock (name);
+ Releasing the lock: gl_lock_unlock (name);
+ De-initialization: gl_lock_destroy (name);
+
+ Read-Write (non-recursive) locks:
+ Type: gl_rwlock_t
+ Declaration: gl_rwlock_define(extern, name)
+ Initializer: gl_rwlock_define_initialized(, name)
+ Initialization: gl_rwlock_init (name);
+ Taking the lock: gl_rwlock_rdlock (name);
+ gl_rwlock_wrlock (name);
+ Releasing the lock: gl_rwlock_unlock (name);
+ De-initialization: gl_rwlock_destroy (name);
+
+ Recursive locks:
+ Type: gl_recursive_lock_t
+ Declaration: gl_recursive_lock_define(extern, name)
+ Initializer: gl_recursive_lock_define_initialized(, name)
+ Initialization: gl_recursive_lock_init (name);
+ Taking the lock: gl_recursive_lock_lock (name);
+ Releasing the lock: gl_recursive_lock_unlock (name);
+ De-initialization: gl_recursive_lock_destroy (name);
+
+ Once-only execution:
+ Type: gl_once_t
+ Initializer: gl_once_define(extern, name)
+ Execution: gl_once (name, initfunction);
+*/
+
+
+#ifndef _LOCK_H
+#define _LOCK_H
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+# include <stdlib.h>
+
+# if PTHREAD_IN_USE_DETECTION_HARD
+
+/* The pthread_in_use() detection needs to be done at runtime. */
+# define pthread_in_use() \
+ glthread_in_use ()
+extern int glthread_in_use (void);
+
+# endif
+
+# if USE_POSIX_THREADS_WEAK
+
+/* Use weak references to the POSIX threads library. */
+
+/* Weak references avoid dragging in external libraries if the other parts
+ of the program don't use them. Here we use them, because we don't want
+ every program that uses libintl to depend on libpthread. This assumes
+ that libpthread would not be loaded after libintl; i.e. if libintl is
+ loaded first, by an executable that does not depend on libpthread, and
+ then a module is dynamically loaded that depends on libpthread, libintl
+ will not be multithread-safe. */
+
+/* The way to test at runtime whether libpthread is present is to test
+ whether a function pointer's value, such as &pthread_mutex_init, is
+ non-NULL. However, some versions of GCC have a bug through which, in
+ PIC mode, &foo != NULL always evaluates to true if there is a direct
+ call to foo(...) in the same function. To avoid this, we test the
+ address of a function in libpthread that we don't use. */
+
+# pragma weak pthread_mutex_init
+# pragma weak pthread_mutex_lock
+# pragma weak pthread_mutex_unlock
+# pragma weak pthread_mutex_destroy
+# pragma weak pthread_rwlock_init
+# pragma weak pthread_rwlock_rdlock
+# pragma weak pthread_rwlock_wrlock
+# pragma weak pthread_rwlock_unlock
+# pragma weak pthread_rwlock_destroy
+# pragma weak pthread_once
+# pragma weak pthread_cond_init
+# pragma weak pthread_cond_wait
+# pragma weak pthread_cond_signal
+# pragma weak pthread_cond_broadcast
+# pragma weak pthread_cond_destroy
+# pragma weak pthread_mutexattr_init
+# pragma weak pthread_mutexattr_settype
+# pragma weak pthread_mutexattr_destroy
+# ifndef pthread_self
+# pragma weak pthread_self
+# endif
+
+# if !PTHREAD_IN_USE_DETECTION_HARD
+# pragma weak pthread_cancel
+# define pthread_in_use() (pthread_cancel != NULL)
+# endif
+
+# else
+
+# if !PTHREAD_IN_USE_DETECTION_HARD
+# define pthread_in_use() 1
+# endif
+
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef pthread_mutex_t gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ PTHREAD_MUTEX_INITIALIZER
+# define gl_lock_init(NAME) \
+ if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
+# define gl_lock_lock(NAME) \
+ if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
+# define gl_lock_unlock(NAME) \
+ if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
+# define gl_lock_destroy(NAME) \
+ if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+# if HAVE_PTHREAD_RWLOCK
+
+# ifdef PTHREAD_RWLOCK_INITIALIZER
+
+typedef pthread_rwlock_t gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ PTHREAD_RWLOCK_INITIALIZER
+# define gl_rwlock_init(NAME) \
+ if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
+# define gl_rwlock_rdlock(NAME) \
+ if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
+# define gl_rwlock_wrlock(NAME) \
+ if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
+# define gl_rwlock_unlock(NAME) \
+ if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
+# define gl_rwlock_destroy(NAME) \
+ if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
+
+# else
+
+typedef struct
+ {
+ int initialized;
+ pthread_mutex_t guard; /* protects the initialization */
+ pthread_rwlock_t rwlock; /* read-write lock */
+ }
+ gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ { 0, PTHREAD_MUTEX_INITIALIZER }
+# define gl_rwlock_init(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_init (&NAME)
+# define gl_rwlock_rdlock(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
+# define gl_rwlock_wrlock(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
+# define gl_rwlock_unlock(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
+# define gl_rwlock_destroy(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
+extern void glthread_rwlock_init (gl_rwlock_t *lock);
+extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
+
+# endif
+
+# else
+
+typedef struct
+ {
+ pthread_mutex_t lock; /* protects the remaining fields */
+ pthread_cond_t waiting_readers; /* waiting readers */
+ pthread_cond_t waiting_writers; /* waiting writers */
+ unsigned int waiting_writers_count; /* number of waiting writers */
+ int runcount; /* number of readers running, or -1 when a writer runs */
+ }
+ gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
+# define gl_rwlock_init(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_init (&NAME)
+# define gl_rwlock_rdlock(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
+# define gl_rwlock_wrlock(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
+# define gl_rwlock_unlock(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
+# define gl_rwlock_destroy(NAME) \
+ if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
+extern void glthread_rwlock_init (gl_rwlock_t *lock);
+extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
+
+# endif
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+# if HAVE_PTHREAD_MUTEX_RECURSIVE
+
+# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+
+typedef pthread_mutex_t gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
+# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+# define gl_recursive_lock_initializer \
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+# else
+# define gl_recursive_lock_initializer \
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+# endif
+# define gl_recursive_lock_init(NAME) \
+ if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
+# define gl_recursive_lock_lock(NAME) \
+ if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
+# define gl_recursive_lock_unlock(NAME) \
+ if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
+# define gl_recursive_lock_destroy(NAME) \
+ if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
+
+# else
+
+typedef struct
+ {
+ pthread_mutex_t recmutex; /* recursive mutex */
+ pthread_mutex_t guard; /* protects the initialization */
+ int initialized;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
+# define gl_recursive_lock_init(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
+# define gl_recursive_lock_lock(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
+# define gl_recursive_lock_unlock(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
+# define gl_recursive_lock_destroy(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
+extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
+
+# endif
+
+# else
+
+/* Old versions of POSIX threads on Solaris did not have recursive locks.
+ We have to implement them ourselves. */
+
+typedef struct
+ {
+ pthread_mutex_t mutex;
+ pthread_t owner;
+ unsigned long depth;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
+# define gl_recursive_lock_init(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
+# define gl_recursive_lock_lock(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
+# define gl_recursive_lock_unlock(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
+# define gl_recursive_lock_destroy(NAME) \
+ if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
+extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
+
+# endif
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef pthread_once_t gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
+# define gl_once(NAME, INITFUNCTION) \
+ do \
+ { \
+ if (pthread_in_use ()) \
+ { \
+ if (pthread_once (&NAME, INITFUNCTION) != 0) \
+ abort (); \
+ } \
+ else \
+ { \
+ if (glthread_once_singlethreaded (&NAME)) \
+ INITFUNCTION (); \
+ } \
+ } \
+ while (0)
+extern int glthread_once_singlethreaded (pthread_once_t *once_control);
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library. */
+
+# include <pth.h>
+# include <stdlib.h>
+
+# if USE_PTH_THREADS_WEAK
+
+/* Use weak references to the GNU Pth threads library. */
+
+# pragma weak pth_mutex_init
+# pragma weak pth_mutex_acquire
+# pragma weak pth_mutex_release
+# pragma weak pth_rwlock_init
+# pragma weak pth_rwlock_acquire
+# pragma weak pth_rwlock_release
+# pragma weak pth_once
+
+# pragma weak pth_cancel
+# define pth_in_use() (pth_cancel != NULL)
+
+# else
+
+# define pth_in_use() 1
+
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef pth_mutex_t gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ PTH_MUTEX_INIT
+# define gl_lock_init(NAME) \
+ if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
+# define gl_lock_lock(NAME) \
+ if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+# define gl_lock_unlock(NAME) \
+ if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
+# define gl_lock_destroy(NAME) \
+ (void)(&NAME)
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef pth_rwlock_t gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ PTH_RWLOCK_INIT
+# define gl_rwlock_init(NAME) \
+ if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
+# define gl_rwlock_rdlock(NAME) \
+ if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
+# define gl_rwlock_wrlock(NAME) \
+ if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
+# define gl_rwlock_unlock(NAME) \
+ if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
+# define gl_rwlock_destroy(NAME) \
+ (void)(&NAME)
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* In Pth, mutexes are recursive by default. */
+typedef pth_mutex_t gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ PTH_MUTEX_INIT
+# define gl_recursive_lock_init(NAME) \
+ if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
+# define gl_recursive_lock_lock(NAME) \
+ if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+# define gl_recursive_lock_unlock(NAME) \
+ if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
+# define gl_recursive_lock_destroy(NAME) \
+ (void)(&NAME)
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef pth_once_t gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
+# define gl_once(NAME, INITFUNCTION) \
+ do \
+ { \
+ if (pth_in_use ()) \
+ { \
+ void (*gl_once_temp) (void) = INITFUNCTION; \
+ if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
+ abort (); \
+ } \
+ else \
+ { \
+ if (glthread_once_singlethreaded (&NAME)) \
+ INITFUNCTION (); \
+ } \
+ } \
+ while (0)
+extern void glthread_once_call (void *arg);
+extern int glthread_once_singlethreaded (pth_once_t *once_control);
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library. */
+
+# include <thread.h>
+# include <synch.h>
+# include <stdlib.h>
+
+# if USE_SOLARIS_THREADS_WEAK
+
+/* Use weak references to the old Solaris threads library. */
+
+# pragma weak mutex_init
+# pragma weak mutex_lock
+# pragma weak mutex_unlock
+# pragma weak mutex_destroy
+# pragma weak rwlock_init
+# pragma weak rw_rdlock
+# pragma weak rw_wrlock
+# pragma weak rw_unlock
+# pragma weak rwlock_destroy
+# pragma weak thr_self
+
+# pragma weak thr_suspend
+# define thread_in_use() (thr_suspend != NULL)
+
+# else
+
+# define thread_in_use() 1
+
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef mutex_t gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS mutex_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ DEFAULTMUTEX
+# define gl_lock_init(NAME) \
+ if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
+# define gl_lock_lock(NAME) \
+ if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
+# define gl_lock_unlock(NAME) \
+ if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
+# define gl_lock_destroy(NAME) \
+ if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef rwlock_t gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ DEFAULTRWLOCK
+# define gl_rwlock_init(NAME) \
+ if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
+# define gl_rwlock_rdlock(NAME) \
+ if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
+# define gl_rwlock_wrlock(NAME) \
+ if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
+# define gl_rwlock_unlock(NAME) \
+ if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
+# define gl_rwlock_destroy(NAME) \
+ if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* Old Solaris threads did not have recursive locks.
+ We have to implement them ourselves. */
+
+typedef struct
+ {
+ mutex_t mutex;
+ thread_t owner;
+ unsigned long depth;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { DEFAULTMUTEX, (thread_t) 0, 0 }
+# define gl_recursive_lock_init(NAME) \
+ if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
+# define gl_recursive_lock_lock(NAME) \
+ if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
+# define gl_recursive_lock_unlock(NAME) \
+ if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
+# define gl_recursive_lock_destroy(NAME) \
+ if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
+extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef struct
+ {
+ volatile int inited;
+ mutex_t mutex;
+ }
+ gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
+# define gl_once(NAME, INITFUNCTION) \
+ do \
+ { \
+ if (thread_in_use ()) \
+ { \
+ glthread_once (&NAME, INITFUNCTION); \
+ } \
+ else \
+ { \
+ if (glthread_once_singlethreaded (&NAME)) \
+ INITFUNCTION (); \
+ } \
+ } \
+ while (0)
+extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
+extern int glthread_once_singlethreaded (gl_once_t *once_control);
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+# include <windows.h>
+
+/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
+ Semaphore types, because
+ - we need only to synchronize inside a single process (address space),
+ not inter-process locking,
+ - we don't need to support trylock operations. (TryEnterCriticalSection
+ does not work on Windows 95/98/ME. Packages that need trylock usually
+ define their own mutex type.) */
+
+/* There is no way to statically initialize a CRITICAL_SECTION. It needs
+ to be done lazily, once only. For this we need spinlocks. */
+
+typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef struct
+ {
+ gl_spinlock_t guard; /* protects the initialization */
+ CRITICAL_SECTION lock;
+ }
+ gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_lock_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ { { 0, -1 } }
+# define gl_lock_init(NAME) \
+ glthread_lock_init (&NAME)
+# define gl_lock_lock(NAME) \
+ glthread_lock_lock (&NAME)
+# define gl_lock_unlock(NAME) \
+ glthread_lock_unlock (&NAME)
+# define gl_lock_destroy(NAME) \
+ glthread_lock_destroy (&NAME)
+extern void glthread_lock_init (gl_lock_t *lock);
+extern void glthread_lock_lock (gl_lock_t *lock);
+extern void glthread_lock_unlock (gl_lock_t *lock);
+extern void glthread_lock_destroy (gl_lock_t *lock);
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* It is impossible to implement read-write locks using plain locks, without
+ introducing an extra thread dedicated to managing read-write locks.
+ Therefore here we need to use the low-level Event type. */
+
+typedef struct
+ {
+ HANDLE *array; /* array of waiting threads, each represented by an event */
+ unsigned int count; /* number of waiting threads */
+ unsigned int alloc; /* length of allocated array */
+ unsigned int offset; /* index of first waiting thread in array */
+ }
+ gl_waitqueue_t;
+typedef struct
+ {
+ gl_spinlock_t guard; /* protects the initialization */
+ CRITICAL_SECTION lock; /* protects the remaining fields */
+ gl_waitqueue_t waiting_readers; /* waiting readers */
+ gl_waitqueue_t waiting_writers; /* waiting writers */
+ int runcount; /* number of readers running, or -1 when a writer runs */
+ }
+ gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ { { 0, -1 } }
+# define gl_rwlock_init(NAME) \
+ glthread_rwlock_init (&NAME)
+# define gl_rwlock_rdlock(NAME) \
+ glthread_rwlock_rdlock (&NAME)
+# define gl_rwlock_wrlock(NAME) \
+ glthread_rwlock_wrlock (&NAME)
+# define gl_rwlock_unlock(NAME) \
+ glthread_rwlock_unlock (&NAME)
+# define gl_rwlock_destroy(NAME) \
+ glthread_rwlock_destroy (&NAME)
+extern void glthread_rwlock_init (gl_rwlock_t *lock);
+extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
+extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* The Win32 documentation says that CRITICAL_SECTION already implements a
+ recursive lock. But we need not rely on it: It's easy to implement a
+ recursive lock without this assumption. */
+
+typedef struct
+ {
+ gl_spinlock_t guard; /* protects the initialization */
+ DWORD owner;
+ unsigned long depth;
+ CRITICAL_SECTION lock;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { { 0, -1 }, 0, 0 }
+# define gl_recursive_lock_init(NAME) \
+ glthread_recursive_lock_init (&NAME)
+# define gl_recursive_lock_lock(NAME) \
+ glthread_recursive_lock_lock (&NAME)
+# define gl_recursive_lock_unlock(NAME) \
+ glthread_recursive_lock_unlock (&NAME)
+# define gl_recursive_lock_destroy(NAME) \
+ glthread_recursive_lock_destroy (&NAME)
+extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
+extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef struct
+ {
+ volatile int inited;
+ volatile long started;
+ CRITICAL_SECTION lock;
+ }
+ gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_once_t NAME = { -1, -1 };
+# define gl_once(NAME, INITFUNCTION) \
+ glthread_once (&NAME, INITFUNCTION)
+extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
+
+#endif
+
+/* ========================================================================= */
+
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+
+/* Provide dummy implementation if threads are not supported. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef int gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME)
+# define gl_lock_define_initialized(STORAGECLASS, NAME)
+# define gl_lock_init(NAME)
+# define gl_lock_lock(NAME)
+# define gl_lock_unlock(NAME)
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef int gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME)
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
+# define gl_rwlock_init(NAME)
+# define gl_rwlock_rdlock(NAME)
+# define gl_rwlock_wrlock(NAME)
+# define gl_rwlock_unlock(NAME)
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+typedef int gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME)
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
+# define gl_recursive_lock_init(NAME)
+# define gl_recursive_lock_lock(NAME)
+# define gl_recursive_lock_unlock(NAME)
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef int gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_once_t NAME = 0;
+# define gl_once(NAME, INITFUNCTION) \
+ do \
+ { \
+ if (NAME == 0) \
+ { \
+ NAME = ~ 0; \
+ INITFUNCTION (); \
+ } \
+ } \
+ while (0)
+
+#endif
+
+/* ========================================================================= */
+
+#endif /* _LOCK_H */
diff --git a/intl/version.c b/intl/version.c
new file mode 100644
index 000000000..a968cf746
--- /dev/null
+++ b/intl/version.c
@@ -0,0 +1,26 @@
+/* libintl library version.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libgnuintl.h"
+
+/* Version number: (major<<16) + (minor<<8) + subminor */
+int libintl_version = LIBINTL_VERSION;