Added missing files.
authorWerner Koch <wk@gnupg.org>
Wed, 13 Dec 2006 16:49:10 +0000 (16:49 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 13 Dec 2006 16:49:10 +0000 (16:49 +0000)
Changed direntry in gnupg.texi from gpg to gpg2.

14 files changed:
TODO
doc/gnupg.texi
doc/gpgv.texi [new file with mode: 0644]
intl/export.h [new file with mode: 0644]
intl/hash-string.c [new file with mode: 0644]
intl/intl-exports.c [new file with mode: 0644]
intl/langprefs.c [new file with mode: 0644]
intl/lock.c [new file with mode: 0644]
intl/lock.h [new file with mode: 0644]
intl/version.c [new file with mode: 0644]
m4/glibc2.m4 [new file with mode: 0644]
m4/libusb.m4 [new file with mode: 0644]
m4/lock.m4 [new file with mode: 0644]
m4/visibility.m4 [new file with mode: 0644]

diff --git a/TODO b/TODO
index 6d2d2f5..39e55fc 100644 (file)
--- a/TODO
+++ b/TODO
 * Extend selinux support to other modules
 
 * Remove -sat PGP2 compatibility hack
+
+* gnupg14/mpi: rsa_verify
+  Is this is optimized for a 160 bit hash?
+
+* Cleanup m4/ on next gettext update
+  There is at least one couple of duplicate files: inttype[_-]h.m4.
index 7ba0c0d..69771f1 100644 (file)
@@ -48,7 +48,7 @@ section entitled ``Copying''.
 
 @dircategory GNU Utilities
 @direntry
-* gpg: (gnupg).            OpenPGP encryption and signing tool.
+* gpg2: (gnupg).           OpenPGP encryption and signing tool.
 * gpgsm: (gnupg).          S/MIME encryption and signing tool.
 @end direntry
 
diff --git a/doc/gpgv.texi b/doc/gpgv.texi
new file mode 100644 (file)
index 0000000..5a9f297
--- /dev/null
@@ -0,0 +1,162 @@
+@c Copyright (C) 2004 Free Software Foundation, Inc.
+@c This is part of the GnuPG manual.
+@c For copying conditions, see the file GnuPG.texi.
+
+@c
+@c This is included by tools.texi.
+@c
+
+@c Begin GnuPG 1.x specific stuff
+@ifset gpgone
+@macro gpgvname
+gpgv
+@end macro
+@manpage gpgv.1
+@node gpgv
+@section Verify OpenPGP signatures
+@ifset manverb
+.B gpgv
+\- Verify OpenPGP signatures
+@end ifset
+
+@mansect synopsis
+@ifset manverb
+.B  gpgv
+.RI [ options ]
+.I signed_files
+@end ifset
+@end ifset
+@c End GnuPG 1.x specific stuff
+
+@c Begin GnuPG 2 specific stuff
+@ifclear gpgone
+@macro gpgvname
+gpgv2
+@end macro
+@manpage gpgv2.1
+@node gpgv
+@section Verify OpenPGP signatures
+@ifset manverb
+.B gpgv2
+\- Verify OpenPGP signatures
+@end ifset
+
+@mansect synopsis
+@ifset manverb
+.B  gpgv2
+.RI [ options ]
+.I signed_files
+@end ifset
+@end ifclear
+@c End GnuPG 2 specific stuff
+
+
+
+@mansect description
+@code{@gpgvname} is an OpenPGP signature verification tool.
+
+This program is actually a stripped down version of @code{gpg} which is
+only able to check signatures. It is somewhat smaller than the fully blown
+@code{gpg} and uses a different (and simpler) way to check that
+the public keys used to make the signature are valid. There are
+no configuration files and only a few options are implemented.
+
+@code{@gpgvname} assumes that all keys in the keyring are trustworthy.
+By default it uses a keyring named @file{trustedkeys.gpg} which is
+assumed to be in the home directory as defined by GnuPG or set by an
+option or an environment variable. An option may be used to specify
+another keyring or even multiple keyrings.
+
+@noindent
+@mansect options
+@code{@gpgvname} recognizes these options:
+
+@table @gnupgtabopt
+
+@item --verbose
+@itemx -v
+@opindex verbose
+Gives more information during processing. If used
+twice, the input data is listed in detail.
+
+@item --quiet
+@itemx -q
+@opindex quiet
+Try to be as quiet as possible.
+
+@item --keyring @var{file}
+@opindex keyring
+Add @var{file} to the list of keyrings.
+If @var{file} begins with a tilde and a slash, these
+are replaced by the HOME directory. If the filename
+does not contain a slash, it is assumed to be in the
+home-directory ("~/.gnupg" if --homedir is not used).
+
+@item --status-fd @var{n}
+@opindex status-fd
+Write special status strings to the file descriptor @var{n}.  See the
+file DETAILS in the documentation for a listing of them.
+
+@item --logger-fd @code{n}
+@opindex logger-fd
+Write log output to file descriptor @code{n} and not to stderr.
+
+@item --ignore-time-conflict
+@opindex ignore-time-conflict
+GnuPG normally checks that the timestamps associated with keys and
+signatures have plausible values. However, sometimes a signature seems to
+be older than the key due to clock problems. This option turns these
+checks into warnings.
+
+@include opt-homedir.texi
+
+@end table
+
+@mansect return value
+
+The program returns 0 if everything was fine, 1 if at least
+one signature was bad, and other error codes for fatal errors.
+
+@mansect examples
+@subsection Examples
+
+@table @asis
+
+@item @gpgvname @code{pgpfile}
+@itemx @gpgvname @code{sigfile} 
+Verify the signature of the file. The second form
+is used for detached signatures, where @code{sigfile} is the detached
+signature (either ASCII armored or binary) and are the signed
+data; if this is not given the name of the file holding the signed data is
+constructed by cutting off the extension (".asc", ".sig" or ".sign") from
+@code{sigfile}.
+
+@end table
+
+@mansect environment
+@subsection Environment
+
+@table @asis
+
+@item HOME
+Used to locate the default home directory.
+
+@item GNUPGHOME
+If set directory used instead of "~/.gnupg".
+
+@end table
+
+@mansect files
+@subsection FILES
+
+@table @asis
+
+@item ~/.gnupg/trustedkeys.gpg
+The default keyring with the allowed keys
+
+@end table
+
+@mansect see also
+@command{gpg2}(1)
+@include see-also-note.texi
+
diff --git a/intl/export.h b/intl/export.h
new file mode 100644 (file)
index 0000000..b5c47ad
--- /dev/null
@@ -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 (file)
index 0000000..3c513f0
--- /dev/null
@@ -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 (file)
index 0000000..7176589
--- /dev/null
@@ -0,0 +1,36 @@
+/* List of exported symbols of libintl on Cygwin.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 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 (file)
index 0000000..5436040
--- /dev/null
@@ -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 <bruno@clisp.org>.  */
+
+#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 (file)
index 0000000..a860459
--- /dev/null
@@ -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 <bruno@clisp.org>, 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 (file)
index 0000000..be99139
--- /dev/null
@@ -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 <bruno@clisp.org>, 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 (file)
index 0000000..a968cf7
--- /dev/null
@@ -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;
diff --git a/m4/glibc2.m4 b/m4/glibc2.m4
new file mode 100644 (file)
index 0000000..e8f5bfe
--- /dev/null
@@ -0,0 +1,30 @@
+# glibc2.m4 serial 1
+dnl Copyright (C) 2000-2002, 2004 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.
+
+# Test for the GNU C Library, version 2.0 or newer.
+# From Bruno Haible.
+
+AC_DEFUN([gt_GLIBC2],
+  [
+    AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer,
+      ac_cv_gnu_library_2,
+      [AC_EGREP_CPP([Lucky GNU user],
+       [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ >= 2)
+  Lucky GNU user
+ #endif
+#endif
+       ],
+       ac_cv_gnu_library_2=yes,
+       ac_cv_gnu_library_2=no)
+      ]
+    )
+    AC_SUBST(GLIBC2)
+    GLIBC2="$ac_cv_gnu_library_2"
+  ]
+)
diff --git a/m4/libusb.m4 b/m4/libusb.m4
new file mode 100644 (file)
index 0000000..809dc1d
--- /dev/null
@@ -0,0 +1,69 @@
+dnl Check for libusb
+dnl Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+dnl
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl Defines HAVE_LIBUSB to 1 if a working libusb setup is found, and sets
+dnl @LIBUSB@ to the necessary libraries.  HAVE_USB_GET_BUSSES is set if
+dnl usb_get_busses() exists.
+
+AC_DEFUN([GNUPG_CHECK_LIBUSB],
+[
+  AC_ARG_WITH(libusb,
+     AC_HELP_STRING([--with-libusb=DIR],
+       [look for the libusb library in DIR]),
+     [_do_libusb=$withval],[_do_libusb=yes])
+
+  if test "$_do_libusb" != "no" ; then
+     if test -d "$withval" ; then
+        CPPFLAGS="${CPPFLAGS} -I$withval/include"
+        LDFLAGS="${LDFLAGS} -L$withval/lib"
+        AC_PATH_PROG([_usb_config],["$_do_libusb/bin/libusb-config"])
+     else
+        AC_PATH_PROG([_usb_config],[libusb-config])
+     fi
+
+     _libusb_save_libs=$LIBS
+     _libusb_save_cflags=$CFLAGS
+
+     if test x$_usb_config != "x" ; then
+        _libusb_try_libs=`$LIBS $_usb_config --libs`
+        _libusb_try_cflags=`$LIBS $_usb_config --cflags`
+     else
+        _libusb_try_libs="-lusb"
+        _libusb_try_cflags=""
+     fi
+
+     LIBS="$LIBS $_libusb_try_libs"
+     CFLAGS="$CFLAGS $_libusb_try_cflags"
+
+     AC_MSG_CHECKING([whether libusb is present and sane])
+
+     AC_LINK_IFELSE(AC_LANG_PROGRAM([#include <usb.h>],[
+usb_bulk_write(NULL,0,NULL,0,0);
+]),_found_libusb=yes,_found_libusb=no)
+
+     AC_MSG_RESULT([$_found_libusb])
+
+     if test $_found_libusb = yes ; then
+        AC_DEFINE(HAVE_LIBUSB,1,
+          [Define to 1 if you have a fully functional libusb library.])
+        AC_SUBST(LIBUSB_CPPFLAGS,$_libusb_try_cflags)
+        AC_SUBST(LIBUSB,$_libusb_try_libs)
+        AC_CHECK_FUNCS(usb_get_busses)
+     fi
+
+     LIBS=$_libusb_save_libs
+     CFLAGS=$_libusb_save_cflags
+
+     unset _libusb_save_libs
+     unset _libusb_save_cflags
+     unset _libusb_try_libs
+     unset _libusb_try_cflags
+     unset _found_libusb
+  fi
+])dnl
diff --git a/m4/lock.m4 b/m4/lock.m4
new file mode 100644 (file)
index 0000000..d1ea1ca
--- /dev/null
@@ -0,0 +1,289 @@
+# lock.m4 serial 2 (gettext-0.15)
+dnl Copyright (C) 2005 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.
+
+dnl From Bruno Haible.
+
+dnl Tests for a multithreading library to be used.
+dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS,
+dnl USE_PTH_THREADS, USE_WIN32_THREADS
+dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use
+dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with
+dnl libtool).
+dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for
+dnl programs that really need multithread functionality. The difference
+dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak
+dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread".
+dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for
+dnl multithread-safe programs.
+
+AC_DEFUN([gl_LOCK],
+[
+  AC_REQUIRE([gl_LOCK_BODY])
+])
+
+dnl The guts of gl_LOCK. Needs to be expanded only once.
+
+AC_DEFUN([gl_LOCK_BODY],
+[
+  dnl Ordering constraints: This macro modifies CPPFLAGS in a way that
+  dnl influences the result of the autoconf tests that test for *_unlocked
+  dnl declarations, on AIX 5 at least. Therefore it must come early.
+  AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl
+  AC_BEFORE([$0], [gl_ARGP])dnl
+
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([AC_GNU_SOURCE]) dnl needed for pthread_rwlock_t on glibc systems
+  dnl Check for multithreading.
+  AC_ARG_ENABLE(threads,
+AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API])
+AC_HELP_STRING([--disable-threads], [build without multithread safety]),
+    gl_use_threads=$enableval, gl_use_threads=yes)
+  gl_threads_api=none
+  LIBTHREAD=
+  LTLIBTHREAD=
+  LIBMULTITHREAD=
+  LTLIBMULTITHREAD=
+  if test "$gl_use_threads" != no; then
+    dnl Check whether the compiler and linker support weak declarations.
+    AC_MSG_CHECKING([whether imported symbols can be declared weak])
+    gl_have_weak=no
+    AC_TRY_LINK([extern void xyzzy ();
+#pragma weak xyzzy], [xyzzy();], [gl_have_weak=yes])
+    AC_MSG_RESULT([$gl_have_weak])
+    if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
+      # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that
+      # it groks <pthread.h>.
+      gl_save_CPPFLAGS="$CPPFLAGS"
+      CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+      AC_CHECK_HEADER(pthread.h, gl_have_pthread_h=yes, gl_have_pthread_h=no)
+      CPPFLAGS="$gl_save_CPPFLAGS"
+      if test "$gl_have_pthread_h" = yes; then
+        # Other possible tests:
+        #   -lpthreads (FSU threads, PCthreads)
+        #   -lgthreads
+        case "$host_os" in
+          osf*)
+            # On OSF/1, the compiler needs the flag -D_REENTRANT so that it
+            # groks <pthread.h>. cc also understands the flag -pthread, but
+            # we don't use it because 1. gcc-2.95 doesn't understand -pthread,
+            # 2. putting a flag into CPPFLAGS that has an effect on the linker
+            # causes the AC_TRY_LINK test below to succeed unexpectedly,
+            # leading to wrong values of LIBTHREAD and LTLIBTHREAD.
+            CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+            ;;
+        esac
+        gl_have_pthread=
+        # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist
+        # in libc. IRIX 6.5 has the first one in both libc and libpthread, but
+        # the second one only in libpthread, and lock.c needs it.
+        AC_TRY_LINK([#include <pthread.h>],
+          [pthread_mutex_lock((pthread_mutex_t*)0);
+           pthread_mutexattr_init((pthread_mutexattr_t*)0);],
+          [gl_have_pthread=yes])
+        # Test for libpthread by looking for pthread_kill. (Not pthread_self,
+        # since it is defined as a macro on OSF/1.)
+        if test -n "$gl_have_pthread"; then
+          # The program links fine without libpthread. But it may actually
+          # need to link with libpthread in order to create multiple threads.
+          AC_CHECK_LIB(pthread, pthread_kill,
+            [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread
+             # On Solaris and HP-UX, most pthread functions exist also in libc.
+             # Therefore pthread_in_use() needs to actually try to create a
+             # thread: pthread_create from libc will fail, whereas
+             # pthread_create will actually create a thread.
+             case "$host_os" in
+               solaris* | hpux*)
+                 AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], 1,
+                   [Define if the pthread_in_use() detection is hard.])
+             esac
+            ])
+        else
+          # Some library is needed. Try libpthread and libc_r.
+          AC_CHECK_LIB(pthread, pthread_kill,
+            [gl_have_pthread=yes
+             LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread
+             LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread])
+          if test -z "$gl_have_pthread"; then
+            # For FreeBSD 4.
+            AC_CHECK_LIB(c_r, pthread_kill,
+              [gl_have_pthread=yes
+               LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r
+               LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r])
+          fi
+        fi
+        if test -n "$gl_have_pthread"; then
+          gl_threads_api=posix
+          AC_DEFINE([USE_POSIX_THREADS], 1,
+            [Define if the POSIX multithreading library can be used.])
+          if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
+            if test $gl_have_weak = yes; then
+              AC_DEFINE([USE_POSIX_THREADS_WEAK], 1,
+                [Define if references to the POSIX multithreading library should be made weak.])
+              LIBTHREAD=
+              LTLIBTHREAD=
+            fi
+          fi
+          # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the
+          # pthread_rwlock_* functions.
+          AC_CHECK_TYPE([pthread_rwlock_t],
+            [AC_DEFINE([HAVE_PTHREAD_RWLOCK], 1,
+               [Define if the POSIX multithreading library has read/write locks.])],
+            [],
+            [#include <pthread.h>])
+          # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro.
+          AC_TRY_COMPILE([#include <pthread.h>],
+            [#if __FreeBSD__ == 4
+error "No, in FreeBSD 4.0 recursive mutexes actually don't work."
+#else
+int x = (int)PTHREAD_MUTEX_RECURSIVE;
+#endif],
+            [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1,
+               [Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE.])])
+          # Some systems optimize for single-threaded programs by default, and
+          # need special flags to disable these optimizations. For example, the
+          # definition of 'errno' in <errno.h>.
+          case "$host_os" in
+            aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;;
+            solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;;
+          esac
+        fi
+      fi
+    fi
+    if test -z "$gl_have_pthread"; then
+      if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then
+        gl_have_solaristhread=
+        gl_save_LIBS="$LIBS"
+        LIBS="$LIBS -lthread"
+        AC_TRY_LINK([#include <thread.h>
+#include <synch.h>],
+          [thr_self();],
+          [gl_have_solaristhread=yes])
+        LIBS="$gl_save_LIBS"
+        if test -n "$gl_have_solaristhread"; then
+          gl_threads_api=solaris
+          LIBTHREAD=-lthread
+          LTLIBTHREAD=-lthread
+          LIBMULTITHREAD="$LIBTHREAD"
+          LTLIBMULTITHREAD="$LTLIBTHREAD"
+          AC_DEFINE([USE_SOLARIS_THREADS], 1,
+            [Define if the old Solaris multithreading library can be used.])
+          if test $gl_have_weak = yes; then
+            AC_DEFINE([USE_SOLARIS_THREADS_WEAK], 1,
+              [Define if references to the old Solaris multithreading library should be made weak.])
+            LIBTHREAD=
+            LTLIBTHREAD=
+          fi
+        fi
+      fi
+    fi
+    if test "$gl_use_threads" = pth; then
+      gl_save_CPPFLAGS="$CPPFLAGS"
+      AC_LIB_LINKFLAGS(pth)
+      gl_have_pth=
+      gl_save_LIBS="$LIBS"
+      LIBS="$LIBS -lpth"
+      AC_TRY_LINK([#include <pth.h>], [pth_self();], gl_have_pth=yes)
+      LIBS="$gl_save_LIBS"
+      if test -n "$gl_have_pth"; then
+        gl_threads_api=pth
+        LIBTHREAD="$LIBPTH"
+        LTLIBTHREAD="$LTLIBPTH"
+        LIBMULTITHREAD="$LIBTHREAD"
+        LTLIBMULTITHREAD="$LTLIBTHREAD"
+        AC_DEFINE([USE_PTH_THREADS], 1,
+          [Define if the GNU Pth multithreading library can be used.])
+        if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
+          if test $gl_have_weak = yes; then
+            AC_DEFINE([USE_PTH_THREADS_WEAK], 1,
+              [Define if references to the GNU Pth multithreading library should be made weak.])
+            LIBTHREAD=
+            LTLIBTHREAD=
+          fi
+        fi
+      else
+        CPPFLAGS="$gl_save_CPPFLAGS"
+      fi
+    fi
+    if test -z "$gl_have_pthread"; then
+      if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then
+        if { case "$host_os" in
+               mingw*) true;;
+               *) false;;
+             esac
+           }; then
+          gl_threads_api=win32
+          AC_DEFINE([USE_WIN32_THREADS], 1,
+            [Define if the Win32 multithreading API can be used.])
+        fi
+      fi
+    fi
+  fi
+  AC_MSG_CHECKING([for multithread API to use])
+  AC_MSG_RESULT([$gl_threads_api])
+  AC_SUBST(LIBTHREAD)
+  AC_SUBST(LTLIBTHREAD)
+  AC_SUBST(LIBMULTITHREAD)
+  AC_SUBST(LTLIBMULTITHREAD)
+  gl_PREREQ_LOCK
+])
+
+# Prerequisites of lib/lock.c.
+AC_DEFUN([gl_PREREQ_LOCK], [
+  AC_REQUIRE([AC_C_INLINE])
+])
+
+dnl Survey of platforms:
+dnl
+dnl Platform          Available   Compiler    Supports   test-lock
+dnl                   flavours    option      weak       result
+dnl ---------------   ---------   ---------   --------   ---------
+dnl Linux 2.4/glibc   posix       -lpthread       Y      OK
+dnl
+dnl GNU Hurd/glibc    posix
+dnl
+dnl FreeBSD 5.3       posix       -lc_r           Y
+dnl                   posix       -lkse ?         Y
+dnl                   posix       -lpthread ?     Y
+dnl                   posix       -lthr           Y
+dnl
+dnl FreeBSD 5.2       posix       -lc_r           Y
+dnl                   posix       -lkse           Y
+dnl                   posix       -lthr           Y
+dnl
+dnl FreeBSD 4.0,4.10  posix       -lc_r           Y      OK
+dnl
+dnl NetBSD 1.6        --
+dnl
+dnl OpenBSD 3.4       posix       -lpthread       Y      OK
+dnl
+dnl MacOS X 10.[123]  posix       -lpthread       Y      OK
+dnl
+dnl Solaris 7,8,9     posix       -lpthread       Y      Sol 7,8: 0.0; Sol 9: OK
+dnl                   solaris     -lthread        Y      Sol 7,8: 0.0; Sol 9: OK
+dnl
+dnl HP-UX 11          posix       -lpthread       N (cc) OK
+dnl                                               Y (gcc)
+dnl
+dnl IRIX 6.5          posix       -lpthread       Y      0.5
+dnl
+dnl AIX 4.3,5.1       posix       -lpthread       N      AIX 4: 0.5; AIX 5: OK
+dnl
+dnl OSF/1 4.0,5.1     posix       -pthread (cc)   N      OK
+dnl                               -lpthread (gcc) Y
+dnl
+dnl Cygwin            posix       -lpthread       Y      OK
+dnl
+dnl Any of the above  pth         -lpth                  0.0
+dnl
+dnl Mingw             win32                       N      OK
+dnl
+dnl BeOS 5            --
+dnl
+dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is
+dnl turned off:
+dnl   OK if all three tests terminate OK,
+dnl   0.5 if the first test terminates OK but the second one loops endlessly,
+dnl   0.0 if the first test already loops endlessly.
diff --git a/m4/visibility.m4 b/m4/visibility.m4
new file mode 100644 (file)
index 0000000..2ff6330
--- /dev/null
@@ -0,0 +1,52 @@
+# visibility.m4 serial 1 (gettext-0.15)
+dnl Copyright (C) 2005 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.
+
+dnl From Bruno Haible.
+
+dnl Tests whether the compiler supports the command-line option
+dnl -fvisibility=hidden and the function and variable attributes
+dnl __attribute__((__visibility__("hidden"))) and
+dnl __attribute__((__visibility__("default"))).
+dnl Does *not* test for __visibility__("protected") - which has tricky
+dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on
+dnl MacOS X.
+dnl Does *not* test for __visibility__("internal") - which has processor
+dnl dependent semantics.
+dnl Does *not* test for #pragma GCC visibility push(hidden) - which is
+dnl "really only recommended for legacy code".
+dnl Set the variable CFLAG_VISIBILITY.
+dnl Defines and sets the variable HAVE_VISIBILITY.
+
+AC_DEFUN([gl_VISIBILITY],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  CFLAG_VISIBILITY=
+  HAVE_VISIBILITY=0
+  if test -n "$GCC"; then
+    AC_MSG_CHECKING([for simple visibility declarations])
+    AC_CACHE_VAL(gl_cv_cc_visibility, [
+      gl_save_CFLAGS="$CFLAGS"
+      CFLAGS="$CFLAGS -fvisibility=hidden"
+      AC_TRY_COMPILE(
+        [extern __attribute__((__visibility__("hidden"))) int hiddenvar;
+         extern __attribute__((__visibility__("default"))) int exportedvar;
+         extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
+         extern __attribute__((__visibility__("default"))) int exportedfunc (void);],
+        [],
+        gl_cv_cc_visibility=yes,
+        gl_cv_cc_visibility=no)
+      CFLAGS="$gl_save_CFLAGS"])
+    AC_MSG_RESULT([$gl_cv_cc_visibility])
+    if test $gl_cv_cc_visibility = yes; then
+      CFLAG_VISIBILITY="-fvisibility=hidden"
+      HAVE_VISIBILITY=1
+    fi
+  fi
+  AC_SUBST([CFLAG_VISIBILITY])
+  AC_SUBST([HAVE_VISIBILITY])
+  AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
+    [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.])
+])