]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
new gnulib + added select + inet_pton.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 26 Oct 2011 21:43:43 +0000 (23:43 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 26 Oct 2011 21:43:43 +0000 (23:43 +0200)
61 files changed:
gl/Makefile.am
gl/arpa_inet.in.h [moved from gl/tests/arpa_inet.in.h with 100% similarity]
gl/errno.in.h
gl/inet_pton.c [moved from gl/tests/inet_pton.c with 100% similarity]
gl/m4/ftruncate.m4 [new file with mode: 0644]
gl/m4/gnulib-cache.m4
gl/m4/gnulib-comp.m4
gl/m4/ioctl.m4 [new file with mode: 0644]
gl/m4/perror.m4 [new file with mode: 0644]
gl/m4/pipe.m4 [new file with mode: 0644]
gl/m4/select.m4 [new file with mode: 0644]
gl/m4/signal_h.m4 [new file with mode: 0644]
gl/m4/strerror_r.m4 [new file with mode: 0644]
gl/m4/sys_ioctl_h.m4 [new file with mode: 0644]
gl/m4/sys_select_h.m4 [new file with mode: 0644]
gl/m4/thread.m4 [new file with mode: 0644]
gl/m4/yield.m4 [new file with mode: 0644]
gl/math.in.h
gl/select.c [new file with mode: 0644]
gl/signal.in.h [new file with mode: 0644]
gl/strerror-override.c
gl/strerror-override.h
gl/sys_select.in.h [new file with mode: 0644]
gl/tests/Makefile.am
gl/tests/connect.c [new file with mode: 0644]
gl/tests/ftruncate.c [new file with mode: 0644]
gl/tests/glthread/lock.c [new file with mode: 0644]
gl/tests/glthread/lock.h [new file with mode: 0644]
gl/tests/glthread/thread.c [new file with mode: 0644]
gl/tests/glthread/thread.h [new file with mode: 0644]
gl/tests/glthread/threadlib.c [new file with mode: 0644]
gl/tests/glthread/yield.h [new file with mode: 0644]
gl/tests/ioctl.c [new file with mode: 0644]
gl/tests/perror.c [new file with mode: 0644]
gl/tests/pipe.c [new file with mode: 0644]
gl/tests/strerror_r.c [new file with mode: 0644]
gl/tests/sys_ioctl.in.h [new file with mode: 0644]
gl/tests/test-connect.c [new file with mode: 0644]
gl/tests/test-ftruncate.c [new file with mode: 0644]
gl/tests/test-ftruncate.sh [new file with mode: 0755]
gl/tests/test-ioctl.c [new file with mode: 0644]
gl/tests/test-lock.c [new file with mode: 0644]
gl/tests/test-perror.c [new file with mode: 0644]
gl/tests/test-perror.sh [new file with mode: 0755]
gl/tests/test-perror2.c [new file with mode: 0644]
gl/tests/test-pipe.c [new file with mode: 0644]
gl/tests/test-select-fd.c [new file with mode: 0644]
gl/tests/test-select-in.sh [new file with mode: 0755]
gl/tests/test-select-out.sh [new file with mode: 0755]
gl/tests/test-select-stdin.c [new file with mode: 0644]
gl/tests/test-select.c [new file with mode: 0644]
gl/tests/test-select.h [new file with mode: 0644]
gl/tests/test-signal-h.c [new file with mode: 0644]
gl/tests/test-strerror_r.c [new file with mode: 0644]
gl/tests/test-sys_ioctl.c [new file with mode: 0644]
gl/tests/test-sys_select.c [new file with mode: 0644]
gl/tests/test-thread_create.c [new file with mode: 0644]
gl/tests/test-thread_self.c [new file with mode: 0644]
gl/tests/w32sock.h [new file with mode: 0644]
gl/w32sock.h
maint.mk

index 894639e45f55d07ec45c8a8edba909eb15cb7013..9bf8f9ce74f3421e105b584b9eb004114f71a790 100644 (file)
@@ -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
similarity index 100%
rename from gl/tests/arpa_inet.in.h
rename to gl/arpa_inet.in.h
index 5a7533aab90624b4c43fcbc4d950c0be962c020b..b6014b43d54c81cd0b3535ace9c9da7cbe51fda4 100644 (file)
 /* 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
 
similarity index 100%
rename from gl/tests/inet_pton.c
rename to gl/inet_pton.c
diff --git a/gl/m4/ftruncate.m4 b/gl/m4/ftruncate.m4
new file mode 100644 (file)
index 0000000..4a47ba4
--- /dev/null
@@ -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])
+])
index 5d7c87ccad19721172827825d1cf88cfe9c4fe7c..b8318a3763640d02ca5c8360287f4129dfe420bd 100644 (file)
@@ -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
index 062e1a319f8ee8a8dc9ce1d899cac3666a372e26..359ff399a03718f2f18e81c93d62876f7fffa1c3 100644 (file)
@@ -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 (file)
index 0000000..a1db8fc
--- /dev/null
@@ -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 (file)
index 0000000..cb17ba3
--- /dev/null
@@ -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 (file)
index 0000000..9013174
--- /dev/null
@@ -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 (file)
index 0000000..a58f0ac
--- /dev/null
@@ -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 (file)
index 0000000..5cf54a0
--- /dev/null
@@ -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 (file)
index 0000000..1d4a653
--- /dev/null
@@ -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 (file)
index 0000000..8c7d112
--- /dev/null
@@ -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 (file)
index 0000000..b1914fb
--- /dev/null
@@ -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 (file)
index 0000000..49a4bc7
--- /dev/null
@@ -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 (file)
index 0000000..15d5ac2
--- /dev/null
@@ -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])
+])
index c92703f2ac6d2d12128fa61cacba5355a1f153c3..e0742ecbf8bdd6ee4eae5e563230728ba0291086 100644 (file)
 
 /* 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 (file)
index 0000000..236b951
--- /dev/null
@@ -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 (file)
index 0000000..e18e0b2
--- /dev/null
@@ -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
index d6ecf2ecae9c29fe9e8088cd5971edf6090e5c83..4e2c32b9c03ad9407a0d58d8c959f431de2fa665 100644 (file)
@@ -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 */
index 81e4a50759485d7e0455d9c3f49563cb96f0ff56..09540b957b3352b5d52613bf0795c34d29ddae3d 100644 (file)
@@ -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 (file)
index 0000000..4406a7a
--- /dev/null
@@ -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 */
index d66ab49a3d2b930128d1efd78747ca906e2402bf..f1e68b6b5871a84f8577555b4ac1314fafa6272b 100644 (file)
@@ -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 (file)
index 0000000..afd13b9
--- /dev/null
@@ -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 (file)
index 0000000..ae1e858
--- /dev/null
@@ -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 (file)
index 0000000..64dbd3f
--- /dev/null
@@ -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 (file)
index 0000000..028d881
--- /dev/null
@@ -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 (file)
index 0000000..83b8c57
--- /dev/null
@@ -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 (file)
index 0000000..064d72f
--- /dev/null
@@ -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 (file)
index 0000000..646defa
--- /dev/null
@@ -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 (file)
index 0000000..4fa2d8b
--- /dev/null
@@ -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 (file)
index 0000000..c6ba989
--- /dev/null
@@ -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 (file)
index 0000000..af4b56c
--- /dev/null
@@ -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 (file)
index 0000000..425dd70
--- /dev/null
@@ -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 (file)
index 0000000..e6cf99b
--- /dev/null
@@ -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 (file)
index 0000000..dc8aeda
--- /dev/null
@@ -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 (file)
index 0000000..84f00b5
--- /dev/null
@@ -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 (file)
index 0000000..c5da4eb
--- /dev/null
@@ -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 (executable)
index 0000000..d7394d2
--- /dev/null
@@ -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 (file)
index 0000000..130ee42
--- /dev/null
@@ -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 (file)
index 0000000..3f8846b
--- /dev/null
@@ -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 (file)
index 0000000..d3751d8
--- /dev/null
@@ -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 (executable)
index 0000000..7274d32
--- /dev/null
@@ -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 (file)
index 0000000..e230f92
--- /dev/null
@@ -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 (file)
index 0000000..90f41f9
--- /dev/null
@@ -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 (file)
index 0000000..de2f3e9
--- /dev/null
@@ -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 (executable)
index 0000000..2a8b742
--- /dev/null
@@ -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 (executable)
index 0000000..c5fd861
--- /dev/null
@@ -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 (file)
index 0000000..5a6f81a
--- /dev/null
@@ -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 (file)
index 0000000..9c6fb9d
--- /dev/null
@@ -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 (file)
index 0000000..4612dfc
--- /dev/null
@@ -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 (file)
index 0000000..7103e1f
--- /dev/null
@@ -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 (file)
index 0000000..956c458
--- /dev/null
@@ -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 (file)
index 0000000..dd01b4a
--- /dev/null
@@ -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 (file)
index 0000000..76596db
--- /dev/null
@@ -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 (file)
index 0000000..1348c8c
--- /dev/null
@@ -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 (file)
index 0000000..816ee09
--- /dev/null
@@ -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 (file)
index 0000000..0b8334e
--- /dev/null
@@ -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;
+    }
+}
index 55280d6497a6b3224e3de2fae47ad5075b75a201..0b8334e4ec5f1f3b082028a858943a442c1edf09 100644 (file)
@@ -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;
index d51fec6638361880f8843af493a6be29619ed3e1..4c711873354714a4ed23ef4ad00331ed6a03328a 100644 (file)
--- a/maint.mk
+++ b/maint.mk
@@ -618,7 +618,7 @@ _stddef_syms_re = NULL|offsetof|ptrdiff_t|size_t|wchar_t
 # Prohibit the inclusion of stddef.h without an actual use.
 sc_prohibit_stddef_without_use:
        @h='stddef.h'                                                   \
-       re='\<($(_stddef_syms_re)) *\('                                 \
+       re='\<($(_stddef_syms_re))\>'                                   \
          $(_sc_header_without_use)
 
 # Prohibit the inclusion of verify.h without an actual use.
@@ -749,10 +749,12 @@ gl_other_headers_ ?= \
 
 # Perl -lne code to extract "significant" cpp-defined symbols from a
 # gnulib header file, eliminating a few common false-positives.
+# The exempted names below are defined only conditionally in gnulib,
+# and hence sometimes must/may be defined in application code.
 gl_extract_significant_defines_ = \
   /^\# *define ([^_ (][^ (]*)(\s*\(|\s+\w+)/\
     && $$2 !~ /(?:rpl_|_used_without_)/\
-    && $$1 !~ /^(?:NSIG)$$/\
+    && $$1 !~ /^(?:NSIG|ENODATA)$$/\
     && $$1 !~ /^(?:SA_RESETHAND|SA_RESTART)$$/\
     and print $$1