From: Bruno Haible Date: Thu, 18 May 2017 23:15:33 +0000 (+0200) Subject: Update gettext-runtime files from gnulib. X-Git-Tag: v0.20~462 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e43b2c6c4e18d0bacdf9937a4c2f4af2a471836;p=thirdparty%2Fgettext.git Update gettext-runtime files from gnulib. * Makefile.am (distcheck-hook): Check also flexmember.m4, flexmember.h. * gettext-runtime/intl/Makefile.in (SOURCES): Add flexmember.h. * gettext-runtime/intl/flexmember.h: New file, from gnulib. * gettext-runtime/intl/localcharset.c: * localcharset.c (relocate2): Define fallback. (get_charset_aliases): Invoke relocate2 instead of relocate. Free the allocated memory. * localcharset.c (WINDOWS_NATIVE): Don't define on Cygwin. * localcharset.c (locale_charset) [WINDOWS_NATIVE]: Don't use the return value from setlocale if it would lead to a buffer overrun. * gettext-runtime/intl/localename.c: * localename.c [__CYGWIN__]: Include , since this is where NL_LOCALE_NAME is defined. * localename.c (WINDOWS_NATIVE): Don't define on Cygwin. * localename.c (gl_locale_name_thread_unsafe): Add clause for Cygwin. * localename.c (struct hash_node): Use FLEXIBLE_ARRAY_MEMBER. * gettext-runtime/intl/lock.c: * lock.c: On glibc systems without PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, use the fallback implementation of rwlocks. * lock.c [USE_POSIX_THREADS] (glthread_rwlock_init_for_glibc): New function. [USE_POSIX_THREADS] (glthread_rwlock_rdlock_multithreaded): Update comment. [USE_PTH_THREADS]: New implementation of rwlocks. [USE_WINDOWS_THREADS] (glthread_rwlock_rdlock_func): Prefer writers over readers. * gettext-runtime/intl/lock.h: * lock.h (pthread_rwlockattr_setkind_np): Don't declare weak on non-glibc platforms. * lock.h: On glibc systems without PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, use the fallback implementation of rwlocks. * lock.h [USE_POSIX_THREADS_WEAK]: Declare also pthread_rwlockattr_init, pthread_rwlockattr_setkind_np, pthread_rwlockattr_destroy weak. * lock.h [USE_POSIX_THREADS]: Test HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER. Use a different implementation of rwlock initialization on glibc systems without HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER. Use a different implementation of rwlocks altogether on non-glibc systems without HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER. [USE_PTH_THREADS]: Use a different implementation of rwlocks altogether. * gettext-runtime/intl/relocatable.c: * relocatable.c (relocate2): New function. * relocatable.c (relocate): Assume pathname is non-NULL. Use ISSLASH macro consistently. Avoid dangerous string concatenation idiom. * gettext-runtime/intl/relocatable.h: * relocatable.h (relocate2): New declaration/macro. * gettext-runtime/intl/vasnprintf.c, gettext-runtime/libasprintf/vasnprintf.c: * vasnprintf.c (FALLTHROUGH): New macro. Use it whenever one switch case falls through into the next. * vasnprintf.c (USE_MSVC__SNPRINTF): New macro. Everywhere, use !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF instead of !HAVE_SNPRINTF_RETVAL_C99. * vasnprintf.c (VASNPRINTF): Move comment down past two cpp directives, so that it takes effect once again. This is clearly not a proper change, and I will revert it once this bug is fixed: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77817 * vasnprintf.c (IF_LINT): Treat GCC_LINT like lint. * gettext-runtime/intl/verify.h: * verify.h (verify) [!__GNUC__]: Use shorter albeit meaningless string to bypass silly compiler limits. * verify.h (assume): Treat GCC_LINT like lint. * gettext-runtime/intl/xsize.h: Update. * gettext-runtime/m4/Makefile.am (EXTRA_DIST): Add flexmember.m4. * gettext-runtime/m4/extern-inline.m4: Update. * gettext-runtime/m4/fcntl-o.m4: Update. * gettext-runtime/m4/flexmember.m4: New file, from gnulib. * gettext-runtime/m4/glibc2.m4: Update. * gettext-runtime/m4/glibc21.m4: Update. * gettext-runtime/m4/intdiv0.m4: Update. * gettext-runtime/m4/intl.m4 (AM_INTL_SUBDIR): Require AC_C_FLEXIBLE_ARRAY_MEMBER. * gettext-runtime/m4/intmax.m4: Update. * gettext-runtime/m4/inttypes-pri.m4: Update. * gettext-runtime/m4/inttypes_h.m4: Update. * gettext-runtime/m4/lock.m4 (gl_LOCK): Invoke gl_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER. * gettext-runtime/m4/longlong.m4: Update. * gettext-runtime/m4/printf-posix.m4: Update. * gettext-runtime/m4/progtest.m4: Update. * gettext-runtime/m4/size_max.m4: Update. * gettext-runtime/m4/stdint_h.m4: Update. * gettext-runtime/m4/threadlib.m4 (gl_THREADLIB_BODY): Don't set PTHREAD_IN_USE_DETECTION_HARD if configuring on Solaris 10 or newer. Reported by Peter Felecan at . * gettext-runtime/m4/uintmax_t.m4: Update. * gettext-runtime/m4/visibility.m4: Update. * gettext-runtime/m4/wchar_t.m4: Update. * gettext-runtime/m4/xsize.m4: Update. * gettext-runtime/tests/test-lock.c: * test-lock.c: On Mac OS X, use named semaphores, not unnamed semaphores. (USE_NAMED_SEMAPHORE, USE_UNNAMED_SEMAPHORE): New macros. (atomic_int_semaphore): New macro. * test-lock.c (USE_SEMAPHORE): Don't set if does not exist. * test-lock.c (USE_SEMAPHORE): New constant. (struct atomic_int, init_atomic_int, get_atomic_int_value, set_atomic_int_value) [USE_SEMAPHORE]: Define using a POSIX semaphore. Suggested by Torvald Riegel . --- diff --git a/Makefile.am b/Makefile.am index 0d8276daf..b92defda0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ ## Makefile for the toplevel directory of GNU gettext -## Copyright (C) 1995-2016 Free Software Foundation, Inc. +## Copyright (C) 1995-2017 Free Software Foundation, Inc. ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -73,6 +73,7 @@ distcheck-hook: cmp -s gettext-runtime/m4/codeset.m4 gettext-tools/gnulib-m4/codeset.m4 cmp -s gettext-runtime/m4/extern-inline.m4 gettext-tools/gnulib-m4/extern-inline.m4 cmp -s gettext-runtime/m4/fcntl-o.m4 gettext-tools/gnulib-m4/fcntl-o.m4 + cmp -s gettext-runtime/m4/flexmember.m4 gettext-tools/gnulib-m4/flexmember.m4 cmp -s gettext-runtime/m4/gettext.m4 gettext-tools/gnulib-m4/gettext.m4 cmp -s gettext-runtime/m4/glibc2.m4 gettext-tools/gnulib-m4/glibc2.m4 cmp -s gettext-runtime/m4/glibc21.m4 gettext-tools/gnulib-m4/glibc21.m4 @@ -102,6 +103,7 @@ distcheck-hook: cmp -s gettext-runtime/m4/xsize.m4 gettext-tools/gnulib-m4/xsize.m4 cmp -s gettext-runtime/libasprintf/gnulib-m4/intmax_t.m4 gettext-tools/gnulib-m4/intmax_t.m4 test "`sed 1,17d gettext-runtime/intl/config.charset | md5sum`" = "`sed 1,17d gettext-tools/gnulib-lib/config.charset | md5sum`" + test "`sed 1,16d gettext-runtime/intl/flexmember.h | md5sum`" = "`sed 1,16d gettext-tools/gnulib-lib/flexmember.h | md5sum`" test "`sed 1,16d gettext-runtime/intl/localcharset.h | md5sum`" = "`sed 1,16d gettext-tools/gnulib-lib/localcharset.h | md5sum`" test "`sed 1,16d gettext-runtime/intl/localcharset.c | md5sum`" = "`sed 1,16d gettext-tools/gnulib-lib/localcharset.c | md5sum`" test "`sed 1,16d gettext-runtime/intl/localename.c | md5sum`" = "`sed 1,16d gettext-tools/gnulib-lib/localename.c | md5sum`" diff --git a/gettext-runtime/intl/Makefile.in b/gettext-runtime/intl/Makefile.in index 3f2b185be..1422bcc22 100644 --- a/gettext-runtime/intl/Makefile.in +++ b/gettext-runtime/intl/Makefile.in @@ -158,6 +158,7 @@ SOURCES = \ relocatable.c \ langprefs.c \ localename.c \ + flexmember.h \ log.c \ printf.c \ setlocale.c \ diff --git a/gettext-runtime/intl/flexmember.h b/gettext-runtime/intl/flexmember.h new file mode 100644 index 000000000..56350a76f --- /dev/null +++ b/gettext-runtime/intl/flexmember.h @@ -0,0 +1,42 @@ +/* Sizes of structs with flexible array members. + + Copyright 2016-2017 Free Software Foundation, Inc. + + This program 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. + + 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + + Written by Paul Eggert. */ + +#include + +/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below. + On older platforms without _Alignof, use a pessimistic bound that is + safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1. + On newer platforms, use _Alignof to get a tighter bound. */ + +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 +# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1)) +#else +# define FLEXALIGNOF(type) _Alignof (type) +#endif + +/* Upper bound on the size of a struct of type TYPE with a flexible + array member named MEMBER that is followed by N bytes of other data. + This is not simply sizeof (TYPE) + N, since it may require + alignment on unusually picky C11 platforms, and + FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. + Yield a value less than N if and only if arithmetic overflow occurs. */ + +#define FLEXSIZEOF(type, member, n) \ + ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \ + & ~ (FLEXALIGNOF (type) - 1)) diff --git a/gettext-runtime/intl/localcharset.c b/gettext-runtime/intl/localcharset.c index 213e726fb..2bd741cfa 100644 --- a/gettext-runtime/intl/localcharset.c +++ b/gettext-runtime/intl/localcharset.c @@ -1,6 +1,6 @@ /* Determine a canonical name for the current locale's character encoding. - Copyright (C) 2000-2006, 2008-2015 Free Software Foundation, Inc. + Copyright (C) 2000-2006, 2008-2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -32,7 +32,7 @@ # define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */ #endif -#if defined _WIN32 || defined __WIN32__ +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ # define WINDOWS_NATIVE # include #endif @@ -75,6 +75,7 @@ # include "relocatable.h" #else # define relocate(pathname) (pathname) +# define relocate2(pathname,allocatedp) (*(allocatedp) = NULL, (pathname)) #endif /* Get LIBDIR. */ @@ -129,6 +130,7 @@ get_charset_aliases (void) if (cp == NULL) { #if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__ || defined OS2) + char *malloc_dir = NULL; const char *dir; const char *base = "charset.alias"; char *file_name; @@ -137,7 +139,7 @@ get_charset_aliases (void) necessary for running the testsuite before "make install". */ dir = getenv ("CHARSETALIASDIR"); if (dir == NULL || dir[0] == '\0') - dir = relocate (LIBDIR); + dir = relocate2 (LIBDIR, &malloc_dir); /* Concatenate dir and base into freshly allocated file_name. */ { @@ -154,6 +156,8 @@ get_charset_aliases (void) } } + free (malloc_dir); + if (file_name == NULL) /* Out of memory. Treat the file as empty. */ cp = ""; @@ -507,7 +511,7 @@ locale_charset (void) current_locale = setlocale (LC_CTYPE, NULL); pdot = strrchr (current_locale, '.'); - if (pdot) + if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) sprintf (buf, "CP%s", pdot + 1); else { diff --git a/gettext-runtime/intl/localename.c b/gettext-runtime/intl/localename.c index 81ab21304..eb0755c6d 100644 --- a/gettext-runtime/intl/localename.c +++ b/gettext-runtime/intl/localename.c @@ -1,5 +1,5 @@ /* Determine name of the currently selected locale. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -33,12 +33,14 @@ #include #include +#include "flexmember.h" + #if HAVE_USELOCALE /* Mac OS X 10.5 defines the locale_t type in . */ # if defined __APPLE__ && defined __MACH__ # include # endif -# if __GLIBC__ >= 2 && !defined __UCLIBC__ +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || defined __CYGWIN__ # include # endif # if !defined IN_LIBINTL @@ -59,7 +61,7 @@ extern char * getlocalename_l(int, locale_t); # endif #endif -#if defined _WIN32 || defined __WIN32__ +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ # define WINDOWS_NATIVE # if !defined IN_LIBINTL # include "glthread/lock.h" @@ -2619,7 +2621,7 @@ string_hash (const void *x) struct hash_node { struct hash_node * volatile next; - char contents[100]; /* has variable size */ + char contents[FLEXIBLE_ARRAY_MEMBER]; }; # define HASH_TABLE_SIZE 257 @@ -2646,7 +2648,7 @@ struniq (const char *string) size = strlen (string) + 1; new_node = (struct hash_node *) - malloc (offsetof (struct hash_node, contents[0]) + size); + malloc (FLEXSIZEOF (struct hash_node, contents, size)); if (new_node == NULL) /* Out of memory. Return a statically allocated string. */ return "C"; @@ -2732,6 +2734,19 @@ gl_locale_name_thread_unsafe (int category, const char *categoryname) # elif defined __sun && HAVE_GETLOCALENAME_L /* Solaris >= 12. */ return getlocalename_l (category, thread_locale); +# elif defined __CYGWIN__ + /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether. + Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside + an opaque struct. */ +# ifdef NL_LOCALE_NAME + return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale); +# else + /* FIXME: Remove when we can assume new-enough Cygwin. */ + struct __locale_t { + char categories[7][32]; + }; + return ((struct __locale_t *) thread_locale)->categories[category]; +# endif # elif defined __ANDROID__ return MB_CUR_MAX == 4 ? "C.UTF-8" : "C"; # endif diff --git a/gettext-runtime/intl/lock.c b/gettext-runtime/intl/lock.c index 69d624d7d..f8784558a 100644 --- a/gettext-runtime/intl/lock.c +++ b/gettext-runtime/intl/lock.c @@ -1,5 +1,5 @@ /* Locking in multithreaded situations. - Copyright (C) 2005-2008, 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2005-2008, 2015-2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -30,9 +30,38 @@ /* ------------------------- gl_rwlock_t datatype ------------------------- */ -# if HAVE_PTHREAD_RWLOCK +# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1))) -# if !defined PTHREAD_RWLOCK_INITIALIZER +# ifdef PTHREAD_RWLOCK_INITIALIZER + +# if !HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER + /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */ + +int +glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock) +{ + pthread_rwlockattr_t attributes; + int err; + + err = pthread_rwlockattr_init (&attributes); + if (err != 0) + return err; + /* Note: PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP is the only value that + causes the writer to be preferred. PTHREAD_RWLOCK_PREFER_WRITER_NP does not + do this; see + http://man7.org/linux/man-pages/man3/pthread_rwlockattr_setkind_np.3.html */ + err = pthread_rwlockattr_setkind_np (&attributes, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); + if (err == 0) + err = pthread_rwlock_init(lock, &attributes); + /* pthread_rwlockattr_destroy always returns 0. It cannot influence the + return value. */ + pthread_rwlockattr_destroy (&attributes); + return err; +} + +# endif +# else int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) @@ -152,11 +181,9 @@ glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) if (err != 0) return err; /* 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. */ + field will not overflow, and whether no writer is waiting. The latter + condition is because POSIX recommends that "write locks shall take + precedence over read locks", to avoid "writer starvation". */ while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0)) { /* This thread has to wait for a while. Enqueue it among the @@ -481,6 +508,141 @@ glthread_once_singlethreaded (pthread_once_t *once_control) /* ------------------------- gl_rwlock_t datatype ------------------------- */ +# if !HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER + +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) +{ + if (!pth_mutex_init (&lock->lock)) + return errno; + if (!pth_cond_init (&lock->waiting_readers)) + return errno; + if (!pth_cond_init (&lock->waiting_writers)) + return errno; + lock->waiting_writers_count = 0; + lock->runcount = 0; + lock->initialized = 1; + return 0; +} + +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + glthread_rwlock_init_multithreaded (lock); + if (!pth_mutex_acquire (&lock->lock, 0, NULL)) + return errno; + /* Test whether only readers are currently running, and whether the runcount + field will not overflow, and whether no writer is waiting. The latter + condition is because POSIX recommends that "write locks shall take + precedence over read locks", to avoid "writer starvation". */ + 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 (!pth_cond_await (&lock->waiting_readers, &lock->lock, NULL)) + { + int err = errno; + pth_mutex_release (&lock->lock); + return err; + } + } + lock->runcount++; + return (!pth_mutex_release (&lock->lock) ? errno : 0); +} + +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + glthread_rwlock_init_multithreaded (lock); + if (!pth_mutex_acquire (&lock->lock, 0, NULL)) + return errno; + /* 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 (!pth_cond_await (&lock->waiting_writers, &lock->lock, NULL)) + { + int err = errno; + lock->waiting_writers_count--; + pth_mutex_release (&lock->lock); + return err; + } + lock->waiting_writers_count--; + } + lock->runcount--; /* runcount becomes -1 */ + return (!pth_mutex_release (&lock->lock) ? errno : 0); +} + +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + if (!lock->initialized) + return EINVAL; + if (!pth_mutex_acquire (&lock->lock, 0, NULL)) + return errno; + if (lock->runcount < 0) + { + /* Drop a writer lock. */ + if (!(lock->runcount == -1)) + { + pth_mutex_release (&lock->lock); + return EINVAL; + } + lock->runcount = 0; + } + else + { + /* Drop a reader lock. */ + if (!(lock->runcount > 0)) + { + pth_mutex_release (&lock->lock); + return EINVAL; + } + 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 (!pth_cond_notify (&lock->waiting_writers, FALSE)) + { + int err = errno; + pth_mutex_release (&lock->lock); + return err; + } + } + else + { + /* Wake up all waiting readers. */ + if (!pth_cond_notify (&lock->waiting_readers, TRUE)) + { + int err = errno; + pth_mutex_release (&lock->lock); + return err; + } + } + } + return (!pth_mutex_release (&lock->lock) ? errno : 0); +} + +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) +{ + lock->initialized = 0; + return 0; +} + +# endif + /* --------------------- gl_recursive_lock_t datatype --------------------- */ /* -------------------------- gl_once_t datatype -------------------------- */ @@ -796,8 +958,10 @@ glthread_rwlock_rdlock_func (gl_rwlock_t *lock) } EnterCriticalSection (&lock->lock); /* Test whether only readers are currently running, and whether the runcount - field will not overflow. */ - if (!(lock->runcount + 1 > 0)) + field will not overflow, and whether no writer is waiting. The latter + condition is because POSIX recommends that "write locks shall take + precedence over read locks", to avoid "writer starvation". */ + if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0)) { /* This thread has to wait for a while. Enqueue it among the waiting_readers. */ diff --git a/gettext-runtime/intl/lock.h b/gettext-runtime/intl/lock.h index 6b173f812..33909ec25 100644 --- a/gettext-runtime/intl/lock.h +++ b/gettext-runtime/intl/lock.h @@ -1,5 +1,5 @@ /* Locking in multithreaded situations. - Copyright (C) 2005-2008, 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2005-2008, 2015-2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -139,6 +139,11 @@ extern int glthread_in_use (void); # pragma weak pthread_mutexattr_init # pragma weak pthread_mutexattr_settype # pragma weak pthread_mutexattr_destroy +# pragma weak pthread_rwlockattr_init +# if __GNU_LIBRARY__ > 1 +# pragma weak pthread_rwlockattr_setkind_np +# endif +# pragma weak pthread_rwlockattr_destroy # ifndef pthread_self # pragma weak pthread_self # endif @@ -176,7 +181,7 @@ typedef pthread_mutex_t gl_lock_t; /* ------------------------- gl_rwlock_t datatype ------------------------- */ -# if HAVE_PTHREAD_RWLOCK +# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1))) # ifdef PTHREAD_RWLOCK_INITIALIZER @@ -185,10 +190,18 @@ typedef pthread_rwlock_t gl_rwlock_t; 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 glthread_rwlock_init(LOCK) \ - (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) +# if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER +# define gl_rwlock_initializer \ + PTHREAD_RWLOCK_INITIALIZER +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) +# else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */ +# define gl_rwlock_initializer \ + PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0) +extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock); +# endif # define glthread_rwlock_rdlock(LOCK) \ (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0) # define glthread_rwlock_wrlock(LOCK) \ @@ -427,6 +440,9 @@ typedef pth_mutex_t gl_lock_t; /* ------------------------- gl_rwlock_t datatype ------------------------- */ +/* Pth pth_rwlock_acquire always prefers readers. No autoconf test so far. */ +# if HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER + typedef pth_rwlock_t gl_rwlock_t; # define gl_rwlock_define(STORAGECLASS, NAME) \ STORAGECLASS pth_rwlock_t NAME; @@ -445,6 +461,42 @@ typedef pth_rwlock_t gl_rwlock_t; # define glthread_rwlock_destroy(LOCK) \ ((void)(LOCK), 0) +# else + +typedef struct + { + int initialized; + pth_mutex_t lock; /* protects the remaining fields */ + pth_cond_t waiting_readers; /* waiting readers */ + pth_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 \ + { 0 } +# define glthread_rwlock_init(LOCK) \ + (pth_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pth_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pth_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pth_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pth_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); + +# endif + /* --------------------- gl_recursive_lock_t datatype --------------------- */ /* In Pth, mutexes are recursive by default. */ diff --git a/gettext-runtime/intl/relocatable.c b/gettext-runtime/intl/relocatable.c index 401f3e0e4..0892e3a42 100644 --- a/gettext-runtime/intl/relocatable.c +++ b/gettext-runtime/intl/relocatable.c @@ -1,5 +1,5 @@ /* Provide relocatable packages. - Copyright (C) 2003-2006, 2008-2016 Free Software Foundation, Inc. + Copyright (C) 2003-2006, 2008-2017 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software: you can redistribute it and/or modify @@ -542,27 +542,26 @@ relocate (const char *pathname) # ifdef __KLIBC__ # undef strncmp - if (pathname && strncmp (pathname, "/@unixroot", 10) == 0 - && (pathname[10] == '\0' || pathname[10] == '/' || pathname[10] == '\\')) + if (strncmp (pathname, "/@unixroot", 10) == 0 + && (pathname[10] == '\0' || ISSLASH (pathname[10]))) { /* kLIBC itself processes /@unixroot prefix */ - return pathname; } else # endif - if (pathname && ISSLASH (pathname[0])) + if (ISSLASH (pathname[0])) { const char *unixroot = getenv ("UNIXROOT"); - if (unixroot && HAS_DEVICE (unixroot) && !unixroot[2]) + if (unixroot && HAS_DEVICE (unixroot) && unixroot[2] == '\0') { char *result = (char *) xmalloc (2 + strlen (pathname) + 1); #ifdef NO_XMALLOC if (result != NULL) #endif { - strcpy (result, unixroot); + memcpy (result, unixroot, 2); strcpy (result + 2, pathname); return result; } @@ -574,4 +573,17 @@ relocate (const char *pathname) return pathname; } +/* Returns the pathname, relocated according to the current installation + directory. + This function sets *ALLOCATEDP to the allocated memory, or to NULL if + no memory allocation occurs. So that, after you're done with the return + value, to reclaim allocated memory, you can do: free (*ALLOCATEDP). */ +const char * +relocate2 (const char *pathname, char **allocatedp) +{ + const char *result = relocate (pathname); + *allocatedp = (result != pathname ? (char *) result : NULL); + return result; +} + #endif diff --git a/gettext-runtime/intl/relocatable.h b/gettext-runtime/intl/relocatable.h index ecad3a76d..11bd9aeee 100644 --- a/gettext-runtime/intl/relocatable.h +++ b/gettext-runtime/intl/relocatable.h @@ -1,5 +1,5 @@ /* Provide relocatable packages. - Copyright (C) 2003, 2005, 2008, 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2008-2017 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software: you can redistribute it and/or modify @@ -52,10 +52,29 @@ extern RELOCATABLE_DLL_EXPORTED void string that you can free with free() after casting it to 'char *'. */ extern const char * relocate (const char *pathname); +/* Returns the pathname, relocated according to the current installation + directory. + This function sets *ALLOCATEDP to the allocated memory, or to NULL if + no memory allocation occurs. So that, after you're done with the return + value, to reclaim allocated memory, you can do: free (*ALLOCATEDP). */ +extern const char * relocate2 (const char *pathname, char **allocatedp); + /* Memory management: relocate() potentially allocates memory, because it has to construct a fresh pathname. If this is a problem because your program - calls relocate() frequently, think about caching the result. Or free the - return value if it was different from the argument pathname. */ + calls relocate() frequently or because you want to fix all potential memory + leaks anyway, you have three options: + 1) Use this idiom: + const char *pathname = ...; + const char *rel_pathname = relocate (pathname); + ... + if (rel_pathname != pathname) + free ((char *) rel_pathname); + 2) Use this idiom: + char *allocated; + const char *rel_pathname = relocate2 (..., &allocated); + ... + free (allocated); + 3) Think about caching the result. */ /* Convenience function: Computes the current installation prefix, based on the original @@ -70,6 +89,7 @@ extern char * compute_curr_prefix (const char *orig_installprefix, /* By default, we use the hardwired pathnames. */ #define relocate(pathname) (pathname) +#define relocate2(pathname,allocatedp) (*(allocatedp) = NULL, (pathname)) #endif diff --git a/gettext-runtime/intl/vasnprintf.c b/gettext-runtime/intl/vasnprintf.c index 236bfe5da..eb8f1fd81 100644 --- a/gettext-runtime/intl/vasnprintf.c +++ b/gettext-runtime/intl/vasnprintf.c @@ -1,5 +1,5 @@ /* vsprintf with automatic memory allocation. - Copyright (C) 1999, 2002-2016 Free Software Foundation, Inc. + Copyright (C) 1999, 2002-2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -118,6 +118,14 @@ # include "fpucw.h" #endif +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + /* Default parameters. */ #ifndef VASNPRINTF # if WIDE_CHAR_VERSION @@ -156,6 +164,7 @@ # define SNPRINTF snwprintf # else # define SNPRINTF _snwprintf +# define USE_MSVC__SNPRINTF 1 # endif # else /* Unix. */ @@ -181,7 +190,9 @@ /* Here we need to call the native snprintf, not rpl_snprintf. */ # undef snprintf # else + /* MSVC versions < 14 did not have snprintf, only _snprintf. */ # define SNPRINTF _snprintf +# define USE_MSVC__SNPRINTF 1 # endif # else /* Unix. */ @@ -195,7 +206,7 @@ /* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" warnings in this file. Use -Dlint to suppress them. */ -#ifdef lint +#if defined GCC_LINT || defined lint # define IF_LINT(Code) Code #else # define IF_LINT(Code) /* empty */ @@ -208,7 +219,7 @@ #undef remainder #define remainder rem -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && !WIDE_CHAR_VERSION # if (HAVE_STRNLEN && !defined _AIX) # define local_strnlen strnlen # else @@ -224,7 +235,7 @@ local_strnlen (const char *string, size_t maxlen) # endif #endif -#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T +#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T # if HAVE_WCSLEN # define local_wcslen wcslen # else @@ -247,7 +258,7 @@ local_wcslen (const wchar_t *s) # endif #endif -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION # if HAVE_WCSNLEN # define local_wcsnlen wcsnlen # else @@ -1517,7 +1528,7 @@ is_borderline (const char *digits, size_t precision) #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF /* Use a different function name, to make it possible that the 'wchar_t' parametrization and the 'char' parametrization get compiled in the same @@ -2392,7 +2403,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } #endif -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T else if (dp->conversion == 's' # if WIDE_CHAR_VERSION && a.arg[dp->arg_index].type != TYPE_WIDE_STRING @@ -4591,10 +4602,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION int has_width; #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION size_t width; #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION int has_precision; size_t precision; #endif @@ -4623,7 +4634,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION has_width = 0; #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION width = 0; if (dp->width_start != dp->width_end) { @@ -4657,7 +4668,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION has_precision = 0; precision = 6; if (dp->precision_start != dp->precision_end) @@ -4832,9 +4843,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, break; # else *fbp++ = 'l'; - /*FALLTHROUGH*/ # endif #endif + FALLTHROUGH; case TYPE_LONGINT: case TYPE_ULONGINT: #if HAVE_WINT_T @@ -5127,7 +5138,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Look at the snprintf() return value. */ if (retcount < 0) { -# if !HAVE_SNPRINTF_RETVAL_C99 +# if !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF /* HP-UX 10.20 snprintf() is doubly deficient: It doesn't understand the '%n' directive, *and* it returns -1 (rather than the length diff --git a/gettext-runtime/intl/verify.h b/gettext-runtime/intl/verify.h index 267de2959..3a2f6d129 100644 --- a/gettext-runtime/intl/verify.h +++ b/gettext-runtime/intl/verify.h @@ -1,6 +1,6 @@ /* Compile-time assert-like macros. - Copyright (C) 2005-2006, 2009-2016 Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2009-2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -248,7 +248,12 @@ template /* Verify requirement R at compile-time, as a declaration without a trailing ';'. */ -#define verify(R) _GL_VERIFY (R, "verify (" #R ")") +#ifdef __GNUC__ +# define verify(R) _GL_VERIFY (R, "verify (" #R ")") +#else +/* PGI barfs if R is long. Play it safe. */ +# define verify(R) _GL_VERIFY (R, "verify (...)") +#endif #ifndef __has_builtin # define __has_builtin(x) 0 @@ -263,7 +268,7 @@ template # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) #elif 1200 <= _MSC_VER # define assume(R) __assume (R) -#elif (defined lint \ +#elif ((defined GCC_LINT || defined lint) \ && (__has_builtin (__builtin_trap) \ || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)))) /* Doing it this way helps various packages when configured with diff --git a/gettext-runtime/intl/xsize.h b/gettext-runtime/intl/xsize.h index c82712d3e..d6a550808 100644 --- a/gettext-runtime/intl/xsize.h +++ b/gettext-runtime/intl/xsize.h @@ -1,6 +1,6 @@ /* xsize.h -- Checked size_t computations. - Copyright (C) 2003, 2008-2016 Free Software Foundation, Inc. + Copyright (C) 2003, 2008-2017 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by diff --git a/gettext-runtime/libasprintf/vasnprintf.c b/gettext-runtime/libasprintf/vasnprintf.c index 236bfe5da..eb8f1fd81 100644 --- a/gettext-runtime/libasprintf/vasnprintf.c +++ b/gettext-runtime/libasprintf/vasnprintf.c @@ -1,5 +1,5 @@ /* vsprintf with automatic memory allocation. - Copyright (C) 1999, 2002-2016 Free Software Foundation, Inc. + Copyright (C) 1999, 2002-2017 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -118,6 +118,14 @@ # include "fpucw.h" #endif +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + /* Default parameters. */ #ifndef VASNPRINTF # if WIDE_CHAR_VERSION @@ -156,6 +164,7 @@ # define SNPRINTF snwprintf # else # define SNPRINTF _snwprintf +# define USE_MSVC__SNPRINTF 1 # endif # else /* Unix. */ @@ -181,7 +190,9 @@ /* Here we need to call the native snprintf, not rpl_snprintf. */ # undef snprintf # else + /* MSVC versions < 14 did not have snprintf, only _snprintf. */ # define SNPRINTF _snprintf +# define USE_MSVC__SNPRINTF 1 # endif # else /* Unix. */ @@ -195,7 +206,7 @@ /* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" warnings in this file. Use -Dlint to suppress them. */ -#ifdef lint +#if defined GCC_LINT || defined lint # define IF_LINT(Code) Code #else # define IF_LINT(Code) /* empty */ @@ -208,7 +219,7 @@ #undef remainder #define remainder rem -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && !WIDE_CHAR_VERSION # if (HAVE_STRNLEN && !defined _AIX) # define local_strnlen strnlen # else @@ -224,7 +235,7 @@ local_strnlen (const char *string, size_t maxlen) # endif #endif -#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T +#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T # if HAVE_WCSLEN # define local_wcslen wcslen # else @@ -247,7 +258,7 @@ local_wcslen (const wchar_t *s) # endif #endif -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION # if HAVE_WCSNLEN # define local_wcsnlen wcsnlen # else @@ -1517,7 +1528,7 @@ is_borderline (const char *digits, size_t precision) #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF /* Use a different function name, to make it possible that the 'wchar_t' parametrization and the 'char' parametrization get compiled in the same @@ -2392,7 +2403,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } #endif -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T else if (dp->conversion == 's' # if WIDE_CHAR_VERSION && a.arg[dp->arg_index].type != TYPE_WIDE_STRING @@ -4591,10 +4602,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION int has_width; #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION size_t width; #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION int has_precision; size_t precision; #endif @@ -4623,7 +4634,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION has_width = 0; #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION width = 0; if (dp->width_start != dp->width_end) { @@ -4657,7 +4668,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION has_precision = 0; precision = 6; if (dp->precision_start != dp->precision_end) @@ -4832,9 +4843,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, break; # else *fbp++ = 'l'; - /*FALLTHROUGH*/ # endif #endif + FALLTHROUGH; case TYPE_LONGINT: case TYPE_ULONGINT: #if HAVE_WINT_T @@ -5127,7 +5138,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Look at the snprintf() return value. */ if (retcount < 0) { -# if !HAVE_SNPRINTF_RETVAL_C99 +# if !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF /* HP-UX 10.20 snprintf() is doubly deficient: It doesn't understand the '%n' directive, *and* it returns -1 (rather than the length diff --git a/gettext-runtime/m4/Makefile.am b/gettext-runtime/m4/Makefile.am index 740e462da..1544a7c46 100644 --- a/gettext-runtime/m4/Makefile.am +++ b/gettext-runtime/m4/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DIST = README \ codeset.m4 \ extern-inline.m4 \ fcntl-o.m4 \ +flexmember.m4 \ gettext.m4 \ glibc2.m4 \ glibc21.m4 \ diff --git a/gettext-runtime/m4/extern-inline.m4 b/gettext-runtime/m4/extern-inline.m4 index 1e578f3de..00f960968 100644 --- a/gettext-runtime/m4/extern-inline.m4 +++ b/gettext-runtime/m4/extern-inline.m4 @@ -1,6 +1,6 @@ dnl 'extern inline' a la ISO C99. -dnl Copyright 2012-2016 Free Software Foundation, Inc. +dnl Copyright 2012-2017 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. diff --git a/gettext-runtime/m4/fcntl-o.m4 b/gettext-runtime/m4/fcntl-o.m4 index 24fcf88d0..3c3b63c52 100644 --- a/gettext-runtime/m4/fcntl-o.m4 +++ b/gettext-runtime/m4/fcntl-o.m4 @@ -1,5 +1,5 @@ # fcntl-o.m4 serial 4 -dnl Copyright (C) 2006, 2009-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2006, 2009-2017 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. diff --git a/gettext-runtime/m4/flexmember.m4 b/gettext-runtime/m4/flexmember.m4 new file mode 100644 index 000000000..9d3b50d15 --- /dev/null +++ b/gettext-runtime/m4/flexmember.m4 @@ -0,0 +1,46 @@ +# serial 5 +# Check for flexible array member support. + +# Copyright (C) 2006, 2009-2017 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Written by Paul Eggert. + +AC_DEFUN([AC_C_FLEXIBLE_ARRAY_MEMBER], +[ + AC_CACHE_CHECK([for flexible array member], + ac_cv_c_flexmember, + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + struct m { struct m *next, **list; char name[]; }; + struct s { struct s *p; struct m *m; int n; double d[]; };]], + [[int m = getchar (); + size_t nbytes = offsetof (struct s, d) + m * sizeof (double); + nbytes += sizeof (struct s) - 1; + nbytes -= nbytes % sizeof (struct s); + struct s *p = malloc (nbytes); + p->p = p; + p->m = NULL; + p->d[0] = 0.0; + return p->d != (double *) NULL;]])], + [ac_cv_c_flexmember=yes], + [ac_cv_c_flexmember=no])]) + if test $ac_cv_c_flexmember = yes; then + AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [], + [Define to nothing if C supports flexible array members, and to + 1 if it does not. That way, with a declaration like 'struct s + { int n; double d@<:@FLEXIBLE_ARRAY_MEMBER@:>@; };', the struct hack + can be used with pre-C99 compilers. + When computing the size of such an object, don't use 'sizeof (struct s)' + as it overestimates the size. Use 'offsetof (struct s, d)' instead. + Don't use 'offsetof (struct s, d@<:@0@:>@)', as this doesn't work with + MSVC and with C++ compilers.]) + else + AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [1]) + fi +]) diff --git a/gettext-runtime/m4/glibc2.m4 b/gettext-runtime/m4/glibc2.m4 index 785bba095..926edbab7 100644 --- a/gettext-runtime/m4/glibc2.m4 +++ b/gettext-runtime/m4/glibc2.m4 @@ -1,5 +1,5 @@ # glibc2.m4 serial 3 -dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2016 Free Software Foundation, +dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2017 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/gettext-runtime/m4/glibc21.m4 b/gettext-runtime/m4/glibc21.m4 index dafebf501..2e30ed688 100644 --- a/gettext-runtime/m4/glibc21.m4 +++ b/gettext-runtime/m4/glibc21.m4 @@ -1,5 +1,5 @@ # glibc21.m4 serial 5 -dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2016 Free Software Foundation, +dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2017 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/gettext-runtime/m4/intdiv0.m4 b/gettext-runtime/m4/intdiv0.m4 index 744b99ea8..bbbc11433 100644 --- a/gettext-runtime/m4/intdiv0.m4 +++ b/gettext-runtime/m4/intdiv0.m4 @@ -1,5 +1,5 @@ # intdiv0.m4 serial 6 (gettext-0.18.2) -dnl Copyright (C) 2002, 2007-2008, 2010-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2002, 2007-2008, 2010-2017 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. diff --git a/gettext-runtime/m4/intl.m4 b/gettext-runtime/m4/intl.m4 index 42fac9535..646c5b5ae 100644 --- a/gettext-runtime/m4/intl.m4 +++ b/gettext-runtime/m4/intl.m4 @@ -1,5 +1,5 @@ -# intl.m4 serial 29 (gettext-0.19) -dnl Copyright (C) 1995-2014, 2016 Free Software Foundation, Inc. +# intl.m4 serial 30 (gettext-0.19.9) +dnl Copyright (C) 1995-2014, 2016-2017 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. @@ -44,6 +44,7 @@ AC_DEFUN([AM_INTL_SUBDIR], AC_REQUIRE([gt_INTL_MACOSX])dnl AC_REQUIRE([gl_EXTERN_INLINE])dnl AC_REQUIRE([gt_GL_ATTRIBUTE])dnl + AC_REQUIRE([AC_C_FLEXIBLE_ARRAY_MEMBER])dnl dnl Support for automake's --enable-silent-rules. case "$enable_silent_rules" in diff --git a/gettext-runtime/m4/intmax.m4 b/gettext-runtime/m4/intmax.m4 index 1a47107f1..b432fae67 100644 --- a/gettext-runtime/m4/intmax.m4 +++ b/gettext-runtime/m4/intmax.m4 @@ -1,5 +1,5 @@ # intmax.m4 serial 6 (gettext-0.18.2) -dnl Copyright (C) 2002-2005, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2002-2005, 2008-2017 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. diff --git a/gettext-runtime/m4/inttypes-pri.m4 b/gettext-runtime/m4/inttypes-pri.m4 index ae20183db..205578782 100644 --- a/gettext-runtime/m4/inttypes-pri.m4 +++ b/gettext-runtime/m4/inttypes-pri.m4 @@ -1,5 +1,5 @@ # inttypes-pri.m4 serial 7 (gettext-0.18.2) -dnl Copyright (C) 1997-2002, 2006, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 1997-2002, 2006, 2008-2017 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. diff --git a/gettext-runtime/m4/inttypes_h.m4 b/gettext-runtime/m4/inttypes_h.m4 index 76571199f..924030505 100644 --- a/gettext-runtime/m4/inttypes_h.m4 +++ b/gettext-runtime/m4/inttypes_h.m4 @@ -1,5 +1,5 @@ # inttypes_h.m4 serial 10 -dnl Copyright (C) 1997-2004, 2006, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 1997-2004, 2006, 2008-2017 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. diff --git a/gettext-runtime/m4/lock.m4 b/gettext-runtime/m4/lock.m4 index 1e83e2365..cb04a67d7 100644 --- a/gettext-runtime/m4/lock.m4 +++ b/gettext-runtime/m4/lock.m4 @@ -1,5 +1,5 @@ -# lock.m4 serial 13 (gettext-0.18.2) -dnl Copyright (C) 2005-2016 Free Software Foundation, Inc. +# lock.m4 serial 14 +dnl Copyright (C) 2005-2017 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. @@ -12,11 +12,16 @@ AC_DEFUN([gl_LOCK], if test "$gl_threads_api" = posix; then # OSF/1 4.0 and Mac OS X 10.1 lack the pthread_rwlock_t type and the # pthread_rwlock_* functions. + has_rwlock=false AC_CHECK_TYPE([pthread_rwlock_t], - [AC_DEFINE([HAVE_PTHREAD_RWLOCK], [1], + [has_rwlock=true + AC_DEFINE([HAVE_PTHREAD_RWLOCK], [1], [Define if the POSIX multithreading library has read/write locks.])], [], [#include ]) + if $has_rwlock; then + gl_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER + fi # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. AC_COMPILE_IFELSE([ AC_LANG_PROGRAM( diff --git a/gettext-runtime/m4/longlong.m4 b/gettext-runtime/m4/longlong.m4 index 36d8b1242..9a3294bc2 100644 --- a/gettext-runtime/m4/longlong.m4 +++ b/gettext-runtime/m4/longlong.m4 @@ -1,5 +1,5 @@ # longlong.m4 serial 17 -dnl Copyright (C) 1999-2007, 2009-2016 Free Software Foundation, Inc. +dnl Copyright (C) 1999-2007, 2009-2017 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. diff --git a/gettext-runtime/m4/printf-posix.m4 b/gettext-runtime/m4/printf-posix.m4 index f9088c090..057793358 100644 --- a/gettext-runtime/m4/printf-posix.m4 +++ b/gettext-runtime/m4/printf-posix.m4 @@ -1,5 +1,5 @@ # printf-posix.m4 serial 6 (gettext-0.18.2) -dnl Copyright (C) 2003, 2007, 2009-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2003, 2007, 2009-2017 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. diff --git a/gettext-runtime/m4/progtest.m4 b/gettext-runtime/m4/progtest.m4 index 9ace7c341..303bc3182 100644 --- a/gettext-runtime/m4/progtest.m4 +++ b/gettext-runtime/m4/progtest.m4 @@ -1,5 +1,5 @@ # progtest.m4 serial 7 (gettext-0.18.2) -dnl Copyright (C) 1996-2003, 2005, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 1996-2003, 2005, 2008-2017 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. diff --git a/gettext-runtime/m4/size_max.m4 b/gettext-runtime/m4/size_max.m4 index de69025d6..05ad1b602 100644 --- a/gettext-runtime/m4/size_max.m4 +++ b/gettext-runtime/m4/size_max.m4 @@ -1,5 +1,5 @@ # size_max.m4 serial 10 -dnl Copyright (C) 2003, 2005-2006, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2003, 2005-2006, 2008-2017 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. diff --git a/gettext-runtime/m4/stdint_h.m4 b/gettext-runtime/m4/stdint_h.m4 index f823b94c3..786eaa3c9 100644 --- a/gettext-runtime/m4/stdint_h.m4 +++ b/gettext-runtime/m4/stdint_h.m4 @@ -1,5 +1,5 @@ # stdint_h.m4 serial 9 -dnl Copyright (C) 1997-2004, 2006, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 1997-2004, 2006, 2008-2017 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. diff --git a/gettext-runtime/m4/threadlib.m4 b/gettext-runtime/m4/threadlib.m4 index b43534ea2..f79fde20f 100644 --- a/gettext-runtime/m4/threadlib.m4 +++ b/gettext-runtime/m4/threadlib.m4 @@ -1,5 +1,5 @@ -# threadlib.m4 serial 11 (gettext-0.18.2) -dnl Copyright (C) 2005-2016 Free Software Foundation, Inc. +# threadlib.m4 serial 12 +dnl Copyright (C) 2005-2017 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. @@ -195,8 +195,10 @@ int main () # 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. + # On Solaris 10 or newer, this test is no longer needed, because + # libc contains the fully functional pthread functions. case "$host_os" in - solaris* | hpux*) + solaris | solaris2.[1-9] | solaris2.[1-9].* | hpux*) AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1], [Define if the pthread_in_use() detection is hard.]) esac diff --git a/gettext-runtime/m4/uintmax_t.m4 b/gettext-runtime/m4/uintmax_t.m4 index 30f4dd5d1..7e3b3dfe3 100644 --- a/gettext-runtime/m4/uintmax_t.m4 +++ b/gettext-runtime/m4/uintmax_t.m4 @@ -1,5 +1,5 @@ # uintmax_t.m4 serial 12 -dnl Copyright (C) 1997-2004, 2007-2016 Free Software Foundation, Inc. +dnl Copyright (C) 1997-2004, 2007-2017 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. diff --git a/gettext-runtime/m4/visibility.m4 b/gettext-runtime/m4/visibility.m4 index e99e3fbad..ce00e7250 100644 --- a/gettext-runtime/m4/visibility.m4 +++ b/gettext-runtime/m4/visibility.m4 @@ -1,5 +1,5 @@ # visibility.m4 serial 5 (gettext-0.18.2) -dnl Copyright (C) 2005, 2008, 2010-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2005, 2008, 2010-2017 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. diff --git a/gettext-runtime/m4/wchar_t.m4 b/gettext-runtime/m4/wchar_t.m4 index 2db8c3f2f..11783d299 100644 --- a/gettext-runtime/m4/wchar_t.m4 +++ b/gettext-runtime/m4/wchar_t.m4 @@ -1,5 +1,5 @@ # wchar_t.m4 serial 4 (gettext-0.18.2) -dnl Copyright (C) 2002-2003, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2002-2003, 2008-2017 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. diff --git a/gettext-runtime/m4/xsize.m4 b/gettext-runtime/m4/xsize.m4 index 16764e89d..5f8505770 100644 --- a/gettext-runtime/m4/xsize.m4 +++ b/gettext-runtime/m4/xsize.m4 @@ -1,5 +1,5 @@ # xsize.m4 serial 5 -dnl Copyright (C) 2003-2004, 2008-2016 Free Software Foundation, Inc. +dnl Copyright (C) 2003-2004, 2008-2017 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. diff --git a/gettext-runtime/tests/test-lock.c b/gettext-runtime/tests/test-lock.c index 51cec3d6b..751b27b50 100644 --- a/gettext-runtime/tests/test-lock.c +++ b/gettext-runtime/tests/test-lock.c @@ -51,12 +51,27 @@ #define EXPLICIT_YIELD 1 /* Whether to use 'volatile' on some variables that communicate information - between threads. If set to 0, a lock is used to protect these variables. - If set to 1, 'volatile' is used; this is theoretically equivalent but can - lead to much slower execution (e.g. 30x slower total run time on a 40-core - machine. */ + between threads. If set to 0, a semaphore or a lock is used to protect + these variables. If set to 1, 'volatile' is used; this is theoretically + equivalent but can lead to much slower execution (e.g. 30x slower total + run time on a 40-core machine), because 'volatile' does not imply any + synchronization/communication between different CPUs. */ #define USE_VOLATILE 0 +#if USE_POSIX_THREADS && HAVE_SEMAPHORE_H +/* Whether to use a semaphore to communicate information between threads. + If set to 0, a lock is used. If set to 1, a semaphore is used. + Uncomment this to reduce the dependencies of this test. */ +# define USE_SEMAPHORE 1 +/* Mac OS X provides only named semaphores (sem_open); its facility for + unnamed semaphores (sem_init) does not work. */ +# if defined __APPLE__ && defined __MACH__ +# define USE_NAMED_SEMAPHORE 1 +# else +# define USE_UNNAMED_SEMAPHORE 1 +# endif +#endif + /* Whether to print debugging messages. */ #define ENABLE_DEBUGGING 0 @@ -80,6 +95,13 @@ #endif #include "lock.h" +#if USE_SEMAPHORE +# include +# include +# include +# include +#endif + #if ENABLE_DEBUGGING # define dbgprintf printf #else @@ -239,6 +261,87 @@ set_atomic_int_value (struct atomic_int *ai, int new_value) { ai->value = new_value; } +#elif USE_SEMAPHORE +/* This atomic_int implementation can only support the values 0 and 1. + It is initially 0 and can be set to 1 only once. */ +# if USE_UNNAMED_SEMAPHORE +struct atomic_int { + sem_t semaphore; +}; +#define atomic_int_semaphore(ai) (&(ai)->semaphore) +static void +init_atomic_int (struct atomic_int *ai) +{ + sem_init (&ai->semaphore, 0, 0); +} +# endif +# if USE_NAMED_SEMAPHORE +struct atomic_int { + sem_t *semaphore; +}; +#define atomic_int_semaphore(ai) ((ai)->semaphore) +static void +init_atomic_int (struct atomic_int *ai) +{ + sem_t *s; + unsigned int count; + for (count = 0; ; count++) + { + char name[80]; + /* Use getpid() in the name, so that different processes running at the + same time will not interfere. Use ai in the name, so that different + atomic_int in the same process will not interfere. Use a count in + the name, so that even in the (unlikely) case that a semaphore with + the specified name already exists, we can try a different name. */ + sprintf (name, "test-lock-%lu-%p-%u", + (unsigned long) getpid (), ai, count); + s = sem_open (name, O_CREAT | O_EXCL, 0600, 0); + if (s == SEM_FAILED) + { + if (errno == EEXIST) + /* Retry with a different name. */ + continue; + else + { + perror ("sem_open failed"); + abort (); + } + } + else + { + /* Try not to leave a semaphore hanging around on the file system + eternally, if we can avoid it. */ + sem_unlink (name); + break; + } + } + ai->semaphore = s; +} +# endif +static int +get_atomic_int_value (struct atomic_int *ai) +{ + if (sem_trywait (atomic_int_semaphore (ai)) == 0) + { + if (sem_post (atomic_int_semaphore (ai))) + abort (); + return 1; + } + else if (errno == EAGAIN) + return 0; + else + abort (); +} +static void +set_atomic_int_value (struct atomic_int *ai, int new_value) +{ + if (new_value == 0) + /* It's already initialized with 0. */ + return; + /* To set the value 1: */ + if (sem_post (atomic_int_semaphore (ai))) + abort (); +} #else struct atomic_int { gl_lock_define (, lock)