summaryrefslogtreecommitdiff
path: root/gl
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-10-26 23:43:43 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-10-26 23:43:43 +0200
commit0a248bf1a8a2d7c82eea0c157984fb0fe4783ec2 (patch)
tree654694dc114420cefe84b8e7c208ed3bfbed9325 /gl
parentb9da2448022a1e095e1a59e898a07d3ade8e8bcf (diff)
downloadgnutls-0a248bf1a8a2d7c82eea0c157984fb0fe4783ec2.tar.gz
new gnulib + added select + inet_pton.
Diffstat (limited to 'gl')
-rw-r--r--gl/Makefile.am134
-rw-r--r--gl/arpa_inet.in.h (renamed from gl/tests/arpa_inet.in.h)0
-rw-r--r--gl/errno.in.h118
-rw-r--r--gl/inet_pton.c (renamed from gl/tests/inet_pton.c)0
-rw-r--r--gl/m4/ftruncate.m424
-rw-r--r--gl/m4/gnulib-cache.m44
-rw-r--r--gl/m4/gnulib-comp.m4143
-rw-r--r--gl/m4/ioctl.m441
-rw-r--r--gl/m4/perror.m463
-rw-r--r--gl/m4/pipe.m415
-rw-r--r--gl/m4/select.m475
-rw-r--r--gl/m4/signal_h.m483
-rw-r--r--gl/m4/strerror_r.m4173
-rw-r--r--gl/m4/sys_ioctl_h.m464
-rw-r--r--gl/m4/sys_select_h.m495
-rw-r--r--gl/m4/thread.m418
-rw-r--r--gl/m4/yield.m419
-rw-r--r--gl/math.in.h71
-rw-r--r--gl/select.c492
-rw-r--r--gl/signal.in.h447
-rw-r--r--gl/strerror-override.c102
-rw-r--r--gl/strerror-override.h2
-rw-r--r--gl/sys_select.in.h288
-rw-r--r--gl/tests/Makefile.am263
-rw-r--r--gl/tests/connect.c56
-rw-r--r--gl/tests/ftruncate.c43
-rw-r--r--gl/tests/glthread/lock.c1058
-rw-r--r--gl/tests/glthread/lock.h928
-rw-r--r--gl/tests/glthread/thread.c232
-rw-r--r--gl/tests/glthread/thread.h401
-rw-r--r--gl/tests/glthread/threadlib.c74
-rw-r--r--gl/tests/glthread/yield.h122
-rw-r--r--gl/tests/ioctl.c79
-rw-r--r--gl/tests/perror.c49
-rw-r--r--gl/tests/pipe.c51
-rw-r--r--gl/tests/strerror_r.c327
-rw-r--r--gl/tests/sys_ioctl.in.h79
-rw-r--r--gl/tests/test-connect.c58
-rw-r--r--gl/tests/test-ftruncate.c59
-rwxr-xr-xgl/tests/test-ftruncate.sh3
-rw-r--r--gl/tests/test-ioctl.c49
-rw-r--r--gl/tests/test-lock.c601
-rw-r--r--gl/tests/test-perror.c37
-rwxr-xr-xgl/tests/test-perror.sh24
-rw-r--r--gl/tests/test-perror2.c137
-rw-r--r--gl/tests/test-pipe.c105
-rw-r--r--gl/tests/test-select-fd.c72
-rwxr-xr-xgl/tests/test-select-in.sh39
-rwxr-xr-xgl/tests/test-select-out.sh35
-rw-r--r--gl/tests/test-select-stdin.c83
-rw-r--r--gl/tests/test-select.c34
-rw-r--r--gl/tests/test-select.h436
-rw-r--r--gl/tests/test-signal-h.c129
-rw-r--r--gl/tests/test-strerror_r.c182
-rw-r--r--gl/tests/test-sys_ioctl.c27
-rw-r--r--gl/tests/test-sys_select.c55
-rw-r--r--gl/tests/test-thread_create.c78
-rw-r--r--gl/tests/test-thread_self.c34
-rw-r--r--gl/tests/w32sock.h136
-rw-r--r--gl/w32sock.h78
60 files changed, 8583 insertions, 141 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am
index 894639e45f..9bf8f9ce74 100644
--- a/gl/Makefile.am
+++ b/gl/Makefile.am
@@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alloca alphasort argp bind byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass getsubopt gettext gettime havelib lib-msvc-compat lib-symbol-versions listen maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in progname read-file recvfrom scandir sendto setsockopt shutdown snprintf socket sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vfprintf-posix vprintf-posix vsnprintf warnings
+# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alloca alphasort argp bind byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass getsubopt gettext gettime havelib inet_pton lib-msvc-compat lib-symbol-versions listen maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in progname read-file recvfrom scandir select sendto setsockopt shutdown snprintf socket sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vfprintf-posix vprintf-posix vsnprintf warnings
AUTOMAKE_OPTIONS = 1.5 gnits
@@ -51,8 +51,10 @@ libgnu_la_DEPENDENCIES = $(gl_LTLIBOBJS)
EXTRA_libgnu_la_SOURCES =
libgnu_la_LDFLAGS = $(AM_LDFLAGS)
libgnu_la_LDFLAGS += -no-undefined
+libgnu_la_LDFLAGS += $(INET_PTON_LIB)
libgnu_la_LDFLAGS += $(LIBSOCKET)
libgnu_la_LDFLAGS += $(LIB_CLOCK_GETTIME)
+libgnu_la_LDFLAGS += $(LIB_SELECT)
libgnu_la_LDFLAGS += $(LTLIBINTL)
## begin gnulib module accept
@@ -123,6 +125,42 @@ libgnu_la_SOURCES += argp.h argp-ba.c argp-eexst.c \
## end gnulib module argp
+## begin gnulib module arpa_inet
+
+BUILT_SOURCES += arpa/inet.h
+
+# We need the following in order to create <arpa/inet.h> when the system
+# doesn't have one.
+arpa/inet.h: arpa_inet.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H)
+ $(AM_V_at)$(MKDIR_P) arpa
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|g' \
+ -e 's|@''NEXT_ARPA_INET_H''@|$(NEXT_ARPA_INET_H)|g' \
+ -e 's|@''HAVE_ARPA_INET_H''@|$(HAVE_ARPA_INET_H)|g' \
+ -e 's/@''GNULIB_INET_NTOP''@/$(GNULIB_INET_NTOP)/g' \
+ -e 's/@''GNULIB_INET_PTON''@/$(GNULIB_INET_PTON)/g' \
+ -e 's|@''HAVE_DECL_INET_NTOP''@|$(HAVE_DECL_INET_NTOP)|g' \
+ -e 's|@''HAVE_DECL_INET_PTON''@|$(HAVE_DECL_INET_PTON)|g' \
+ -e 's|@''REPLACE_INET_NTOP''@|$(REPLACE_INET_NTOP)|g' \
+ -e 's|@''REPLACE_INET_PTON''@|$(REPLACE_INET_PTON)|g' \
+ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ < $(srcdir)/arpa_inet.in.h; \
+ } > $@-t && \
+ mv $@-t $@
+MOSTLYCLEANFILES += arpa/inet.h arpa/inet.h-t
+MOSTLYCLEANDIRS += arpa
+
+EXTRA_DIST += arpa_inet.in.h
+
+## end gnulib module arpa_inet
+
## begin gnulib module bind
@@ -542,6 +580,15 @@ EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath
## end gnulib module havelib
+## begin gnulib module inet_pton
+
+
+EXTRA_DIST += inet_pton.c
+
+EXTRA_libgnu_la_SOURCES += inet_pton.c
+
+## end gnulib module inet_pton
+
## begin gnulib module intprops
@@ -997,6 +1044,15 @@ EXTRA_libgnu_la_SOURCES += scandir.c
## end gnulib module scandir
+## begin gnulib module select
+
+
+EXTRA_DIST += select.c
+
+EXTRA_libgnu_la_SOURCES += select.c
+
+## end gnulib module select
+
## begin gnulib module sendto
@@ -1024,6 +1080,48 @@ EXTRA_libgnu_la_SOURCES += shutdown.c
## end gnulib module shutdown
+## begin gnulib module signal-h
+
+BUILT_SOURCES += signal.h
+
+# We need the following in order to create <signal.h> when the system
+# doesn't have a complete one.
+signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+ sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''NEXT_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \
+ -e 's|@''GNULIB_PTHREAD_SIGMASK''@|$(GNULIB_PTHREAD_SIGMASK)|g' \
+ -e 's|@''GNULIB_RAISE''@|$(GNULIB_RAISE)|g' \
+ -e 's/@''GNULIB_SIGNAL_H_SIGPIPE''@/$(GNULIB_SIGNAL_H_SIGPIPE)/g' \
+ -e 's/@''GNULIB_SIGPROCMASK''@/$(GNULIB_SIGPROCMASK)/g' \
+ -e 's/@''GNULIB_SIGACTION''@/$(GNULIB_SIGACTION)/g' \
+ -e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \
+ -e 's|@''HAVE_PTHREAD_SIGMASK''@|$(HAVE_PTHREAD_SIGMASK)|g' \
+ -e 's|@''HAVE_RAISE''@|$(HAVE_RAISE)|g' \
+ -e 's|@''HAVE_SIGSET_T''@|$(HAVE_SIGSET_T)|g' \
+ -e 's|@''HAVE_SIGINFO_T''@|$(HAVE_SIGINFO_T)|g' \
+ -e 's|@''HAVE_SIGACTION''@|$(HAVE_SIGACTION)|g' \
+ -e 's|@''HAVE_STRUCT_SIGACTION_SA_SIGACTION''@|$(HAVE_STRUCT_SIGACTION_SA_SIGACTION)|g' \
+ -e 's|@''HAVE_TYPE_VOLATILE_SIG_ATOMIC_T''@|$(HAVE_TYPE_VOLATILE_SIG_ATOMIC_T)|g' \
+ -e 's|@''HAVE_SIGHANDLER_T''@|$(HAVE_SIGHANDLER_T)|g' \
+ -e 's|@''REPLACE_PTHREAD_SIGMASK''@|$(REPLACE_PTHREAD_SIGMASK)|g' \
+ -e 's|@''REPLACE_RAISE''@|$(REPLACE_RAISE)|g' \
+ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ < $(srcdir)/signal.in.h; \
+ } > $@-t && \
+ mv $@-t $@
+MOSTLYCLEANFILES += signal.h signal.h-t
+
+EXTRA_DIST += signal.in.h
+
+## end gnulib module signal-h
+
## begin gnulib module signbit
@@ -1712,6 +1810,40 @@ EXTRA_libgnu_la_SOURCES += strverscmp.c
## end gnulib module strverscmp
+## begin gnulib module sys_select
+
+BUILT_SOURCES += sys/select.h
+
+# We need the following in order to create <sys/select.h> when the system
+# doesn't have one that works with the given compiler.
+sys/select.h: sys_select.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
+ $(AM_V_at)$(MKDIR_P) sys
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''NEXT_SYS_SELECT_H''@|$(NEXT_SYS_SELECT_H)|g' \
+ -e 's|@''HAVE_SYS_SELECT_H''@|$(HAVE_SYS_SELECT_H)|g' \
+ -e 's/@''GNULIB_PSELECT''@/$(GNULIB_PSELECT)/g' \
+ -e 's/@''GNULIB_SELECT''@/$(GNULIB_SELECT)/g' \
+ -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
+ -e 's|@''HAVE_PSELECT''@|$(HAVE_PSELECT)|g' \
+ -e 's|@''REPLACE_PSELECT''@|$(REPLACE_PSELECT)|g' \
+ -e 's|@''REPLACE_SELECT''@|$(REPLACE_SELECT)|g' \
+ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ < $(srcdir)/sys_select.in.h; \
+ } > $@-t && \
+ mv $@-t $@
+MOSTLYCLEANFILES += sys/select.h sys/select.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_select.in.h
+
+## end gnulib module sys_select
+
## begin gnulib module sys_socket
BUILT_SOURCES += sys/socket.h
diff --git a/gl/tests/arpa_inet.in.h b/gl/arpa_inet.in.h
index 5264853b59..5264853b59 100644
--- a/gl/tests/arpa_inet.in.h
+++ b/gl/arpa_inet.in.h
diff --git a/gl/errno.in.h b/gl/errno.in.h
index 5a7533aab9..b6014b43d5 100644
--- a/gl/errno.in.h
+++ b/gl/errno.in.h
@@ -33,50 +33,106 @@
/* On native Windows platforms, many macros are not defined. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-/* POSIX says that EAGAIN and EWOULDBLOCK may have the same value. */
-# define EWOULDBLOCK EAGAIN
-
-/* Values >= 100 seem safe to use. */
-# define ETXTBSY 100
-# define GNULIB_defined_ETXTBSY 1
+/* These are the same values as defined by MSVC 10, for interoperability. */
+
+# ifndef ENOMSG
+# define ENOMSG 122
+# define GNULIB_defined_ENOMSG 1
+# endif
+
+# ifndef EIDRM
+# define EIDRM 111
+# define GNULIB_defined_EIDRM 1
+# endif
+
+# ifndef ENOLINK
+# define ENOLINK 121
+# define GNULIB_defined_ENOLINK 1
+# endif
+
+# ifndef EPROTO
+# define EPROTO 134
+# define GNULIB_defined_EPROTO 1
+# endif
+
+# ifndef EBADMSG
+# define EBADMSG 104
+# define GNULIB_defined_EBADMSG 1
+# endif
+
+# ifndef EOVERFLOW
+# define EOVERFLOW 132
+# define GNULIB_defined_EOVERFLOW 1
+# endif
+
+# ifndef ENOTSUP
+# define ENOTSUP 129
+# define GNULIB_defined_ENOTSUP 1
+# endif
+
+# ifndef ENETRESET
+# define ENETRESET 117
+# define GNULIB_defined_ENETRESET 1
+# endif
+
+# ifndef ECONNABORTED
+# define ECONNABORTED 106
+# define GNULIB_defined_ECONNABORTED 1
+# endif
+
+# ifndef ECANCELED
+# define ECANCELED 105
+# define GNULIB_defined_ECANCELED 1
+# endif
+
+# ifndef EINPROGRESS
+# define EINPROGRESS 112
+# define EALREADY 103
+# define ENOTSOCK 128
+# define EDESTADDRREQ 109
+# define EMSGSIZE 115
+# define EPROTOTYPE 136
+# define ENOPROTOOPT 123
+# define EPROTONOSUPPORT 135
+# define EOPNOTSUPP 130
+# define EAFNOSUPPORT 102
+# define EADDRINUSE 100
+# define EADDRNOTAVAIL 101
+# define ENETDOWN 116
+# define ENETUNREACH 118
+# define ECONNRESET 108
+# define ENOBUFS 119
+# define EISCONN 113
+# define ENOTCONN 126
+# define ETIMEDOUT 138
+# define ECONNREFUSED 107
+# define ELOOP 114
+# define EHOSTUNREACH 110
+# define EWOULDBLOCK 140
+# define ETXTBSY 139
+# define ENODATA 120 /* not required by POSIX */
+# define ENOSR 124 /* not required by POSIX */
+# define ENOSTR 125 /* not required by POSIX */
+# define ENOTRECOVERABLE 127 /* not required by POSIX */
+# define EOWNERDEAD 133 /* not required by POSIX */
+# define ETIME 137 /* not required by POSIX */
+# define EOTHER 131 /* not required by POSIX */
+# define GNULIB_defined_ESOCK 1
+# endif
/* These are intentionally the same values as the WSA* error numbers, defined
in <winsock2.h>. */
-# define EINPROGRESS 10036
-# define EALREADY 10037
-# define ENOTSOCK 10038
-# define EDESTADDRREQ 10039
-# define EMSGSIZE 10040
-# define EPROTOTYPE 10041
-# define ENOPROTOOPT 10042
-# define EPROTONOSUPPORT 10043
# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */
-# define EOPNOTSUPP 10045
# define EPFNOSUPPORT 10046 /* not required by POSIX */
-# define EAFNOSUPPORT 10047
-# define EADDRINUSE 10048
-# define EADDRNOTAVAIL 10049
-# define ENETDOWN 10050
-# define ENETUNREACH 10051
-# define ENETRESET 10052
-# define ECONNABORTED 10053
-# define ECONNRESET 10054
-# define ENOBUFS 10055
-# define EISCONN 10056
-# define ENOTCONN 10057
# define ESHUTDOWN 10058 /* not required by POSIX */
# define ETOOMANYREFS 10059 /* not required by POSIX */
-# define ETIMEDOUT 10060
-# define ECONNREFUSED 10061
-# define ELOOP 10062
# define EHOSTDOWN 10064 /* not required by POSIX */
-# define EHOSTUNREACH 10065
# define EPROCLIM 10067 /* not required by POSIX */
# define EUSERS 10068 /* not required by POSIX */
# define EDQUOT 10069
# define ESTALE 10070
# define EREMOTE 10071 /* not required by POSIX */
-# define GNULIB_defined_ESOCK 1
+# define GNULIB_defined_EWINSOCK 1
# endif
diff --git a/gl/tests/inet_pton.c b/gl/inet_pton.c
index cb1a872e9b..cb1a872e9b 100644
--- a/gl/tests/inet_pton.c
+++ b/gl/inet_pton.c
diff --git a/gl/m4/ftruncate.m4 b/gl/m4/ftruncate.m4
new file mode 100644
index 0000000000..4a47ba4297
--- /dev/null
+++ b/gl/m4/ftruncate.m4
@@ -0,0 +1,24 @@
+# serial 18
+
+# See if we need to emulate a missing ftruncate function using chsize.
+
+# Copyright (C) 2000-2001, 2003-2007, 2009-2011 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.
+
+AC_DEFUN([gl_FUNC_FTRUNCATE],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_CHECK_FUNCS_ONCE([ftruncate])
+ if test $ac_cv_func_ftruncate = no; then
+ HAVE_FTRUNCATE=0
+ fi
+])
+
+# Prerequisites of lib/ftruncate.c.
+AC_DEFUN([gl_PREREQ_FTRUNCATE],
+[
+ AC_REQUIRE([AC_C_INLINE])
+ AC_CHECK_FUNCS([chsize])
+])
diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4
index 5d7c87ccad..b8318a3763 100644
--- a/gl/m4/gnulib-cache.m4
+++ b/gl/m4/gnulib-cache.m4
@@ -27,7 +27,7 @@
# Specification in the form of a command-line invocation:
-# gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alloca alphasort argp bind byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass getsubopt gettext gettime havelib lib-msvc-compat lib-symbol-versions listen maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in progname read-file recvfrom scandir sendto setsockopt shutdown snprintf socket sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vfprintf-posix vprintf-posix vsnprintf warnings
+# gnulib-tool --import --dir=. --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lseek-tests --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files accept alloca alphasort argp bind byteswap c-ctype crypto/hmac-md5 crypto/md5 error extensions func getpass getsubopt gettext gettime havelib inet_pton lib-msvc-compat lib-symbol-versions listen maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in progname read-file recvfrom scandir select sendto setsockopt shutdown snprintf socket sockets socklen stdint strcase strverscmp sys_socket sys_stat time_r timespec u64 unistd valgrind-tests vasprintf version-etc version-etc-fsf vfprintf-posix vprintf-posix vsnprintf warnings
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([gl/override])
@@ -49,6 +49,7 @@ gl_MODULES([
gettext
gettime
havelib
+ inet_pton
lib-msvc-compat
lib-symbol-versions
listen
@@ -62,6 +63,7 @@ gl_MODULES([
read-file
recvfrom
scandir
+ select
sendto
setsockopt
shutdown
diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4
index 062e1a319f..359ff399a0 100644
--- a/gl/m4/gnulib-comp.m4
+++ b/gl/m4/gnulib-comp.m4
@@ -61,6 +61,8 @@ AC_DEFUN([gl_EARLY],
# Code from module close:
# Code from module close-tests:
# Code from module closedir:
+ # Code from module connect:
+ # Code from module connect-tests:
# Code from module crypto/hmac-md5:
# Code from module crypto/hmac-md5-tests:
# Code from module crypto/md5:
@@ -111,6 +113,8 @@ AC_DEFUN([gl_EARLY],
# Code from module ftello:
AC_REQUIRE([AC_FUNC_FSEEKO])
# Code from module ftello-tests:
+ # Code from module ftruncate:
+ # Code from module ftruncate-tests:
# Code from module func:
# Code from module func-tests:
# Code from module fwrite-tests:
@@ -145,6 +149,8 @@ AC_DEFUN([gl_EARLY],
# Code from module inttypes:
# Code from module inttypes-incomplete:
# Code from module inttypes-tests:
+ # Code from module ioctl:
+ # Code from module ioctl-tests:
# Code from module isnand-nolibm:
# Code from module isnand-nolibm-tests:
# Code from module isnanf-nolibm:
@@ -157,6 +163,8 @@ AC_DEFUN([gl_EARLY],
# Code from module lib-symbol-versions:
# Code from module listen:
# Code from module listen-tests:
+ # Code from module lock:
+ # Code from module lock-tests:
# Code from module lseek:
# Code from module lstat:
# Code from module lstat-tests:
@@ -188,6 +196,10 @@ AC_DEFUN([gl_EARLY],
# Code from module opendir:
# Code from module pathmax:
# Code from module pathmax-tests:
+ # Code from module perror:
+ # Code from module perror-tests:
+ # Code from module pipe-posix:
+ # Code from module pipe-posix-tests:
# Code from module printf-frexp:
# Code from module printf-frexp-tests:
# Code from module printf-frexpl:
@@ -205,6 +217,8 @@ AC_DEFUN([gl_EARLY],
# Code from module recvfrom-tests:
# Code from module same-inode:
# Code from module scandir:
+ # Code from module select:
+ # Code from module select-tests:
# Code from module sendto:
# Code from module sendto-tests:
# Code from module setenv:
@@ -213,6 +227,8 @@ AC_DEFUN([gl_EARLY],
# Code from module setsockopt-tests:
# Code from module shutdown:
# Code from module shutdown-tests:
+ # Code from module signal-h:
+ # Code from module signal-h-tests:
# Code from module signbit:
# Code from module signbit-tests:
# Code from module size_max:
@@ -255,6 +271,8 @@ AC_DEFUN([gl_EARLY],
# Code from module strerror:
# Code from module strerror-override:
# Code from module strerror-tests:
+ # Code from module strerror_r-posix:
+ # Code from module strerror_r-posix-tests:
# Code from module string:
# Code from module string-tests:
# Code from module strings:
@@ -266,6 +284,10 @@ AC_DEFUN([gl_EARLY],
# Code from module strverscmp-tests:
# Code from module symlink:
# Code from module symlink-tests:
+ # Code from module sys_ioctl:
+ # Code from module sys_ioctl-tests:
+ # Code from module sys_select:
+ # Code from module sys_select-tests:
# Code from module sys_socket:
# Code from module sys_socket-tests:
# Code from module sys_stat:
@@ -278,6 +300,10 @@ AC_DEFUN([gl_EARLY],
# Code from module sys_uio-tests:
# Code from module sysexits:
# Code from module sysexits-tests:
+ # Code from module thread:
+ # Code from module thread-tests:
+ # Code from module threadlib:
+ gl_THREADLIB_EARLY
# Code from module time:
# Code from module time-tests:
# Code from module time_r:
@@ -311,6 +337,7 @@ AC_DEFUN([gl_EARLY],
# Code from module wchar:
# Code from module wchar-tests:
# Code from module xsize:
+ # Code from module yield:
])
# This macro should be invoked from ./configure.ac, in the section
@@ -347,6 +374,8 @@ gl_ARGP
m4_ifdef([AM_XGETTEXT_OPTION],
[AM_][XGETTEXT_OPTION([--flag=argp_error:2:c-format])
AM_][XGETTEXT_OPTION([--flag=argp_failure:4:c-format])])
+gl_HEADER_ARPA_INET
+AC_PROG_MKDIR_P
AC_REQUIRE([gl_HEADER_SYS_SOCKET])
if test "$ac_cv_header_winsock2_h" = yes; then
AC_LIBOBJ([bind])
@@ -478,6 +507,12 @@ m4_if(m4_version_compare([2.61a.100],
m4_defn([m4_PACKAGE_VERSION])), [1], [],
[AC_CONFIG_LINKS([$GNUmakefile:$GNUmakefile], [],
[GNUmakefile=$GNUmakefile])])
+gl_FUNC_INET_PTON
+if test $HAVE_INET_PTON = 0 || test $REPLACE_INET_NTOP = 1; then
+ AC_LIBOBJ([inet_pton])
+ gl_PREREQ_INET_PTON
+fi
+gl_ARPA_INET_MODULE_INDICATOR([inet_pton])
gl_FUNC_ISNAND_NO_LIBM
if test $gl_func_isnand_no_libm != yes; then
AC_LIBOBJ([isnand])
@@ -587,6 +622,11 @@ if test $HAVE_SCANDIR = 0; then
gl_PREREQ_SCANDIR
fi
gl_DIRENT_MODULE_INDICATOR([scandir])
+gl_FUNC_SELECT
+if test $REPLACE_SELECT = 1; then
+ AC_LIBOBJ([select])
+fi
+gl_SYS_SELECT_MODULE_INDICATOR([select])
AC_REQUIRE([gl_HEADER_SYS_SOCKET])
if test "$ac_cv_header_winsock2_h" = yes; then
AC_LIBOBJ([sendto])
@@ -602,6 +642,7 @@ if test "$ac_cv_header_winsock2_h" = yes; then
AC_LIBOBJ([shutdown])
fi
gl_SYS_SOCKET_MODULE_INDICATOR([shutdown])
+gl_SIGNAL_H
gl_SIGNBIT
if test $REPLACE_SIGNBIT = 1; then
AC_LIBOBJ([signbitf])
@@ -694,6 +735,8 @@ if test $HAVE_STRVERSCMP = 0; then
gl_PREREQ_STRVERSCMP
fi
gl_STRING_MODULE_INDICATOR([strverscmp])
+gl_HEADER_SYS_SELECT
+AC_PROG_MKDIR_P
gl_HEADER_SYS_SOCKET
AC_PROG_MKDIR_P
gl_HEADER_SYS_STAT_H
@@ -778,13 +821,16 @@ changequote([, ])dnl
AC_SUBST([gltests_WITNESS])
gl_module_indicator_condition=$gltests_WITNESS
m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [$gl_module_indicator_condition])
-gl_HEADER_ARPA_INET
-AC_PROG_MKDIR_P
gl_FUNC_CLOSE
if test $REPLACE_CLOSE = 1; then
AC_LIBOBJ([close])
fi
gl_UNISTD_MODULE_INDICATOR([close])
+AC_REQUIRE([gl_HEADER_SYS_SOCKET])
+if test "$ac_cv_header_winsock2_h" = yes; then
+ AC_LIBOBJ([connect])
+fi
+gl_SYS_SOCKET_MODULE_INDICATOR([connect])
gl_FUNC_DUP2
if test $HAVE_DUP2 = 0 || test $REPLACE_DUP2 = 1; then
AC_LIBOBJ([dup2])
@@ -804,6 +850,12 @@ gl_FUNC_UNGETC_WORKS
gl_FUNC_UNGETC_WORKS
gl_FUNC_UNGETC_WORKS
gl_FUNC_UNGETC_WORKS
+gl_FUNC_FTRUNCATE
+if test $HAVE_FTRUNCATE = 0; then
+ AC_LIBOBJ([ftruncate])
+ gl_PREREQ_FTRUNCATE
+fi
+gl_UNISTD_MODULE_INDICATOR([ftruncate])
gl_FUNC_GETCWD_LGPL
if test $REPLACE_GETCWD = 1; then
AC_LIBOBJ([getcwd-lgpl])
@@ -815,19 +867,19 @@ if test $REPLACE_GETPAGESIZE = 1; then
fi
gl_UNISTD_MODULE_INDICATOR([getpagesize])
AC_REQUIRE([AC_C_INLINE])
-gl_FUNC_INET_PTON
-if test $HAVE_INET_PTON = 0 || test $REPLACE_INET_NTOP = 1; then
- AC_LIBOBJ([inet_pton])
- gl_PREREQ_INET_PTON
-fi
-gl_ARPA_INET_MODULE_INDICATOR([inet_pton])
AC_C_BIGENDIAN
gl_INTTYPES_H
gl_INTTYPES_INCOMPLETE
+gl_FUNC_IOCTL
+if test $HAVE_IOCTL = 0 || test $REPLACE_IOCTL = 1; then
+ AC_LIBOBJ([ioctl])
+fi
+gl_SYS_IOCTL_MODULE_INDICATOR([ioctl])
gl_DOUBLE_EXPONENT_LOCATION
gl_FLOAT_EXPONENT_LOCATION
gl_LONG_DOUBLE_EXPONENT_LOCATION
AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])
+gl_LOCK
gl_FUNC_LSTAT
if test $REPLACE_LSTAT = 1; then
AC_LIBOBJ([lstat])
@@ -846,6 +898,16 @@ if test $REPLACE_OPEN = 1; then
fi
gl_FCNTL_MODULE_INDICATOR([open])
gl_PATHMAX
+gl_FUNC_PERROR
+if test $REPLACE_PERROR = 1; then
+ AC_LIBOBJ([perror])
+fi
+gl_STRING_MODULE_INDICATOR([perror])
+gl_FUNC_PIPE
+if test $HAVE_PIPE = 0; then
+ AC_LIBOBJ([pipe])
+fi
+gl_UNISTD_MODULE_INDICATOR([pipe])
gl_FUNC_PUTENV
if test $REPLACE_PUTENV = 1; then
AC_LIBOBJ([putenv])
@@ -855,6 +917,7 @@ dnl Check for prerequisites for memory fence checks.
gl_FUNC_MMAP_ANON
AC_CHECK_HEADERS_ONCE([sys/mman.h])
AC_CHECK_FUNCS_ONCE([mprotect])
+AC_CHECK_HEADERS_ONCE([sys/wait.h])
gl_FUNC_SETENV
if test $HAVE_SETENV = 0 || test $REPLACE_SETENV = 1; then
AC_LIBOBJ([setenv])
@@ -872,6 +935,12 @@ fi
gl_SYS_STAT_MODULE_INDICATOR([stat])
gt_TYPE_WCHAR_T
gt_TYPE_WINT_T
+gl_FUNC_STRERROR_R
+if test $HAVE_DECL_STRERROR_R = 0 || test $REPLACE_STRERROR_R = 1; then
+ AC_LIBOBJ([strerror_r])
+ gl_PREREQ_STRERROR_R
+fi
+gl_STRING_MODULE_INDICATOR([strerror_r])
dnl Check for prerequisites for memory fence checks.
gl_FUNC_MMAP_ANON
AC_CHECK_HEADERS_ONCE([sys/mman.h])
@@ -881,7 +950,11 @@ if test $HAVE_SYMLINK = 0 || test $REPLACE_SYMLINK = 1; then
AC_LIBOBJ([symlink])
fi
gl_UNISTD_MODULE_INDICATOR([symlink])
+gl_SYS_IOCTL_H
+AC_PROG_MKDIR_P
AC_CHECK_FUNCS_ONCE([shutdown])
+gl_THREAD
+gl_THREADLIB
gl_FUNC_UNSETENV
if test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1; then
AC_LIBOBJ([unsetenv])
@@ -891,6 +964,7 @@ gl_STDLIB_MODULE_INDICATOR([unsetenv])
gl_VALGRIND_TESTS
abs_aux_dir=`cd "$ac_aux_dir"; pwd`
AC_SUBST([abs_aux_dir])
+gl_YIELD
m4_popdef([gl_MODULE_INDICATOR_CONDITION])
m4_ifval(gltests_LIBSOURCES_LIST, [
m4_syscmd([test ! -d ]m4_defn([gltests_LIBSOURCES_DIR])[ ||
@@ -1008,6 +1082,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/argp-pvh.c
lib/argp-xinl.c
lib/argp.h
+ lib/arpa_inet.in.h
lib/asnprintf.c
lib/asprintf.c
lib/basename-lgpl.c
@@ -1055,6 +1130,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/gettimeofday.c
lib/hmac-md5.c
lib/hmac.h
+ lib/inet_pton.c
lib/intprops.h
lib/isnan.c
lib/isnand-nolibm.h
@@ -1102,9 +1178,11 @@ AC_DEFUN([gl_FILE_LIST], [
lib/realloc.c
lib/recvfrom.c
lib/scandir.c
+ lib/select.c
lib/sendto.c
lib/setsockopt.c
lib/shutdown.c
+ lib/signal.in.h
lib/signbitd.c
lib/signbitf.c
lib/signbitl.c
@@ -1136,6 +1214,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/strndup.c
lib/strnlen.c
lib/strverscmp.c
+ lib/sys_select.in.h
lib/sys_socket.in.h
lib/sys_stat.in.h
lib/sys_time.in.h
@@ -1194,6 +1273,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/fstat.m4
m4/ftell.m4
m4/ftello.m4
+ m4/ftruncate.m4
m4/func.m4
m4/getcwd.m4
m4/getdelim.m4
@@ -1220,6 +1300,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/inttypes-pri.m4
m4/inttypes.m4
m4/inttypes_h.m4
+ m4/ioctl.m4
m4/isnand.m4
m4/isnanf.m4
m4/isnanl.m4
@@ -1257,6 +1338,8 @@ AC_DEFUN([gl_FILE_LIST], [
m4/open.m4
m4/opendir.m4
m4/pathmax.m4
+ m4/perror.m4
+ m4/pipe.m4
m4/po.m4
m4/printf-frexp.m4
m4/printf-frexpl.m4
@@ -1269,7 +1352,9 @@ AC_DEFUN([gl_FILE_LIST], [
m4/readdir.m4
m4/realloc.m4
m4/scandir.m4
+ m4/select.m4
m4/setenv.m4
+ m4/signal_h.m4
m4/signbit.m4
m4/size_max.m4
m4/sleep.m4
@@ -1291,18 +1376,22 @@ AC_DEFUN([gl_FILE_LIST], [
m4/strchrnul.m4
m4/strdup.m4
m4/strerror.m4
+ m4/strerror_r.m4
m4/string_h.m4
m4/strings_h.m4
m4/strndup.m4
m4/strnlen.m4
m4/strverscmp.m4
m4/symlink.m4
+ m4/sys_ioctl_h.m4
+ m4/sys_select_h.m4
m4/sys_socket_h.m4
m4/sys_stat_h.m4
m4/sys_time_h.m4
m4/sys_types_h.m4
m4/sys_uio_h.m4
m4/sysexits.m4
+ m4/thread.m4
m4/threadlib.m4
m4/time_h.m4
m4/time_r.m4
@@ -1324,6 +1413,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/wchar_t.m4
m4/wint_t.m4
m4/xsize.m4
+ m4/yield.m4
tests/infinity.h
tests/init.sh
tests/macros.h
@@ -1341,6 +1431,7 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-byteswap.c
tests/test-c-ctype.c
tests/test-close.c
+ tests/test-connect.c
tests/test-dirent.c
tests/test-dup2.c
tests/test-environ.c
@@ -1376,6 +1467,8 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-ftello3.c
tests/test-ftello4.c
tests/test-ftello4.sh
+ tests/test-ftruncate.c
+ tests/test-ftruncate.sh
tests/test-func.c
tests/test-fwrite.c
tests/test-getcwd-lgpl.c
@@ -1391,6 +1484,7 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-inet_pton.c
tests/test-intprops.c
tests/test-inttypes.c
+ tests/test-ioctl.c
tests/test-isnand-nolibm.c
tests/test-isnand.h
tests/test-isnanf-nolibm.c
@@ -1398,6 +1492,7 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-isnanl-nolibm.c
tests/test-isnanl.h
tests/test-listen.c
+ tests/test-lock.c
tests/test-lstat.c
tests/test-lstat.h
tests/test-malloc-gnu.c
@@ -1410,6 +1505,10 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-open.c
tests/test-open.h
tests/test-pathmax.c
+ tests/test-perror.c
+ tests/test-perror.sh
+ tests/test-perror2.c
+ tests/test-pipe.c
tests/test-printf-frexp.c
tests/test-printf-frexpl.c
tests/test-printf-posix.h
@@ -1417,10 +1516,17 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-rawmemchr.c
tests/test-read-file.c
tests/test-recvfrom.c
+ tests/test-select-fd.c
+ tests/test-select-in.sh
+ tests/test-select-out.sh
+ tests/test-select-stdin.c
+ tests/test-select.c
+ tests/test-select.h
tests/test-sendto.c
tests/test-setenv.c
tests/test-setsockopt.c
tests/test-shutdown.c
+ tests/test-signal-h.c
tests/test-signbit.c
tests/test-sleep.c
tests/test-snprintf.c
@@ -1434,12 +1540,15 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-stdlib.c
tests/test-strchrnul.c
tests/test-strerror.c
+ tests/test-strerror_r.c
tests/test-string.c
tests/test-strings.c
tests/test-strnlen.c
tests/test-strverscmp.c
tests/test-symlink.c
tests/test-symlink.h
+ tests/test-sys_ioctl.c
+ tests/test-sys_select.c
tests/test-sys_socket.c
tests/test-sys_stat.c
tests/test-sys_time.c
@@ -1447,6 +1556,8 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-sys_uio.c
tests/test-sys_wait.h
tests/test-sysexits.c
+ tests/test-thread_create.c
+ tests/test-thread_self.c
tests/test-time.c
tests/test-u64.c
tests/test-unistd.c
@@ -1466,29 +1577,41 @@ AC_DEFUN([gl_FILE_LIST], [
tests/test-vsnprintf.c
tests/test-wchar.c
tests/zerosize-ptr.h
- tests=lib/arpa_inet.in.h
tests=lib/binary-io.h
tests=lib/close.c
+ tests=lib/connect.c
tests=lib/dup2.c
tests=lib/fcntl.in.h
tests=lib/fdopen.c
+ tests=lib/ftruncate.c
tests=lib/getcwd-lgpl.c
tests=lib/getpagesize.c
+ tests=lib/glthread/lock.c
+ tests=lib/glthread/lock.h
+ tests=lib/glthread/thread.c
+ tests=lib/glthread/thread.h
+ tests=lib/glthread/threadlib.c
+ tests=lib/glthread/yield.h
tests=lib/ignore-value.h
- tests=lib/inet_pton.c
tests=lib/inttypes.in.h
+ tests=lib/ioctl.c
tests=lib/lstat.c
tests=lib/malloca.c
tests=lib/malloca.h
tests=lib/malloca.valgrind
tests=lib/open.c
tests=lib/pathmax.h
+ tests=lib/perror.c
+ tests=lib/pipe.c
tests=lib/putenv.c
tests=lib/same-inode.h
tests=lib/setenv.c
tests=lib/stat.c
+ tests=lib/strerror_r.c
tests=lib/symlink.c
+ tests=lib/sys_ioctl.in.h
tests=lib/unsetenv.c
+ tests=lib/w32sock.h
top/GNUmakefile
top/maint.mk
])
diff --git a/gl/m4/ioctl.m4 b/gl/m4/ioctl.m4
new file mode 100644
index 0000000000..a1db8fc096
--- /dev/null
+++ b/gl/m4/ioctl.m4
@@ -0,0 +1,41 @@
+# ioctl.m4 serial 4
+dnl Copyright (C) 2008-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_IOCTL],
+[
+ AC_REQUIRE([gl_SYS_IOCTL_H_DEFAULTS])
+ AC_REQUIRE([gl_HEADER_SYS_SOCKET])
+ HAVE_IOCTL=1
+ if test "$ac_cv_header_winsock2_h" = yes; then
+ dnl Even if the 'socket' module is not used here, another part of the
+ dnl application may use it and pass file descriptors that refer to
+ dnl sockets to the ioctl() function. So enable the support for sockets.
+ HAVE_IOCTL=0
+ else
+ AC_CHECK_FUNCS([ioctl])
+ dnl On glibc systems, the second parameter is 'unsigned long int request',
+ dnl not 'int request'. We cannot simply cast the function pointer, but
+ dnl instead need a wrapper.
+ AC_CACHE_CHECK([for ioctl with POSIX signature],
+ [gl_cv_func_ioctl_posix_signature],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <sys/ioctl.h>]],
+ [[extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ int ioctl (int, int, ...);
+ ]])
+ ],
+ [gl_cv_func_ioctl_posix_signature=yes],
+ [gl_cv_func_ioctl_posix_signature=no])
+ ])
+ if test $gl_cv_func_ioctl_posix_signature != yes; then
+ REPLACE_IOCTL=1
+ fi
+ fi
+])
diff --git a/gl/m4/perror.m4 b/gl/m4/perror.m4
new file mode 100644
index 0000000000..cb17ba38be
--- /dev/null
+++ b/gl/m4/perror.m4
@@ -0,0 +1,63 @@
+# perror.m4 serial 6
+dnl Copyright (C) 2008-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_PERROR],
+[
+ AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+ AC_REQUIRE([gl_HEADER_ERRNO_H])
+ AC_REQUIRE([gl_FUNC_STRERROR_R])
+ AC_REQUIRE([gl_FUNC_STRERROR_0])
+ dnl We intentionally do not check for the broader REPLACE_STRERROR_R,
+ dnl since on glibc systems, strerror_r is replaced only for signature
+ dnl issues, and perror is just fine. Rather, we only want to
+ dnl replace perror if strerror_r was replaced for a content fix.
+ if test "$ERRNO_H:$REPLACE_STRERROR_0" != :0; then
+ dnl The system's perror() cannot know about the new errno values we add
+ dnl to <errno.h>, or any fix for strerror(0). Replace it.
+ REPLACE_PERROR=1
+ fi
+ case ${gl_cv_func_strerror_r_works-unset} in
+ unset|*yes)
+ AC_CACHE_CHECK([whether perror matches strerror],
+ [gl_cv_func_perror_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <errno.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ ]],
+ [[char *str = strerror (-1);
+ if (!getenv("CONFTEST_OUTPUT")) return 0;
+ if (!str) str = "";
+ puts (str);
+ errno = -1;
+ perror ("");
+ return 0;
+ ]])],
+ [if CONFTEST_OUTPUT=1 ./conftest$EXEEXT >conftest.txt1 2>conftest.txt2 \
+ && cmp conftest.txt1 conftest.txt2 >/dev/null; then
+ gl_cv_func_perror_works=yes
+ else
+ gl_cv_func_perror_works=no
+ fi
+ rm -rf conftest.txt1 conftest.txt2],
+ [gl_cv_func_perror_works=no],
+ [dnl Guess no when cross-compiling.
+ gl_cv_func_perror_works="guessing no"
+ ])
+ ])
+ if test "$gl_cv_func_perror_works" != yes; then
+ REPLACE_PERROR=1
+ fi
+ ;;
+ *)
+ dnl The system's perror() probably inherits the bugs in the
+ dnl system's strerror_r(). Replace it.
+ REPLACE_PERROR=1
+ ;;
+ esac
+])
diff --git a/gl/m4/pipe.m4 b/gl/m4/pipe.m4
new file mode 100644
index 0000000000..901317470f
--- /dev/null
+++ b/gl/m4/pipe.m4
@@ -0,0 +1,15 @@
+# pipe.m4 serial 2
+dnl Copyright (C) 2010-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_PIPE],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
+ AC_CHECK_FUNCS_ONCE([pipe])
+ if test $ac_cv_func_pipe != yes; then
+ HAVE_PIPE=0
+ fi
+])
diff --git a/gl/m4/select.m4 b/gl/m4/select.m4
new file mode 100644
index 0000000000..a58f0ac3a1
--- /dev/null
+++ b/gl/m4/select.m4
@@ -0,0 +1,75 @@
+# select.m4 serial 6
+dnl Copyright (C) 2009-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_SELECT],
+[
+ AC_REQUIRE([gl_HEADER_SYS_SELECT])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_REQUIRE([gl_SOCKETS])
+ if test "$ac_cv_header_winsock2_h" = yes; then
+ REPLACE_SELECT=1
+ else
+ dnl On Interix 3.5, select(0, NULL, NULL, NULL, timeout) fails with error
+ dnl EFAULT.
+ AC_CHECK_HEADERS_ONCE([sys/select.h])
+ AC_CACHE_CHECK([whether select supports a 0 argument],
+ [gl_cv_func_select_supports0],
+ [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#include <sys/time.h>
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+int main ()
+{
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 5;
+ return select (0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout) < 0;
+}]])], [gl_cv_func_select_supports0=yes], [gl_cv_func_select_supports0=no],
+ [
+changequote(,)dnl
+ case "$host_os" in
+ # Guess no on Interix.
+ interix*) gl_cv_func_select_supports0="guessing no";;
+ # Guess yes otherwise.
+ *) gl_cv_func_select_supports0="guessing yes";;
+ esac
+changequote([,])dnl
+ ])
+ ])
+ case "$gl_cv_func_select_supports0" in
+ *yes) ;;
+ *) REPLACE_SELECT=1 ;;
+ esac
+ fi
+
+ dnl Determine the needed libraries.
+ LIB_SELECT="$LIBSOCKET"
+ if test $REPLACE_SELECT = 1; then
+ case "$host_os" in
+ mingw*)
+ dnl On the MSVC platform, the function MsgWaitForMultipleObjects
+ dnl (used in lib/select.c) requires linking with -luser32. On mingw,
+ dnl it is implicit.
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE([[
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+int
+main ()
+{
+ MsgWaitForMultipleObjects (0, NULL, 0, 0, 0);
+ return 0;
+}]])],
+ [],
+ [LIB_SELECT="$LIB_SELECT -luser32"])
+ ;;
+ esac
+ fi
+ AC_SUBST([LIB_SELECT])
+])
diff --git a/gl/m4/signal_h.m4 b/gl/m4/signal_h.m4
new file mode 100644
index 0000000000..5cf54a062f
--- /dev/null
+++ b/gl/m4/signal_h.m4
@@ -0,0 +1,83 @@
+# signal_h.m4 serial 18
+dnl Copyright (C) 2007-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_SIGNAL_H],
+[
+ AC_REQUIRE([gl_SIGNAL_H_DEFAULTS])
+ AC_REQUIRE([gl_CHECK_TYPE_SIGSET_T])
+ gl_NEXT_HEADERS([signal.h])
+
+# AIX declares sig_atomic_t to already include volatile, and C89 compilers
+# then choke on 'volatile sig_atomic_t'. C99 requires that it compile.
+ AC_CHECK_TYPE([volatile sig_atomic_t], [],
+ [HAVE_TYPE_VOLATILE_SIG_ATOMIC_T=0], [[
+#include <signal.h>
+ ]])
+
+ dnl Ensure the type pid_t gets defined.
+ AC_REQUIRE([AC_TYPE_PID_T])
+
+ AC_REQUIRE([AC_TYPE_UID_T])
+
+ dnl Persuade glibc <signal.h> to define sighandler_t.
+ AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+ AC_CHECK_TYPE([sighandler_t], [], [HAVE_SIGHANDLER_T=0], [[
+#include <signal.h>
+ ]])
+
+ dnl Check for declarations of anything we want to poison if the
+ dnl corresponding gnulib module is not in use.
+ gl_WARN_ON_USE_PREPARE([[#include <signal.h>
+ ]], [pthread_sigmask sigaction
+ sigaddset sigdelset sigemptyset sigfillset sigismember
+ sigpending sigprocmask])
+])
+
+AC_DEFUN([gl_CHECK_TYPE_SIGSET_T],
+[
+ AC_CHECK_TYPES([sigset_t],
+ [gl_cv_type_sigset_t=yes], [gl_cv_type_sigset_t=no],
+ [[
+ #include <signal.h>
+ /* Mingw defines sigset_t not in <signal.h>, but in <sys/types.h>. */
+ #include <sys/types.h>
+ ]])
+ if test $gl_cv_type_sigset_t != yes; then
+ HAVE_SIGSET_T=0
+ fi
+])
+
+AC_DEFUN([gl_SIGNAL_MODULE_INDICATOR],
+[
+ dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+ AC_REQUIRE([gl_SIGNAL_H_DEFAULTS])
+ gl_MODULE_INDICATOR_SET_VARIABLE([$1])
+ dnl Define it also as a C macro, for the benefit of the unit tests.
+ gl_MODULE_INDICATOR_FOR_TESTS([$1])
+])
+
+AC_DEFUN([gl_SIGNAL_H_DEFAULTS],
+[
+ GNULIB_PTHREAD_SIGMASK=0; AC_SUBST([GNULIB_PTHREAD_SIGMASK])
+ GNULIB_RAISE=0; AC_SUBST([GNULIB_RAISE])
+ GNULIB_SIGNAL_H_SIGPIPE=0; AC_SUBST([GNULIB_SIGNAL_H_SIGPIPE])
+ GNULIB_SIGPROCMASK=0; AC_SUBST([GNULIB_SIGPROCMASK])
+ GNULIB_SIGACTION=0; AC_SUBST([GNULIB_SIGACTION])
+ dnl Assume proper GNU behavior unless another module says otherwise.
+ HAVE_POSIX_SIGNALBLOCKING=1; AC_SUBST([HAVE_POSIX_SIGNALBLOCKING])
+ HAVE_PTHREAD_SIGMASK=1; AC_SUBST([HAVE_PTHREAD_SIGMASK])
+ HAVE_RAISE=1; AC_SUBST([HAVE_RAISE])
+ HAVE_SIGSET_T=1; AC_SUBST([HAVE_SIGSET_T])
+ HAVE_SIGINFO_T=1; AC_SUBST([HAVE_SIGINFO_T])
+ HAVE_SIGACTION=1; AC_SUBST([HAVE_SIGACTION])
+ HAVE_STRUCT_SIGACTION_SA_SIGACTION=1;
+ AC_SUBST([HAVE_STRUCT_SIGACTION_SA_SIGACTION])
+ HAVE_TYPE_VOLATILE_SIG_ATOMIC_T=1;
+ AC_SUBST([HAVE_TYPE_VOLATILE_SIG_ATOMIC_T])
+ HAVE_SIGHANDLER_T=1; AC_SUBST([HAVE_SIGHANDLER_T])
+ REPLACE_PTHREAD_SIGMASK=0; AC_SUBST([REPLACE_PTHREAD_SIGMASK])
+ REPLACE_RAISE=0; AC_SUBST([REPLACE_RAISE])
+])
diff --git a/gl/m4/strerror_r.m4 b/gl/m4/strerror_r.m4
new file mode 100644
index 0000000000..1d4a653d2c
--- /dev/null
+++ b/gl/m4/strerror_r.m4
@@ -0,0 +1,173 @@
+# strerror_r.m4 serial 14
+dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_STRERROR_R],
+[
+ AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+ AC_REQUIRE([gl_FUNC_STRERROR_R_WORKS])
+
+ dnl Persuade Solaris <string.h> to declare strerror_r().
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+ dnl Some systems don't declare strerror_r() if _THREAD_SAFE and _REENTRANT
+ dnl are not defined.
+ AC_CHECK_DECLS_ONCE([strerror_r])
+ if test $ac_cv_have_decl_strerror_r = no; then
+ HAVE_DECL_STRERROR_R=0
+ fi
+
+ if test $ac_cv_func_strerror_r = yes; then
+ if test "$ERRNO_H:$REPLACE_STRERROR_0" = :0; then
+ if test $gl_cv_func_strerror_r_posix_signature = yes; then
+ case "$gl_cv_func_strerror_r_works" in
+ dnl The system's strerror_r has bugs. Replace it.
+ *no) REPLACE_STRERROR_R=1 ;;
+ esac
+ else
+ dnl The system's strerror_r() has a wrong signature. Replace it.
+ REPLACE_STRERROR_R=1
+ fi
+ else
+ dnl The system's strerror_r() cannot know about the new errno values we
+ dnl add to <errno.h>, or any fix for strerror(0). Replace it.
+ REPLACE_STRERROR_R=1
+ fi
+ fi
+])
+
+# Prerequisites of lib/strerror_r.c.
+AC_DEFUN([gl_PREREQ_STRERROR_R], [
+ dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r.
+ AC_CHECK_FUNCS_ONCE([__xpg_strerror_r])
+ AC_CHECK_FUNCS_ONCE([catgets])
+ AC_CHECK_FUNCS_ONCE([snprintf])
+])
+
+# Detect if strerror_r works, but without affecting whether a replacement
+# strerror_r will be used.
+AC_DEFUN([gl_FUNC_STRERROR_R_WORKS],
+[
+ AC_REQUIRE([gl_HEADER_ERRNO_H])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_REQUIRE([gl_FUNC_STRERROR_0])
+
+ AC_CHECK_FUNCS_ONCE([strerror_r])
+ if test $ac_cv_func_strerror_r = yes; then
+ if test "$ERRNO_H:$REPLACE_STRERROR_0" = :0; then
+ dnl The POSIX prototype is: int strerror_r (int, char *, size_t);
+ dnl glibc, Cygwin: char *strerror_r (int, char *, size_t);
+ dnl AIX 5.1, OSF/1 5.1: int strerror_r (int, char *, int);
+ AC_CACHE_CHECK([for strerror_r with POSIX signature],
+ [gl_cv_func_strerror_r_posix_signature],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <string.h>
+ int strerror_r (int, char *, size_t);
+ ]],
+ [])],
+ [gl_cv_func_strerror_r_posix_signature=yes],
+ [gl_cv_func_strerror_r_posix_signature=no])
+ ])
+ if test $gl_cv_func_strerror_r_posix_signature = yes; then
+ dnl AIX 6.1 strerror_r fails by returning -1, not an error number.
+ dnl HP-UX 11.31 strerror_r always fails when the buffer length argument
+ dnl is less than 80.
+ dnl FreeBSD 8.s strerror_r claims failure on 0
+ dnl MacOS X 10.5 strerror_r treats 0 like -1
+ dnl Solaris 10 strerror_r corrupts errno on failure
+ AC_CACHE_CHECK([whether strerror_r works],
+ [gl_cv_func_strerror_r_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <errno.h>
+ #include <string.h>
+ ]],
+ [[int result = 0;
+ char buf[79];
+ if (strerror_r (EACCES, buf, 0) < 0)
+ result |= 1;
+ errno = 0;
+ if (strerror_r (EACCES, buf, sizeof buf) != 0)
+ result |= 2;
+ strcpy (buf, "Unknown");
+ if (strerror_r (0, buf, sizeof buf) != 0)
+ result |= 4;
+ if (errno)
+ result |= 8;
+ if (strstr (buf, "nknown") || strstr (buf, "ndefined"))
+ result |= 0x10;
+ errno = 0;
+ *buf = 0;
+ if (strerror_r (-3, buf, sizeof buf) < 0)
+ result |= 0x20;
+ if (errno)
+ result |= 0x40;
+ if (!*buf)
+ result |= 0x80;
+ return result;
+ ]])],
+ [gl_cv_func_strerror_r_works=yes],
+ [gl_cv_func_strerror_r_works=no],
+ [
+changequote(,)dnl
+ case "$host_os" in
+ # Guess no on AIX.
+ aix*) gl_cv_func_strerror_r_works="guessing no";;
+ # Guess no on HP-UX.
+ hpux*) gl_cv_func_strerror_r_works="guessing no";;
+ # Guess no on BSD variants.
+ *bsd*) gl_cv_func_strerror_r_works="guessing no";;
+ # Guess yes otherwise.
+ *) gl_cv_func_strerror_r_works="guessing yes";;
+ esac
+changequote([,])dnl
+ ])
+ ])
+ else
+ dnl The system's strerror() has a wrong signature.
+ dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r.
+ AC_CHECK_FUNCS_ONCE([__xpg_strerror_r])
+ dnl In glibc < 2.14, __xpg_strerror_r does not populate buf on failure.
+ dnl In cygwin < 1.7.10, __xpg_strerror_r clobbers strerror's buffer.
+ if test $ac_cv_func___xpg_strerror_r = yes; then
+ AC_CACHE_CHECK([whether __xpg_strerror_r works],
+ [gl_cv_func_strerror_r_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <errno.h>
+ #include <string.h>
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ int __xpg_strerror_r(int, char *, size_t);
+ ]],
+ [[int result = 0;
+ char buf[256] = "^";
+ char copy[256];
+ char *str = strerror (-1);
+ strcpy (copy, str);
+ if (__xpg_strerror_r (-2, buf, 1) == 0)
+ result |= 1;
+ if (*buf)
+ result |= 2;
+ __xpg_strerror_r (-2, buf, 256);
+ if (strcmp (str, copy))
+ result |= 4;
+ return result;
+ ]])],
+ [gl_cv_func_strerror_r_works=yes],
+ [gl_cv_func_strerror_r_works=no],
+ [dnl Guess no on all platforms that have __xpg_strerror_r,
+ dnl at least until fixed glibc and cygwin are more common.
+ gl_cv_func_strerror_r_works="guessing no"
+ ])
+ ])
+ fi
+ fi
+ fi
+ fi
+])
diff --git a/gl/m4/sys_ioctl_h.m4 b/gl/m4/sys_ioctl_h.m4
new file mode 100644
index 0000000000..8c7d112cf9
--- /dev/null
+++ b/gl/m4/sys_ioctl_h.m4
@@ -0,0 +1,64 @@
+# sys_ioctl_h.m4 serial 10
+dnl Copyright (C) 2008-2011 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 Written by Bruno Haible.
+
+AC_DEFUN([gl_SYS_IOCTL_H],
+[
+ dnl Use AC_REQUIRE here, so that the default behavior below is expanded
+ dnl once only, before all statements that occur in other macros.
+ AC_REQUIRE([gl_SYS_IOCTL_H_DEFAULTS])
+
+ AC_CHECK_HEADERS_ONCE([sys/ioctl.h])
+ if test $ac_cv_header_sys_ioctl_h = yes; then
+ HAVE_SYS_IOCTL_H=1
+ dnl Test whether <sys/ioctl.h> declares ioctl(), or whether some other
+ dnl header file, such as <unistd.h> or <stropts.h>, is needed for that.
+ AC_CACHE_CHECK([whether <sys/ioctl.h> declares ioctl],
+ [gl_cv_decl_ioctl_in_sys_ioctl_h],
+ [dnl We cannot use AC_CHECK_DECL because it produces its own messages.
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [AC_INCLUDES_DEFAULT([#include <sys/ioctl.h>])],
+ [(void) ioctl;])],
+ [gl_cv_decl_ioctl_in_sys_ioctl_h=yes],
+ [gl_cv_decl_ioctl_in_sys_ioctl_h=no])
+ ])
+ else
+ HAVE_SYS_IOCTL_H=0
+ fi
+ AC_SUBST([HAVE_SYS_IOCTL_H])
+ dnl <sys/ioctl.h> is always overridden, because of GNULIB_POSIXCHECK.
+ gl_CHECK_NEXT_HEADERS([sys/ioctl.h])
+
+ dnl Check for declarations of anything we want to poison if the
+ dnl corresponding gnulib module is not in use.
+ gl_WARN_ON_USE_PREPARE([[#include <sys/ioctl.h>
+/* Some platforms declare ioctl in the wrong header. */
+#if !(defined __GLIBC__ && !defined __UCLIBC__)
+# include <unistd.h>
+#endif
+ ]], [ioctl])
+])
+
+AC_DEFUN([gl_SYS_IOCTL_MODULE_INDICATOR],
+[
+ dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+ AC_REQUIRE([gl_SYS_IOCTL_H_DEFAULTS])
+ gl_MODULE_INDICATOR_SET_VARIABLE([$1])
+ dnl Define it also as a C macro, for the benefit of the unit tests.
+ gl_MODULE_INDICATOR_FOR_TESTS([$1])
+])
+
+AC_DEFUN([gl_SYS_IOCTL_H_DEFAULTS],
+[
+ GNULIB_IOCTL=0; AC_SUBST([GNULIB_IOCTL])
+ dnl Assume proper GNU behavior unless another module says otherwise.
+ SYS_IOCTL_H_HAVE_WINSOCK2_H=0; AC_SUBST([SYS_IOCTL_H_HAVE_WINSOCK2_H])
+ SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS=0;
+ AC_SUBST([SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS])
+ REPLACE_IOCTL=0; AC_SUBST([REPLACE_IOCTL])
+])
diff --git a/gl/m4/sys_select_h.m4 b/gl/m4/sys_select_h.m4
new file mode 100644
index 0000000000..b1914fb80f
--- /dev/null
+++ b/gl/m4/sys_select_h.m4
@@ -0,0 +1,95 @@
+# sys_select_h.m4 serial 20
+dnl Copyright (C) 2006-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_HEADER_SYS_SELECT],
+[
+ AC_REQUIRE([AC_C_RESTRICT])
+ AC_REQUIRE([gl_SYS_SELECT_H_DEFAULTS])
+ AC_CACHE_CHECK([whether <sys/select.h> is self-contained],
+ [gl_cv_header_sys_select_h_selfcontained],
+ [
+ dnl Test against two bugs:
+ dnl 1. On many platforms, <sys/select.h> assumes prior inclusion of
+ dnl <sys/types.h>.
+ dnl 2. On OSF/1 4.0, <sys/select.h> provides only a forward declaration
+ dnl of 'struct timeval', and no definition of this type.
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/select.h>]],
+ [[struct timeval b;]])],
+ [gl_cv_header_sys_select_h_selfcontained=yes],
+ [gl_cv_header_sys_select_h_selfcontained=no])
+ dnl Test against another bug:
+ dnl 3. On Solaris 10, <sys/select.h> provides an FD_ZERO implementation
+ dnl that relies on memset(), but without including <string.h>.
+ if test $gl_cv_header_sys_select_h_selfcontained = yes; then
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <sys/select.h>]],
+ [[int memset; int bzero;]])
+ ],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include <sys/select.h>]], [[
+ #undef memset
+ #define memset nonexistent_memset
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ void *memset (void *, int, unsigned long);
+ #undef bzero
+ #define bzero nonexistent_bzero
+ extern
+ #ifdef __cplusplus
+ "C"
+ #endif
+ void bzero (void *, unsigned long);
+ fd_set fds;
+ FD_ZERO (&fds);
+ ]])
+ ],
+ [],
+ [gl_cv_header_sys_select_h_selfcontained=no])
+ ])
+ fi
+ ])
+ dnl <sys/select.h> is always overridden, because of GNULIB_POSIXCHECK.
+ gl_CHECK_NEXT_HEADERS([sys/select.h])
+ if test $ac_cv_header_sys_select_h = yes; then
+ HAVE_SYS_SELECT_H=1
+ else
+ HAVE_SYS_SELECT_H=0
+ fi
+ AC_SUBST([HAVE_SYS_SELECT_H])
+ gl_PREREQ_SYS_H_WINSOCK2
+
+ dnl Check for declarations of anything we want to poison if the
+ dnl corresponding gnulib module is not in use.
+ gl_WARN_ON_USE_PREPARE([[
+/* Some systems require prerequisite headers. */
+#include <sys/types.h>
+#if !(defined __GLIBC__ && !defined __UCLIBC__) && HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/select.h>
+ ]], [pselect select])
+])
+
+AC_DEFUN([gl_SYS_SELECT_MODULE_INDICATOR],
+[
+ dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+ AC_REQUIRE([gl_SYS_SELECT_H_DEFAULTS])
+ gl_MODULE_INDICATOR_SET_VARIABLE([$1])
+ dnl Define it also as a C macro, for the benefit of the unit tests.
+ gl_MODULE_INDICATOR_FOR_TESTS([$1])
+])
+
+AC_DEFUN([gl_SYS_SELECT_H_DEFAULTS],
+[
+ GNULIB_PSELECT=0; AC_SUBST([GNULIB_PSELECT])
+ GNULIB_SELECT=0; AC_SUBST([GNULIB_SELECT])
+ dnl Assume proper GNU behavior unless another module says otherwise.
+ HAVE_PSELECT=1; AC_SUBST([HAVE_PSELECT])
+ REPLACE_PSELECT=0; AC_SUBST([REPLACE_PSELECT])
+ REPLACE_SELECT=0; AC_SUBST([REPLACE_SELECT])
+])
diff --git a/gl/m4/thread.m4 b/gl/m4/thread.m4
new file mode 100644
index 0000000000..49a4bc772f
--- /dev/null
+++ b/gl/m4/thread.m4
@@ -0,0 +1,18 @@
+# thread.m4 serial 2
+dnl Copyright (C) 2008-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_THREAD],
+[
+ AC_REQUIRE([gl_THREADLIB])
+ AC_REQUIRE([AC_C_INLINE])
+
+ if test $gl_threads_api = posix; then
+ gl_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBMULTITHREAD"
+ AC_CHECK_FUNCS([pthread_atfork])
+ LIBS="$gl_save_LIBS"
+ fi
+])
diff --git a/gl/m4/yield.m4 b/gl/m4/yield.m4
new file mode 100644
index 0000000000..15d5ac208c
--- /dev/null
+++ b/gl/m4/yield.m4
@@ -0,0 +1,19 @@
+# yield.m4 serial 2
+dnl Copyright (C) 2005-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_YIELD],
+[
+ AC_REQUIRE([gl_THREADLIB])
+ dnl On some systems, sched_yield is in librt, rather than in libpthread.
+ YIELD_LIB=
+ if test $gl_threads_api = posix; then
+ dnl Solaris has sched_yield in librt, not in libpthread or libc.
+ AC_CHECK_LIB([rt], [sched_yield], [YIELD_LIB=-lrt],
+ [dnl Solaris 2.5.1, 2.6 has sched_yield in libposix4, not librt.
+ AC_CHECK_LIB([posix4], [sched_yield], [YIELD_LIB=-lposix4])])
+ fi
+ AC_SUBST([YIELD_LIB])
+])
diff --git a/gl/math.in.h b/gl/math.in.h
index c92703f2ac..e0742ecbf8 100644
--- a/gl/math.in.h
+++ b/gl/math.in.h
@@ -35,6 +35,44 @@
/* The definition of _GL_WARN_ON_USE is copied here. */
+#ifdef __cplusplus
+/* Helper macros to define type-generic function FUNC as overloaded functions,
+ rather than as macros like in C. POSIX declares these with an argument of
+ real-floating (that is, one of float, double, or long double). */
+# define _GL_MATH_CXX_REAL_FLOATING_DECL_1(func) \
+static inline int \
+_gl_cxx_ ## func ## f (float f) \
+{ \
+ return func (f); \
+} \
+static inline int \
+_gl_cxx_ ## func ## d (double d) \
+{ \
+ return func (d); \
+} \
+static inline int \
+_gl_cxx_ ## func ## l (long double l) \
+{ \
+ return func (l); \
+}
+# define _GL_MATH_CXX_REAL_FLOATING_DECL_2(func) \
+inline int \
+func (float f) \
+{ \
+ return _gl_cxx_ ## func ## f (f); \
+} \
+inline int \
+func (double d) \
+{ \
+ return _gl_cxx_ ## func ## d (d); \
+} \
+inline int \
+func (long double l) \
+{ \
+ return _gl_cxx_ ## func ## l (l); \
+}
+#endif
+
/* Helper macros to define a portability warning for the
classification macro FUNC called with VALUE. POSIX declares the
classification macros with an argument of real-floating (that is,
@@ -1030,6 +1068,13 @@ _GL_EXTERN_C int gl_isfinitel (long double x);
sizeof (x) == sizeof (double) ? gl_isfinited (x) : \
gl_isfinitef (x))
# endif
+# ifdef __cplusplus
+# ifdef isfinite
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (isfinite)
+# undef isfinite
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (isfinite)
+# endif
+# endif
#elif defined GNULIB_POSIXCHECK
# if defined isfinite
_GL_WARN_REAL_FLOATING_DECL (isfinite);
@@ -1050,6 +1095,13 @@ _GL_EXTERN_C int gl_isinfl (long double x);
sizeof (x) == sizeof (double) ? gl_isinfd (x) : \
gl_isinff (x))
# endif
+# ifdef __cplusplus
+# ifdef isinf
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (isinf)
+# undef isinf
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (isinf)
+# endif
+# endif
#elif defined GNULIB_POSIXCHECK
# if defined isinf
_GL_WARN_REAL_FLOATING_DECL (isinf);
@@ -1161,9 +1213,17 @@ _GL_EXTERN_C int rpl_isnanl (long double x);
sizeof (x) == sizeof (double) ? __builtin_isnan ((double)(x)) : \
__builtin_isnanf ((float)(x)))
# endif
+# ifdef __cplusplus
+# ifdef isnan
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (isnan)
+# undef isnan
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (isnan)
+# endif
+# else
/* Ensure isnan is a macro. */
-# ifndef isnan
-# define isnan isnan
+# ifndef isnan
+# define isnan isnan
+# endif
# endif
#elif defined GNULIB_POSIXCHECK
# if defined isnan
@@ -1227,6 +1287,13 @@ _GL_EXTERN_C int gl_signbitl (long double arg);
sizeof (x) == sizeof (double) ? gl_signbitd (x) : \
gl_signbitf (x))
# endif
+# ifdef __cplusplus
+# ifdef signbit
+_GL_MATH_CXX_REAL_FLOATING_DECL_1 (signbit)
+# undef signbit
+_GL_MATH_CXX_REAL_FLOATING_DECL_2 (signbit)
+# endif
+# endif
#elif defined GNULIB_POSIXCHECK
# if defined signbit
_GL_WARN_REAL_FLOATING_DECL (signbit);
diff --git a/gl/select.c b/gl/select.c
new file mode 100644
index 0000000000..236b951443
--- /dev/null
+++ b/gl/select.c
@@ -0,0 +1,492 @@
+/* Emulation for select(2)
+ Contributed by Paolo Bonzini.
+
+ Copyright 2008-2011 Free Software Foundation, Inc.
+
+ This file is part of gnulib.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+#include <alloca.h>
+#include <assert.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Native Win32. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <conio.h>
+#include <time.h>
+
+#include "msvc-nothrow.h"
+
+struct bitset {
+ unsigned char in[FD_SETSIZE / CHAR_BIT];
+ unsigned char out[FD_SETSIZE / CHAR_BIT];
+};
+
+/* Declare data structures for ntdll functions. */
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+ ULONG NamedPipeType;
+ ULONG NamedPipeConfiguration;
+ ULONG MaximumInstances;
+ ULONG CurrentInstances;
+ ULONG InboundQuota;
+ ULONG ReadDataAvailable;
+ ULONG OutboundQuota;
+ ULONG WriteQuotaAvailable;
+ ULONG NamedPipeState;
+ ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK
+{
+ union {
+ DWORD Status;
+ PVOID Pointer;
+ } u;
+ ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef enum _FILE_INFORMATION_CLASS {
+ FilePipeLocalInformation = 24
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef DWORD (WINAPI *PNtQueryInformationFile)
+ (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
+
+#ifndef PIPE_BUF
+#define PIPE_BUF 512
+#endif
+
+#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
+
+static BOOL
+IsSocketHandle (HANDLE h)
+{
+ WSANETWORKEVENTS ev;
+
+ if (IsConsoleHandle (h))
+ return FALSE;
+
+ /* Under Wine, it seems that getsockopt returns 0 for pipes too.
+ WSAEnumNetworkEvents instead distinguishes the two correctly. */
+ ev.lNetworkEvents = 0xDEADBEEF;
+ WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
+ return ev.lNetworkEvents != 0xDEADBEEF;
+}
+
+/* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
+
+static int
+win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
+ struct bitset *xbits)
+{
+ BOOL read, write, except;
+ int i, ret;
+ INPUT_RECORD *irbuffer;
+ DWORD avail, nbuffer;
+ BOOL bRet;
+ IO_STATUS_BLOCK iosb;
+ FILE_PIPE_LOCAL_INFORMATION fpli;
+ static PNtQueryInformationFile NtQueryInformationFile;
+ static BOOL once_only;
+
+ read = write = except = FALSE;
+ switch (GetFileType (h))
+ {
+ case FILE_TYPE_DISK:
+ read = TRUE;
+ write = TRUE;
+ break;
+
+ case FILE_TYPE_PIPE:
+ if (!once_only)
+ {
+ NtQueryInformationFile = (PNtQueryInformationFile)
+ GetProcAddress (GetModuleHandle ("ntdll.dll"),
+ "NtQueryInformationFile");
+ once_only = TRUE;
+ }
+
+ if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
+ {
+ if (avail)
+ read = TRUE;
+ }
+ else if (GetLastError () == ERROR_BROKEN_PIPE)
+ ;
+
+ else
+ {
+ /* It was the write-end of the pipe. Check if it is writable.
+ If NtQueryInformationFile fails, optimistically assume the pipe is
+ writable. This could happen on Win9x, where NtQueryInformationFile
+ is not available, or if we inherit a pipe that doesn't permit
+ FILE_READ_ATTRIBUTES access on the write end (I think this should
+ not happen since WinXP SP2; WINE seems fine too). Otherwise,
+ ensure that enough space is available for atomic writes. */
+ memset (&iosb, 0, sizeof (iosb));
+ memset (&fpli, 0, sizeof (fpli));
+
+ if (!NtQueryInformationFile
+ || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
+ FilePipeLocalInformation)
+ || fpli.WriteQuotaAvailable >= PIPE_BUF
+ || (fpli.OutboundQuota < PIPE_BUF &&
+ fpli.WriteQuotaAvailable == fpli.OutboundQuota))
+ write = TRUE;
+ }
+ break;
+
+ case FILE_TYPE_CHAR:
+ write = TRUE;
+ if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+ break;
+
+ ret = WaitForSingleObject (h, 0);
+ if (ret == WAIT_OBJECT_0)
+ {
+ if (!IsConsoleHandle (h))
+ {
+ read = TRUE;
+ break;
+ }
+
+ nbuffer = avail = 0;
+ bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
+
+ /* Screen buffers handles are filtered earlier. */
+ assert (bRet);
+ if (nbuffer == 0)
+ {
+ except = TRUE;
+ break;
+ }
+
+ irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
+ bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
+ if (!bRet || avail == 0)
+ {
+ except = TRUE;
+ break;
+ }
+
+ for (i = 0; i < avail; i++)
+ if (irbuffer[i].EventType == KEY_EVENT)
+ read = TRUE;
+ }
+ break;
+
+ default:
+ ret = WaitForSingleObject (h, 0);
+ write = TRUE;
+ if (ret == WAIT_OBJECT_0)
+ read = TRUE;
+
+ break;
+ }
+
+ ret = 0;
+ if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+ {
+ rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+ ret++;
+ }
+
+ if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+ {
+ wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+ ret++;
+ }
+
+ if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
+ {
+ xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
+ ret++;
+ }
+
+ return ret;
+}
+
+int
+rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
+ struct timeval *timeout)
+{
+ static struct timeval tv0;
+ static HANDLE hEvent;
+ HANDLE h, handle_array[FD_SETSIZE + 2];
+ fd_set handle_rfds, handle_wfds, handle_xfds;
+ struct bitset rbits, wbits, xbits;
+ unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
+ DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
+ MSG msg;
+ int i, fd, rc;
+
+ if (nfds > FD_SETSIZE)
+ nfds = FD_SETSIZE;
+
+ if (!timeout)
+ wait_timeout = INFINITE;
+ else
+ {
+ wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+
+ /* select is also used as a portable usleep. */
+ if (!rfds && !wfds && !xfds)
+ {
+ Sleep (wait_timeout);
+ return 0;
+ }
+ }
+
+ if (!hEvent)
+ hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+ handle_array[0] = hEvent;
+ nhandles = 1;
+ nsock = 0;
+
+ /* Copy descriptors to bitsets. At the same time, eliminate
+ bits in the "wrong" direction for console input buffers
+ and screen buffers, because screen buffers are waitable
+ and they will block until a character is available. */
+ memset (&rbits, 0, sizeof (rbits));
+ memset (&wbits, 0, sizeof (wbits));
+ memset (&xbits, 0, sizeof (xbits));
+ memset (anyfds_in, 0, sizeof (anyfds_in));
+ if (rfds)
+ for (i = 0; i < rfds->fd_count; i++)
+ {
+ fd = rfds->fd_array[i];
+ h = (HANDLE) _get_osfhandle (fd);
+ if (IsConsoleHandle (h)
+ && !GetNumberOfConsoleInputEvents (h, &nbuffer))
+ continue;
+
+ rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ }
+ else
+ rfds = (fd_set *) alloca (sizeof (fd_set));
+
+ if (wfds)
+ for (i = 0; i < wfds->fd_count; i++)
+ {
+ fd = wfds->fd_array[i];
+ h = (HANDLE) _get_osfhandle (fd);
+ if (IsConsoleHandle (h)
+ && GetNumberOfConsoleInputEvents (h, &nbuffer))
+ continue;
+
+ wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ }
+ else
+ wfds = (fd_set *) alloca (sizeof (fd_set));
+
+ if (xfds)
+ for (i = 0; i < xfds->fd_count; i++)
+ {
+ fd = xfds->fd_array[i];
+ xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
+ }
+ else
+ xfds = (fd_set *) alloca (sizeof (fd_set));
+
+ /* Zero all the fd_sets, including the application's. */
+ FD_ZERO (rfds);
+ FD_ZERO (wfds);
+ FD_ZERO (xfds);
+ FD_ZERO (&handle_rfds);
+ FD_ZERO (&handle_wfds);
+ FD_ZERO (&handle_xfds);
+
+ /* Classify handles. Create fd sets for sockets, poll the others. */
+ for (i = 0; i < nfds; i++)
+ {
+ if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+ continue;
+
+ h = (HANDLE) _get_osfhandle (i);
+ if (!h)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (IsSocketHandle (h))
+ {
+ int requested = FD_CLOSE;
+
+ /* See above; socket handles are mapped onto select, but we
+ need to map descriptors to handles. */
+ if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ requested |= FD_READ | FD_ACCEPT;
+ FD_SET ((SOCKET) h, rfds);
+ FD_SET ((SOCKET) h, &handle_rfds);
+ }
+ if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ requested |= FD_WRITE | FD_CONNECT;
+ FD_SET ((SOCKET) h, wfds);
+ FD_SET ((SOCKET) h, &handle_wfds);
+ }
+ if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ requested |= FD_OOB;
+ FD_SET ((SOCKET) h, xfds);
+ FD_SET ((SOCKET) h, &handle_xfds);
+ }
+
+ WSAEventSelect ((SOCKET) h, hEvent, requested);
+ nsock++;
+ }
+ else
+ {
+ handle_array[nhandles++] = h;
+
+ /* Poll now. If we get an event, do not wait below. */
+ if (wait_timeout != 0
+ && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
+ wait_timeout = 0;
+ }
+ }
+
+ if (wait_timeout == 0 || nsock == 0)
+ rc = 0;
+ else
+ {
+ /* See if we need to wait in the loop below. If any select is ready,
+ do MsgWaitForMultipleObjects anyway to dispatch messages, but
+ no need to call select again. */
+ rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
+ if (rc == 0)
+ {
+ /* Restore the fd_sets for the other select we do below. */
+ memcpy (&handle_rfds, rfds, sizeof (fd_set));
+ memcpy (&handle_wfds, wfds, sizeof (fd_set));
+ memcpy (&handle_xfds, xfds, sizeof (fd_set));
+ }
+ else
+ wait_timeout = 0;
+ }
+
+ for (;;)
+ {
+ ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
+ wait_timeout, QS_ALLINPUT);
+
+ if (ret == WAIT_OBJECT_0 + nhandles)
+ {
+ /* new input of some other kind */
+ BOOL bRet;
+ while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+ else
+ break;
+ }
+
+ /* If we haven't done it yet, check the status of the sockets. */
+ if (rc == 0 && nsock > 0)
+ rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
+
+ /* Now fill in the results. */
+ FD_ZERO (rfds);
+ FD_ZERO (wfds);
+ FD_ZERO (xfds);
+
+ /* Place a sentinel at the end of the array. */
+ handle_array[nhandles] = NULL;
+ nhandles = 1;
+ for (i = 0; i < nfds; i++)
+ {
+ if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+ continue;
+
+ h = (HANDLE) _get_osfhandle (i);
+ if (h != handle_array[nhandles])
+ {
+ /* Perform handle->descriptor mapping. Don't update rc, as these
+ results are counted in the return value of Winsock's select. */
+ WSAEventSelect ((SOCKET) h, NULL, 0);
+ if (FD_ISSET (h, &handle_rfds))
+ FD_SET (i, rfds);
+ if (FD_ISSET (h, &handle_wfds))
+ FD_SET (i, wfds);
+ if (FD_ISSET (h, &handle_xfds))
+ FD_SET (i, xfds);
+ }
+ else
+ {
+ /* Not a socket. */
+ nhandles++;
+ win32_poll_handle (h, i, &rbits, &wbits, &xbits);
+ if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ rc++;
+ FD_SET (i, rfds);
+ }
+ if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ rc++;
+ FD_SET (i, wfds);
+ }
+ if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ {
+ rc++;
+ FD_SET (i, xfds);
+ }
+ }
+ }
+
+ return rc;
+}
+
+#else /* ! Native Win32. */
+
+#include <sys/select.h>
+
+#undef select
+
+int
+rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
+ struct timeval *timeout)
+{
+ /* Interix 3.5 has a bug: it does not support nfds == 0. */
+ if (nfds == 0)
+ {
+ nfds = 1;
+ rfds = NULL;
+ wfds = NULL;
+ xfds = NULL;
+ }
+ return select (nfds, rfds, wfds, xfds, timeout);
+}
+
+#endif
diff --git a/gl/signal.in.h b/gl/signal.in.h
new file mode 100644
index 0000000000..e18e0b2983
--- /dev/null
+++ b/gl/signal.in.h
@@ -0,0 +1,447 @@
+/* A GNU-like <signal.h>.
+
+ Copyright (C) 2006-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+#if defined __need_sig_atomic_t || defined __need_sigset_t || defined _GL_ALREADY_INCLUDING_SIGNAL_H || (defined _SIGNAL_H && !defined __SIZEOF_PTHREAD_MUTEX_T)
+/* Special invocation convention:
+ - Inside glibc header files.
+ - On glibc systems we have a sequence of nested includes
+ <signal.h> -> <ucontext.h> -> <signal.h>.
+ In this situation, the functions are not yet declared, therefore we cannot
+ provide the C++ aliases.
+ - On glibc systems with GCC 4.3 we have a sequence of nested includes
+ <csignal> -> </usr/include/signal.h> -> <sys/ucontext.h> -> <signal.h>.
+ In this situation, some of the functions are not yet declared, therefore
+ we cannot provide the C++ aliases. */
+
+# @INCLUDE_NEXT@ @NEXT_SIGNAL_H@
+
+#else
+/* Normal invocation convention. */
+
+#ifndef _@GUARD_PREFIX@_SIGNAL_H
+
+#define _GL_ALREADY_INCLUDING_SIGNAL_H
+
+/* Define pid_t, uid_t.
+ Also, mingw defines sigset_t not in <signal.h>, but in <sys/types.h>.
+ On Solaris 10, <signal.h> includes <sys/types.h>, which eventually includes
+ us; so include <sys/types.h> now, before the second inclusion guard. */
+#include <sys/types.h>
+
+/* The include_next requires a split double-inclusion guard. */
+#@INCLUDE_NEXT@ @NEXT_SIGNAL_H@
+
+#undef _GL_ALREADY_INCLUDING_SIGNAL_H
+
+#ifndef _@GUARD_PREFIX@_SIGNAL_H
+#define _@GUARD_PREFIX@_SIGNAL_H
+
+/* MacOS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6 declare
+ pthread_sigmask in <pthread.h>, not in <signal.h>.
+ But avoid namespace pollution on glibc systems.*/
+#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \
+ && ((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ || defined __sun) \
+ && ! defined __GLIBC__
+# include <pthread.h>
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
+
+/* The definition of _GL_ARG_NONNULL is copied here. */
+
+/* The definition of _GL_WARN_ON_USE is copied here. */
+
+/* On AIX, sig_atomic_t already includes volatile. C99 requires that
+ 'volatile sig_atomic_t' ignore the extra modifier, but C89 did not.
+ Hence, redefine this to a non-volatile type as needed. */
+#if ! @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@
+# if !GNULIB_defined_sig_atomic_t
+typedef int rpl_sig_atomic_t;
+# undef sig_atomic_t
+# define sig_atomic_t rpl_sig_atomic_t
+# define GNULIB_defined_sig_atomic_t 1
+# endif
+#endif
+
+/* A set or mask of signals. */
+#if !@HAVE_SIGSET_T@
+# if !GNULIB_defined_sigset_t
+typedef unsigned int sigset_t;
+# define GNULIB_defined_sigset_t 1
+# endif
+#endif
+
+/* Define sighandler_t, the type of signal handlers. A GNU extension. */
+#if !@HAVE_SIGHANDLER_T@
+# ifdef __cplusplus
+extern "C" {
+# endif
+# if !GNULIB_defined_sighandler_t
+typedef void (*sighandler_t) (int);
+# define GNULIB_defined_sighandler_t 1
+# endif
+# ifdef __cplusplus
+}
+# endif
+#endif
+
+
+#if @GNULIB_SIGNAL_H_SIGPIPE@
+# ifndef SIGPIPE
+/* Define SIGPIPE to a value that does not overlap with other signals. */
+# define SIGPIPE 13
+# define GNULIB_defined_SIGPIPE 1
+/* To actually use SIGPIPE, you also need the gnulib modules 'sigprocmask',
+ 'write', 'stdio'. */
+# endif
+#endif
+
+
+/* Maximum signal number + 1. */
+#ifndef NSIG
+# if defined __TANDEM
+# define NSIG 32
+# endif
+#endif
+
+
+#if @GNULIB_PTHREAD_SIGMASK@
+# if @REPLACE_PTHREAD_SIGMASK@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef pthread_sigmask
+# define pthread_sigmask rpl_pthread_sigmask
+# endif
+_GL_FUNCDECL_RPL (pthread_sigmask, int,
+ (int how, const sigset_t *new_mask, sigset_t *old_mask));
+_GL_CXXALIAS_RPL (pthread_sigmask, int,
+ (int how, const sigset_t *new_mask, sigset_t *old_mask));
+# else
+# if !@HAVE_PTHREAD_SIGMASK@
+_GL_FUNCDECL_SYS (pthread_sigmask, int,
+ (int how, const sigset_t *new_mask, sigset_t *old_mask));
+# endif
+_GL_CXXALIAS_SYS (pthread_sigmask, int,
+ (int how, const sigset_t *new_mask, sigset_t *old_mask));
+# endif
+_GL_CXXALIASWARN (pthread_sigmask);
+#elif defined GNULIB_POSIXCHECK
+# undef pthread_sigmask
+# if HAVE_RAW_DECL_PTHREAD_SIGMASK
+_GL_WARN_ON_USE (pthread_sigmask, "pthread_sigmask is not portable - "
+ "use gnulib module pthread_sigmask for portability");
+# endif
+#endif
+
+
+#if @GNULIB_RAISE@
+# if @REPLACE_RAISE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef raise
+# define raise rpl_raise
+# endif
+_GL_FUNCDECL_RPL (raise, int, (int sig));
+_GL_CXXALIAS_RPL (raise, int, (int sig));
+# else
+# if !@HAVE_RAISE@
+_GL_FUNCDECL_SYS (raise, int, (int sig));
+# endif
+_GL_CXXALIAS_SYS (raise, int, (int sig));
+# endif
+_GL_CXXALIASWARN (raise);
+#elif defined GNULIB_POSIXCHECK
+# undef raise
+/* Assume raise is always declared. */
+_GL_WARN_ON_USE (raise, "raise can crash on native Windows - "
+ "use gnulib module raise for portability");
+#endif
+
+
+#if @GNULIB_SIGPROCMASK@
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+
+# ifndef GNULIB_defined_signal_blocking
+# define GNULIB_defined_signal_blocking 1
+# endif
+
+/* Maximum signal number + 1. */
+# ifndef NSIG
+# define NSIG 32
+# endif
+
+/* This code supports only 32 signals. */
+# if !GNULIB_defined_verify_NSIG_constraint
+typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1];
+# define GNULIB_defined_verify_NSIG_constraint 1
+# endif
+
+# endif
+
+/* Test whether a given signal is contained in a signal set. */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X. */
+# if defined __cplusplus && defined GNULIB_NAMESPACE
+# undef sigismember
+# endif
+# else
+_GL_FUNCDECL_SYS (sigismember, int, (const sigset_t *set, int sig)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigismember, int, (const sigset_t *set, int sig));
+_GL_CXXALIASWARN (sigismember);
+
+/* Initialize a signal set to the empty set. */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X. */
+# if defined __cplusplus && defined GNULIB_NAMESPACE
+# undef sigemptyset
+# endif
+# else
+_GL_FUNCDECL_SYS (sigemptyset, int, (sigset_t *set) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigemptyset, int, (sigset_t *set));
+_GL_CXXALIASWARN (sigemptyset);
+
+/* Add a signal to a signal set. */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X. */
+# if defined __cplusplus && defined GNULIB_NAMESPACE
+# undef sigaddset
+# endif
+# else
+_GL_FUNCDECL_SYS (sigaddset, int, (sigset_t *set, int sig)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigaddset, int, (sigset_t *set, int sig));
+_GL_CXXALIASWARN (sigaddset);
+
+/* Remove a signal from a signal set. */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X. */
+# if defined __cplusplus && defined GNULIB_NAMESPACE
+# undef sigdelset
+# endif
+# else
+_GL_FUNCDECL_SYS (sigdelset, int, (sigset_t *set, int sig)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigdelset, int, (sigset_t *set, int sig));
+_GL_CXXALIASWARN (sigdelset);
+
+/* Fill a signal set with all possible signals. */
+# if @HAVE_POSIX_SIGNALBLOCKING@
+/* This function is defined as a macro on MacOS X. */
+# if defined __cplusplus && defined GNULIB_NAMESPACE
+# undef sigfillset
+# endif
+# else
+_GL_FUNCDECL_SYS (sigfillset, int, (sigset_t *set) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigfillset, int, (sigset_t *set));
+_GL_CXXALIASWARN (sigfillset);
+
+/* Return the set of those blocked signals that are pending. */
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+_GL_FUNCDECL_SYS (sigpending, int, (sigset_t *set) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (sigpending, int, (sigset_t *set));
+_GL_CXXALIASWARN (sigpending);
+
+/* If OLD_SET is not NULL, put the current set of blocked signals in *OLD_SET.
+ Then, if SET is not NULL, affect the current set of blocked signals by
+ combining it with *SET as indicated in OPERATION.
+ In this implementation, you are not allowed to change a signal handler
+ while the signal is blocked. */
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+# define SIG_BLOCK 0 /* blocked_set = blocked_set | *set; */
+# define SIG_SETMASK 1 /* blocked_set = *set; */
+# define SIG_UNBLOCK 2 /* blocked_set = blocked_set & ~*set; */
+_GL_FUNCDECL_SYS (sigprocmask, int,
+ (int operation, const sigset_t *set, sigset_t *old_set));
+# endif
+_GL_CXXALIAS_SYS (sigprocmask, int,
+ (int operation, const sigset_t *set, sigset_t *old_set));
+_GL_CXXALIASWARN (sigprocmask);
+
+/* Install the handler FUNC for signal SIG, and return the previous
+ handler. */
+# ifdef __cplusplus
+extern "C" {
+# endif
+# if !GNULIB_defined_function_taking_int_returning_void_t
+typedef void (*_gl_function_taking_int_returning_void_t) (int);
+# define GNULIB_defined_function_taking_int_returning_void_t 1
+# endif
+# ifdef __cplusplus
+}
+# endif
+# if !@HAVE_POSIX_SIGNALBLOCKING@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define signal rpl_signal
+# endif
+_GL_FUNCDECL_RPL (signal, _gl_function_taking_int_returning_void_t,
+ (int sig, _gl_function_taking_int_returning_void_t func));
+_GL_CXXALIAS_RPL (signal, _gl_function_taking_int_returning_void_t,
+ (int sig, _gl_function_taking_int_returning_void_t func));
+# else
+_GL_CXXALIAS_SYS (signal, _gl_function_taking_int_returning_void_t,
+ (int sig, _gl_function_taking_int_returning_void_t func));
+# endif
+_GL_CXXALIASWARN (signal);
+
+# if !@HAVE_POSIX_SIGNALBLOCKING@ && GNULIB_defined_SIGPIPE
+/* Raise signal SIGPIPE. */
+_GL_EXTERN_C int _gl_raise_SIGPIPE (void);
+# endif
+
+#elif defined GNULIB_POSIXCHECK
+# undef sigaddset
+# if HAVE_RAW_DECL_SIGADDSET
+_GL_WARN_ON_USE (sigaddset, "sigaddset is unportable - "
+ "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigdelset
+# if HAVE_RAW_DECL_SIGDELSET
+_GL_WARN_ON_USE (sigdelset, "sigdelset is unportable - "
+ "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigemptyset
+# if HAVE_RAW_DECL_SIGEMPTYSET
+_GL_WARN_ON_USE (sigemptyset, "sigemptyset is unportable - "
+ "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigfillset
+# if HAVE_RAW_DECL_SIGFILLSET
+_GL_WARN_ON_USE (sigfillset, "sigfillset is unportable - "
+ "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigismember
+# if HAVE_RAW_DECL_SIGISMEMBER
+_GL_WARN_ON_USE (sigismember, "sigismember is unportable - "
+ "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigpending
+# if HAVE_RAW_DECL_SIGPENDING
+_GL_WARN_ON_USE (sigpending, "sigpending is unportable - "
+ "use the gnulib module sigprocmask for portability");
+# endif
+# undef sigprocmask
+# if HAVE_RAW_DECL_SIGPROCMASK
+_GL_WARN_ON_USE (sigprocmask, "sigprocmask is unportable - "
+ "use the gnulib module sigprocmask for portability");
+# endif
+#endif /* @GNULIB_SIGPROCMASK@ */
+
+
+#if @GNULIB_SIGACTION@
+# if !@HAVE_SIGACTION@
+
+# if !@HAVE_SIGINFO_T@
+
+# if !GNULIB_defined_siginfo_types
+
+/* Present to allow compilation, but unsupported by gnulib. */
+union sigval
+{
+ int sival_int;
+ void *sival_ptr;
+};
+
+/* Present to allow compilation, but unsupported by gnulib. */
+struct siginfo_t
+{
+ int si_signo;
+ int si_code;
+ int si_errno;
+ pid_t si_pid;
+ uid_t si_uid;
+ void *si_addr;
+ int si_status;
+ long si_band;
+ union sigval si_value;
+};
+typedef struct siginfo_t siginfo_t;
+
+# define GNULIB_defined_siginfo_types 1
+# endif
+
+# endif /* !@HAVE_SIGINFO_T@ */
+
+/* We assume that platforms which lack the sigaction() function also lack
+ the 'struct sigaction' type, and vice versa. */
+
+# if !GNULIB_defined_struct_sigaction
+
+struct sigaction
+{
+ union
+ {
+ void (*_sa_handler) (int);
+ /* Present to allow compilation, but unsupported by gnulib. POSIX
+ says that implementations may, but not must, make sa_sigaction
+ overlap with sa_handler, but we know of no implementation where
+ they do not overlap. */
+ void (*_sa_sigaction) (int, siginfo_t *, void *);
+ } _sa_func;
+ sigset_t sa_mask;
+ /* Not all POSIX flags are supported. */
+ int sa_flags;
+};
+# define sa_handler _sa_func._sa_handler
+# define sa_sigaction _sa_func._sa_sigaction
+/* Unsupported flags are not present. */
+# define SA_RESETHAND 1
+# define SA_NODEFER 2
+# define SA_RESTART 4
+
+# define GNULIB_defined_struct_sigaction 1
+# endif
+
+_GL_FUNCDECL_SYS (sigaction, int, (int, const struct sigaction *restrict,
+ struct sigaction *restrict));
+
+# elif !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@
+
+# define sa_sigaction sa_handler
+
+# endif /* !@HAVE_SIGACTION@, !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ */
+
+_GL_CXXALIAS_SYS (sigaction, int, (int, const struct sigaction *restrict,
+ struct sigaction *restrict));
+_GL_CXXALIASWARN (sigaction);
+
+#elif defined GNULIB_POSIXCHECK
+# undef sigaction
+# if HAVE_RAW_DECL_SIGACTION
+_GL_WARN_ON_USE (sigaction, "sigaction is unportable - "
+ "use the gnulib module sigaction for portability");
+# endif
+#endif
+
+/* Some systems don't have SA_NODEFER. */
+#ifndef SA_NODEFER
+# define SA_NODEFER 0
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_SIGNAL_H */
+#endif /* _@GUARD_PREFIX@_SIGNAL_H */
+#endif
diff --git a/gl/strerror-override.c b/gl/strerror-override.c
index d6ecf2ecae..4e2c32b9c0 100644
--- a/gl/strerror-override.c
+++ b/gl/strerror-override.c
@@ -23,7 +23,7 @@
#include <errno.h>
-#if GNULIB_defined_ESOCK /* native Windows platforms */
+#if GNULIB_defined_EWINSOCK /* native Windows platforms */
# if HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
@@ -42,13 +42,7 @@ strerror_override (int errnum)
return "Success";
#endif
-#if GNULIB_defined_ETXTBSY
- case ETXTBSY:
- return "Text file busy";
-#endif
-
-#if GNULIB_defined_ESOCK /* native Windows platforms */
- /* EWOULDBLOCK is the same as EAGAIN. */
+#if GNULIB_defined_ESOCK /* native Windows platforms with older <errno.h> */
case EINPROGRESS:
return "Operation now in progress";
case EALREADY:
@@ -65,12 +59,8 @@ strerror_override (int errnum)
return "Protocol not available";
case EPROTONOSUPPORT:
return "Protocol not supported";
- case ESOCKTNOSUPPORT:
- return "Socket type not supported";
case EOPNOTSUPP:
return "Operation not supported";
- case EPFNOSUPPORT:
- return "Protocol family not supported";
case EAFNOSUPPORT:
return "Address family not supported by protocol";
case EADDRINUSE:
@@ -81,10 +71,6 @@ strerror_override (int errnum)
return "Network is down";
case ENETUNREACH:
return "Network is unreachable";
- case ENETRESET:
- return "Network dropped connection on reset";
- case ECONNABORTED:
- return "Software caused connection abort";
case ECONNRESET:
return "Connection reset by peer";
case ENOBUFS:
@@ -93,20 +79,44 @@ strerror_override (int errnum)
return "Transport endpoint is already connected";
case ENOTCONN:
return "Transport endpoint is not connected";
- case ESHUTDOWN:
- return "Cannot send after transport endpoint shutdown";
- case ETOOMANYREFS:
- return "Too many references: cannot splice";
case ETIMEDOUT:
return "Connection timed out";
case ECONNREFUSED:
return "Connection refused";
case ELOOP:
return "Too many levels of symbolic links";
- case EHOSTDOWN:
- return "Host is down";
case EHOSTUNREACH:
return "No route to host";
+ case EWOULDBLOCK:
+ return "Operation would block";
+ case ETXTBSY:
+ return "Text file busy";
+ case ENODATA:
+ return "No data available";
+ case ENOSR:
+ return "Out of streams resources";
+ case ENOSTR:
+ return "Device not a stream";
+ case ENOTRECOVERABLE:
+ return "State not recoverable";
+ case EOWNERDEAD:
+ return "Owner died";
+ case ETIME:
+ return "Timer expired";
+ case EOTHER:
+ return "Other error";
+#endif
+#if GNULIB_defined_EWINSOCK /* native Windows platforms */
+ case ESOCKTNOSUPPORT:
+ return "Socket type not supported";
+ case EPFNOSUPPORT:
+ return "Protocol family not supported";
+ case ESHUTDOWN:
+ return "Cannot send after transport endpoint shutdown";
+ case ETOOMANYREFS:
+ return "Too many references: cannot splice";
+ case EHOSTDOWN:
+ return "Host is down";
case EPROCLIM:
return "Too many processes";
case EUSERS:
@@ -134,36 +144,36 @@ strerror_override (int errnum)
/* WSAEINVAL maps to EINVAL */
/* WSAEMFILE maps to EMFILE */
/* WSAEWOULDBLOCK maps to EWOULDBLOCK */
- /* WSAEINPROGRESS is EINPROGRESS */
- /* WSAEALREADY is EALREADY */
- /* WSAENOTSOCK is ENOTSOCK */
- /* WSAEDESTADDRREQ is EDESTADDRREQ */
- /* WSAEMSGSIZE is EMSGSIZE */
- /* WSAEPROTOTYPE is EPROTOTYPE */
- /* WSAENOPROTOOPT is ENOPROTOOPT */
- /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */
+ /* WSAEINPROGRESS maps to EINPROGRESS */
+ /* WSAEALREADY maps to EALREADY */
+ /* WSAENOTSOCK maps to ENOTSOCK */
+ /* WSAEDESTADDRREQ maps to EDESTADDRREQ */
+ /* WSAEMSGSIZE maps to EMSGSIZE */
+ /* WSAEPROTOTYPE maps to EPROTOTYPE */
+ /* WSAENOPROTOOPT maps to ENOPROTOOPT */
+ /* WSAEPROTONOSUPPORT maps to EPROTONOSUPPORT */
/* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */
- /* WSAEOPNOTSUPP is EOPNOTSUPP */
+ /* WSAEOPNOTSUPP maps to EOPNOTSUPP */
/* WSAEPFNOSUPPORT is EPFNOSUPPORT */
- /* WSAEAFNOSUPPORT is EAFNOSUPPORT */
- /* WSAEADDRINUSE is EADDRINUSE */
- /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */
- /* WSAENETDOWN is ENETDOWN */
- /* WSAENETUNREACH is ENETUNREACH */
- /* WSAENETRESET is ENETRESET */
- /* WSAECONNABORTED is ECONNABORTED */
- /* WSAECONNRESET is ECONNRESET */
- /* WSAENOBUFS is ENOBUFS */
- /* WSAEISCONN is EISCONN */
- /* WSAENOTCONN is ENOTCONN */
+ /* WSAEAFNOSUPPORT maps to EAFNOSUPPORT */
+ /* WSAEADDRINUSE maps to EADDRINUSE */
+ /* WSAEADDRNOTAVAIL maps to EADDRNOTAVAIL */
+ /* WSAENETDOWN maps to ENETDOWN */
+ /* WSAENETUNREACH maps to ENETUNREACH */
+ /* WSAENETRESET maps to ENETRESET */
+ /* WSAECONNABORTED maps to ECONNABORTED */
+ /* WSAECONNRESET maps to ECONNRESET */
+ /* WSAENOBUFS maps to ENOBUFS */
+ /* WSAEISCONN maps to EISCONN */
+ /* WSAENOTCONN maps to ENOTCONN */
/* WSAESHUTDOWN is ESHUTDOWN */
/* WSAETOOMANYREFS is ETOOMANYREFS */
- /* WSAETIMEDOUT is ETIMEDOUT */
- /* WSAECONNREFUSED is ECONNREFUSED */
- /* WSAELOOP is ELOOP */
+ /* WSAETIMEDOUT maps to ETIMEDOUT */
+ /* WSAECONNREFUSED maps to ECONNREFUSED */
+ /* WSAELOOP maps to ELOOP */
/* WSAENAMETOOLONG maps to ENAMETOOLONG */
/* WSAEHOSTDOWN is EHOSTDOWN */
- /* WSAEHOSTUNREACH is EHOSTUNREACH */
+ /* WSAEHOSTUNREACH maps to EHOSTUNREACH */
/* WSAENOTEMPTY maps to ENOTEMPTY */
/* WSAEPROCLIM is EPROCLIM */
/* WSAEUSERS is EUSERS */
diff --git a/gl/strerror-override.h b/gl/strerror-override.h
index 81e4a50759..09540b957b 100644
--- a/gl/strerror-override.h
+++ b/gl/strerror-override.h
@@ -29,8 +29,8 @@
/* If ERRNUM maps to an errno value defined by gnulib, return a string
describing the error. Otherwise return NULL. */
# if REPLACE_STRERROR_0 \
- || GNULIB_defined_ETXTBSY \
|| GNULIB_defined_ESOCK \
+ || GNULIB_defined_EWINSOCK \
|| GNULIB_defined_ENOMSG \
|| GNULIB_defined_EIDRM \
|| GNULIB_defined_ENOLINK \
diff --git a/gl/sys_select.in.h b/gl/sys_select.in.h
new file mode 100644
index 0000000000..4406a7a30d
--- /dev/null
+++ b/gl/sys_select.in.h
@@ -0,0 +1,288 @@
+/* Substitute for <sys/select.h>.
+ Copyright (C) 2007-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+# if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+# endif
+@PRAGMA_COLUMNS@
+
+/* On OSF/1, <sys/types.h> and <sys/time.h> include <sys/select.h>.
+ Simply delegate to the system's header in this case. */
+#if @HAVE_SYS_SELECT_H@ && defined __osf__ && (defined _SYS_TYPES_H_ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H) && defined _OSF_SOURCE
+
+# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+#elif @HAVE_SYS_SELECT_H@ && defined __osf__ && (defined _SYS_TIME_H_ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H) && defined _OSF_SOURCE
+
+# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+/* On IRIX 6.5, <sys/timespec.h> includes <sys/types.h>, which includes
+ <sys/bsd_types.h>, which includes <sys/select.h>. At this point we cannot
+ include <signal.h>, because that includes <internal/signal_core.h>, which
+ gives a syntax error because <sys/timespec.h> has not been completely
+ processed. Simply delegate to the system's header in this case. */
+#elif @HAVE_SYS_SELECT_H@ && defined __sgi && (defined _SYS_BSD_TYPES_H && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H)
+
+# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+#else
+
+#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
+
+/* On many platforms, <sys/select.h> assumes prior inclusion of
+ <sys/types.h>. Also, mingw defines sigset_t there, instead of
+ in <signal.h> where it belongs. */
+#include <sys/types.h>
+
+/* Get definition of 'sigset_t'.
+ But avoid namespace pollution on glibc systems. */
+#if !(defined __GLIBC__ && !defined __UCLIBC__)
+# include <signal.h>
+#endif
+
+#if @HAVE_SYS_SELECT_H@
+
+/* On OSF/1 4.0, <sys/select.h> provides only a forward declaration
+ of 'struct timeval', and no definition of this type.
+ Also, MacOS X, AIX, HP-UX, IRIX, Solaris, Interix declare select()
+ in <sys/time.h>.
+ But avoid namespace pollution on glibc systems. */
+# ifndef __GLIBC__
+# include <sys/time.h>
+# endif
+
+/* On AIX 7 and Solaris 10, <sys/select.h> provides an FD_ZERO implementation
+ that relies on memset(), but without including <string.h>.
+ But in any case avoid namespace pollution on glibc systems. */
+# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \
+ && ! defined __GLIBC__
+# include <string.h>
+# endif
+
+/* The include_next requires a split double-inclusion guard. */
+# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
+
+#endif
+
+#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
+#define _@GUARD_PREFIX@_SYS_SELECT_H
+
+#if !@HAVE_SYS_SELECT_H@
+/* A platform that lacks <sys/select.h>. */
+/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros
+ on most platforms. */
+# include <sys/time.h>
+/* On HP-UX 11, <sys/time.h> provides an FD_ZERO implementation
+ that relies on memset(), but without including <string.h>. */
+# if defined __hpux
+# include <string.h>
+# endif
+/* On native Windows platforms:
+ Get the 'fd_set' type.
+ Get the close() declaration before we override it. */
+# if @HAVE_WINSOCK2_H@
+# if !defined _GL_INCLUDING_WINSOCK2_H
+# define _GL_INCLUDING_WINSOCK2_H
+# include <winsock2.h>
+# undef _GL_INCLUDING_WINSOCK2_H
+# endif
+# include <io.h>
+# endif
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
+
+/* The definition of _GL_WARN_ON_USE is copied here. */
+
+
+/* Fix some definitions from <winsock2.h>. */
+
+#if @HAVE_WINSOCK2_H@
+
+# if !GNULIB_defined_rpl_fd_isset
+
+/* Re-define FD_ISSET to avoid a WSA call while we are not using
+ network sockets. */
+static inline int
+rpl_fd_isset (SOCKET fd, fd_set * set)
+{
+ u_int i;
+ if (set == NULL)
+ return 0;
+
+ for (i = 0; i < set->fd_count; i++)
+ if (set->fd_array[i] == fd)
+ return 1;
+
+ return 0;
+}
+
+# define GNULIB_defined_rpl_fd_isset 1
+# endif
+
+# undef FD_ISSET
+# define FD_ISSET(fd, set) rpl_fd_isset(fd, set)
+
+#endif
+
+/* Hide some function declarations from <winsock2.h>. */
+
+#if @HAVE_WINSOCK2_H@
+# if !defined _@GUARD_PREFIX@_UNISTD_H
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef close
+# define close close_used_without_including_unistd_h
+# else
+ _GL_WARN_ON_USE (close,
+ "close() used without including <unistd.h>");
+# endif
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef gethostname
+# define gethostname gethostname_used_without_including_unistd_h
+# else
+ _GL_WARN_ON_USE (gethostname,
+ "gethostname() used without including <unistd.h>");
+# endif
+# endif
+# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef socket
+# define socket socket_used_without_including_sys_socket_h
+# undef connect
+# define connect connect_used_without_including_sys_socket_h
+# undef accept
+# define accept accept_used_without_including_sys_socket_h
+# undef bind
+# define bind bind_used_without_including_sys_socket_h
+# undef getpeername
+# define getpeername getpeername_used_without_including_sys_socket_h
+# undef getsockname
+# define getsockname getsockname_used_without_including_sys_socket_h
+# undef getsockopt
+# define getsockopt getsockopt_used_without_including_sys_socket_h
+# undef listen
+# define listen listen_used_without_including_sys_socket_h
+# undef recv
+# define recv recv_used_without_including_sys_socket_h
+# undef send
+# define send send_used_without_including_sys_socket_h
+# undef recvfrom
+# define recvfrom recvfrom_used_without_including_sys_socket_h
+# undef sendto
+# define sendto sendto_used_without_including_sys_socket_h
+# undef setsockopt
+# define setsockopt setsockopt_used_without_including_sys_socket_h
+# undef shutdown
+# define shutdown shutdown_used_without_including_sys_socket_h
+# else
+ _GL_WARN_ON_USE (socket,
+ "socket() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (connect,
+ "connect() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (accept,
+ "accept() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (bind,
+ "bind() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getpeername,
+ "getpeername() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockname,
+ "getsockname() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockopt,
+ "getsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (listen,
+ "listen() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recv,
+ "recv() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (send,
+ "send() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recvfrom,
+ "recvfrom() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (sendto,
+ "sendto() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (setsockopt,
+ "setsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (shutdown,
+ "shutdown() used without including <sys/socket.h>");
+# endif
+# endif
+#endif
+
+
+#if @GNULIB_PSELECT@
+# if @REPLACE_PSELECT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef pselect
+# define pselect rpl_pselect
+# endif
+_GL_FUNCDECL_RPL (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+_GL_CXXALIAS_RPL (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+# else
+# if !@HAVE_PSELECT@
+_GL_FUNCDECL_SYS (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+# endif
+_GL_CXXALIAS_SYS (pselect, int,
+ (int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
+ struct timespec const *restrict, const sigset_t *restrict));
+# endif
+_GL_CXXALIASWARN (pselect);
+#elif defined GNULIB_POSIXCHECK
+# undef pselect
+# if HAVE_RAW_DECL_PSELECT
+_GL_WARN_ON_USE (pselect, "pselect is not portable - "
+ "use gnulib module pselect for portability");
+# endif
+#endif
+
+#if @GNULIB_SELECT@
+# if @REPLACE_SELECT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef select
+# define select rpl_select
+# endif
+_GL_FUNCDECL_RPL (select, int,
+ (int, fd_set *, fd_set *, fd_set *, struct timeval *));
+_GL_CXXALIAS_RPL (select, int,
+ (int, fd_set *, fd_set *, fd_set *, struct timeval *));
+# else
+_GL_CXXALIAS_SYS (select, int,
+ (int, fd_set *, fd_set *, fd_set *, struct timeval *));
+# endif
+_GL_CXXALIASWARN (select);
+#elif @HAVE_WINSOCK2_H@
+# undef select
+# define select select_used_without_requesting_gnulib_module_select
+#elif defined GNULIB_POSIXCHECK
+# undef select
+# if HAVE_RAW_DECL_SELECT
+_GL_WARN_ON_USE (select, "select is not always POSIX compliant - "
+ "use gnulib module select for portability");
+# endif
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
+#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
+#endif /* OSF/1 */
diff --git a/gl/tests/Makefile.am b/gl/tests/Makefile.am
index d66ab49a3d..f1e68b6b58 100644
--- a/gl/tests/Makefile.am
+++ b/gl/tests/Makefile.am
@@ -22,7 +22,7 @@
#
# Generated by gnulib-tool.
-AUTOMAKE_OPTIONS = 1.5 foreign
+AUTOMAKE_OPTIONS = 1.5 foreign subdir-objects
SUBDIRS = .
TESTS =
@@ -85,42 +85,6 @@ EXTRA_DIST += test-argp.c test-argp-2.sh
## end gnulib module argp-tests
-## begin gnulib module arpa_inet
-
-BUILT_SOURCES += arpa/inet.h
-
-# We need the following in order to create <arpa/inet.h> when the system
-# doesn't have one.
-arpa/inet.h: arpa_inet.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H)
- $(AM_V_at)$(MKDIR_P) arpa
- $(AM_V_GEN)rm -f $@-t $@ && \
- { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- sed -e 's|@''GUARD_PREFIX''@|GL|g' \
- -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
- -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
- -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
- -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|g' \
- -e 's|@''NEXT_ARPA_INET_H''@|$(NEXT_ARPA_INET_H)|g' \
- -e 's|@''HAVE_ARPA_INET_H''@|$(HAVE_ARPA_INET_H)|g' \
- -e 's/@''GNULIB_INET_NTOP''@/$(GNULIB_INET_NTOP)/g' \
- -e 's/@''GNULIB_INET_PTON''@/$(GNULIB_INET_PTON)/g' \
- -e 's|@''HAVE_DECL_INET_NTOP''@|$(HAVE_DECL_INET_NTOP)|g' \
- -e 's|@''HAVE_DECL_INET_PTON''@|$(HAVE_DECL_INET_PTON)|g' \
- -e 's|@''REPLACE_INET_NTOP''@|$(REPLACE_INET_NTOP)|g' \
- -e 's|@''REPLACE_INET_PTON''@|$(REPLACE_INET_PTON)|g' \
- -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
- -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
- -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
- < $(srcdir)/arpa_inet.in.h; \
- } > $@-t && \
- mv $@-t $@
-MOSTLYCLEANFILES += arpa/inet.h arpa/inet.h-t
-MOSTLYCLEANDIRS += arpa
-
-EXTRA_DIST += arpa_inet.in.h
-
-## end gnulib module arpa_inet
-
## begin gnulib module arpa_inet-tests
TESTS += test-arpa_inet
@@ -187,6 +151,24 @@ EXTRA_DIST += test-close.c signature.h macros.h
## end gnulib module close-tests
+## begin gnulib module connect
+
+
+EXTRA_DIST += connect.c w32sock.h
+
+EXTRA_libtests_a_SOURCES += connect.c
+
+## end gnulib module connect
+
+## begin gnulib module connect-tests
+
+TESTS += test-connect
+check_PROGRAMS += test-connect
+test_connect_LDADD = $(LDADD) @LIBSOCKET@ $(INET_PTON_LIB)
+EXTRA_DIST += test-connect.c signature.h macros.h
+
+## end gnulib module connect-tests
+
## begin gnulib module crypto/hmac-md5-tests
TESTS += test-hmac-md5
@@ -407,6 +389,23 @@ EXTRA_DIST += test-ftello.c test-ftello.sh test-ftello2.sh test-ftello3.c test-f
## end gnulib module ftello-tests
+## begin gnulib module ftruncate
+
+
+EXTRA_DIST += ftruncate.c
+
+EXTRA_libtests_a_SOURCES += ftruncate.c
+
+## end gnulib module ftruncate
+
+## begin gnulib module ftruncate-tests
+
+TESTS += test-ftruncate.sh
+check_PROGRAMS += test-ftruncate
+EXTRA_DIST += test-ftruncate.c test-ftruncate.sh signature.h macros.h
+
+## end gnulib module ftruncate-tests
+
## begin gnulib module func-tests
TESTS += test-func
@@ -510,15 +509,6 @@ EXTRA_DIST += test-ignore-value.c
## end gnulib module ignore-value-tests
-## begin gnulib module inet_pton
-
-
-EXTRA_DIST += inet_pton.c
-
-EXTRA_libtests_a_SOURCES += inet_pton.c
-
-## end gnulib module inet_pton
-
## begin gnulib module inet_pton-tests
TESTS += test-inet_pton
@@ -586,6 +576,23 @@ EXTRA_DIST += test-inttypes.c
## end gnulib module inttypes-tests
+## begin gnulib module ioctl
+
+
+EXTRA_DIST += ioctl.c w32sock.h
+
+EXTRA_libtests_a_SOURCES += ioctl.c
+
+## end gnulib module ioctl
+
+## begin gnulib module ioctl-tests
+
+TESTS += test-ioctl
+check_PROGRAMS += test-ioctl
+EXTRA_DIST += test-ioctl.c signature.h macros.h
+
+## end gnulib module ioctl-tests
+
## begin gnulib module isnand-nolibm-tests
TESTS += test-isnand-nolibm
@@ -622,6 +629,21 @@ EXTRA_DIST += test-listen.c signature.h macros.h
## end gnulib module listen-tests
+## begin gnulib module lock
+
+libtests_a_SOURCES += glthread/lock.h glthread/lock.c
+
+## end gnulib module lock
+
+## begin gnulib module lock-tests
+
+TESTS += test-lock
+check_PROGRAMS += test-lock
+test_lock_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
+EXTRA_DIST += test-lock.c
+
+## end gnulib module lock-tests
+
## begin gnulib module lstat
@@ -728,6 +750,40 @@ EXTRA_DIST += test-pathmax.c
## end gnulib module pathmax-tests
+## begin gnulib module perror
+
+
+EXTRA_DIST += perror.c
+
+EXTRA_libtests_a_SOURCES += perror.c
+
+## end gnulib module perror
+
+## begin gnulib module perror-tests
+
+TESTS += test-perror.sh test-perror2
+check_PROGRAMS += test-perror test-perror2
+EXTRA_DIST += init.sh macros.h signature.h test-perror.c test-perror2.c test-perror.sh
+
+## end gnulib module perror-tests
+
+## begin gnulib module pipe-posix
+
+
+EXTRA_DIST += pipe.c
+
+EXTRA_libtests_a_SOURCES += pipe.c
+
+## end gnulib module pipe-posix
+
+## begin gnulib module pipe-posix-tests
+
+TESTS += test-pipe
+check_PROGRAMS += test-pipe
+EXTRA_DIST += test-pipe.c signature.h macros.h
+
+## end gnulib module pipe-posix-tests
+
## begin gnulib module printf-frexp-tests
TESTS += test-printf-frexp
@@ -785,6 +841,18 @@ EXTRA_DIST += same-inode.h
## end gnulib module same-inode
+## begin gnulib module select-tests
+
+TESTS += test-select test-select-in.sh test-select-out.sh
+# test-select-stdin has to be run by hand.
+check_PROGRAMS += test-select test-select-fd test-select-stdin
+test_select_LDADD = $(LDADD) @LIB_SELECT@ @LIBSOCKET@ $(INET_PTON_LIB)
+test_select_fd_LDADD = $(LDADD) @LIB_SELECT@
+test_select_stdin_LDADD = $(LDADD) @LIB_SELECT@
+EXTRA_DIST += macros.h signature.h test-select.c test-select.h test-select-fd.c test-select-in.sh test-select-out.sh test-select-stdin.c
+
+## end gnulib module select-tests
+
## begin gnulib module sendto-tests
TESTS += test-sendto
@@ -829,6 +897,14 @@ EXTRA_DIST += test-shutdown.c signature.h macros.h
## end gnulib module shutdown-tests
+## begin gnulib module signal-h-tests
+
+TESTS += test-signal-h
+check_PROGRAMS += test-signal-h
+EXTRA_DIST += test-signal-h.c
+
+## end gnulib module signal-h-tests
+
## begin gnulib module signbit-tests
TESTS += test-signbit
@@ -1019,6 +1095,23 @@ EXTRA_DIST += test-strerror.c signature.h macros.h
## end gnulib module strerror-tests
+## begin gnulib module strerror_r-posix
+
+
+EXTRA_DIST += strerror_r.c
+
+EXTRA_libtests_a_SOURCES += strerror_r.c
+
+## end gnulib module strerror_r-posix
+
+## begin gnulib module strerror_r-posix-tests
+
+TESTS += test-strerror_r
+check_PROGRAMS += test-strerror_r
+EXTRA_DIST += test-strerror_r.c signature.h macros.h
+
+## end gnulib module strerror_r-posix-tests
+
## begin gnulib module string-tests
TESTS += test-string
@@ -1068,6 +1161,54 @@ EXTRA_DIST += test-symlink.h test-symlink.c signature.h macros.h
## end gnulib module symlink-tests
+## begin gnulib module sys_ioctl
+
+BUILT_SOURCES += sys/ioctl.h
+
+# We need the following in order to create <sys/ioctl.h> when the system
+# does not have a complete one.
+sys/ioctl.h: sys_ioctl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H)
+ $(AM_V_at)$(MKDIR_P) sys
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's|@''GUARD_PREFIX''@|GL|g' \
+ -e 's|@''HAVE_SYS_IOCTL_H''@|$(HAVE_SYS_IOCTL_H)|g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''NEXT_SYS_IOCTL_H''@|$(NEXT_SYS_IOCTL_H)|g' \
+ -e 's/@''GNULIB_IOCTL''@/$(GNULIB_IOCTL)/g' \
+ -e 's|@''SYS_IOCTL_H_HAVE_WINSOCK2_H''@|$(SYS_IOCTL_H_HAVE_WINSOCK2_H)|g' \
+ -e 's|@''SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|g' \
+ -e 's|@''REPLACE_IOCTL''@|$(REPLACE_IOCTL)|g' \
+ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ < $(srcdir)/sys_ioctl.in.h; \
+ } > $@-t && \
+ mv $@-t $@
+MOSTLYCLEANFILES += sys/ioctl.h sys/ioctl.h-t
+MOSTLYCLEANDIRS += sys
+
+EXTRA_DIST += sys_ioctl.in.h
+
+## end gnulib module sys_ioctl
+
+## begin gnulib module sys_ioctl-tests
+
+TESTS += test-sys_ioctl
+check_PROGRAMS += test-sys_ioctl
+EXTRA_DIST += test-sys_ioctl.c
+
+## end gnulib module sys_ioctl-tests
+
+## begin gnulib module sys_select-tests
+
+TESTS += test-sys_select
+check_PROGRAMS += test-sys_select
+EXTRA_DIST += test-sys_select.c signature.h
+
+## end gnulib module sys_select-tests
+
## begin gnulib module sys_socket-tests
TESTS += test-sys_socket
@@ -1116,6 +1257,30 @@ EXTRA_DIST += test-sysexits.c
## end gnulib module sysexits-tests
+## begin gnulib module thread
+
+libtests_a_SOURCES += glthread/thread.h glthread/thread.c
+
+## end gnulib module thread
+
+## begin gnulib module thread-tests
+
+TESTS += test-thread_self test-thread_create
+check_PROGRAMS += test-thread_self test-thread_create
+test_thread_self_LDADD = $(LDADD) @LIBTHREAD@
+test_thread_create_LDADD = $(LDADD) @LIBMULTITHREAD@
+EXTRA_DIST += test-thread_self.c test-thread_create.c macros.h
+
+## end gnulib module thread-tests
+
+## begin gnulib module threadlib
+
+libtests_a_SOURCES += glthread/threadlib.c
+
+EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath
+
+## end gnulib module threadlib
+
## begin gnulib module time-tests
TESTS += test-time
@@ -1235,6 +1400,12 @@ EXTRA_DIST += test-wchar.c
## end gnulib module wchar-tests
+## begin gnulib module yield
+
+libtests_a_SOURCES += glthread/yield.h
+
+## end gnulib module yield
+
# Clean up after Solaris cc.
clean-local:
rm -rf SunWS_cache
diff --git a/gl/tests/connect.c b/gl/tests/connect.c
new file mode 100644
index 0000000000..afd13b9f8d
--- /dev/null
+++ b/gl/tests/connect.c
@@ -0,0 +1,56 @@
+/* connect.c --- wrappers for Windows connect function
+
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paolo Bonzini */
+
+#include <config.h>
+
+#define WIN32_LEAN_AND_MEAN
+/* Get winsock2.h. */
+#include <sys/socket.h>
+
+/* Get set_winsock_errno, FD_TO_SOCKET etc. */
+#include "w32sock.h"
+
+#undef connect
+
+int
+rpl_connect (int fd, const struct sockaddr *sockaddr, socklen_t len)
+{
+ SOCKET sock = FD_TO_SOCKET (fd);
+
+ if (sock == INVALID_SOCKET)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ else
+ {
+ int r = connect (sock, sockaddr, len);
+ if (r < 0)
+ {
+ /* EINPROGRESS is not returned by WinSock 2.0; for backwards
+ compatibility, connect(2) uses EWOULDBLOCK. */
+ if (WSAGetLastError () == WSAEWOULDBLOCK)
+ WSASetLastError (WSAEINPROGRESS);
+
+ set_winsock_errno ();
+ }
+
+ return r;
+ }
+}
diff --git a/gl/tests/ftruncate.c b/gl/tests/ftruncate.c
new file mode 100644
index 0000000000..ae1e85890c
--- /dev/null
+++ b/gl/tests/ftruncate.c
@@ -0,0 +1,43 @@
+/* ftruncate emulations for native Windows.
+ This file is in the public domain. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#if HAVE_CHSIZE
+
+# include <errno.h>
+# include <io.h>
+
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+# include "msvc-inval.h"
+static inline int
+chsize_nothrow (int fd, long length)
+{
+ int result;
+
+ TRY_MSVC_INVAL
+ {
+ result = chsize (fd, length);
+ }
+ CATCH_MSVC_INVAL
+ {
+ result = -1;
+ errno = EBADF;
+ }
+ DONE_MSVC_INVAL;
+
+ return result;
+}
+# define chsize chsize_nothrow
+# endif
+
+int
+ftruncate (int fd, off_t length)
+{
+ return chsize (fd, length);
+}
+
+#endif
diff --git a/gl/tests/glthread/lock.c b/gl/tests/glthread/lock.c
new file mode 100644
index 0000000000..64dbd3f518
--- /dev/null
+++ b/gl/tests/glthread/lock.c
@@ -0,0 +1,1058 @@
+/* Locking in multithreaded situations.
+ Copyright (C) 2005-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, 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. */
+
+#include <config.h>
+
+#include "glthread/lock.h"
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+# if HAVE_PTHREAD_RWLOCK
+
+# if !defined PTHREAD_RWLOCK_INITIALIZER
+
+int
+glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_rwlock_init (&lock->rwlock, NULL);
+ if (err != 0)
+ return err;
+ lock->initialized = 1;
+ return 0;
+}
+
+int
+glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->guard);
+ if (err != 0)
+ return err;
+ if (!lock->initialized)
+ {
+ err = glthread_rwlock_init_multithreaded (lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->guard);
+ return err;
+ }
+ }
+ err = pthread_mutex_unlock (&lock->guard);
+ if (err != 0)
+ return err;
+ }
+ return pthread_rwlock_rdlock (&lock->rwlock);
+}
+
+int
+glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->guard);
+ if (err != 0)
+ return err;
+ if (!lock->initialized)
+ {
+ err = glthread_rwlock_init_multithreaded (lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->guard);
+ return err;
+ }
+ }
+ err = pthread_mutex_unlock (&lock->guard);
+ if (err != 0)
+ return err;
+ }
+ return pthread_rwlock_wrlock (&lock->rwlock);
+}
+
+int
+glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ return EINVAL;
+ return pthread_rwlock_unlock (&lock->rwlock);
+}
+
+int
+glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ if (!lock->initialized)
+ return EINVAL;
+ err = pthread_rwlock_destroy (&lock->rwlock);
+ if (err != 0)
+ return err;
+ lock->initialized = 0;
+ return 0;
+}
+
+# endif
+
+# else
+
+int
+glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_init (&lock->lock, NULL);
+ if (err != 0)
+ return err;
+ err = pthread_cond_init (&lock->waiting_readers, NULL);
+ if (err != 0)
+ return err;
+ err = pthread_cond_init (&lock->waiting_writers, NULL);
+ if (err != 0)
+ return err;
+ lock->waiting_writers_count = 0;
+ lock->runcount = 0;
+ return 0;
+}
+
+int
+glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_lock (&lock->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. */
+ while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_readers. */
+ err = pthread_cond_wait (&lock->waiting_readers, &lock->lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ }
+ lock->runcount++;
+ return pthread_mutex_unlock (&lock->lock);
+}
+
+int
+glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_lock (&lock->lock);
+ if (err != 0)
+ return err;
+ /* 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++;
+ err = pthread_cond_wait (&lock->waiting_writers, &lock->lock);
+ if (err != 0)
+ {
+ lock->waiting_writers_count--;
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ lock->waiting_writers_count--;
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ return pthread_mutex_unlock (&lock->lock);
+}
+
+int
+glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_lock (&lock->lock);
+ if (err != 0)
+ return err;
+ if (lock->runcount < 0)
+ {
+ /* Drop a writer lock. */
+ if (!(lock->runcount == -1))
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return EINVAL;
+ }
+ lock->runcount = 0;
+ }
+ else
+ {
+ /* Drop a reader lock. */
+ if (!(lock->runcount > 0))
+ {
+ pthread_mutex_unlock (&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. */
+ err = pthread_cond_signal (&lock->waiting_writers);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ }
+ else
+ {
+ /* Wake up all waiting readers. */
+ err = pthread_cond_broadcast (&lock->waiting_readers);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ }
+ }
+ return pthread_mutex_unlock (&lock->lock);
+}
+
+int
+glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_destroy (&lock->lock);
+ if (err != 0)
+ return err;
+ err = pthread_cond_destroy (&lock->waiting_readers);
+ if (err != 0)
+ return err;
+ err = pthread_cond_destroy (&lock->waiting_writers);
+ if (err != 0)
+ return err;
+ return 0;
+}
+
+# endif
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+# if HAVE_PTHREAD_MUTEX_RECURSIVE
+
+# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ pthread_mutexattr_t attributes;
+ int err;
+
+ err = pthread_mutexattr_init (&attributes);
+ if (err != 0)
+ return err;
+ err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutex_init (lock, &attributes);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutexattr_destroy (&attributes);
+ if (err != 0)
+ return err;
+ return 0;
+}
+
+# else
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ pthread_mutexattr_t attributes;
+ int err;
+
+ err = pthread_mutexattr_init (&attributes);
+ if (err != 0)
+ return err;
+ err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutex_init (&lock->recmutex, &attributes);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutexattr_destroy (&attributes);
+ if (err != 0)
+ return err;
+ lock->initialized = 1;
+ return 0;
+}
+
+int
+glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->guard);
+ if (err != 0)
+ return err;
+ if (!lock->initialized)
+ {
+ err = glthread_recursive_lock_init_multithreaded (lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->guard);
+ return err;
+ }
+ }
+ err = pthread_mutex_unlock (&lock->guard);
+ if (err != 0)
+ return err;
+ }
+ return pthread_mutex_lock (&lock->recmutex);
+}
+
+int
+glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (!lock->initialized)
+ return EINVAL;
+ return pthread_mutex_unlock (&lock->recmutex);
+}
+
+int
+glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
+{
+ int err;
+
+ if (!lock->initialized)
+ return EINVAL;
+ err = pthread_mutex_destroy (&lock->recmutex);
+ if (err != 0)
+ return err;
+ lock->initialized = 0;
+ return 0;
+}
+
+# endif
+
+# else
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_init (&lock->mutex, NULL);
+ if (err != 0)
+ return err;
+ lock->owner = (pthread_t) 0;
+ lock->depth = 0;
+ return 0;
+}
+
+int
+glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
+{
+ pthread_t self = pthread_self ();
+ if (lock->owner != self)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->mutex);
+ if (err != 0)
+ return err;
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ {
+ lock->depth--;
+ return EAGAIN;
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != pthread_self ())
+ return EPERM;
+ if (lock->depth == 0)
+ return EINVAL;
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = (pthread_t) 0;
+ return pthread_mutex_unlock (&lock->mutex);
+ }
+ else
+ return 0;
+}
+
+int
+glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != (pthread_t) 0)
+ return EBUSY;
+ return pthread_mutex_destroy (&lock->mutex);
+}
+
+# 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 -------------------------- */
+
+static 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_multithreaded (pth_once_t *once_control, void (*initfunction) (void))
+{
+ void (*temp) (void) = initfunction;
+ return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0);
+}
+
+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 --------------------- */
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ int err;
+
+ err = mutex_init (&lock->mutex, USYNC_THREAD, NULL);
+ if (err != 0)
+ return err;
+ lock->owner = (thread_t) 0;
+ lock->depth = 0;
+ return 0;
+}
+
+int
+glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
+{
+ thread_t self = thr_self ();
+ if (lock->owner != self)
+ {
+ int err;
+
+ err = mutex_lock (&lock->mutex);
+ if (err != 0)
+ return err;
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ {
+ lock->depth--;
+ return EAGAIN;
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != thr_self ())
+ return EPERM;
+ if (lock->depth == 0)
+ return EINVAL;
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = (thread_t) 0;
+ return mutex_unlock (&lock->mutex);
+ }
+ else
+ return 0;
+}
+
+int
+glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != (thread_t) 0)
+ return EBUSY;
+ return mutex_destroy (&lock->mutex);
+}
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+int
+glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void))
+{
+ if (!once_control->inited)
+ {
+ int err;
+
+ /* Use the mutex to guarantee that if another thread is already calling
+ the initfunction, this thread waits until it's finished. */
+ err = mutex_lock (&once_control->mutex);
+ if (err != 0)
+ return err;
+ if (!once_control->inited)
+ {
+ once_control->inited = 1;
+ initfunction ();
+ }
+ return mutex_unlock (&once_control->mutex);
+ }
+ else
+ return 0;
+}
+
+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_func (gl_lock_t *lock)
+{
+ InitializeCriticalSection (&lock->lock);
+ lock->guard.done = 1;
+}
+
+int
+glthread_lock_lock_func (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);
+ return 0;
+}
+
+int
+glthread_lock_unlock_func (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glthread_lock_destroy_func (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ DeleteCriticalSection (&lock->lock);
+ lock->guard.done = 0;
+ return 0;
+}
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* In this file, the waitqueues are implemented as circular arrays. */
+#define gl_waitqueue_t gl_carray_waitqueue_t
+
+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;
+ }
+ /* Whether the created event is a manual-reset one or an auto-reset one,
+ does not matter, since we will wait on it only once. */
+ 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_func (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;
+}
+
+int
+glthread_rwlock_rdlock_func (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 0;
+ }
+ else
+ {
+ /* Allocation failure. Weird. */
+ do
+ {
+ LeaveCriticalSection (&lock->lock);
+ Sleep (1);
+ EnterCriticalSection (&lock->lock);
+ }
+ while (!(lock->runcount + 1 > 0));
+ }
+ }
+ lock->runcount++;
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glthread_rwlock_wrlock_func (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 0;
+ }
+ 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);
+ return 0;
+}
+
+int
+glthread_rwlock_unlock_func (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ 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))
+ {
+ LeaveCriticalSection (&lock->lock);
+ return EPERM;
+ }
+ 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);
+ return 0;
+}
+
+int
+glthread_rwlock_destroy_func (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ if (lock->runcount != 0)
+ return EBUSY;
+ 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;
+ return 0;
+}
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+void
+glthread_recursive_lock_init_func (gl_recursive_lock_t *lock)
+{
+ lock->owner = 0;
+ lock->depth = 0;
+ InitializeCriticalSection (&lock->lock);
+ lock->guard.done = 1;
+}
+
+int
+glthread_recursive_lock_lock_func (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? */
+ {
+ lock->depth--;
+ return EAGAIN;
+ }
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != GetCurrentThreadId ())
+ return EPERM;
+ if (lock->depth == 0)
+ return EINVAL;
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = 0;
+ LeaveCriticalSection (&lock->lock);
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != 0)
+ return EBUSY;
+ DeleteCriticalSection (&lock->lock);
+ lock->guard.done = 0;
+ return 0;
+}
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+void
+glthread_once_func (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/gl/tests/glthread/lock.h b/gl/tests/glthread/lock.h
new file mode 100644
index 0000000000..028d881d4c
--- /dev/null
+++ b/gl/tests/glthread/lock.h
@@ -0,0 +1,928 @@
+/* Locking in multithreaded situations.
+ Copyright (C) 2005-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, 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);
+ Equivalent functions with control of error handling:
+ Initialization: err = glthread_lock_init (&name);
+ Taking the lock: err = glthread_lock_lock (&name);
+ Releasing the lock: err = glthread_lock_unlock (&name);
+ De-initialization: err = glthread_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);
+ Equivalent functions with control of error handling:
+ Initialization: err = glthread_rwlock_init (&name);
+ Taking the lock: err = glthread_rwlock_rdlock (&name);
+ err = glthread_rwlock_wrlock (&name);
+ Releasing the lock: err = glthread_rwlock_unlock (&name);
+ De-initialization: err = glthread_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);
+ Equivalent functions with control of error handling:
+ Initialization: err = glthread_recursive_lock_init (&name);
+ Taking the lock: err = glthread_recursive_lock_lock (&name);
+ Releasing the lock: err = glthread_recursive_lock_unlock (&name);
+ De-initialization: err = glthread_recursive_lock_destroy (&name);
+
+ Once-only execution:
+ Type: gl_once_t
+ Initializer: gl_once_define(extern, name)
+ Execution: gl_once (name, initfunction);
+ Equivalent functions with control of error handling:
+ Execution: err = glthread_once (&name, initfunction);
+*/
+
+
+#ifndef _LOCK_H
+#define _LOCK_H
+
+#include <errno.h>
+#include <stdlib.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# 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 glthread_lock_init(LOCK) \
+ (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
+# define glthread_lock_lock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
+# define glthread_lock_unlock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
+# define glthread_lock_destroy(LOCK) \
+ (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
+
+/* ------------------------- 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 glthread_rwlock_init(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
+
+# 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 glthread_rwlock_init(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (pthread_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
+
+# 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 glthread_rwlock_init(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (pthread_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 --------------------- */
+
+# 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 glthread_recursive_lock_init(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+
+# 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 glthread_recursive_lock_init(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_multithreaded (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 glthread_recursive_lock_init(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_multithreaded (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 glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (pthread_in_use () \
+ ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
+ : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
+extern int glthread_once_singlethreaded (pthread_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library. */
+
+# include <pth.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# 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 glthread_lock_init(LOCK) \
+ (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
+# define glthread_lock_lock(LOCK) \
+ (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
+# define glthread_lock_unlock(LOCK) \
+ (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
+# define glthread_lock_destroy(LOCK) \
+ ((void)(LOCK), 0)
+
+/* ------------------------- 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 glthread_rwlock_init(LOCK) \
+ (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ ((void)(LOCK), 0)
+
+/* --------------------- 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 glthread_recursive_lock_init(LOCK) \
+ (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ ((void)(LOCK), 0)
+
+/* -------------------------- 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 glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (pth_in_use () \
+ ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
+ : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
+extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void));
+extern int glthread_once_singlethreaded (pth_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library. */
+
+# include <thread.h>
+# include <synch.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# 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 glthread_lock_init(LOCK) \
+ (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0)
+# define glthread_lock_lock(LOCK) \
+ (thread_in_use () ? mutex_lock (LOCK) : 0)
+# define glthread_lock_unlock(LOCK) \
+ (thread_in_use () ? mutex_unlock (LOCK) : 0)
+# define glthread_lock_destroy(LOCK) \
+ (thread_in_use () ? mutex_destroy (LOCK) : 0)
+
+/* ------------------------- 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 glthread_rwlock_init(LOCK) \
+ (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (thread_in_use () ? rw_rdlock (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (thread_in_use () ? rw_wrlock (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (thread_in_use () ? rw_unlock (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (thread_in_use () ? rwlock_destroy (LOCK) : 0)
+
+/* --------------------- 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 glthread_recursive_lock_init(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_multithreaded (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 glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (thread_in_use () \
+ ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
+ : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
+extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void));
+extern int glthread_once_singlethreaded (gl_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* 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 glthread_lock_init(LOCK) \
+ (glthread_lock_init_func (LOCK), 0)
+# define glthread_lock_lock(LOCK) \
+ glthread_lock_lock_func (LOCK)
+# define glthread_lock_unlock(LOCK) \
+ glthread_lock_unlock_func (LOCK)
+# define glthread_lock_destroy(LOCK) \
+ glthread_lock_destroy_func (LOCK)
+extern void glthread_lock_init_func (gl_lock_t *lock);
+extern int glthread_lock_lock_func (gl_lock_t *lock);
+extern int glthread_lock_unlock_func (gl_lock_t *lock);
+extern int glthread_lock_destroy_func (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_carray_waitqueue_t;
+typedef struct
+ {
+ gl_spinlock_t guard; /* protects the initialization */
+ CRITICAL_SECTION lock; /* protects the remaining fields */
+ gl_carray_waitqueue_t waiting_readers; /* waiting readers */
+ gl_carray_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 glthread_rwlock_init(LOCK) \
+ (glthread_rwlock_init_func (LOCK), 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ glthread_rwlock_rdlock_func (LOCK)
+# define glthread_rwlock_wrlock(LOCK) \
+ glthread_rwlock_wrlock_func (LOCK)
+# define glthread_rwlock_unlock(LOCK) \
+ glthread_rwlock_unlock_func (LOCK)
+# define glthread_rwlock_destroy(LOCK) \
+ glthread_rwlock_destroy_func (LOCK)
+extern void glthread_rwlock_init_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_destroy_func (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 glthread_recursive_lock_init(LOCK) \
+ (glthread_recursive_lock_init_func (LOCK), 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ glthread_recursive_lock_lock_func (LOCK)
+# define glthread_recursive_lock_unlock(LOCK) \
+ glthread_recursive_lock_unlock_func (LOCK)
+# define glthread_recursive_lock_destroy(LOCK) \
+ glthread_recursive_lock_destroy_func (LOCK)
+extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_func (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 glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0)
+extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void));
+
+# ifdef __cplusplus
+}
+# endif
+
+#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 glthread_lock_init(NAME) 0
+# define glthread_lock_lock(NAME) 0
+# define glthread_lock_unlock(NAME) 0
+# define glthread_lock_destroy(NAME) 0
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef int gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME)
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
+# define glthread_rwlock_init(NAME) 0
+# define glthread_rwlock_rdlock(NAME) 0
+# define glthread_rwlock_wrlock(NAME) 0
+# define glthread_rwlock_unlock(NAME) 0
+# define glthread_rwlock_destroy(NAME) 0
+
+/* --------------------- 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 glthread_recursive_lock_init(NAME) 0
+# define glthread_recursive_lock_lock(NAME) 0
+# define glthread_recursive_lock_unlock(NAME) 0
+# define glthread_recursive_lock_destroy(NAME) 0
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef int gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_once_t NAME = 0;
+# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
+
+#endif
+
+/* ========================================================================= */
+
+/* Macros with built-in error handling. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+#define gl_lock_init(NAME) \
+ do \
+ { \
+ if (glthread_lock_init (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_lock_lock(NAME) \
+ do \
+ { \
+ if (glthread_lock_lock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_lock_unlock(NAME) \
+ do \
+ { \
+ if (glthread_lock_unlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_lock_destroy(NAME) \
+ do \
+ { \
+ if (glthread_lock_destroy (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+#define gl_rwlock_init(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_init (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_rdlock(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_rdlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_wrlock(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_wrlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_unlock(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_unlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_destroy(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_destroy (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+#define gl_recursive_lock_init(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_init (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_recursive_lock_lock(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_lock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_recursive_lock_unlock(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_unlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_recursive_lock_destroy(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_destroy (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+#define gl_once(NAME, INITFUNCTION) \
+ do \
+ { \
+ if (glthread_once (&NAME, INITFUNCTION)) \
+ abort (); \
+ } \
+ while (0)
+
+/* ========================================================================= */
+
+#endif /* _LOCK_H */
diff --git a/gl/tests/glthread/thread.c b/gl/tests/glthread/thread.c
new file mode 100644
index 0000000000..83b8c57caf
--- /dev/null
+++ b/gl/tests/glthread/thread.c
@@ -0,0 +1,232 @@
+/* Creating and controlling threads.
+ Copyright (C) 2005-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, 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. */
+
+#include <config.h>
+
+/* Specification. */
+#include "glthread/thread.h"
+
+#include <stdlib.h>
+#include "glthread/lock.h"
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+#include <pthread.h>
+
+#ifdef PTW32_VERSION
+
+const gl_thread_t gl_null_thread /* = { .p = NULL } */;
+
+#endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+#include <process.h>
+
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+/* The Thread-Local Storage (TLS) key that allows to access each thread's
+ 'struct gl_thread_struct *' pointer. */
+static DWORD self_key = (DWORD)-1;
+
+/* Initializes self_key. This function must only be called once. */
+static void
+do_init_self_key (void)
+{
+ self_key = TlsAlloc ();
+ /* If this fails, we're hosed. */
+ if (self_key == (DWORD)-1)
+ abort ();
+}
+
+/* Initializes self_key. */
+static void
+init_self_key (void)
+{
+ gl_once_define(static, once)
+ gl_once (once, do_init_self_key);
+}
+
+/* This structure contains information about a thread.
+ It is stored in TLS under key self_key. */
+struct gl_thread_struct
+{
+ /* Fields for managing the handle. */
+ HANDLE volatile handle;
+ CRITICAL_SECTION handle_lock;
+ /* Fields for managing the exit value. */
+ void * volatile result;
+ /* Fields for managing the thread start. */
+ void * (*func) (void *);
+ void *arg;
+};
+
+/* Return a real HANDLE object for the current thread. */
+static inline HANDLE
+get_current_thread_handle (void)
+{
+ HANDLE this_handle;
+
+ /* GetCurrentThread() returns a pseudo-handle, i.e. only a symbolic
+ identifier, not a real handle. */
+ if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+ GetCurrentProcess (), &this_handle,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ abort ();
+ return this_handle;
+}
+
+gl_thread_t
+gl_thread_self_func (void)
+{
+ gl_thread_t thread;
+
+ if (self_key == (DWORD)-1)
+ init_self_key ();
+ thread = TlsGetValue (self_key);
+ if (thread == NULL)
+ {
+ /* This happens only in threads that have not been created through
+ glthread_create(), such as the main thread. */
+ for (;;)
+ {
+ thread =
+ (struct gl_thread_struct *)
+ malloc (sizeof (struct gl_thread_struct));
+ if (thread != NULL)
+ break;
+ /* Memory allocation failed. There is not much we can do. Have to
+ busy-loop, waiting for the availability of memory. */
+ Sleep (1);
+ }
+
+ thread->handle = get_current_thread_handle ();
+ InitializeCriticalSection (&thread->handle_lock);
+ thread->result = NULL; /* just to be deterministic */
+ TlsSetValue (self_key, thread);
+ }
+ return thread;
+}
+
+/* The main function of a freshly creating thread. It's a wrapper around
+ the FUNC and ARG arguments passed to glthread_create_func. */
+static unsigned int WINAPI
+wrapper_func (void *varg)
+{
+ struct gl_thread_struct *thread = (struct gl_thread_struct *)varg;
+
+ EnterCriticalSection (&thread->handle_lock);
+ /* Create a new handle for the thread only if the parent thread did not yet
+ fill in the handle. */
+ if (thread->handle == NULL)
+ thread->handle = get_current_thread_handle ();
+ LeaveCriticalSection (&thread->handle_lock);
+
+ if (self_key == (DWORD)-1)
+ init_self_key ();
+ TlsSetValue (self_key, thread);
+
+ /* Run the thread. Store the exit value if the thread was not terminated
+ otherwise. */
+ thread->result = thread->func (thread->arg);
+ return 0;
+}
+
+int
+glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg)
+{
+ struct gl_thread_struct *thread =
+ (struct gl_thread_struct *) malloc (sizeof (struct gl_thread_struct));
+ if (thread == NULL)
+ return ENOMEM;
+ thread->handle = NULL;
+ InitializeCriticalSection (&thread->handle_lock);
+ thread->result = NULL; /* just to be deterministic */
+ thread->func = func;
+ thread->arg = arg;
+
+ {
+ unsigned int thread_id;
+ HANDLE thread_handle;
+
+ thread_handle = (HANDLE)
+ _beginthreadex (NULL, 100000, wrapper_func, thread, 0, &thread_id);
+ /* calls CreateThread with the same arguments */
+ if (thread_handle == NULL)
+ {
+ DeleteCriticalSection (&thread->handle_lock);
+ free (thread);
+ return EAGAIN;
+ }
+
+ EnterCriticalSection (&thread->handle_lock);
+ if (thread->handle == NULL)
+ thread->handle = thread_handle;
+ else
+ /* thread->handle was already set by the thread itself. */
+ CloseHandle (thread_handle);
+ LeaveCriticalSection (&thread->handle_lock);
+
+ *threadp = thread;
+ return 0;
+ }
+}
+
+int
+glthread_join_func (gl_thread_t thread, void **retvalp)
+{
+ if (thread == NULL)
+ return EINVAL;
+
+ if (thread == gl_thread_self ())
+ return EDEADLK;
+
+ if (WaitForSingleObject (thread->handle, INFINITE) == WAIT_FAILED)
+ return EINVAL;
+
+ if (retvalp != NULL)
+ *retvalp = thread->result;
+
+ DeleteCriticalSection (&thread->handle_lock);
+ CloseHandle (thread->handle);
+ free (thread);
+
+ return 0;
+}
+
+int
+gl_thread_exit_func (void *retval)
+{
+ gl_thread_t thread = gl_thread_self ();
+ thread->result = retval;
+ _endthreadex (0); /* calls ExitThread (0) */
+ abort ();
+}
+
+#endif
+
+/* ========================================================================= */
diff --git a/gl/tests/glthread/thread.h b/gl/tests/glthread/thread.h
new file mode 100644
index 0000000000..064d72f415
--- /dev/null
+++ b/gl/tests/glthread/thread.h
@@ -0,0 +1,401 @@
+/* Creating and controlling threads.
+ Copyright (C) 2005-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, 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 primitives for creating and controlling threads.
+
+ Thread data type: gl_thread_t.
+
+ Creating a thread:
+ thread = gl_thread_create (func, arg);
+ Or with control of error handling:
+ err = glthread_create (&thread, func, arg);
+ extern int glthread_create (gl_thread_t *result,
+ void *(*func) (void *), void *arg);
+
+ Querying and changing the signal mask of a thread (not supported on all
+ platforms):
+ gl_thread_sigmask (how, newmask, oldmask);
+ Or with control of error handling:
+ err = glthread_sigmask (how, newmask, oldmask);
+ extern int glthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask);
+
+ Waiting for termination of another thread:
+ gl_thread_join (thread, &return_value);
+ Or with control of error handling:
+ err = glthread_join (thread, &return_value);
+ extern int glthread_join (gl_thread_t thread, void **return_value_ptr);
+
+ Getting a reference to the current thread:
+ current = gl_thread_self ();
+ extern gl_thread_t gl_thread_self (void);
+
+ Getting a reference to the current thread as a pointer, for debugging:
+ ptr = gl_thread_self_pointer ();
+ extern void * gl_thread_self_pointer (void);
+
+ Terminating the current thread:
+ gl_thread_exit (return_value);
+ extern _Noreturn void gl_thread_exit (void *return_value);
+
+ Requesting custom code to be executed at fork() time(not supported on all
+ platforms):
+ gl_thread_atfork (prepare_func, parent_func, child_func);
+ Or with control of error handling:
+ err = glthread_atfork (prepare_func, parent_func, child_func);
+ extern int glthread_atfork (void (*prepare_func) (void),
+ void (*parent_func) (void),
+ void (*child_func) (void));
+ Note that even on platforms where this is supported, use of fork() and
+ threads together is problematic, see
+ <http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00062.html>
+ */
+
+
+#ifndef _GLTHREAD_THREAD_H
+#define _GLTHREAD_THREAD_H
+
+#include <errno.h>
+#include <stdlib.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# 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_create
+# pragma weak pthread_sigmask
+# pragma weak pthread_join
+# ifndef pthread_self
+# pragma weak pthread_self
+# endif
+# pragma weak pthread_exit
+# if HAVE_PTHREAD_ATFORK
+# pragma weak pthread_atfork
+# 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_thread_t datatype -------------------------- */
+
+/* This choice of gl_thread_t assumes that
+ pthread_equal (a, b) is equivalent to ((a) == (b)).
+ This is the case on all platforms in use in 2008. */
+typedef pthread_t gl_thread_t;
+# define glthread_create(THREADP, FUNC, ARG) \
+ (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS)
+# define glthread_sigmask(HOW, SET, OSET) \
+ (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0)
+# define glthread_join(THREAD, RETVALP) \
+ (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0)
+# ifdef PTW32_VERSION
+ /* In pthreads-win32, pthread_t is a struct with a pointer field 'p' and
+ other fields. */
+# define gl_thread_self() \
+ (pthread_in_use () ? pthread_self () : gl_null_thread)
+# define gl_thread_self_pointer() \
+ (pthread_in_use () ? pthread_self ().p : NULL)
+extern const gl_thread_t gl_null_thread;
+# else
+# define gl_thread_self() \
+ (pthread_in_use () ? pthread_self () : (pthread_t) NULL)
+# define gl_thread_self_pointer() \
+ (pthread_in_use () ? (void *) pthread_self () : NULL)
+# endif
+# define gl_thread_exit(RETVAL) \
+ (pthread_in_use () ? pthread_exit (RETVAL) : 0)
+
+# if HAVE_PTHREAD_ATFORK
+# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \
+ (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) : 0)
+# else
+# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library. */
+
+# include <pth.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_PTH_THREADS_WEAK
+
+/* Use weak references to the GNU Pth threads library. */
+
+# pragma weak pth_spawn
+# pragma weak pth_sigmask
+# pragma weak pth_join
+# pragma weak pth_self
+# pragma weak pth_exit
+
+# pragma weak pth_cancel
+# define pth_in_use() (pth_cancel != NULL)
+
+# else
+
+# define pth_in_use() 1
+
+# endif
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+typedef pth_t gl_thread_t;
+# define glthread_create(THREADP, FUNC, ARG) \
+ (pth_in_use () ? ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errno) : 0)
+# define glthread_sigmask(HOW, SET, OSET) \
+ (pth_in_use () && !pth_sigmask (HOW, SET, OSET) ? errno : 0)
+# define glthread_join(THREAD, RETVALP) \
+ (pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0)
+# define gl_thread_self() \
+ (pth_in_use () ? (void *) pth_self () : NULL)
+# define gl_thread_self_pointer() \
+ gl_thread_self ()
+# define gl_thread_exit(RETVAL) \
+ (pth_in_use () ? pth_exit (RETVAL) : 0)
+# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library. */
+
+# include <thread.h>
+# include <synch.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_SOLARIS_THREADS_WEAK
+
+/* Use weak references to the old Solaris threads library. */
+
+# pragma weak thr_create
+# pragma weak thr_join
+# pragma weak thr_self
+# pragma weak thr_exit
+
+# pragma weak thr_suspend
+# define thread_in_use() (thr_suspend != NULL)
+
+# else
+
+# define thread_in_use() 1
+
+# endif
+
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+typedef thread_t gl_thread_t;
+# define glthread_create(THREADP, FUNC, ARG) \
+ (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0)
+# define glthread_sigmask(HOW, SET, OSET) \
+ (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0)
+# define glthread_join(THREAD, RETVALP) \
+ (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0)
+# define gl_thread_self() \
+ (thread_in_use () ? (void *) thr_self () : NULL)
+# define gl_thread_self_pointer() \
+ gl_thread_self ()
+# define gl_thread_exit(RETVAL) \
+ (thread_in_use () ? thr_exit (RETVAL) : 0)
+# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+/* The gl_thread_t is a pointer to a structure in memory.
+ Why not the thread handle? If it were the thread handle, it would be hard
+ to implement gl_thread_self() (since GetCurrentThread () returns a pseudo-
+ handle, DuplicateHandle (GetCurrentThread ()) returns a handle that must be
+ closed afterwards, and there is no function for quickly retrieving a thread
+ handle from its id).
+ Why not the thread id? I tried it. It did not work: Sometimes ids appeared
+ that did not belong to running threads, and glthread_join failed with ESRCH.
+ */
+typedef struct gl_thread_struct *gl_thread_t;
+# define glthread_create(THREADP, FUNC, ARG) \
+ glthread_create_func (THREADP, FUNC, ARG)
+# define glthread_sigmask(HOW, SET, OSET) \
+ /* unsupported */ 0
+# define glthread_join(THREAD, RETVALP) \
+ glthread_join_func (THREAD, RETVALP)
+# define gl_thread_self() \
+ gl_thread_self_func ()
+# define gl_thread_self_pointer() \
+ gl_thread_self ()
+# define gl_thread_exit(RETVAL) \
+ gl_thread_exit_func (RETVAL)
+# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
+extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg);
+extern int glthread_join_func (gl_thread_t thread, void **retvalp);
+extern gl_thread_t gl_thread_self_func (void);
+extern int gl_thread_exit_func (void *retval);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+
+/* Provide dummy implementation if threads are not supported. */
+
+typedef int gl_thread_t;
+# define glthread_create(THREADP, FUNC, ARG) ENOSYS
+# define glthread_sigmask(HOW, SET, OSET) 0
+# define glthread_join(THREAD, RETVALP) 0
+# define gl_thread_self() 0
+# define gl_thread_self_pointer() \
+ ((void *) gl_thread_self ())
+# define gl_thread_exit(RETVAL) 0
+# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
+
+#endif
+
+/* ========================================================================= */
+
+/* Macros with built-in error handling. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline gl_thread_t
+gl_thread_create (void *(*func) (void *arg), void *arg)
+{
+ gl_thread_t thread;
+ int ret;
+
+ ret = glthread_create (&thread, func, arg);
+ if (ret != 0)
+ abort ();
+ return thread;
+}
+#define gl_thread_sigmask(HOW, SET, OSET) \
+ do \
+ { \
+ if (glthread_sigmask (HOW, SET, OSET)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_thread_join(THREAD, RETVAL) \
+ do \
+ { \
+ if (glthread_join (THREAD, RETVAL)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_thread_atfork(PREPARE, PARENT, CHILD) \
+ do \
+ { \
+ if (glthread_atfork (PREPARE, PARENT, CHILD)) \
+ abort (); \
+ } \
+ while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GLTHREAD_THREAD_H */
diff --git a/gl/tests/glthread/threadlib.c b/gl/tests/glthread/threadlib.c
new file mode 100644
index 0000000000..646defa21b
--- /dev/null
+++ b/gl/tests/glthread/threadlib.c
@@ -0,0 +1,74 @@
+/* Multithreading primitives.
+ Copyright (C) 2005-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, 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. */
+
+#include <config.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+# include <stdlib.h>
+
+# 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
+
+#endif
+
+/* ========================================================================= */
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
diff --git a/gl/tests/glthread/yield.h b/gl/tests/glthread/yield.h
new file mode 100644
index 0000000000..4fa2d8b1b7
--- /dev/null
+++ b/gl/tests/glthread/yield.h
@@ -0,0 +1,122 @@
+/* Yielding the processor to other threads and processes.
+ Copyright (C) 2005-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* This file contains a primitive for yielding the processor to other threads.
+ extern void gl_thread_yield (void);
+ */
+
+#ifndef _GLTHREAD_YIELD_H
+#define _GLTHREAD_YIELD_H
+
+#include <errno.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <sched.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define gl_thread_yield() \
+ sched_yield ()
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library. */
+
+# include <pth.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define gl_thread_yield() \
+ pth_yield (NULL)
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library. */
+
+# include <thread.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define gl_thread_yield() \
+ thr_yield ()
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define gl_thread_yield() \
+ Sleep (0)
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+
+/* Provide dummy implementation if threads are not supported. */
+
+# define gl_thread_yield() 0
+
+#endif
+
+/* ========================================================================= */
+
+#endif /* _GLTHREAD_YIELD_H */
diff --git a/gl/tests/ioctl.c b/gl/tests/ioctl.c
new file mode 100644
index 0000000000..c6ba989ee5
--- /dev/null
+++ b/gl/tests/ioctl.c
@@ -0,0 +1,79 @@
+/* ioctl.c --- wrappers for Windows ioctl function
+
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paolo Bonzini */
+
+#include <config.h>
+
+#include <sys/ioctl.h>
+
+#include <stdarg.h>
+
+#if HAVE_IOCTL
+
+/* Provide a wrapper with the POSIX prototype. */
+# undef ioctl
+int
+rpl_ioctl (int fd, int request, ... /* {void *,char *} arg */)
+{
+ void *buf;
+ va_list args;
+
+ va_start (args, request);
+ buf = va_arg (args, void *);
+ va_end (args);
+
+ /* Cast 'request' so that when the system's ioctl function takes a 64-bit
+ request argument, the value gets zero-extended, not sign-extended. */
+ return ioctl (fd, (unsigned int) request, buf);
+}
+
+#else /* mingw */
+
+# include <errno.h>
+
+# include "fd-hook.h"
+
+static int
+primary_ioctl (int fd, int request, void *arg)
+{
+ /* We don't support FIONBIO on pipes here. If you want to make pipe
+ fds non-blocking, use the gnulib 'nonblocking' module, until
+ gnulib implements fcntl F_GETFL / F_SETFL with O_NONBLOCK. */
+
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+ioctl (int fd, int request, ... /* {void *,char *} arg */)
+{
+ void *arg;
+ va_list args;
+
+ va_start (args, request);
+ arg = va_arg (args, void *);
+ va_end (args);
+
+# if WINDOWS_SOCKETS
+ return execute_all_ioctl_hooks (primary_ioctl, fd, request, arg);
+# else
+ return primary_ioctl (fd, request, arg);
+# endif
+}
+
+#endif
diff --git a/gl/tests/perror.c b/gl/tests/perror.c
new file mode 100644
index 0000000000..af4b56cd40
--- /dev/null
+++ b/gl/tests/perror.c
@@ -0,0 +1,49 @@
+/* Print a message describing error code.
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+ Written by Bruno Haible and Simon Josefsson.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <stdio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "strerror-override.h"
+
+/* Use the system functions, not the gnulib overrides in this file. */
+#undef fprintf
+
+void
+perror (const char *string)
+{
+ char stackbuf[STACKBUF_LEN];
+ int ret;
+
+ /* Our implementation guarantees that this will be a non-empty
+ string, even if it returns EINVAL; and stackbuf should be sized
+ large enough to avoid ERANGE. */
+ ret = strerror_r (errno, stackbuf, sizeof stackbuf);
+ if (ret == ERANGE)
+ abort ();
+
+ if (string != NULL && *string != '\0')
+ fprintf (stderr, "%s: %s\n", string, stackbuf);
+ else
+ fprintf (stderr, "%s\n", stackbuf);
+}
diff --git a/gl/tests/pipe.c b/gl/tests/pipe.c
new file mode 100644
index 0000000000..425dd70ef4
--- /dev/null
+++ b/gl/tests/pipe.c
@@ -0,0 +1,51 @@
+/* Create a pipe.
+ Copyright (C) 2009-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Native Woe32 API. */
+
+/* Get _pipe(). */
+# include <io.h>
+
+/* Get _O_BINARY. */
+# include <fcntl.h>
+
+int
+pipe (int fd[2])
+{
+ /* Mingw changes fd to {-1,-1} on failure, but this violates
+ http://austingroupbugs.net/view.php?id=467 */
+ int tmp[2];
+ int result = _pipe (tmp, 4096, _O_BINARY);
+ if (!result)
+ {
+ fd[0] = tmp[0];
+ fd[1] = tmp[1];
+ }
+ return result;
+}
+
+#else
+
+# error "This platform lacks a pipe function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
+
+#endif
diff --git a/gl/tests/strerror_r.c b/gl/tests/strerror_r.c
new file mode 100644
index 0000000000..e6cf99b254
--- /dev/null
+++ b/gl/tests/strerror_r.c
@@ -0,0 +1,327 @@
+/* strerror_r.c --- POSIX compatible system error routine
+
+ Copyright (C) 2010-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2010. */
+
+#include <config.h>
+
+/* Enable declaration of sys_nerr and sys_errlist in <errno.h> on NetBSD. */
+#define _NETBSD_SOURCE 1
+
+/* Specification. */
+#include <string.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "strerror-override.h"
+
+#if (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__) && HAVE___XPG_STRERROR_R /* glibc >= 2.3.4, cygwin >= 1.7.9 */
+
+# define USE_XPG_STRERROR_R 1
+
+#elif HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__)
+
+/* The system's strerror_r function is OK, except that its third argument
+ is 'int', not 'size_t', or its return type is wrong. */
+
+# include <limits.h>
+
+# define USE_SYSTEM_STRERROR_R 1
+
+#else /* (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__ ? !HAVE___XPG_STRERROR_R : !HAVE_DECL_STRERROR_R) */
+
+/* Use the system's strerror(). Exclude glibc and cygwin because the
+ system strerror_r has the wrong return type, and cygwin 1.7.9
+ strerror_r clobbers strerror. */
+# undef strerror
+
+# define USE_SYSTEM_STRERROR 1
+
+# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __sgi || (defined __sun && !defined _LP64) || defined __CYGWIN__
+
+/* No locking needed. */
+
+/* Get catgets internationalization functions. */
+# if HAVE_CATGETS
+# include <nl_types.h>
+# endif
+
+/* Get sys_nerr, sys_errlist on HP-UX (otherwise only declared in C++ mode).
+ Get sys_nerr, sys_errlist on IRIX (otherwise only declared with _SGIAPI). */
+# if defined __hpux || defined __sgi
+extern int sys_nerr;
+extern char *sys_errlist[];
+# endif
+
+/* Get sys_nerr on Solaris. */
+# if defined __sun && !defined _LP64
+extern int sys_nerr;
+# endif
+
+# else
+
+# include "glthread/lock.h"
+
+/* This lock protects the buffer returned by strerror(). We assume that
+ no other uses of strerror() exist in the program. */
+gl_lock_define_initialized(static, strerror_lock)
+
+# endif
+
+#endif
+
+/* On MSVC, there is no snprintf() function, just a _snprintf().
+ It is of lower quality, but sufficient for the simple use here.
+ We only have to make sure to NUL terminate the result (_snprintf
+ does not NUL terminate, like strncpy). */
+#if !HAVE_SNPRINTF
+static int
+local_snprintf (char *buf, size_t buflen, const char *format, ...)
+{
+ va_list args;
+ int result;
+
+ va_start (args, format);
+ result = _vsnprintf (buf, buflen, format, args);
+ va_end (args);
+ if (buflen > 0 && (result < 0 || result >= buflen))
+ buf[buflen - 1] = '\0';
+ return result;
+}
+# define snprintf local_snprintf
+#endif
+
+/* Copy as much of MSG into BUF as possible, without corrupting errno.
+ Return 0 if MSG fit in BUFLEN, otherwise return ERANGE. */
+static int
+safe_copy (char *buf, size_t buflen, const char *msg)
+{
+ size_t len = strlen (msg);
+ int ret;
+
+ if (len < buflen)
+ {
+ /* Although POSIX allows memcpy() to corrupt errno, we don't
+ know of any implementation where this is a real problem. */
+ memcpy (buf, msg, len + 1);
+ ret = 0;
+ }
+ else
+ {
+ memcpy (buf, msg, buflen - 1);
+ buf[buflen - 1] = '\0';
+ ret = ERANGE;
+ }
+ return ret;
+}
+
+
+int
+strerror_r (int errnum, char *buf, size_t buflen)
+#undef strerror_r
+{
+ /* Filter this out now, so that rest of this replacement knows that
+ there is room for a non-empty message and trailing NUL. */
+ if (buflen <= 1)
+ {
+ if (buflen)
+ *buf = '\0';
+ return ERANGE;
+ }
+ *buf = '\0';
+
+ /* Check for gnulib overrides. */
+ {
+ char const *msg = strerror_override (errnum);
+
+ if (msg)
+ return safe_copy (buf, buflen, msg);
+ }
+
+ {
+ int ret;
+ int saved_errno = errno;
+
+#if USE_XPG_STRERROR_R
+
+ {
+ extern int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
+
+ ret = __xpg_strerror_r (errnum, buf, buflen);
+ if (ret < 0)
+ ret = errno;
+ if (!*buf)
+ {
+ /* glibc 2.13 would not touch buf on err, so we have to fall
+ back to GNU strerror_r which always returns a thread-safe
+ untruncated string to (partially) copy into our buf. */
+ safe_copy (buf, buflen, strerror_r (errnum, buf, buflen));
+ }
+ }
+
+#elif USE_SYSTEM_STRERROR_R
+
+ if (buflen > INT_MAX)
+ buflen = INT_MAX;
+
+# ifdef __hpux
+ /* On HP-UX 11.31, strerror_r always fails when buflen < 80; it
+ also fails to change buf on EINVAL. */
+ {
+ char stackbuf[80];
+
+ if (buflen < sizeof stackbuf)
+ {
+ ret = strerror_r (errnum, stackbuf, sizeof stackbuf);
+ if (ret == 0)
+ ret = safe_copy (buf, buflen, stackbuf);
+ }
+ else
+ ret = strerror_r (errnum, buf, buflen);
+ }
+# else
+ ret = strerror_r (errnum, buf, buflen);
+
+ /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
+ if (ret < 0)
+ ret = errno;
+# endif
+
+# ifdef _AIX
+ /* AIX returns 0 rather than ERANGE when truncating strings; try
+ again until we are sure we got the entire string. */
+ if (!ret && strlen (buf) == buflen - 1)
+ {
+ char stackbuf[STACKBUF_LEN];
+ size_t len;
+ strerror_r (errnum, stackbuf, sizeof stackbuf);
+ len = strlen (stackbuf);
+ /* STACKBUF_LEN should have been large enough. */
+ if (len + 1 == sizeof stackbuf)
+ abort ();
+ if (buflen <= len)
+ ret = ERANGE;
+ }
+# else
+ /* Solaris 10 does not populate buf on ERANGE. OpenBSD 4.7
+ truncates early on ERANGE rather than return a partial integer.
+ We prefer the maximal string. We set buf[0] earlier, and we
+ know of no implementation that modifies buf to be an
+ unterminated string, so this strlen should be portable in
+ practice (rather than pulling in a safer strnlen). */
+ if (ret == ERANGE && strlen (buf) < buflen - 1)
+ {
+ char stackbuf[STACKBUF_LEN];
+
+ /* STACKBUF_LEN should have been large enough. */
+ if (strerror_r (errnum, stackbuf, sizeof stackbuf) == ERANGE)
+ abort ();
+ safe_copy (buf, buflen, stackbuf);
+ }
+# endif
+
+#else /* USE_SYSTEM_STRERROR */
+
+ /* Try to do what strerror (errnum) does, but without clobbering the
+ buffer used by strerror(). */
+
+# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __CYGWIN__ /* NetBSD, HP-UX, native Win32, Cygwin */
+
+ /* NetBSD: sys_nerr, sys_errlist are declared through _NETBSD_SOURCE
+ and <errno.h> above.
+ HP-UX: sys_nerr, sys_errlist are declared explicitly above.
+ native Win32: sys_nerr, sys_errlist are declared in <stdlib.h>.
+ Cygwin: sys_nerr, sys_errlist are declared in <errno.h>. */
+ if (errnum >= 0 && errnum < sys_nerr)
+ {
+# if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
+# if defined __NetBSD__
+ nl_catd catd = catopen ("libc", NL_CAT_LOCALE);
+ const char *errmsg =
+ (catd != (nl_catd)-1
+ ? catgets (catd, 1, errnum, sys_errlist[errnum])
+ : sys_errlist[errnum]);
+# endif
+# if defined __hpux
+ nl_catd catd = catopen ("perror", NL_CAT_LOCALE);
+ const char *errmsg =
+ (catd != (nl_catd)-1
+ ? catgets (catd, 1, 1 + errnum, sys_errlist[errnum])
+ : sys_errlist[errnum]);
+# endif
+# else
+ const char *errmsg = sys_errlist[errnum];
+# endif
+ if (errmsg == NULL || *errmsg == '\0')
+ ret = EINVAL;
+ else
+ ret = safe_copy (buf, buflen, errmsg);
+# if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
+ if (catd != (nl_catd)-1)
+ catclose (catd);
+# endif
+ }
+ else
+ ret = EINVAL;
+
+# elif defined __sgi || (defined __sun && !defined _LP64) /* IRIX, Solaris <= 9 32-bit */
+
+ /* For a valid error number, the system's strerror() function returns
+ a pointer to a not copied string, not to a buffer. */
+ if (errnum >= 0 && errnum < sys_nerr)
+ {
+ char *errmsg = strerror (errnum);
+
+ if (errmsg == NULL || *errmsg == '\0')
+ ret = EINVAL;
+ else
+ ret = safe_copy (buf, buflen, errmsg);
+ }
+ else
+ ret = EINVAL;
+
+# else
+
+ gl_lock_lock (strerror_lock);
+
+ {
+ char *errmsg = strerror (errnum);
+
+ /* For invalid error numbers, strerror() on
+ - IRIX 6.5 returns NULL,
+ - HP-UX 11 returns an empty string. */
+ if (errmsg == NULL || *errmsg == '\0')
+ ret = EINVAL;
+ else
+ ret = safe_copy (buf, buflen, errmsg);
+ }
+
+ gl_lock_unlock (strerror_lock);
+
+# endif
+
+#endif
+
+ if (ret == EINVAL && !*buf)
+ snprintf (buf, buflen, "Unknown error %d", errnum);
+
+ errno = saved_errno;
+ return ret;
+ }
+}
diff --git a/gl/tests/sys_ioctl.in.h b/gl/tests/sys_ioctl.in.h
new file mode 100644
index 0000000000..dc8aedabe0
--- /dev/null
+++ b/gl/tests/sys_ioctl.in.h
@@ -0,0 +1,79 @@
+/* Substitute for and wrapper around <sys/ioctl.h>.
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _@GUARD_PREFIX@_SYS_IOCTL_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* The include_next requires a split double-inclusion guard. */
+#if @HAVE_SYS_IOCTL_H@
+# @INCLUDE_NEXT@ @NEXT_SYS_IOCTL_H@
+#endif
+
+#ifndef _@GUARD_PREFIX@_SYS_IOCTL_H
+#define _@GUARD_PREFIX@_SYS_IOCTL_H
+
+/* AIX 5.1 and Solaris 10 declare ioctl() in <unistd.h> and in <stropts.h>,
+ but not in <sys/ioctl.h>.
+ But avoid namespace pollution on glibc systems. */
+#ifndef __GLIBC__
+# include <unistd.h>
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
+
+/* The definition of _GL_WARN_ON_USE is copied here. */
+
+
+/* Declare overridden functions. */
+
+#if @GNULIB_IOCTL@
+# if @REPLACE_IOCTL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef ioctl
+# define ioctl rpl_ioctl
+# endif
+_GL_FUNCDECL_RPL (ioctl, int,
+ (int fd, int request, ... /* {void *,char *} arg */));
+_GL_CXXALIAS_RPL (ioctl, int,
+ (int fd, int request, ... /* {void *,char *} arg */));
+# else
+# if @SYS_IOCTL_H_HAVE_WINSOCK2_H@ || 1
+_GL_FUNCDECL_SYS (ioctl, int,
+ (int fd, int request, ... /* {void *,char *} arg */));
+# endif
+_GL_CXXALIAS_SYS (ioctl, int,
+ (int fd, int request, ... /* {void *,char *} arg */));
+# endif
+_GL_CXXALIASWARN (ioctl);
+#elif @SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
+# undef ioctl
+# define ioctl ioctl_used_without_requesting_gnulib_module_ioctl
+#elif defined GNULIB_POSIXCHECK
+# undef ioctl
+# if HAVE_RAW_DECL_IOCTL
+_GL_WARN_ON_USE (ioctl, "ioctl does not portably work on sockets - "
+ "use gnulib module ioctl for portability");
+# endif
+#endif
+
+
+#endif /* _@GUARD_PREFIX@_SYS_IOCTL_H */
+#endif /* _@GUARD_PREFIX@_SYS_IOCTL_H */
diff --git a/gl/tests/test-connect.c b/gl/tests/test-connect.c
new file mode 100644
index 0000000000..84f00b5425
--- /dev/null
+++ b/gl/tests/test-connect.c
@@ -0,0 +1,58 @@
+/* Test connecting a client socket.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <sys/socket.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (connect, int, (int, const struct sockaddr *, socklen_t));
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "sockets.h"
+#include "macros.h"
+
+int
+main (void)
+{
+ gl_sockets_startup (SOCKETS_1_1);
+
+ /* Test behaviour for invalid file descriptors. */
+ {
+ struct sockaddr_in addr;
+
+ addr.sin_family = AF_INET;
+ inet_pton (AF_INET, "127.0.0.1", &addr.sin_addr);
+ addr.sin_port = htons (80);
+ {
+ errno = 0;
+ ASSERT (connect (-1, (const struct sockaddr *) &addr, sizeof (addr))
+ == -1);
+ ASSERT (errno == EBADF);
+ }
+ {
+ errno = 0;
+ ASSERT (connect (99, (const struct sockaddr *) &addr, sizeof (addr))
+ == -1);
+ ASSERT (errno == EBADF);
+ }
+ }
+
+ return 0;
+}
diff --git a/gl/tests/test-ftruncate.c b/gl/tests/test-ftruncate.c
new file mode 100644
index 0000000000..c5da4eb24d
--- /dev/null
+++ b/gl/tests/test-ftruncate.c
@@ -0,0 +1,59 @@
+/* Test truncating a file.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (ftruncate, int, (int, off_t));
+
+#include <errno.h>
+#include <fcntl.h>
+
+#include "macros.h"
+
+int
+main (int argc, char *argv[])
+{
+ const char *filename = argv[1];
+
+ /* Test behaviour for invalid file descriptors. */
+ {
+ errno = 0;
+ ASSERT (ftruncate (-1, 0) == -1);
+ ASSERT (errno == EBADF);
+ }
+ {
+ errno = 0;
+ ASSERT (ftruncate (99, 0) == -1);
+ ASSERT (errno == EBADF);
+ }
+
+ /* Test behaviour for read-only file descriptors. */
+ {
+ int fd = open (filename, O_RDONLY);
+ ASSERT (fd >= 0);
+ errno = 0;
+ ASSERT (ftruncate (fd, 0) == -1);
+ ASSERT (errno == EBADF || errno == EINVAL
+ || errno == EACCES /* seen on mingw */
+ );
+ close (fd);
+ }
+
+ return 0;
+}
diff --git a/gl/tests/test-ftruncate.sh b/gl/tests/test-ftruncate.sh
new file mode 100755
index 0000000000..d7394d2bfe
--- /dev/null
+++ b/gl/tests/test-ftruncate.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec ./test-ftruncate${EXEEXT} "$srcdir/test-ftruncate.sh"
diff --git a/gl/tests/test-ioctl.c b/gl/tests/test-ioctl.c
new file mode 100644
index 0000000000..130ee427c4
--- /dev/null
+++ b/gl/tests/test-ioctl.c
@@ -0,0 +1,49 @@
+/* Test of ioctl() function.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <sys/ioctl.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (ioctl, int, (int, int, ...));
+
+#include <errno.h>
+
+#include "macros.h"
+
+int
+main (void)
+{
+#ifdef FIONREAD
+ /* Test behaviour for invalid file descriptors. */
+ {
+ int value;
+ errno = 0;
+ ASSERT (ioctl (-1, FIONREAD, &value) == -1);
+ ASSERT (errno == EBADF);
+ }
+ {
+ int value;
+ errno = 0;
+ ASSERT (ioctl (99, FIONREAD, &value) == -1);
+ ASSERT (errno == EBADF);
+ }
+#endif
+
+ return 0;
+}
diff --git a/gl/tests/test-lock.c b/gl/tests/test-lock.c
new file mode 100644
index 0000000000..3f8846bc22
--- /dev/null
+++ b/gl/tests/test-lock.c
@@ -0,0 +1,601 @@
+/* Test of locking in multithreaded situations.
+ Copyright (C) 2005, 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005. */
+
+#include <config.h>
+
+#if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WIN32_THREADS
+
+#if USE_POSIX_THREADS
+# define TEST_POSIX_THREADS 1
+#endif
+#if USE_SOLARIS_THREADS
+# define TEST_SOLARIS_THREADS 1
+#endif
+#if USE_PTH_THREADS
+# define TEST_PTH_THREADS 1
+#endif
+#if USE_WIN32_THREADS
+# define TEST_WIN32_THREADS 1
+#endif
+
+/* Whether to enable locking.
+ Uncomment this to get a test program without locking, to verify that
+ it crashes. */
+#define ENABLE_LOCKING 1
+
+/* Which tests to perform.
+ Uncomment some of these, to verify that all tests crash if no locking
+ is enabled. */
+#define DO_TEST_LOCK 1
+#define DO_TEST_RWLOCK 1
+#define DO_TEST_RECURSIVE_LOCK 1
+#define DO_TEST_ONCE 1
+
+/* Whether to help the scheduler through explicit yield().
+ Uncomment this to see if the operating system has a fair scheduler. */
+#define EXPLICIT_YIELD 1
+
+/* Whether to print debugging messages. */
+#define ENABLE_DEBUGGING 0
+
+/* Number of simultaneous threads. */
+#define THREAD_COUNT 10
+
+/* Number of operations performed in each thread.
+ This is quite high, because with a smaller count, say 5000, we often get
+ an "OK" result even without ENABLE_LOCKING (on Linux/x86). */
+#define REPEAT_COUNT 50000
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !ENABLE_LOCKING
+# undef USE_POSIX_THREADS
+# undef USE_SOLARIS_THREADS
+# undef USE_PTH_THREADS
+# undef USE_WIN32_THREADS
+#endif
+#include "glthread/lock.h"
+
+#if !ENABLE_LOCKING
+# if TEST_POSIX_THREADS
+# define USE_POSIX_THREADS 1
+# endif
+# if TEST_SOLARIS_THREADS
+# define USE_SOLARIS_THREADS 1
+# endif
+# if TEST_PTH_THREADS
+# define USE_PTH_THREADS 1
+# endif
+# if TEST_WIN32_THREADS
+# define USE_WIN32_THREADS 1
+# endif
+#endif
+
+#include "glthread/thread.h"
+#include "glthread/yield.h"
+
+#if ENABLE_DEBUGGING
+# define dbgprintf printf
+#else
+# define dbgprintf if (0) printf
+#endif
+
+#if EXPLICIT_YIELD
+# define yield() gl_thread_yield ()
+#else
+# define yield()
+#endif
+
+#define ACCOUNT_COUNT 4
+
+static int account[ACCOUNT_COUNT];
+
+static int
+random_account (void)
+{
+ return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
+}
+
+static void
+check_accounts (void)
+{
+ int i, sum;
+
+ sum = 0;
+ for (i = 0; i < ACCOUNT_COUNT; i++)
+ sum += account[i];
+ if (sum != ACCOUNT_COUNT * 1000)
+ abort ();
+}
+
+
+/* ------------------- Test normal (non-recursive) locks ------------------- */
+
+/* Test normal locks by having several bank accounts and several threads
+ which shuffle around money between the accounts and another thread
+ checking that all the money is still there. */
+
+gl_lock_define_initialized(static, my_lock)
+
+static void *
+lock_mutator_thread (void *arg)
+{
+ int repeat;
+
+ for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
+ {
+ int i1, i2, value;
+
+ dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
+ gl_lock_lock (my_lock);
+ dbgprintf ("Mutator %p after lock\n", gl_thread_self_pointer ());
+
+ i1 = random_account ();
+ i2 = random_account ();
+ value = ((unsigned int) rand () >> 3) % 10;
+ account[i1] += value;
+ account[i2] -= value;
+
+ dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
+ gl_lock_unlock (my_lock);
+ dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ());
+
+ dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
+ gl_lock_lock (my_lock);
+ check_accounts ();
+ gl_lock_unlock (my_lock);
+ dbgprintf ("Mutator %p after check unlock\n", gl_thread_self_pointer ());
+
+ yield ();
+ }
+
+ dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
+ return NULL;
+}
+
+static volatile int lock_checker_done;
+
+static void *
+lock_checker_thread (void *arg)
+{
+ while (!lock_checker_done)
+ {
+ dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
+ gl_lock_lock (my_lock);
+ check_accounts ();
+ gl_lock_unlock (my_lock);
+ dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ());
+
+ yield ();
+ }
+
+ dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
+ return NULL;
+}
+
+static void
+test_lock (void)
+{
+ int i;
+ gl_thread_t checkerthread;
+ gl_thread_t threads[THREAD_COUNT];
+
+ /* Initialization. */
+ for (i = 0; i < ACCOUNT_COUNT; i++)
+ account[i] = 1000;
+ lock_checker_done = 0;
+
+ /* Spawn the threads. */
+ checkerthread = gl_thread_create (lock_checker_thread, NULL);
+ for (i = 0; i < THREAD_COUNT; i++)
+ threads[i] = gl_thread_create (lock_mutator_thread, NULL);
+
+ /* Wait for the threads to terminate. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ gl_thread_join (threads[i], NULL);
+ lock_checker_done = 1;
+ gl_thread_join (checkerthread, NULL);
+ check_accounts ();
+}
+
+
+/* ----------------- Test read-write (non-recursive) locks ----------------- */
+
+/* Test read-write locks by having several bank accounts and several threads
+ which shuffle around money between the accounts and several other threads
+ that check that all the money is still there. */
+
+gl_rwlock_define_initialized(static, my_rwlock)
+
+static void *
+rwlock_mutator_thread (void *arg)
+{
+ int repeat;
+
+ for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
+ {
+ int i1, i2, value;
+
+ dbgprintf ("Mutator %p before wrlock\n", gl_thread_self_pointer ());
+ gl_rwlock_wrlock (my_rwlock);
+ dbgprintf ("Mutator %p after wrlock\n", gl_thread_self_pointer ());
+
+ i1 = random_account ();
+ i2 = random_account ();
+ value = ((unsigned int) rand () >> 3) % 10;
+ account[i1] += value;
+ account[i2] -= value;
+
+ dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
+ gl_rwlock_unlock (my_rwlock);
+ dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ());
+
+ yield ();
+ }
+
+ dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
+ return NULL;
+}
+
+static volatile int rwlock_checker_done;
+
+static void *
+rwlock_checker_thread (void *arg)
+{
+ while (!rwlock_checker_done)
+ {
+ dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
+ gl_rwlock_rdlock (my_rwlock);
+ check_accounts ();
+ gl_rwlock_unlock (my_rwlock);
+ dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ());
+
+ yield ();
+ }
+
+ dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
+ return NULL;
+}
+
+static void
+test_rwlock (void)
+{
+ int i;
+ gl_thread_t checkerthreads[THREAD_COUNT];
+ gl_thread_t threads[THREAD_COUNT];
+
+ /* Initialization. */
+ for (i = 0; i < ACCOUNT_COUNT; i++)
+ account[i] = 1000;
+ rwlock_checker_done = 0;
+
+ /* Spawn the threads. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ checkerthreads[i] = gl_thread_create (rwlock_checker_thread, NULL);
+ for (i = 0; i < THREAD_COUNT; i++)
+ threads[i] = gl_thread_create (rwlock_mutator_thread, NULL);
+
+ /* Wait for the threads to terminate. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ gl_thread_join (threads[i], NULL);
+ rwlock_checker_done = 1;
+ for (i = 0; i < THREAD_COUNT; i++)
+ gl_thread_join (checkerthreads[i], NULL);
+ check_accounts ();
+}
+
+
+/* -------------------------- Test recursive locks -------------------------- */
+
+/* Test recursive locks by having several bank accounts and several threads
+ which shuffle around money between the accounts (recursively) and another
+ thread checking that all the money is still there. */
+
+gl_recursive_lock_define_initialized(static, my_reclock)
+
+static void
+recshuffle (void)
+{
+ int i1, i2, value;
+
+ dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
+ gl_recursive_lock_lock (my_reclock);
+ dbgprintf ("Mutator %p after lock\n", gl_thread_self_pointer ());
+
+ i1 = random_account ();
+ i2 = random_account ();
+ value = ((unsigned int) rand () >> 3) % 10;
+ account[i1] += value;
+ account[i2] -= value;
+
+ /* Recursive with probability 0.5. */
+ if (((unsigned int) rand () >> 3) % 2)
+ recshuffle ();
+
+ dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
+ gl_recursive_lock_unlock (my_reclock);
+ dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ());
+}
+
+static void *
+reclock_mutator_thread (void *arg)
+{
+ int repeat;
+
+ for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
+ {
+ recshuffle ();
+
+ dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
+ gl_recursive_lock_lock (my_reclock);
+ check_accounts ();
+ gl_recursive_lock_unlock (my_reclock);
+ dbgprintf ("Mutator %p after check unlock\n", gl_thread_self_pointer ());
+
+ yield ();
+ }
+
+ dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
+ return NULL;
+}
+
+static volatile int reclock_checker_done;
+
+static void *
+reclock_checker_thread (void *arg)
+{
+ while (!reclock_checker_done)
+ {
+ dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
+ gl_recursive_lock_lock (my_reclock);
+ check_accounts ();
+ gl_recursive_lock_unlock (my_reclock);
+ dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ());
+
+ yield ();
+ }
+
+ dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
+ return NULL;
+}
+
+static void
+test_recursive_lock (void)
+{
+ int i;
+ gl_thread_t checkerthread;
+ gl_thread_t threads[THREAD_COUNT];
+
+ /* Initialization. */
+ for (i = 0; i < ACCOUNT_COUNT; i++)
+ account[i] = 1000;
+ reclock_checker_done = 0;
+
+ /* Spawn the threads. */
+ checkerthread = gl_thread_create (reclock_checker_thread, NULL);
+ for (i = 0; i < THREAD_COUNT; i++)
+ threads[i] = gl_thread_create (reclock_mutator_thread, NULL);
+
+ /* Wait for the threads to terminate. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ gl_thread_join (threads[i], NULL);
+ reclock_checker_done = 1;
+ gl_thread_join (checkerthread, NULL);
+ check_accounts ();
+}
+
+
+/* ------------------------ Test once-only execution ------------------------ */
+
+/* Test once-only execution by having several threads attempt to grab a
+ once-only task simultaneously (triggered by releasing a read-write lock). */
+
+gl_once_define(static, fresh_once)
+static int ready[THREAD_COUNT];
+static gl_lock_t ready_lock[THREAD_COUNT];
+#if ENABLE_LOCKING
+static gl_rwlock_t fire_signal[REPEAT_COUNT];
+#else
+static volatile int fire_signal_state;
+#endif
+static gl_once_t once_control;
+static int performed;
+gl_lock_define_initialized(static, performed_lock)
+
+static void
+once_execute (void)
+{
+ gl_lock_lock (performed_lock);
+ performed++;
+ gl_lock_unlock (performed_lock);
+}
+
+static void *
+once_contender_thread (void *arg)
+{
+ int id = (int) (long) arg;
+ int repeat;
+
+ for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
+ {
+ /* Tell the main thread that we're ready. */
+ gl_lock_lock (ready_lock[id]);
+ ready[id] = 1;
+ gl_lock_unlock (ready_lock[id]);
+
+ if (repeat == REPEAT_COUNT)
+ break;
+
+ dbgprintf ("Contender %p waiting for signal for round %d\n",
+ gl_thread_self_pointer (), repeat);
+#if ENABLE_LOCKING
+ /* Wait for the signal to go. */
+ gl_rwlock_rdlock (fire_signal[repeat]);
+ /* And don't hinder the others (if the scheduler is unfair). */
+ gl_rwlock_unlock (fire_signal[repeat]);
+#else
+ /* Wait for the signal to go. */
+ while (fire_signal_state <= repeat)
+ yield ();
+#endif
+ dbgprintf ("Contender %p got the signal for round %d\n",
+ gl_thread_self_pointer (), repeat);
+
+ /* Contend for execution. */
+ gl_once (once_control, once_execute);
+ }
+
+ return NULL;
+}
+
+static void
+test_once (void)
+{
+ int i, repeat;
+ gl_thread_t threads[THREAD_COUNT];
+
+ /* Initialize all variables. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ {
+ ready[i] = 0;
+ gl_lock_init (ready_lock[i]);
+ }
+#if ENABLE_LOCKING
+ for (i = 0; i < REPEAT_COUNT; i++)
+ gl_rwlock_init (fire_signal[i]);
+#else
+ fire_signal_state = 0;
+#endif
+
+ /* Block all fire_signals. */
+ for (i = REPEAT_COUNT-1; i >= 0; i--)
+ gl_rwlock_wrlock (fire_signal[i]);
+
+ /* Spawn the threads. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ threads[i] = gl_thread_create (once_contender_thread, (void *) (long) i);
+
+ for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
+ {
+ /* Wait until every thread is ready. */
+ dbgprintf ("Main thread before synchonizing for round %d\n", repeat);
+ for (;;)
+ {
+ int ready_count = 0;
+ for (i = 0; i < THREAD_COUNT; i++)
+ {
+ gl_lock_lock (ready_lock[i]);
+ ready_count += ready[i];
+ gl_lock_unlock (ready_lock[i]);
+ }
+ if (ready_count == THREAD_COUNT)
+ break;
+ yield ();
+ }
+ dbgprintf ("Main thread after synchonizing for round %d\n", repeat);
+
+ if (repeat > 0)
+ {
+ /* Check that exactly one thread executed the once_execute()
+ function. */
+ if (performed != 1)
+ abort ();
+ }
+
+ if (repeat == REPEAT_COUNT)
+ break;
+
+ /* Preparation for the next round: Initialize once_control. */
+ memcpy (&once_control, &fresh_once, sizeof (gl_once_t));
+
+ /* Preparation for the next round: Reset the performed counter. */
+ performed = 0;
+
+ /* Preparation for the next round: Reset the ready flags. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ {
+ gl_lock_lock (ready_lock[i]);
+ ready[i] = 0;
+ gl_lock_unlock (ready_lock[i]);
+ }
+
+ /* Signal all threads simultaneously. */
+ dbgprintf ("Main thread giving signal for round %d\n", repeat);
+#if ENABLE_LOCKING
+ gl_rwlock_unlock (fire_signal[repeat]);
+#else
+ fire_signal_state = repeat + 1;
+#endif
+ }
+
+ /* Wait for the threads to terminate. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ gl_thread_join (threads[i], NULL);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+int
+main ()
+{
+#if TEST_PTH_THREADS
+ if (!pth_init ())
+ abort ();
+#endif
+
+#if DO_TEST_LOCK
+ printf ("Starting test_lock ..."); fflush (stdout);
+ test_lock ();
+ printf (" OK\n"); fflush (stdout);
+#endif
+#if DO_TEST_RWLOCK
+ printf ("Starting test_rwlock ..."); fflush (stdout);
+ test_rwlock ();
+ printf (" OK\n"); fflush (stdout);
+#endif
+#if DO_TEST_RECURSIVE_LOCK
+ printf ("Starting test_recursive_lock ..."); fflush (stdout);
+ test_recursive_lock ();
+ printf (" OK\n"); fflush (stdout);
+#endif
+#if DO_TEST_ONCE
+ printf ("Starting test_once ..."); fflush (stdout);
+ test_once ();
+ printf (" OK\n"); fflush (stdout);
+#endif
+
+ return 0;
+}
+
+#else
+
+/* No multithreading available. */
+
+#include <stdio.h>
+
+int
+main ()
+{
+ fputs ("Skipping test: multithreading not enabled\n", stderr);
+ return 77;
+}
+
+#endif
diff --git a/gl/tests/test-perror.c b/gl/tests/test-perror.c
new file mode 100644
index 0000000000..d3751d8976
--- /dev/null
+++ b/gl/tests/test-perror.c
@@ -0,0 +1,37 @@
+/* Test of perror() function.
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (perror, void, (char const *));
+
+#include <errno.h>
+
+int
+main (int argc, char **argv)
+{
+ const char *prefix = (argc > 1 ? argv[1] : NULL);
+
+ errno = EACCES; perror (prefix);
+ errno = ETIMEDOUT; perror (prefix);
+ errno = EOVERFLOW; perror (prefix);
+
+ return 0;
+}
diff --git a/gl/tests/test-perror.sh b/gl/tests/test-perror.sh
new file mode 100755
index 0000000000..7274d3223f
--- /dev/null
+++ b/gl/tests/test-perror.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+: ${srcdir=.}
+. "$srcdir/init.sh"; path_prepend_ .
+
+# Test NULL prefix. Result should not contain a number.
+test-perror 2>&1 >/dev/null | LC_ALL=C tr -d '\r' > t-perror.tmp
+grep '[0-9]' t-perror.tmp > /dev/null \
+ && fail_ "result should not contain a number"
+
+# Test empty prefix. Result should be the same.
+test-perror '' 2>&1 >/dev/null | LC_ALL=C tr -d '\r' > t-perror1.tmp
+diff t-perror.tmp t-perror1.tmp \
+ || fail_ "empty prefix should behave like NULL argument"
+
+# Test non-empty prefix.
+test-perror foo 2>&1 >/dev/null | LC_ALL=C tr -d '\r' > t-perror3.tmp
+sed -e 's/^/foo: /' < t-perror.tmp > t-perror2.tmp
+diff t-perror2.tmp t-perror3.tmp || fail_ "prefix applied incorrectly"
+
+# Test exit status.
+test-perror >out 2>/dev/null || fail_ "unexpected exit status"
+test -s out && fail_ "unexpected output"
+
+Exit 0
diff --git a/gl/tests/test-perror2.c b/gl/tests/test-perror2.c
new file mode 100644
index 0000000000..e230f92320
--- /dev/null
+++ b/gl/tests/test-perror2.c
@@ -0,0 +1,137 @@
+/* Test of perror() function.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+/* This test intentionally parses stderr. So, we arrange to have fd 10
+ (outside the range of interesting fd's during the test) set up to
+ duplicate the original stderr. */
+#define BACKUP_STDERR_FILENO 10
+#define ASSERT_STREAM myerr
+#include "macros.h"
+
+static FILE *myerr;
+
+#define BASE "test-perror2"
+
+int
+main (void)
+{
+ /* We change fd 2 later, so save it in fd 10. */
+ if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
+ || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
+ return 2;
+
+ ASSERT (freopen (BASE ".tmp", "w+", stderr) == stderr);
+
+ /* Test that perror does not clobber strerror buffer. */
+ {
+ const char *msg1;
+ const char *msg2;
+ const char *msg3;
+ const char *msg4;
+ char *str1;
+ char *str2;
+ char *str3;
+ char *str4;
+
+ msg1 = strerror (ENOENT);
+ ASSERT (msg1);
+ str1 = strdup (msg1);
+ ASSERT (str1);
+
+ msg2 = strerror (ERANGE);
+ ASSERT (msg2);
+ str2 = strdup (msg2);
+ ASSERT (str2);
+
+ msg3 = strerror (-4);
+ ASSERT (msg3);
+ str3 = strdup (msg3);
+ ASSERT (str3);
+
+ msg4 = strerror (1729576);
+ ASSERT (msg4);
+ str4 = strdup (msg4);
+ ASSERT (str4);
+
+ errno = EACCES;
+ perror ("");
+ errno = -5;
+ perror ("");
+ ASSERT (!ferror (stderr));
+ ASSERT (msg1 == msg2 || msg1 == msg4 || STREQ (msg1, str1));
+ ASSERT (msg2 == msg4 || STREQ (msg2, str2));
+ ASSERT (msg3 == msg4 || STREQ (msg3, str3));
+ ASSERT (STREQ (msg4, str4));
+
+ free (str1);
+ free (str2);
+ free (str3);
+ free (str4);
+ }
+
+ /* Test that perror uses the same message as strerror. */
+ {
+ int errs[] = { EACCES, 0, -3, };
+ int i;
+ for (i = 0; i < SIZEOF (errs); i++)
+ {
+ char buf[256];
+ char *err = strerror (errs[i]);
+
+ ASSERT (err);
+ ASSERT (strlen (err) < sizeof buf);
+ rewind (stderr);
+ ASSERT (ftruncate (fileno (stderr), 0) == 0);
+ errno = errs[i];
+ perror (NULL);
+ ASSERT (!ferror (stderr));
+ rewind (stderr);
+ ASSERT (fgets (buf, sizeof buf, stderr) == buf);
+ ASSERT (strstr (buf, err));
+ }
+ }
+
+ /* Test that perror reports write failure. */
+ {
+ ASSERT (freopen (BASE ".tmp", "r", stderr) == stderr);
+ ASSERT (setvbuf (stderr, NULL, _IONBF, BUFSIZ) == 0);
+ errno = -1;
+ ASSERT (!ferror (stderr));
+ perror (NULL);
+#if 0
+ /* Commented out until cygwin behaves:
+ http://sourceware.org/ml/newlib/2011/msg00228.html */
+ ASSERT (errno > 0);
+ /* Commented out until glibc behaves:
+ http://sourceware.org/bugzilla/show_bug.cgi?id=12792 */
+ ASSERT (ferror (stderr));
+#endif
+ }
+
+ ASSERT (fclose (stderr) == 0);
+ ASSERT (remove (BASE ".tmp") == 0);
+
+ return 0;
+}
diff --git a/gl/tests/test-pipe.c b/gl/tests/test-pipe.c
new file mode 100644
index 0000000000..90f41f9107
--- /dev/null
+++ b/gl/tests/test-pipe.c
@@ -0,0 +1,105 @@
+/* Test of pipe.
+ Copyright (C) 2009-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (pipe, int, (int[2]));
+
+#include <fcntl.h>
+#include <stdbool.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the Win32 API functions. */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* Get _get_osfhandle. */
+# include "msvc-nothrow.h"
+#endif
+
+#include "binary-io.h"
+#include "macros.h"
+
+/* Return true if FD is open. */
+static bool
+is_open (int fd)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ /* On Win32, the initial state of unassigned standard file
+ descriptors is that they are open but point to an
+ INVALID_HANDLE_VALUE, and there is no fcntl. */
+ return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
+#else
+# ifndef F_GETFL
+# error Please port fcntl to your platform
+# endif
+ return 0 <= fcntl (fd, F_GETFL);
+#endif
+}
+
+/* Return true if FD is not inherited to child processes. */
+static bool
+is_cloexec (int fd)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ HANDLE h = (HANDLE) _get_osfhandle (fd);
+ DWORD flags;
+ ASSERT (GetHandleInformation (h, &flags));
+ return (flags & HANDLE_FLAG_INHERIT) == 0;
+#else
+ int flags;
+ ASSERT ((flags = fcntl (fd, F_GETFD)) >= 0);
+ return (flags & FD_CLOEXEC) != 0;
+#endif
+}
+
+/* Return true if FD is in non-blocking mode. */
+static bool
+is_nonblocking (int fd)
+{
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ /* We don't use the non-blocking mode for sockets here. */
+ return 0;
+#else
+ int flags;
+ ASSERT ((flags = fcntl (fd, F_GETFL)) >= 0);
+ return (flags & O_NONBLOCK) != 0;
+#endif
+}
+
+int
+main ()
+{
+ int fd[2];
+
+ fd[0] = -1;
+ fd[1] = -1;
+ ASSERT (pipe (fd) >= 0);
+ ASSERT (fd[0] >= 0);
+ ASSERT (fd[1] >= 0);
+ ASSERT (fd[0] != fd[1]);
+ ASSERT (is_open (fd[0]));
+ ASSERT (is_open (fd[1]));
+ ASSERT (!is_cloexec (fd[0]));
+ ASSERT (!is_cloexec (fd[1]));
+ ASSERT (!is_nonblocking (fd[0]));
+ ASSERT (!is_nonblocking (fd[1]));
+
+ return 0;
+}
diff --git a/gl/tests/test-select-fd.c b/gl/tests/test-select-fd.c
new file mode 100644
index 0000000000..de2f3e9c46
--- /dev/null
+++ b/gl/tests/test-select-fd.c
@@ -0,0 +1,72 @@
+/* Test of select() substitute, reading or writing from a given file descriptor.
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2008. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/select.h>
+
+int
+main (int argc, char *argv[])
+{
+ if (argc == 4)
+ {
+ char mode = argv[1][0];
+
+ if (mode == 'r' || mode == 'w')
+ {
+ int fd = atoi (argv[2]);
+
+ if (fd >= 0)
+ {
+ const char *result_file_name = argv[3];
+ FILE *result_file = fopen (result_file_name, "wb");
+
+ if (result_file != NULL)
+ {
+ fd_set fds;
+ struct timeval timeout;
+ int ret;
+
+ FD_ZERO (&fds);
+ FD_SET (fd, &fds);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 10000;
+ ret = (mode == 'r'
+ ? select (fd + 1, &fds, NULL, NULL, &timeout)
+ : select (fd + 1, NULL, &fds, NULL, &timeout));
+ if (ret < 0)
+ {
+ perror ("select failed");
+ exit (1);
+ }
+ if ((ret == 0) != ! FD_ISSET (fd, &fds))
+ {
+ fprintf (stderr, "incorrect return value\n");
+ exit (1);
+ }
+ fprintf (result_file, "%d\n", ret);
+ exit (0);
+ }
+ }
+ }
+ }
+ fprintf (stderr, "Usage: test-select-fd mode fd result-file-name\n");
+ exit (1);
+}
diff --git a/gl/tests/test-select-in.sh b/gl/tests/test-select-in.sh
new file mode 100755
index 0000000000..2a8b742268
--- /dev/null
+++ b/gl/tests/test-select-in.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+# Test select() on file descriptors opened for reading.
+
+# This test is known to fail on Solaris 2.6 and older, due to its handling
+# of /dev/null.
+
+tmpfiles=""
+trap 'rm -fr $tmpfiles' 1 2 3 15
+
+tmpfiles="$tmpfiles t-select-in.tmp"
+
+# Regular files.
+
+rm -f t-select-in.tmp
+./test-select-fd${EXEEXT} r 0 t-select-in.tmp < ./test-select-fd${EXEEXT}
+test `cat t-select-in.tmp` = "1" || exit 1
+
+# Pipes.
+
+rm -f t-select-in.tmp
+{ sleep 1; echo abc; } | \
+ { ./test-select-fd${EXEEXT} r 0 t-select-in.tmp; cat > /dev/null; }
+test `cat t-select-in.tmp` = "0" || exit 1
+
+rm -f t-select-in.tmp
+echo abc | { sleep 1; ./test-select-fd${EXEEXT} r 0 t-select-in.tmp; }
+test `cat t-select-in.tmp` = "1" || exit 1
+
+# Special files.
+# This part of the test is known to fail on Solaris 2.6 and older.
+
+# Doesn't work under mingw -- simon@josefsson.org
+#rm -f t-select-in.tmp
+#./test-select-fd${EXEEXT} r 0 t-select-in.tmp < /dev/null
+#test `cat t-select-in.tmp` = "1" || exit 1
+
+rm -fr $tmpfiles
+
+exit 0
diff --git a/gl/tests/test-select-out.sh b/gl/tests/test-select-out.sh
new file mode 100755
index 0000000000..c5fd8619f6
--- /dev/null
+++ b/gl/tests/test-select-out.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# Test select() on file descriptors opened for writing.
+
+tmpfiles=""
+trap 'rm -fr $tmpfiles' 1 2 3 15
+
+tmpfiles="$tmpfiles t-select-out.out t-select-out.tmp"
+
+# Regular files.
+
+rm -f t-select-out.tmp
+./test-select-fd${EXEEXT} w 1 t-select-out.tmp > t-select-out.out
+test `cat t-select-out.tmp` = "1" || exit 1
+
+# Pipes.
+
+if false; then # This test fails on some platforms.
+ rm -f t-select-out.tmp
+ ( { echo abc; ./test-select-fd${EXEEXT} w 1 t-select-out.tmp; } | { sleep 1; cat; } ) > /dev/null
+ test `cat t-select-out.tmp` = "0" || exit 1
+fi
+
+rm -f t-select-out.tmp
+( { sleep 1; echo abc; ./test-select-fd${EXEEXT} w 1 t-select-out.tmp; } | cat) > /dev/null
+test `cat t-select-out.tmp` = "1" || exit 1
+
+# Special files.
+
+rm -f t-select-out.tmp
+./test-select-fd${EXEEXT} w 1 t-select-out.tmp > /dev/null
+test `cat t-select-out.tmp` = "1" || exit 1
+
+rm -fr $tmpfiles
+
+exit 0
diff --git a/gl/tests/test-select-stdin.c b/gl/tests/test-select-stdin.c
new file mode 100644
index 0000000000..5a6f81a86a
--- /dev/null
+++ b/gl/tests/test-select-stdin.c
@@ -0,0 +1,83 @@
+/* Test of select() substitute, reading from stdin.
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2008. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "macros.h"
+
+int
+main (void)
+{
+ printf ("Applying select() from standard input. Press Ctrl-C to abort.\n");
+ for (;;)
+ {
+ struct timeval before;
+ struct timeval after;
+ unsigned long spent_usec;
+ fd_set readfds;
+ struct timeval timeout;
+ int ret;
+
+ gettimeofday (&before, NULL);
+
+ FD_ZERO (&readfds);
+ FD_SET (0, &readfds);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000;
+ ret = select (1, &readfds, NULL, NULL, &timeout);
+
+ gettimeofday (&after, NULL);
+ spent_usec = (after.tv_sec - before.tv_sec) * 1000000
+ + after.tv_usec - before.tv_usec;
+
+ if (ret < 0)
+ {
+ perror ("select failed");
+ exit (1);
+ }
+ if ((ret == 0) != ! FD_ISSET (0, &readfds))
+ {
+ fprintf (stderr, "incorrect return value\n");
+ exit (1);
+ }
+ if (ret == 0)
+ {
+ if (spent_usec < 250000)
+ {
+ fprintf (stderr, "returned too early\n");
+ exit (1);
+ }
+ /* Timeout */
+ printf (".");
+ ASSERT (fflush (stdout) == 0);
+ }
+ else
+ {
+ char c;
+
+ printf ("Input available! Trying to read 1 byte...\n");
+ ASSERT (read (0, &c, 1) == 1);
+ }
+ }
+}
diff --git a/gl/tests/test-select.c b/gl/tests/test-select.c
new file mode 100644
index 0000000000..9c6fb9dbc7
--- /dev/null
+++ b/gl/tests/test-select.c
@@ -0,0 +1,34 @@
+/* Test of select() substitute.
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paolo Bonzini, 2008. */
+
+#include <config.h>
+
+#include <sys/select.h>
+
+#include "signature.h"
+
+SIGNATURE_CHECK (select, int, (int, fd_set *, fd_set *, fd_set *,
+ struct timeval *));
+
+#include "test-select.h"
+
+int
+main (void)
+{
+ return test_function (select);
+}
diff --git a/gl/tests/test-select.h b/gl/tests/test-select.h
new file mode 100644
index 0000000000..4612dfc719
--- /dev/null
+++ b/gl/tests/test-select.h
@@ -0,0 +1,436 @@
+/* Test of select() substitute.
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paolo Bonzini, 2008. */
+
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "macros.h"
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_NATIVE
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#ifndef SO_REUSEPORT
+# define SO_REUSEPORT SO_REUSEADDR
+#endif
+
+#define TEST_PORT 12345
+
+
+typedef int (*select_fn) (int, fd_set *, fd_set *, fd_set *, struct timeval *);
+
+
+/* Minimal testing infrastructure. */
+
+static int failures;
+
+static void
+failed (const char *reason)
+{
+ if (++failures > 1)
+ printf (" ");
+ printf ("failed (%s)\n", reason);
+}
+
+static int
+test (void (*fn) (select_fn), select_fn my_select, const char *msg)
+{
+ failures = 0;
+ printf ("%s... ", msg);
+ fflush (stdout);
+ fn (my_select);
+
+ if (!failures)
+ printf ("passed\n");
+
+ return failures;
+}
+
+
+/* Funny socket code. */
+
+static int
+open_server_socket (void)
+{
+ int s, x;
+ struct sockaddr_in ia;
+
+ s = socket (AF_INET, SOCK_STREAM, 0);
+
+ memset (&ia, 0, sizeof (ia));
+ ia.sin_family = AF_INET;
+ inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr);
+ ia.sin_port = htons (TEST_PORT);
+ if (bind (s, (struct sockaddr *) &ia, sizeof (ia)) < 0)
+ {
+ perror ("bind");
+ exit (77);
+ }
+
+ x = 1;
+ setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
+
+ if (listen (s, 1) < 0)
+ {
+ perror ("listen");
+ exit (77);
+ }
+
+ return s;
+}
+
+static int
+connect_to_socket (bool blocking)
+{
+ int s;
+ struct sockaddr_in ia;
+
+ s = socket (AF_INET, SOCK_STREAM, 0);
+
+ memset (&ia, 0, sizeof (ia));
+ ia.sin_family = AF_INET;
+ inet_pton (AF_INET, "127.0.0.1", &ia.sin_addr);
+ ia.sin_port = htons (TEST_PORT);
+
+ if (!blocking)
+ {
+#ifdef WIN32_NATIVE
+ unsigned long iMode = 1;
+ ioctl (s, FIONBIO, (char *) &iMode);
+
+#elif defined F_GETFL
+ int oldflags = fcntl (s, F_GETFL, NULL);
+
+ if (!(oldflags & O_NONBLOCK))
+ fcntl (s, F_SETFL, oldflags | O_NONBLOCK);
+#endif
+ }
+
+ if (connect (s, (struct sockaddr *) &ia, sizeof (ia)) < 0
+ && (blocking || errno != EINPROGRESS))
+ {
+ perror ("connect");
+ exit (77);
+ }
+
+ return s;
+}
+
+
+/* A slightly more convenient interface to select(2).
+ Waits until a specific event occurs on a file descriptor FD.
+ EV is a bit mask of events to look for:
+ SEL_IN - input can be polled without blocking,
+ SEL_OUT - output can be provided without blocking,
+ SEL_EXC - an exception occurred,
+ A maximum wait time is specified by TIMEOUT.
+ *TIMEOUT = { 0, 0 } means to return immediately,
+ TIMEOUT = NULL means to wait indefinitely. */
+
+enum { SEL_IN = 1, SEL_OUT = 2, SEL_EXC = 4 };
+
+static int
+do_select (int fd, int ev, struct timeval *timeout, select_fn my_select)
+{
+ fd_set rfds, wfds, xfds;
+ int r, rev;
+
+ FD_ZERO (&rfds);
+ FD_ZERO (&wfds);
+ FD_ZERO (&xfds);
+ if (ev & SEL_IN)
+ FD_SET (fd, &rfds);
+ if (ev & SEL_OUT)
+ FD_SET (fd, &wfds);
+ if (ev & SEL_EXC)
+ FD_SET (fd, &xfds);
+ r = my_select (fd + 1, &rfds, &wfds, &xfds, timeout);
+ if (r < 0)
+ return r;
+
+ rev = 0;
+ if (FD_ISSET (fd, &rfds))
+ rev |= SEL_IN;
+ if (FD_ISSET (fd, &wfds))
+ rev |= SEL_OUT;
+ if (FD_ISSET (fd, &xfds))
+ rev |= SEL_EXC;
+ if (rev && r == 0)
+ failed ("select returned 0");
+ if (rev & ~ev)
+ failed ("select returned unrequested events");
+
+ return rev;
+}
+
+static int
+do_select_nowait (int fd, int ev, select_fn my_select)
+{
+ struct timeval tv0;
+ tv0.tv_sec = 0;
+ tv0.tv_usec = 0;
+ return do_select (fd, ev, &tv0, my_select);
+}
+
+static int
+do_select_wait (int fd, int ev, select_fn my_select)
+{
+ return do_select (fd, ev, NULL, my_select);
+}
+
+
+/* Test select(2) for TTYs. */
+
+#ifdef INTERACTIVE
+static void
+test_tty (select_fn my_select)
+{
+ if (do_select_nowait (0, SEL_IN, my_select) != 0)
+ failed ("can read");
+ if (do_select_nowait (0, SEL_OUT, my_select) == 0)
+ failed ("cannot write");
+
+ if (do_select_wait (0, SEL_IN, my_select) == 0)
+ failed ("return with infinite timeout");
+
+ getchar ();
+ if (do_select_nowait (0, SEL_IN, my_select) != 0)
+ failed ("can read after getc");
+}
+#endif
+
+
+/* Test select(2) on invalid file descriptors. */
+
+static int
+do_select_bad_fd (int fd, int ev, struct timeval *timeout, select_fn my_select)
+{
+ fd_set rfds, wfds, xfds;
+
+ FD_ZERO (&rfds);
+ FD_ZERO (&wfds);
+ FD_ZERO (&xfds);
+ if (ev & SEL_IN)
+ FD_SET (fd, &rfds);
+ if (ev & SEL_OUT)
+ FD_SET (fd, &wfds);
+ if (ev & SEL_EXC)
+ FD_SET (fd, &xfds);
+ return my_select (fd + 1, &rfds, &wfds, &xfds, timeout);
+ /* In this case, when fd is invalid, on some platforms, the bit for fd
+ is left alone in the fd_set, whereas on other platforms it is cleared.
+ So, don't check the bit for fd here. */
+}
+
+static int
+do_select_bad_fd_nowait (int fd, int ev, select_fn my_select)
+{
+ struct timeval tv0;
+ tv0.tv_sec = 0;
+ tv0.tv_usec = 0;
+ return do_select_bad_fd (fd, ev, &tv0, my_select);
+}
+
+static void
+test_bad_fd (select_fn my_select)
+{
+ /* This tests fails on OSF/1 and native Windows, even with fd = 16. */
+#if !(defined __osf__ || defined WIN32_NATIVE)
+ int fd;
+
+ /* On Linux, MacOS X, *BSD, values of fd like 99 or 399 are discarded
+ by the kernel early and therefore do *not* lead to EBADF, as required
+ by POSIX. */
+# if defined __linux__ || (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
+ fd = 16;
+# else
+ fd = 99;
+# endif
+
+ if (do_select_bad_fd_nowait (fd, SEL_IN, my_select) == 0 || errno != EBADF)
+ failed ("invalid fd among rfds");
+ if (do_select_bad_fd_nowait (fd, SEL_OUT, my_select) == 0 || errno != EBADF)
+ failed ("invalid fd among wfds");
+ if (do_select_bad_fd_nowait (fd, SEL_EXC, my_select) == 0 || errno != EBADF)
+ failed ("invalid fd among xfds");
+#endif
+}
+
+
+/* Test select(2) for unconnected nonblocking sockets. */
+
+static void
+test_connect_first (select_fn my_select)
+{
+ int s = open_server_socket ();
+ struct sockaddr_in ia;
+ socklen_t addrlen;
+
+ int c1, c2;
+
+ if (do_select_nowait (s, SEL_IN | SEL_EXC, my_select) != 0)
+ failed ("can read, socket not connected");
+
+ c1 = connect_to_socket (false);
+
+ if (do_select_wait (s, SEL_IN | SEL_EXC, my_select) != SEL_IN)
+ failed ("expecting readability on passive socket");
+ if (do_select_nowait (s, SEL_IN | SEL_EXC, my_select) != SEL_IN)
+ failed ("expecting readability on passive socket");
+
+ addrlen = sizeof (ia);
+ c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
+ ASSERT (close (s) == 0);
+ ASSERT (close (c1) == 0);
+ ASSERT (close (c2) == 0);
+}
+
+
+/* Test select(2) for unconnected blocking sockets. */
+
+static void
+test_accept_first (select_fn my_select)
+{
+#ifndef WIN32_NATIVE
+ int s = open_server_socket ();
+ struct sockaddr_in ia;
+ socklen_t addrlen;
+ char buf[3];
+ int c, pid;
+
+ pid = fork ();
+ if (pid < 0)
+ return;
+
+ if (pid == 0)
+ {
+ addrlen = sizeof (ia);
+ c = accept (s, (struct sockaddr *) &ia, &addrlen);
+ ASSERT (close (s) == 0);
+ ASSERT (write (c, "foo", 3) == 3);
+ ASSERT (read (c, buf, 3) == 3);
+ shutdown (c, SHUT_RD);
+ ASSERT (close (c) == 0);
+ exit (0);
+ }
+ else
+ {
+ ASSERT (close (s) == 0);
+ c = connect_to_socket (true);
+ if (do_select_nowait (c, SEL_OUT, my_select) != SEL_OUT)
+ failed ("cannot write after blocking connect");
+ ASSERT (write (c, "foo", 3) == 3);
+ wait (&pid);
+ if (do_select_wait (c, SEL_IN, my_select) != SEL_IN)
+ failed ("cannot read data left in the socket by closed process");
+ ASSERT (read (c, buf, 3) == 3);
+ ASSERT (write (c, "foo", 3) == 3);
+ (void) close (c); /* may fail with errno = ECONNRESET */
+ }
+#endif
+}
+
+
+/* Common code for pipes and connected sockets. */
+
+static void
+test_pair (int rd, int wd, select_fn my_select)
+{
+ char buf[3];
+ if (do_select_wait (wd, SEL_IN | SEL_OUT | SEL_EXC, my_select) != SEL_OUT)
+ failed ("expecting writability before writing");
+ if (do_select_nowait (wd, SEL_IN | SEL_OUT | SEL_EXC, my_select) != SEL_OUT)
+ failed ("expecting writability before writing");
+
+ ASSERT (write (wd, "foo", 3) == 3);
+ if (do_select_wait (rd, SEL_IN, my_select) != SEL_IN)
+ failed ("expecting readability after writing");
+ if (do_select_nowait (rd, SEL_IN, my_select) != SEL_IN)
+ failed ("expecting readability after writing");
+
+ ASSERT (read (rd, buf, 3) == 3);
+}
+
+
+/* Test select(2) on connected sockets. */
+
+static void
+test_socket_pair (select_fn my_select)
+{
+ struct sockaddr_in ia;
+
+ socklen_t addrlen = sizeof (ia);
+ int s = open_server_socket ();
+ int c1 = connect_to_socket (false);
+ int c2 = accept (s, (struct sockaddr *) &ia, &addrlen);
+
+ ASSERT (close (s) == 0);
+
+ test_pair (c1, c2, my_select);
+ ASSERT (close (c1) == 0);
+ ASSERT (write (c2, "foo", 3) == 3);
+ (void) close (c2); /* may fail with errno = ECONNRESET */
+}
+
+
+/* Test select(2) on pipes. */
+
+static void
+test_pipe (select_fn my_select)
+{
+ int fd[2];
+
+ ASSERT (pipe (fd) == 0);
+ test_pair (fd[0], fd[1], my_select);
+ ASSERT (close (fd[0]) == 0);
+ ASSERT (close (fd[1]) == 0);
+}
+
+
+/* Do them all. */
+
+static int
+test_function (select_fn my_select)
+{
+ int result = 0;
+
+#ifdef INTERACTIVE
+ printf ("Please press Enter\n");
+ test (test_tty, "TTY", my_select);
+#endif
+
+ result += test (test_bad_fd, my_select, "Invalid fd test");
+ result += test (test_connect_first, my_select, "Unconnected socket test");
+ result += test (test_socket_pair, my_select, "Connected sockets test");
+ result += test (test_accept_first, my_select, "General socket test with fork");
+ result += test (test_pipe, my_select, "Pipe test");
+
+ return result;
+}
diff --git a/gl/tests/test-signal-h.c b/gl/tests/test-signal-h.c
new file mode 100644
index 0000000000..7103e1ff19
--- /dev/null
+++ b/gl/tests/test-signal-h.c
@@ -0,0 +1,129 @@
+/* Test of <signal.h> substitute.
+ Copyright (C) 2009-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Eric Blake <ebb9@byu.net>, 2009. */
+
+#include <config.h>
+
+#include <signal.h>
+
+/* Check for required types. */
+struct
+{
+ size_t a;
+ uid_t b;
+ volatile sig_atomic_t c;
+ sigset_t d;
+ pid_t e;
+#if 0
+ /* Not guaranteed by gnulib. */
+ pthread_t f;
+ struct timespec g;
+#endif
+} s;
+
+/* Check that NSIG is defined. */
+int nsig = NSIG;
+
+int
+main (void)
+{
+ switch (0)
+ {
+ /* The following are guaranteed by C. */
+ case 0:
+ case SIGABRT:
+ case SIGFPE:
+ case SIGILL:
+ case SIGINT:
+ case SIGSEGV:
+ case SIGTERM:
+ /* The following is guaranteed by gnulib. */
+#if GNULIB_SIGPIPE || defined SIGPIPE
+ case SIGPIPE:
+#endif
+ /* Ensure no conflict with other standardized names. */
+#ifdef SIGALRM
+ case SIGALRM:
+#endif
+ /* On Haiku, SIGBUS is mistakenly equal to SIGSEGV. */
+#if defined SIGBUS && SIGBUS != SIGSEGV
+ case SIGBUS:
+#endif
+#ifdef SIGCHLD
+ case SIGCHLD:
+#endif
+#ifdef SIGCONT
+ case SIGCONT:
+#endif
+#ifdef SIGHUP
+ case SIGHUP:
+#endif
+#ifdef SIGKILL
+ case SIGKILL:
+#endif
+#ifdef SIGQUIT
+ case SIGQUIT:
+#endif
+#ifdef SIGSTOP
+ case SIGSTOP:
+#endif
+#ifdef SIGTSTP
+ case SIGTSTP:
+#endif
+#ifdef SIGTTIN
+ case SIGTTIN:
+#endif
+#ifdef SIGTTOU
+ case SIGTTOU:
+#endif
+#ifdef SIGUSR1
+ case SIGUSR1:
+#endif
+#ifdef SIGUSR2
+ case SIGUSR2:
+#endif
+#ifdef SIGSYS
+ case SIGSYS:
+#endif
+#ifdef SIGTRAP
+ case SIGTRAP:
+#endif
+#ifdef SIGURG
+ case SIGURG:
+#endif
+#ifdef SIGVTALRM
+ case SIGVTALRM:
+#endif
+#ifdef SIGXCPU
+ case SIGXCPU:
+#endif
+#ifdef SIGXFSZ
+ case SIGXFSZ:
+#endif
+ /* SIGRTMIN and SIGRTMAX need not be compile-time constants. */
+#if 0
+# ifdef SIGRTMIN
+ case SIGRTMIN:
+# endif
+# ifdef SIGRTMAX
+ case SIGRTMAX:
+# endif
+#endif
+ ;
+ }
+ return s.a + s.b + s.c + s.e;
+}
diff --git a/gl/tests/test-strerror_r.c b/gl/tests/test-strerror_r.c
new file mode 100644
index 0000000000..956c458d7b
--- /dev/null
+++ b/gl/tests/test-strerror_r.c
@@ -0,0 +1,182 @@
+/* Test of strerror_r() function.
+ Copyright (C) 2007-2011 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (strerror_r, int, (int, char *, size_t));
+
+#include <errno.h>
+
+#include "macros.h"
+
+int
+main (void)
+{
+ char buf[100];
+ int ret;
+
+ /* Test results with valid errnum and enough room. */
+
+ errno = 0;
+ buf[0] = '\0';
+ ASSERT (strerror_r (EACCES, buf, sizeof buf) == 0);
+ ASSERT (buf[0] != '\0');
+ ASSERT (errno == 0);
+ ASSERT (strlen (buf) < sizeof buf);
+
+ errno = 0;
+ buf[0] = '\0';
+ ASSERT (strerror_r (ETIMEDOUT, buf, sizeof buf) == 0);
+ ASSERT (buf[0] != '\0');
+ ASSERT (errno == 0);
+ ASSERT (strlen (buf) < sizeof buf);
+
+ errno = 0;
+ buf[0] = '\0';
+ ASSERT (strerror_r (EOVERFLOW, buf, sizeof buf) == 0);
+ ASSERT (buf[0] != '\0');
+ ASSERT (errno == 0);
+ ASSERT (strlen (buf) < sizeof buf);
+
+ /* POSIX requires strerror (0) to succeed. Reject use of "Unknown
+ error", but allow "Success", "No error", or even Solaris' "Error
+ 0" which are distinct patterns from true out-of-range strings.
+ http://austingroupbugs.net/view.php?id=382 */
+ errno = 0;
+ buf[0] = '\0';
+ ret = strerror_r (0, buf, sizeof buf);
+ ASSERT (ret == 0);
+ ASSERT (buf[0]);
+ ASSERT (errno == 0);
+ ASSERT (strstr (buf, "nknown") == NULL);
+ ASSERT (strstr (buf, "ndefined") == NULL);
+
+ /* Test results with out-of-range errnum and enough room. POSIX
+ allows an empty string on success, and allows an unchanged buf on
+ error, but these are not useful, so we guarantee contents. */
+ errno = 0;
+ buf[0] = '^';
+ ret = strerror_r (-3, buf, sizeof buf);
+ ASSERT (ret == 0 || ret == EINVAL);
+ ASSERT (buf[0] != '^');
+ ASSERT (*buf);
+ ASSERT (errno == 0);
+ ASSERT (strlen (buf) < sizeof buf);
+
+ /* Test results with a too small buffer. POSIX requires an error;
+ only ERANGE for 0 and valid errors, and a choice of ERANGE or
+ EINVAL for out-of-range values. On error, POSIX permits buf to
+ be empty, unchanged, or unterminated, but these are not useful,
+ so we guarantee NUL-terminated truncated contents for all but
+ size 0. http://austingroupbugs.net/view.php?id=398. Also ensure
+ that no out-of-bounds writes occur. */
+ {
+ int errs[] = { EACCES, 0, -3, };
+ int j;
+
+ buf[sizeof buf - 1] = '\0';
+ for (j = 0; j < SIZEOF (errs); j++)
+ {
+ int err = errs[j];
+ char buf2[sizeof buf] = "";
+ size_t len;
+ size_t i;
+
+ strerror_r (err, buf2, sizeof buf2);
+ len = strlen (buf2);
+ ASSERT (len < sizeof buf);
+
+ for (i = 0; i <= len; i++)
+ {
+ memset (buf, '^', sizeof buf - 1);
+ errno = 0;
+ ret = strerror_r (err, buf, i);
+ ASSERT (errno == 0);
+ if (err < 0)
+ ASSERT (ret == ERANGE || ret == EINVAL);
+ else
+ ASSERT (ret == ERANGE);
+ if (i)
+ {
+ ASSERT (strncmp (buf, buf2, i - 1) == 0);
+ ASSERT (buf[i - 1] == '\0');
+ }
+ ASSERT (strspn (buf + i, "^") == sizeof buf - 1 - i);
+ }
+
+ strcpy (buf, "BADFACE");
+ errno = 0;
+ ret = strerror_r (err, buf, len + 1);
+ ASSERT (ret != ERANGE);
+ ASSERT (errno == 0);
+ ASSERT (strcmp (buf, buf2) == 0);
+ }
+ }
+
+#if GNULIB_STRERROR
+ /* Test that strerror_r does not clobber strerror buffer. On some
+ platforms, this test can only succeed if gnulib also replaces
+ strerror. */
+ {
+ const char *msg1;
+ const char *msg2;
+ const char *msg3;
+ const char *msg4;
+ char *str1;
+ char *str2;
+ char *str3;
+ char *str4;
+
+ msg1 = strerror (ENOENT);
+ ASSERT (msg1);
+ str1 = strdup (msg1);
+ ASSERT (str1);
+
+ msg2 = strerror (ERANGE);
+ ASSERT (msg2);
+ str2 = strdup (msg2);
+ ASSERT (str2);
+
+ msg3 = strerror (-4);
+ ASSERT (msg3);
+ str3 = strdup (msg3);
+ ASSERT (str3);
+
+ msg4 = strerror (1729576);
+ ASSERT (msg4);
+ str4 = strdup (msg4);
+ ASSERT (str4);
+
+ strerror_r (EACCES, buf, sizeof buf);
+ strerror_r (-5, buf, sizeof buf);
+ ASSERT (msg1 == msg2 || msg1 == msg4 || STREQ (msg1, str1));
+ ASSERT (msg2 == msg4 || STREQ (msg2, str2));
+ ASSERT (msg3 == msg4 || STREQ (msg3, str3));
+ ASSERT (STREQ (msg4, str4));
+
+ free (str1);
+ free (str2);
+ free (str3);
+ free (str4);
+ }
+#endif
+
+ return 0;
+}
diff --git a/gl/tests/test-sys_ioctl.c b/gl/tests/test-sys_ioctl.c
new file mode 100644
index 0000000000..dd01b4aadd
--- /dev/null
+++ b/gl/tests/test-sys_ioctl.c
@@ -0,0 +1,27 @@
+/* Test of <sys/ioctl.h> substitute.
+ Copyright (C) 2009-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Eric Blake <ebb9@byu.net>, 2009. */
+
+#include <config.h>
+
+#include <sys/ioctl.h>
+
+int
+main (void)
+{
+ return 0;
+}
diff --git a/gl/tests/test-sys_select.c b/gl/tests/test-sys_select.c
new file mode 100644
index 0000000000..76596dba30
--- /dev/null
+++ b/gl/tests/test-sys_select.c
@@ -0,0 +1,55 @@
+/* Test of <sys/select.h> substitute.
+ Copyright (C) 2007-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2007. */
+
+#include <config.h>
+
+#include <sys/select.h>
+
+#include "signature.h"
+
+/* The following may be macros without underlying functions, so only
+ check signature if they are not macros. */
+#ifndef FD_CLR
+SIGNATURE_CHECK (FD_CLR, void, (int, fd_set *));
+#endif
+#ifndef FD_ISSET
+SIGNATURE_CHECK (FD_ISSET, void, (int, fd_set *));
+#endif
+#ifndef FD_SET
+SIGNATURE_CHECK (FD_SET, int, (int, fd_set *));
+#endif
+#ifndef FD_ZERO
+SIGNATURE_CHECK (FD_ZERO, void, (fd_set *));
+#endif
+
+/* Check that the 'struct timeval' type is defined. */
+struct timeval t1;
+
+/* Check that sigset_t is defined. */
+sigset_t t2;
+
+int
+main (void)
+{
+ /* Check that FD_ZERO can be used. This should not yield a warning
+ such as "warning: implicit declaration of function 'memset'". */
+ fd_set fds;
+ FD_ZERO (&fds);
+
+ return 0;
+}
diff --git a/gl/tests/test-thread_create.c b/gl/tests/test-thread_create.c
new file mode 100644
index 0000000000..1348c8c3c6
--- /dev/null
+++ b/gl/tests/test-thread_create.c
@@ -0,0 +1,78 @@
+/* Test of gl_thread_create () macro.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2011. */
+
+#include <config.h>
+
+#include "glthread/thread.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "macros.h"
+
+static gl_thread_t main_thread_before;
+static gl_thread_t main_thread_after;
+static gl_thread_t worker_thread;
+
+static int dummy;
+static volatile int work_done;
+
+static void *
+worker_thread_func (void *arg)
+{
+ work_done = 1;
+ return &dummy;
+}
+
+int
+main ()
+{
+ main_thread_before = gl_thread_self ();
+
+ if (glthread_create (&worker_thread, worker_thread_func, NULL) == 0)
+ {
+ void *ret;
+
+ /* Check that gl_thread_self () has the same value before than after the
+ first call to gl_thread_create (). */
+ main_thread_after = gl_thread_self ();
+ ASSERT (memcmp (&main_thread_before, &main_thread_after,
+ sizeof (gl_thread_t))
+ == 0);
+
+ gl_thread_join (worker_thread, &ret);
+
+ /* Check the return value of the thread. */
+ ASSERT (ret == &dummy);
+
+ /* Check that worker_thread_func () has finished executing. */
+ ASSERT (work_done);
+
+ return 0;
+ }
+ else
+ {
+#if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WIN32_THREADS
+ fputs ("glthread_create failed\n", stderr);
+ return 1;
+#else
+ fputs ("Skipping test: multithreading not enabled\n", stderr);
+ return 77;
+#endif
+ }
+}
diff --git a/gl/tests/test-thread_self.c b/gl/tests/test-thread_self.c
new file mode 100644
index 0000000000..816ee09680
--- /dev/null
+++ b/gl/tests/test-thread_self.c
@@ -0,0 +1,34 @@
+/* Test of gl_thread_self () macro.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2011. */
+
+#include <config.h>
+
+#include "glthread/thread.h"
+
+gl_thread_t main_thread;
+
+int
+main ()
+{
+ /* Check that gl_thread_self () can be used with just $(LIBTHREAD), not
+ $(LIBMULTITHREAD), i.e. in libraries that are multithread-safe but don't
+ create threads themselves. */
+ main_thread = gl_thread_self ();
+
+ return 0;
+}
diff --git a/gl/tests/w32sock.h b/gl/tests/w32sock.h
new file mode 100644
index 0000000000..0b8334e4ec
--- /dev/null
+++ b/gl/tests/w32sock.h
@@ -0,0 +1,136 @@
+/* w32sock.h --- internal auxilliary functions for Windows socket functions
+
+ Copyright (C) 2008-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paolo Bonzini */
+
+#include <errno.h>
+
+/* Get O_RDWR and O_BINARY. */
+#include <fcntl.h>
+
+/* Get _open_osfhandle(). */
+#include <io.h>
+
+/* Get _get_osfhandle(). */
+#include "msvc-nothrow.h"
+
+#define FD_TO_SOCKET(fd) ((SOCKET) _get_osfhandle ((fd)))
+#define SOCKET_TO_FD(fh) (_open_osfhandle ((long) (fh), O_RDWR | O_BINARY))
+
+static inline void
+set_winsock_errno (void)
+{
+ int err = WSAGetLastError ();
+
+ /* Map some WSAE* errors to the runtime library's error codes. */
+ switch (err)
+ {
+ case WSA_INVALID_HANDLE:
+ errno = EBADF;
+ break;
+ case WSA_NOT_ENOUGH_MEMORY:
+ errno = ENOMEM;
+ break;
+ case WSA_INVALID_PARAMETER:
+ errno = EINVAL;
+ break;
+ case WSAENAMETOOLONG:
+ errno = ENAMETOOLONG;
+ break;
+ case WSAENOTEMPTY:
+ errno = ENOTEMPTY;
+ break;
+ case WSAEWOULDBLOCK:
+ errno = EWOULDBLOCK;
+ break;
+ case WSAEINPROGRESS:
+ errno = EINPROGRESS;
+ break;
+ case WSAEALREADY:
+ errno = EALREADY;
+ break;
+ case WSAENOTSOCK:
+ errno = ENOTSOCK;
+ break;
+ case WSAEDESTADDRREQ:
+ errno = EDESTADDRREQ;
+ break;
+ case WSAEMSGSIZE:
+ errno = EMSGSIZE;
+ break;
+ case WSAEPROTOTYPE:
+ errno = EPROTOTYPE;
+ break;
+ case WSAENOPROTOOPT:
+ errno = ENOPROTOOPT;
+ break;
+ case WSAEPROTONOSUPPORT:
+ errno = EPROTONOSUPPORT;
+ break;
+ case WSAEOPNOTSUPP:
+ errno = EOPNOTSUPP;
+ break;
+ case WSAEAFNOSUPPORT:
+ errno = EAFNOSUPPORT;
+ break;
+ case WSAEADDRINUSE:
+ errno = EADDRINUSE;
+ break;
+ case WSAEADDRNOTAVAIL:
+ errno = EADDRNOTAVAIL;
+ break;
+ case WSAENETDOWN:
+ errno = ENETDOWN;
+ break;
+ case WSAENETUNREACH:
+ errno = ENETUNREACH;
+ break;
+ case WSAENETRESET:
+ errno = ENETRESET;
+ break;
+ case WSAECONNABORTED:
+ errno = ECONNABORTED;
+ break;
+ case WSAECONNRESET:
+ errno = ECONNRESET;
+ break;
+ case WSAENOBUFS:
+ errno = ENOBUFS;
+ break;
+ case WSAEISCONN:
+ errno = EISCONN;
+ break;
+ case WSAENOTCONN:
+ errno = ENOTCONN;
+ break;
+ case WSAETIMEDOUT:
+ errno = ETIMEDOUT;
+ break;
+ case WSAECONNREFUSED:
+ errno = ECONNREFUSED;
+ break;
+ case WSAELOOP:
+ errno = ELOOP;
+ break;
+ case WSAEHOSTUNREACH:
+ errno = EHOSTUNREACH;
+ break;
+ default:
+ errno = (err > 10000 && err < 10025) ? err - 10000 : err;
+ break;
+ }
+}
diff --git a/gl/w32sock.h b/gl/w32sock.h
index 55280d6497..0b8334e4ec 100644
--- a/gl/w32sock.h
+++ b/gl/w32sock.h
@@ -48,15 +48,87 @@ set_winsock_errno (void)
case WSA_INVALID_PARAMETER:
errno = EINVAL;
break;
- case WSAEWOULDBLOCK:
- errno = EWOULDBLOCK;
- break;
case WSAENAMETOOLONG:
errno = ENAMETOOLONG;
break;
case WSAENOTEMPTY:
errno = ENOTEMPTY;
break;
+ case WSAEWOULDBLOCK:
+ errno = EWOULDBLOCK;
+ break;
+ case WSAEINPROGRESS:
+ errno = EINPROGRESS;
+ break;
+ case WSAEALREADY:
+ errno = EALREADY;
+ break;
+ case WSAENOTSOCK:
+ errno = ENOTSOCK;
+ break;
+ case WSAEDESTADDRREQ:
+ errno = EDESTADDRREQ;
+ break;
+ case WSAEMSGSIZE:
+ errno = EMSGSIZE;
+ break;
+ case WSAEPROTOTYPE:
+ errno = EPROTOTYPE;
+ break;
+ case WSAENOPROTOOPT:
+ errno = ENOPROTOOPT;
+ break;
+ case WSAEPROTONOSUPPORT:
+ errno = EPROTONOSUPPORT;
+ break;
+ case WSAEOPNOTSUPP:
+ errno = EOPNOTSUPP;
+ break;
+ case WSAEAFNOSUPPORT:
+ errno = EAFNOSUPPORT;
+ break;
+ case WSAEADDRINUSE:
+ errno = EADDRINUSE;
+ break;
+ case WSAEADDRNOTAVAIL:
+ errno = EADDRNOTAVAIL;
+ break;
+ case WSAENETDOWN:
+ errno = ENETDOWN;
+ break;
+ case WSAENETUNREACH:
+ errno = ENETUNREACH;
+ break;
+ case WSAENETRESET:
+ errno = ENETRESET;
+ break;
+ case WSAECONNABORTED:
+ errno = ECONNABORTED;
+ break;
+ case WSAECONNRESET:
+ errno = ECONNRESET;
+ break;
+ case WSAENOBUFS:
+ errno = ENOBUFS;
+ break;
+ case WSAEISCONN:
+ errno = EISCONN;
+ break;
+ case WSAENOTCONN:
+ errno = ENOTCONN;
+ break;
+ case WSAETIMEDOUT:
+ errno = ETIMEDOUT;
+ break;
+ case WSAECONNREFUSED:
+ errno = ECONNREFUSED;
+ break;
+ case WSAELOOP:
+ errno = ELOOP;
+ break;
+ case WSAEHOSTUNREACH:
+ errno = EHOSTUNREACH;
+ break;
default:
errno = (err > 10000 && err < 10025) ? err - 10000 : err;
break;