summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ChangeLog505
-rw-r--r--DEPENDENCIES32
-rw-r--r--NEWS5
-rwxr-xr-xbuild-aux/config.guess11
-rwxr-xr-xbuild-aux/config.libpath2
-rwxr-xr-xbuild-aux/config.rpath4
-rwxr-xr-xbuild-aux/config.sub11
-rwxr-xr-xbuild-aux/gitlog-to-changelog5
-rwxr-xr-xbuild-aux/install-reloc20
-rwxr-xr-xbuild-aux/reloc-ldflags2
-rw-r--r--build-aux/texinfo.tex30
-rw-r--r--config/srclist.txt2
-rw-r--r--doc/INSTALL6
-rw-r--r--doc/INSTALL.ISO6
-rw-r--r--doc/INSTALL.UTF-86
-rw-r--r--doc/glibc-functions/sethostname.texi2
-rw-r--r--doc/install.texi4
-rw-r--r--doc/posix-functions/expl.texi2
-rw-r--r--doc/posix-functions/expm1l.texi2
-rw-r--r--doc/posix-functions/fmaf.texi4
-rw-r--r--doc/posix-functions/getaddrinfo.texi3
-rw-r--r--doc/posix-functions/getcwd.texi2
-rw-r--r--doc/posix-functions/getlogin_r.texi2
-rw-r--r--doc/posix-functions/initstate.texi7
-rw-r--r--doc/posix-functions/log10l.texi2
-rw-r--r--doc/posix-functions/log1pl.texi4
-rw-r--r--doc/posix-functions/log2l.texi7
-rw-r--r--doc/posix-functions/logl.texi2
-rw-r--r--doc/posix-functions/open_memstream.texi3
-rw-r--r--doc/posix-functions/posix_spawn_file_actions_addclose.texi4
-rw-r--r--doc/posix-functions/pthread_sigmask.texi2
-rw-r--r--doc/posix-functions/remainderl.texi4
-rw-r--r--doc/posix-functions/srandom.texi4
-rw-r--r--doc/posix-functions/wcwidth.texi2
-rw-r--r--doc/posix-headers/stddef.texi4
-rw-r--r--doc/relocatable.texi7
-rw-r--r--lib/argp-namefrob.h41
-rw-r--r--lib/asyncsafe-spin.c11
-rw-r--r--lib/canonicalize-lgpl.c7
-rw-r--r--lib/dynarray.h2
-rw-r--r--lib/free.c16
-rw-r--r--lib/glob.c2
-rw-r--r--lib/glob.in.h4
-rw-r--r--lib/malloc.c16
-rw-r--r--lib/malloc/dynarray_at_failure.c4
-rw-r--r--lib/malloc/dynarray_emplace_enlarge.c4
-rw-r--r--lib/malloc/dynarray_finalize.c4
-rw-r--r--lib/malloc/dynarray_resize.c4
-rw-r--r--lib/malloc/dynarray_resize_clear.c4
-rw-r--r--lib/mbtowc-lock.h10
-rw-r--r--lib/mempcpy.c5
-rw-r--r--lib/parse-datetime.y122
-rw-r--r--lib/passfd.c14
-rw-r--r--lib/rawmemchr.c5
-rw-r--r--lib/realloc.c20
-rw-r--r--lib/regcomp.c8
-rw-r--r--lib/regex_internal.c1
-rw-r--r--lib/regex_internal.h5
-rw-r--r--lib/regexec.c89
-rw-r--r--lib/relocwrapper.c20
-rw-r--r--lib/scratch_buffer.h91
-rw-r--r--lib/simple-atomic.c360
-rw-r--r--lib/simple-atomic.h49
-rw-r--r--lib/stddef.in.h13
-rw-r--r--lib/string-buffer.c297
-rw-r--r--lib/string-buffer.h85
-rw-r--r--lib/unlocked-io.h26
-rw-r--r--m4/c-stack.m44
-rw-r--r--m4/expl.m48
-rw-r--r--m4/expm1l.m412
-rw-r--r--m4/free.m47
-rw-r--r--m4/getcwd-abort-bug.m419
-rw-r--r--m4/host-cpu-c-abi.m46
-rw-r--r--m4/host-os.m43
-rw-r--r--m4/lib-ld.m44
-rw-r--r--m4/log10l.m48
-rw-r--r--m4/log1pl.m4102
-rw-r--r--m4/log2l.m494
-rw-r--r--m4/logl.m48
-rw-r--r--m4/malloc.m44
-rw-r--r--m4/mbrtoc32.m44
-rw-r--r--m4/mprotect.m44
-rw-r--r--m4/posix_spawn.m411
-rw-r--r--m4/printf.m410
-rw-r--r--m4/pthread_sigmask.m410
-rw-r--r--m4/realloc.m44
-rw-r--r--m4/relocatable.m47
-rw-r--r--m4/remainderl.m488
-rw-r--r--m4/setlocale_null.m46
-rw-r--r--m4/strfmon_l.m44
-rw-r--r--m4/threadlib.m46
-rw-r--r--m4/utime.m44
-rw-r--r--m4/visibility.m43
-rw-r--r--m4/wcwidth.m48
-rw-r--r--modules/canonicalize3
-rw-r--r--modules/canonicalize-lgpl3
-rw-r--r--modules/linked-list-tests12
-rw-r--r--modules/malloc-posix1
-rw-r--r--modules/parse-datetime2
-rw-r--r--modules/parse-datetime221
-rw-r--r--modules/posix_spawn_file_actions_addchdir-tests1
-rw-r--r--modules/posix_spawn_file_actions_addclose-tests1
-rw-r--r--modules/posix_spawn_file_actions_adddup2-tests1
-rw-r--r--modules/posix_spawn_file_actions_addfchdir-tests1
-rw-r--r--modules/posix_spawn_file_actions_addopen-tests1
-rw-r--r--modules/realloc-posix1
-rw-r--r--modules/relocatable-prog-wrapper31
-rw-r--r--modules/scratch_buffer3
-rw-r--r--modules/simple-atomic25
-rw-r--r--modules/simple-atomic-tests14
-rw-r--r--modules/string-buffer26
-rw-r--r--modules/string-buffer-tests11
-rw-r--r--tests/test-asyncsafe-linked_list.c322
-rwxr-xr-xtests/test-asyncsafe-linked_list.sh16
-rw-r--r--tests/test-c32isalnum.c4
-rw-r--r--tests/test-c32isalpha.c4
-rw-r--r--tests/test-c32isblank.c2
-rw-r--r--tests/test-c32islower.c8
-rw-r--r--tests/test-c32isupper.c4
-rw-r--r--tests/test-immutable.c2
-rw-r--r--tests/test-posix_spawn_file_actions_addclose.c2
-rw-r--r--tests/test-posixtm.c2
-rw-r--r--tests/test-regex.c145
-rw-r--r--tests/test-simple-atomic.c234
-rw-r--r--tests/test-string-buffer.c115
-rw-r--r--top/maint.mk6
126 files changed, 3185 insertions, 346 deletions
diff --git a/ChangeLog b/ChangeLog
index 43d1a16..9f6818c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,508 @@
+2021-03-03 Bruno Haible <bruno@clisp.org>
+
+ asyncsafe-spin, simple-atomic: Add support for tcc/x86.
+ * lib/asyncsafe-spin.c (memory_barrier): With tcc/x86, don't use the
+ 'mfence' instruction.
+ * lib/simple-atomic.c (memory_barrier): Likewise.
+
+ asyncsafe-spin, simple-atomic: Add support for tcc.
+ * lib/asyncsafe-spin.c (memory_barrier, atomic_compare_and_swap): On
+ i386 and x86_64, treat tcc like older GCC or clang.
+ * lib/simple-atomic.c (memory_barrier, atomic_compare_and_swap,
+ atomic_compare_and_swap_ptr): Likewise.
+
+2021-03-02 Bruno Haible <bruno@clisp.org>
+
+ stddef: Work around an interoperability problem of tcc with glibc.
+ Reported by Luca Saiu <positron@gnu.org> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2021-03/msg00011.html>.
+ * lib/stddef.in.h [__TINYC__]: In case of the special invocation
+ convention, undefine the macros that TinyCC's <stddef.h> should undefine
+ but doesn't.
+ * doc/posix-headers/stddef.texi: Mention the TinyCC bug.
+
+2021-03-02 Paul Eggert <eggert@cs.ucla.edu>
+
+ mbrtowc: port to AIX 7.1 with xlc 12.1
+ Fix a problem with locks when building GNU Tar (Savannah commit
+ 55f2a0772e08b9febac3ac0de5cb048d4c60d2f5) on AIX 7.1 with IBM XL
+ C/C++ V12.1 using ‘./configure CC=xlc’. The link fails due to
+ missing definitions of pthread_mutex_lock and
+ pthread_mutex_unlock. GNU Tar uses unlocked-io and so
+ should not need to worry about multithreading or locks.
+ * lib/mbtowc-lock.h (mbtowc_with_lock) [USE_UNLOCKED_IO]:
+ Don’t bother with locks, since this app is single-threaded.
+ There may be similar linking problems with lib/nl_langinfo.c and
+ lib/setlocale_null.c but my GNU Tar build didn’t run into them, so
+ I left them alone for now.
+
+2021-03-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ unlocked-io: do not redefine getc_unlocked etc.
+ I ran into this problem on AIX 7.1 with GNU Tar, which
+ enables visibility of getc_unlocked etc. after testing
+ whether they’re declared, causing argp-namefrob.h and
+ unlocked-io.h to redefine the macros.
+ * lib/argp-namefrob.h, lib/unlocked-io.h:
+ (clearerr_unlocked, feof_unlocked ferror_unlocked)
+ (fflush_unlocked, fgets_unlocked, fputc_unlocked, fputs_unlocked)
+ (fread_unlocked, fwrite_unlocked, getc_unlocked, getchar_unlocked)
+ (putc_unlocked, putchar_unlocked): Do not define if already defined.
+
+ parse-datetime2: new module
+ This splits the old parse-datetime into two parts; the
+ first is parse-datetime2 which supports all the new bells
+ and whistles, the second is parse-datetime, which reverts to
+ its original intent. This avoids some bogus diagnostics
+ when build GNU Tar with gcc -flto -fanalyze and
+ with --enable-gcc-warnings. And it slims down the
+ executable a bit.
+ * NEWS: Mention this.
+ * lib/parse-datetime.y (parser_control) [!GNULIB_PARSE_DATETIME2]:
+ Omit parse_datetime_debug member.
+ (debugging): New function. Use it everywhere the old code
+ would load parse_datetime_debug.
+ (parse_datetime_body): New static function, with the body
+ of the old parse_datetime2. Set pc.parse_datetime_debug
+ only if GNULIB_PARSE_DATETIME2.
+ (parse_datetime2, parse_datetime): Use this new function.
+ (parse_datetime2) [!GNULIB_PARSE_DATETIME2]: Remove.
+ * modules/parse-datetime2: New file.
+
+2021-02-27 Bruno Haible <bruno@clisp.org>
+
+ string-buffer: Fixes.
+ * modules/string-buffer (License): Change to LGPL.
+ * tests/test-string-buffer.c (main): Add another sb_appendf call, that
+ is more likely to fail.
+
+2021-02-25 Bernhard Voelker <mail@bernhard-voelker.de>
+
+ gitlog-to-changelog: output SHA in "empty commit message" warning
+ * build-aux/gitlog-to-changelog: Add $sha to above warning diagnostic.
+
+2021-02-24 Paul Eggert <eggert@cs.ucla.edu>
+
+ glob: include libc-config.h in a more-standard way
+ Inspired by Tom Tromey’s report for RHEL 6 in:
+ https://lists.gnu.org/r/bug-gnulib/2021-02/msg00088.html
+ * lib/glob.c [!_LIBC]: Include libc-config.h, not just config.h
+ * lib/glob.in.h: Include libc-config.h only if needed.
+
+2021-02-21 Bruno Haible <bruno@clisp.org>
+
+ string-buffer: Add tests.
+ * tests/test-string-buffer.c: New file.
+ * modules/string-buffer-tests: New file.
+
+ string-buffer: New module.
+ * lib/string-buffer.h: New file.
+ * lib/string-buffer.c: New file.
+ * modules/string-buffer: New file.
+ * doc/posix-functions/open_memstream.texi: Mention the new module.
+
+2021-02-21 Bruno Haible <bruno@clisp.org>
+
+ scratch_buffer: Document the exported API.
+ * lib/scratch_buffer.h: Add comments, taken from
+ lib/malloc/scratch_buffer.h.
+
+2021-02-21 Bruno Haible <bruno@clisp.org>
+
+ DEPENDENCIES: Update.
+ * DEPENDENCIES: Require GCC >= 3.1. Tell where to find working GNU m4
+ tarballs. Mention awk. Point to pre-built packages for gettext, bison,
+ gperf, texinfo.
+
+2021-02-20 Bruno Haible <bruno@clisp.org>
+
+ parse-datetime: Fix comment.
+ * modules/parse-datetime (Makefile.am): Fix comment.
+
+2021-02-16 Bruno Haible <bruno@clisp.org>
+
+ passfd: Fix test failure on FreeBSD >= 12 and NetBSD in 64-bit mode.
+ * lib/passfd.c (recvfd): Use the CMSG_SPACE macro to compute the value
+ for msg_controllen.
+
+2021-02-16 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port better to macOS Mojave
+ Problem reported by Tom Shields in:
+ https://lists.gnu.org/r/bug-gnulib/2021-02/msg00064.html
+ * config/srclist.txt: Comment out dynarray_finalize.c.
+ * lib/dynarray.h (__libc_dynarray_at_failure): Don’t include
+ libc-config.h here, as that’s the includer’s responsibility.
+ * lib/malloc/dynarray_at_failure.c:
+ * lib/malloc/dynarray_emplace_enlarge.c:
+ * lib/malloc/dynarray_finalize.c:
+ * lib/malloc/dynarray_resize.c:
+ * lib/malloc/dynarray_resize_clear.c:
+ If _LIBC is not defined, include libc-config.h.
+
+2021-02-15 Bruno Haible <bruno@clisp.org>
+
+ linked-list test: Add test for SIGNAL_SAFE_LIST. (It currently fails.)
+ * tests/test-asyncsafe-linked_list.sh: New file.
+ * tests/test-asyncsafe-linked_list.c: New file.
+ * modules/linked-list-tests (Files): Add them.
+ (Depends-on): Add thread, yield, nanosleep, sigaction, sigprocmask.
+ (Makefile.am): Arrange to compile test-asyncsafe-linked_list.c and run
+ test-asyncsafe-linked_list.sh.
+
+2021-02-14 Bruno Haible <bruno@clisp.org>
+
+ simple-atomic: Add tests.
+ * tests/test-simple-atomic.c: New file.
+ * modules/simple-atomic-tests: New file.
+
+ simple-atomic: New module.
+ * lib/simple-atomic.h: New file.
+ * lib/simple-atomic.c: New file, based on lib/asyncsafe-spin.c.
+ * modules/simple-atomic: New file.
+
+2021-02-14 Bruno Haible <bruno@clisp.org>
+
+ Fix distinction of 32-bit/64-bit mode with xlc 13.1.3 on AIX.
+ * m4/host-cpu-c-abi.m4 (gl_HOST_CPU_C_ABI, gl_HOST_CPU_C_ABI_32BIT):
+ Test __LP64__ instead of _ARCH_PPC64.
+ * m4/lib-ld.m4 (AC_LIB_PROG_LD): Likewise.
+ * lib/stddef.in.h: Likewise.
+
+2021-02-13 Ozkan Sezer <sezeroz@gmail.com>
+
+ lib-symbol-visibility: Make it work with -Wmissing-prototypes.
+ * m4/visibility.m4 (gl_VISIBILITY): Avoid error from simultaneous use of
+ -Wmissing-prototypes and -Werror.
+
+2021-02-08 Bruno Haible <bruno@clisp.org>
+
+ stddef: Fix test-stddef compilation error on MidnightBSD/x86.
+ * lib/stddef.in.h (_GL_STDDEF_ALIGNAS, rpl_max_align_t, max_align_t):
+ Don't ignore HAVE_MAX_ALIGN_T if the compiler is clang.
+
+2021-02-08 Bruno Haible <bruno@clisp.org>
+
+ Document non-standard prototypes on MidnightBSD.
+ * doc/posix-functions/initstate.texi: Mention different prototype on
+ MidnightBSD 2.0.
+ * doc/posix-functions/srandom.texi: Likewise.
+ * doc/posix-functions/getlogin_r.texi: Likewise.
+ * doc/glibc-functions/sethostname.texi: Likewise.
+
+2021-02-08 Bruno Haible <bruno@clisp.org>
+
+ posixtm tests: Fix warnings seen on MidnightBSD/x86.
+ * tests/test-posixtm.c (main): Convert two 'time_t' values to 'long' for
+ printing.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ Add cross-compilation guesses for MidnightBSD.
+ * m4/malloc.m4 (_AC_FUNC_MALLOC_IF): When cross-compiling, use the
+ result from native compilation.
+ * m4/realloc.m4 (_AC_FUNC_REALLOC_IF): Likewise.
+ * m4/mbrtoc32.m4 (gl_MBRTOC32_SANITYCHECK): Likewise.
+ * m4/mprotect.m4 (gl_FUNC_MPROTECT_WORKS): Likewise.
+ * m4/posix_spawn.m4 (gl_POSIX_SPAWN_SECURE): Likewise.
+ * m4/printf.m4 (gl_PRINTF_SIZES_C99, gl_PRINTF_INFINITE,
+ gl_PRINTF_INFINITE_LONG_DOUBLE, gl_PRINTF_DIRECTIVE_F,
+ gl_SNPRINTF_TRUNCATION_C99, gl_SNPRINTF_RETVAL_C99,
+ gl_SNPRINTF_DIRECTIVE_N, gl_VSNPRINTF_ZEROSIZE_C99): Likewise.
+ * m4/strfmon_l.m4 (gl_FUNC_STRFMON_L): Likewise.
+ * m4/setlocale_null.m4 (gl_FUNC_SETLOCALE_NULL): Use predetermined
+ result on MidnightBSD.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ threadlib: Add support for MidnightBSD.
+ * m4/threadlib.m4 (gl_WEAK_SYMBOLS, gl_THREADLIB_BODY): On MidnightBSD,
+ use the same test as on FreeBSD.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ host-os: Add support for MidnightBSD.
+ * m4/host-os.m4 (gl_HOST_OS): On MidnightBSD, set HOST_OPERATING_SYSTEM
+ to "MidnightBSD", not "Midnightbsd".
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ c-stack: Adjust for MidnightBSD.
+ * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): On MidnightBSD,
+ set FAULT_YIELDS_SIGBUS.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ relocatable-prog: Add support for MidnightBSD.
+ * m4/relocatable.m4 (gl_RELOCATABLE_BODY): Use the ELF $ORIGIN trick
+ also on MidnightBSD >= 1.1.
+ * build-aux/config.libpath: Treat MidnightBSD like FreeBSD.
+ * build-aux/reloc-ldflags: Likewise.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ havelib: Add support for MidnightBSD.
+ * build-aux/config.rpath: Treat MidnightBSD like FreeBSD >= 4.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ wcwidth: Document MidnightBSD bug.
+ * doc/posix-functions/wcwidth.texi: Mention MidnightBSD as an affected
+ platform.
+ * m4/wcwidth.m4 (gl_FUNC_WCWIDTH): Update comments.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ pthread_sigmask: Document MidnightBSD bug.
+ * doc/posix-functions/pthread_sigmask.texi: Mention MidnightBSD as an
+ affected platform.
+ * m4/pthread_sigmask.m4 (gl_FUNC_PTHREAD_SIGMASK): Update
+ cross-compilation guess accordingly.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ immutable: Avoid test failures on MidnightBSD.
+ * tests/test-immutable.c (install_segv_handler): On FreeBSD, install the
+ handler also for SIGBUS.
+
+2021-02-07 Bruno Haible <bruno@clisp.org>
+
+ c32is*: Avoid test failures on MidnightBSD.
+ * tests/test-c32isalnum.c (main): On FreeBSD, disable tests that fail on
+ MidnightBSD 1.1.
+ * tests/test-c32isalpha.c (main): Likewise.
+ * tests/test-c32isblank.c (main): Likewise.
+ * tests/test-c32islower.c (main): Likewise.
+ * tests/test-c32isupper.c (main): Likewise.
+
+2021-02-05 Paul Eggert <eggert@cs.ucla.edu>
+
+ regex: fix comment location
+ * lib/regexec.c (update_regs): Move comment.
+
+ regex-tests: add bug 11053 test
+ * tests/test-regex.c (main): New test case for glibc bug 11053.
+
+ regex: debug check for set member duplicates
+ * lib/regex_internal.c (re_node_set_insert): Add a DEBUG_ASSERT
+ that would have caught some recently-fixed performance bugs
+ that caused sets to contain duplicate members.
+
+ regex: fix longstanding backref match bug
+ This fixes a longstanding glibc bug concerning backreferences
+ <https://sourceware.org/11053> (2009-12-04).
+ * lib/regexec.c (proceed_next_node, push_fail_stack)
+ (pop_fail_stack): Push and pop the previous registers
+ as well as the current ones. All callers changed.
+ (set_regs): Also pop if CUR_NODE has already been checked,
+ so that it does not get added as a duplicate set entry.
+ (update_regs): Fix comment location.
+ * tests/test-regex.c (tests): New constant.
+ (bug_regex11): New test function.
+ (main): Bump alarm value. Call new test function.
+
+ regex: avoid duplicate in espilon closure
+ * lib/regcomp.c (calc_eclosure_iter): Insert NODE into epsilon
+ closure first rather than last. Otherwise, the epsilon closure
+ might contain a duplicate of NODE.
+
+ regex-tests: fix typo
+ * tests/test-regex.c (main): Fix typo that would have caused an
+ old test case to report incorrect values on failure.
+
+ regex: make it easier to merge into glibc
+ * lib/regex_internal.h [_LIBC]: Do not include Gnulib’s dynarray.h.
+
+ regex: minor refactoring
+ * lib/regexec.c (proceed_next_node): Use more-local decls.
+
+ regex: avoid undefined behavior
+ * lib/regexec.c (pop_fail_stack): If the stack is empty, return -1
+ instead of indulging in undefined behavior. This simplifies
+ callers, and avoids undefined behavior in some cases (see glibc
+ bug 11053, though this change does not fix that overall bug).
+
+ regex: improve comments
+ * lib/regexec.c: Add and correct comments about return values.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ relocatable-prog-wrapper: Tweak today's patch.
+ * build-aux/install-reloc (func_create_wrapper): Clean up free.o.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ fmaf: Document QEMU bug.
+ * doc/posix-functions/fmaf.texi: Add note about QEMU bug.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ remainderl: Work around musl libc bug.
+ * doc/posix-functions/remainderl.texi: Document musl libc bug.
+ * m4/remainderl.m4 (gl_FUNC_REMAINDERL_WORKS): Add more tests. Update
+ cross compilation guess.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ log2l: Work around musl libc bugs.
+ * doc/posix-functions/log2l.texi: Document musl libc bugs.
+ * m4/log2l.m4 (gl_FUNC_LOG2L_WORKS): Add more tests. Update cross
+ compilation guess.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ log1pl: Work around musl libc bug.
+ * doc/posix-functions/log1pl.texi: Document musl libc bug.
+ * m4/log1pl.m4 (gl_FUNC_LOG1PL_WORKS): New macro.
+ (gl_FUNC_LOG1PL): Invoke it.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ log10l: Document musl libc bug.
+ * doc/posix-functions/log10l.texi: Document musl libc bug.
+ * m4/log10l.m4 (gl_FUNC_LOG10L_WORKS): Update comment and cross
+ compilation guess.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ logl: Document musl libc bug.
+ * doc/posix-functions/logl.texi: Document musl libc bug.
+ * m4/logl.m4 (gl_FUNC_LOGL_WORKS): Update comment and cross
+ compilation guess.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ expm1l: Document musl libc bug.
+ * doc/posix-functions/expm1l.texi: Document musl libc bug.
+ * m4/expm1l.m4 (gl_FUNC_EXPM1L): Update comment and cross
+ compilation guess.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ expl: Document musl libc bug.
+ * doc/posix-functions/expl.texi: Document musl libc bug.
+ * m4/expl.m4 (gl_FUNC_EXPL): Update comment and cross
+ compilation guess.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ relocatable-prog-wrapper: Update after recent changes.
+ * lib/relocwrapper.c: Update comments.
+ * modules/relocatable-prog-wrapper (Files): Add lib/scratch_buffer.h,
+ lib/malloc/scratch_buffer*, lib/malloc.c, lib/realloc.c, lib/free.c,
+ lib/mempcpy.c, lib/rawmemchr.c, m4/lstat.m4. Remove lib/lstat.c.
+ (Depends-on): Add c99, eloop-threshold, fcntl-h, idx, intprops,
+ libc-config, stddef, sys_stat. Remove alloca-opt.
+ (configure.ac): Invoke gl_FUNC_MALLOC_POSIX, gl_FUNC_REALLOC_POSIX,
+ gl_FUNC_FREE, gl_FUNC_MEMPCPY, gl_FUNC_RAWMEMCHR.
+ * lib/canonicalize-lgpl.c (memmove): Undefine in the relocwrapper.
+ * build-aux/install-reloc (func_create_wrapper): Compile also
+ malloc/scratch_buffer_*.c, malloc.c, realloc.c, free.c, mempcpy.c,
+ rawmemchr.c. Don't compile lstat.c.
+
+ Make it possible to compile rawmemchr.c separately, unconditionally.
+ * lib/rawmemchr.c: Don't define rawmemchr if not needed.
+
+ Make it possible to compile mempcpy.c separately, unconditionally.
+ * lib/mempcpy.c: Don't define mempcpy if not needed.
+
+ Make it possible to compile free.c separately, unconditionally.
+ * m4/free.m4 (gl_FUNC_FREE): Define HAVE_FREE_POSIX.
+ * lib/free.c: Don't define rpl_free if not needed.
+
+ Make it possible to compile realloc.c separately, unconditionally.
+ * modules/realloc-posix (configure.ac): Invoke gl_MODULE_INDICATOR.
+ * lib/realloc.c: Don't define rpl_realloc if not needed.
+
+ Make it possible to compile malloc.c separately, unconditionally.
+ * modules/malloc-posix (configure.ac): Invoke gl_MODULE_INDICATOR.
+ * lib/malloc.c: Don't define rpl_malloc if not needed.
+
+2021-01-31 Bruno Haible <bruno@clisp.org>
+
+ canonicalize-lgpl: Simplify.
+ * lib/canonicalize-lgpl.c (_GL_USE_STDLIB_ALLOC): Remove macro.
+
+2021-01-30 Bruno Haible <bruno@clisp.org>
+
+ canonicalize, canonicalize-lgpl: Straighten dependencies.
+ * modules/canonicalize-lgpl (Depends-on): Remove free-posix,
+ malloc-posix. Add unistd.
+ * modules/canonicalize (Depends-on): Remove free-posix, xalloc.
+ Add unistd.
+
+2021-01-30 Bruno Haible <bruno@clisp.org>
+
+ scratch_buffer: Fix dependencies.
+ * modules/scratch_buffer (Depends-on): Add malloc-posix, realloc-posix,
+ free-posix.
+
+2021-01-26 Bruno Haible <bruno@clisp.org>
+
+ doc: More precise wording.
+ Reported by Reuben Thomas <rrt@sc3d.org> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2021-01/msg00300.html>.
+ * doc/relocatable.texi (Enabling Relocatability): Talk about package
+ management systems in general.
+
+ doc: Remove obsolete text.
+ Suggested by Reuben Thomas <rrt@sc3d.org> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2021-01/msg00299.html>.
+ * doc/relocatable.texi (Enabling Relocatability): Stop mentioning an
+ issue of libtool 1.5.x.
+
+2021-01-26 Simon Josefsson <simon@josefsson.org>
+
+ maintainer-makefile: Mimic bootstrap's gnulib-srcdir guessing.
+ * top/maint.mk (gnulib_dir): If $(srcdir)/gnulib doesn't exist,
+ fall back to $GNULIB_SRCDIR.
+
+2021-01-25 Bruno Haible <bruno@clisp.org>
+
+ posix_spawn_file_actions_* tests: Fix module dependencies.
+ * modules/posix_spawn_file_actions_addclose-tests (Depends-on): Add
+ posix_spawn_file_actions_destroy.
+ * modules/posix_spawn_file_actions_addopen-tests (Depends-on): Likewise.
+ * modules/posix_spawn_file_actions_adddup2-tests (Depends-on): Likewise.
+ * modules/posix_spawn_file_actions_addchdir-tests (Depends-on):
+ Likewise.
+ * modules/posix_spawn_file_actions_addfchdir-tests (Depends-on):
+ Likewise.
+
+2021-01-25 Bruno Haible <bruno@clisp.org>
+
+ posix_spawn_file_actions_addclose: Relax configure test.
+ * m4/posix_spawn.m4 (gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE): Test a
+ negative file descriptor, not an out-of-range file descriptor.
+ * tests/test-posix_spawn_file_actions_addclose.c (main): Add comment.
+ * doc/posix-functions/posix_spawn_file_actions_addclose.texi: Update.
+
+2021-01-25 Simon Josefsson <simon@josefsson.org>
+
+ getaddrinfo: Doc fix.
+ * doc/posix-functions/getaddrinfo.texi (getaddrinfo): Gnulib does
+ not support IDN.
+
+2021-01-24 Bruno Haible <bruno@clisp.org>
+
+ getcwd: Fix cross-compilation guess for musl libc.
+ * m4/getcwd-abort-bug.m4 (gl_FUNC_GETCWD_ABORT_BUG): Guess no also on
+ musl libc.
+ * doc/posix-functions/getcwd.texi: Update platform info.
+
+2021-01-24 Bruno Haible <bruno@clisp.org>
+
+ expm1l: Fix configure test result with GCC 10 on powerpc64le.
+ * m4/expm1l.m4 (gl_FUNC_EXPM1L): Change test to avoid GCC optimization.
+
+2021-01-23 Bruno Haible <bruno@clisp.org>
+
+ utime: Fix configure test (regression 2020-12-04).
+ Reported by Ryan Schmidt <wget@ryandesign.com> via Tim Rühsen in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2021-01/msg00282.html>.
+ * m4/utime.m4 (gl_FUNC_UTIME): In the test program, include <utime.h>,
+ not <time.h>.
+
2021-01-23 Paul Eggert <eggert@cs.ucla.edu>
libc-config: port to Xcode 7
diff --git a/DEPENDENCIES b/DEPENDENCIES
index e7b9593..fe70558 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -9,7 +9,7 @@ at any time.
* A C runtime, compiler, linker, etc.
+ Mandatory. Using the platform's native 'cc' gives good portability
- exposure, but you can also use GCC 2.95 or newer.
+ exposure, but you can also use GCC 3.1 or newer.
+ GCC Homepage:
https://gcc.gnu.org/
+ Download:
@@ -25,7 +25,10 @@ at any time.
https://ftp.gnu.org/gnu/make/
* GNU M4 1.4.5 or newer.
- + 1.4.5 or newer is mandatory, but 1.4.9 or newer is recommended.
+ + Mandatory.
+ 1.4.5 or newer is mandatory, but 1.4.9 or newer is recommended.
+ If you want to build it from source, use the tarball from
+ https://gitlab.com/gnu-m4/ci-distcheck/-/jobs/artifacts/master/raw/m4-snapshot.tar?job=check-optimized
+ Homepage:
https://www.gnu.org/software/m4/
+ Download:
@@ -90,6 +93,15 @@ at any time.
+ Download:
https://ftp.gnu.org/gnu/grep/
+* Awk.
+ + Mandatory.
+ Using the platform's native awk, mawk, or nawk gives good portability
+ exposure, but you can also use GNU awk.
+ + Homepage:
+ https://www.gnu.org/software/gawk/
+ + Download:
+ https://ftp.gnu.org/gnu/gawk/
+
* GNU gettext.
+ If your project wants to follow GNU Coding Standards:
+ Always use the newest available gettext release, see
@@ -104,6 +116,10 @@ at any time.
https://www.gnu.org/software/gettext/
+ Download:
https://ftp.gnu.org/gnu/gettext/
+ + Pre-built package name:
+ - On Debian and Debian-based systems: gettext,
+ - On Red Hat distributions: gettext.
+ - Other: https://repology.org/project/gettext/versions
* Bison 2.0 or newer.
+ Recommended.
@@ -112,6 +128,10 @@ at any time.
https://www.gnu.org/software/bison/
+ Download:
https://ftp.gnu.org/gnu/bison/
+ + Pre-built package name:
+ - On Debian and Debian-based systems: bison,
+ - On Red Hat distributions: bison.
+ - Other: https://repology.org/project/bison/versions
* GNU gperf 3.0.1 or newer.
+ 3.0.1 or newer is mandatory, but 3.1 or newer is recommended.
@@ -120,6 +140,10 @@ at any time.
https://www.gnu.org/software/gperf/
+ Download:
https://ftp.gnu.org/gnu/gperf/
+ + Pre-built package name:
+ - On Debian and Debian-based systems: gperf,
+ - On Red Hat distributions: gperf.
+ - Other: https://repology.org/project/gperf/versions
* Texinfo 4.6 or newer.
+ Recommended.
@@ -128,6 +152,10 @@ at any time.
https://www.gnu.org/software/texinfo/
+ Download:
https://ftp.gnu.org/gnu/texinfo/
+ + Pre-built package name:
+ - On Debian and Debian-based systems: texinfo,
+ - On Red Hat distributions: texinfo.
+ - Other: https://repology.org/project/texinfo/versions
* GNU sed.
+ Recommended.
diff --git a/NEWS b/NEWS
index c347ecd..318055a 100644
--- a/NEWS
+++ b/NEWS
@@ -60,6 +60,11 @@ User visible incompatible changes
Date Modules Changes
+2021-02-28 parse-datetime The parse_datetime2 function has been moved
+ to the new parse-datetime2 module, so that
+ programs that need just parse_datetime need
+ not build the fancier function.
+
2020-12-23 execute These functions no longer execute scripts without
spawn-pipe '#!' marker through /bin/sh. To execute such a
posix_spawn script as a shell script, either add a '#!/bin/sh'
diff --git a/build-aux/config.guess b/build-aux/config.guess
index f772702..1972fda 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# Copyright 1992-2021 Free Software Foundation, Inc.
-timestamp='2021-01-01'
+timestamp='2021-01-25'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -188,10 +188,9 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
- "/sbin/$sysctl" 2>/dev/null || \
- "/usr/sbin/$sysctl" 2>/dev/null || \
+ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
echo unknown))
case "$UNAME_MACHINE_ARCH" in
aarch64eb) machine=aarch64_be-unknown ;;
@@ -1483,8 +1482,8 @@ EOF
i*86:rdos:*:*)
echo "$UNAME_MACHINE"-pc-rdos
exit ;;
- i*86:AROS:*:*)
- echo "$UNAME_MACHINE"-pc-aros
+ *:AROS:*:*)
+ echo "$UNAME_MACHINE"-unknown-aros
exit ;;
x86_64:VMkernel:*:*)
echo "$UNAME_MACHINE"-unknown-esx
diff --git a/build-aux/config.libpath b/build-aux/config.libpath
index 6d0e550..0823857 100755
--- a/build-aux/config.libpath
+++ b/build-aux/config.libpath
@@ -66,7 +66,7 @@ case $host_os in
dgux*)
shlibpath_var=LD_LIBRARY_PATH
;;
- freebsd* | dragonfly*)
+ freebsd* | dragonfly* | midnightbsd*)
shlibpath_var=LD_LIBRARY_PATH
;;
gnu*)
diff --git a/build-aux/config.rpath b/build-aux/config.rpath
index 69988c5..4b7dc49 100755
--- a/build-aux/config.rpath
+++ b/build-aux/config.rpath
@@ -371,7 +371,7 @@ else
hardcode_direct=yes
hardcode_minus_L=yes
;;
- freebsd* | dragonfly*)
+ freebsd* | dragonfly* | midnightbsd*)
hardcode_libdir_flag_spec='-R$libdir'
hardcode_direct=yes
;;
@@ -547,7 +547,7 @@ case "$host_os" in
freebsd[23].*)
library_names_spec='$libname$shrext$versuffix'
;;
- freebsd* | dragonfly*)
+ freebsd* | dragonfly* | midnightbsd*)
library_names_spec='$libname$shrext'
;;
gnu*)
diff --git a/build-aux/config.sub b/build-aux/config.sub
index b0f8492..63c1f1c 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2021 Free Software Foundation, Inc.
-timestamp='2021-01-07'
+timestamp='2021-01-08'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -1683,12 +1683,15 @@ fi
# Now, validate our (potentially fixed-up) OS.
case $os in
- # Sometimes we do "kernel-abi", so those need to count as OSes.
+ # Sometimes we do "kernel-libc", so those need to count as OSes.
musl* | newlib* | uclibc*)
;;
- # Likewise for "kernel-libc"
+ # Likewise for "kernel-abi"
eabi* | gnueabi*)
;;
+ # VxWorks passes extra cpu info in the 4th filed.
+ simlinux | simwindows | spe)
+ ;;
# Now accept the basic system types.
# The portable systems comes first.
# Each alternative MUST end in a * to match a version number.
@@ -1751,6 +1754,8 @@ case $kernel-$os in
;;
kfreebsd*-gnu* | kopensolaris*-gnu*)
;;
+ vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ ;;
nto-qnx*)
;;
os2-emx)
diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
index de76f65..9ff15f6 100755
--- a/build-aux/gitlog-to-changelog
+++ b/build-aux/gitlog-to-changelog
@@ -35,7 +35,7 @@
eval 'exec perl -wSx "$0" "$@"'
if 0;
-my $VERSION = '2020-04-04 15:07'; # UTC
+my $VERSION = '2021-02-24 23:42'; # UTC
# The definition above must lie within the first 8 lines in order
# for the Emacs time-stamp write hook (at end) to update it.
# If you change this file with Emacs, please let the write hook
@@ -455,7 +455,8 @@ sub git_dir_option($)
# If there were any lines
if (@line == 0)
{
- warn "$ME: warning: empty commit message:\n $date_line\n";
+ warn "$ME: warning: empty commit message:\n"
+ . " commit $sha\n $date_line\n";
}
else
{
diff --git a/build-aux/install-reloc b/build-aux/install-reloc
index bb43e5d..f77b0d1 100755
--- a/build-aux/install-reloc
+++ b/build-aux/install-reloc
@@ -237,8 +237,16 @@ func_create_wrapper ()
"$srcdir"/readlink.c \
"$srcdir"/stat.c \
"$srcdir"/canonicalize-lgpl.c \
+ "$srcdir"/malloc/scratch_buffer_dupfree.c \
+ "$srcdir"/malloc/scratch_buffer_grow.c \
+ "$srcdir"/malloc/scratch_buffer_grow_preserve.c \
+ "$srcdir"/malloc/scratch_buffer_set_array_size.c \
+ "$srcdir"/malloc.c \
+ "$srcdir"/realloc.c \
+ "$srcdir"/free.c \
+ "$srcdir"/mempcpy.c \
+ "$srcdir"/rawmemchr.c \
"$srcdir"/malloca.c \
- "$srcdir"/lstat.c \
"$srcdir"/relocatable.c \
"$srcdir"/setenv.c \
"$srcdir"/c-ctype.c \
@@ -255,8 +263,16 @@ func_create_wrapper ()
readlink.o \
stat.o \
canonicalize-lgpl.o \
+ scratch_buffer_dupfree.o \
+ scratch_buffer_grow.o \
+ scratch_buffer_grow_preserve.o \
+ scratch_buffer_set_array_size.o \
+ malloc.o \
+ realloc.o \
+ free.o \
+ mempcpy.o \
+ rawmemchr.o \
malloca.o \
- lstat.o \
relocatable.o \
setenv.o \
c-ctype.o
diff --git a/build-aux/reloc-ldflags b/build-aux/reloc-ldflags
index fff3d79..ff748fe 100755
--- a/build-aux/reloc-ldflags
+++ b/build-aux/reloc-ldflags
@@ -56,7 +56,7 @@ esac
origin_token=
case "$host_os" in
linux* | gnu* | kfreebsd* | \
- freebsd* | dragonfly* | \
+ freebsd* | dragonfly* | midnightbsd* | \
netbsd* | \
openbsd* | \
solaris* | \
diff --git a/build-aux/texinfo.tex b/build-aux/texinfo.tex
index dac7ae3..2bab634 100644
--- a/build-aux/texinfo.tex
+++ b/build-aux/texinfo.tex
@@ -3,9 +3,9 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2020-11-25.18}
+\def\texinfoversion{2021-02-20.11}
%
-% Copyright 1985, 1986, 1988, 1990-2020 Free Software Foundation, Inc.
+% Copyright 1985, 1986, 1988, 1990-2021 Free Software Foundation, Inc.
%
% This texinfo.tex file is free software: you can redistribute it and/or
% modify it under the terms of the GNU General Public License as
@@ -8931,7 +8931,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\else
\ifhavexrefs
% We (should) know the real title if we have the xref values.
- \def\printedrefname{\refx{#1-title}{}}%
+ \def\printedrefname{\refx{#1-title}}%
\else
% Otherwise just copy the Info node name.
\def\printedrefname{\ignorespaces #1}%
@@ -9025,7 +9025,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% If the user specified the print name (third arg) to the ref,
% print it instead of our usual "Figure 1.2".
\ifdim\wd\printedrefnamebox = 0pt
- \refx{#1-snt}{}%
+ \refx{#1-snt}%
\else
\printedrefname
\fi
@@ -9060,9 +9060,9 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\else
% Reference within this manual.
%
- % Only output a following space if the -snt ref is nonempty; for
- % @unnumbered and @anchor, it won't be.
- \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+ % Only output a following space if the -snt ref is nonempty, as the ref
+ % will be empty for @unnumbered and @anchor.
+ \setbox2 = \hbox{\ignorespaces \refx{#1-snt}}%
\ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
%
% output the `[mynode]' via the macro below so it can be overridden.
@@ -9073,7 +9073,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
,\space
%
% output the `page 3'.
- \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+ \turnoffactive \putwordpage\tie\refx{#1-pg}%
% Add a , if xref followed by a space
\if\space\noexpand\tokenafterxref ,%
\else\ifx\ \tokenafterxref ,% @TAB
@@ -9150,9 +9150,8 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi\fi\fi
}
-% \refx{NAME}{SUFFIX} - reference a cross-reference string named NAME. SUFFIX
-% is output afterwards if non-empty.
-\def\refx#1#2{%
+% \refx{NAME} - reference a cross-reference string named NAME.
+\def\refx#1{%
\requireauxfile
{%
\indexnofonts
@@ -9179,7 +9178,6 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% It's defined, so just use it.
\thisrefX
\fi
- #2% Output the suffix in any case.
}
% This is the macro invoked by entries in the aux file. Define a control
@@ -9289,10 +9287,10 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\catcode`\[=\other
\catcode`\]=\other
\catcode`\"=\other
- \catcode`\_=\other
- \catcode`\|=\other
- \catcode`\<=\other
- \catcode`\>=\other
+ \catcode`\_=\active
+ \catcode`\|=\active
+ \catcode`\<=\active
+ \catcode`\>=\active
\catcode`\$=\other
\catcode`\#=\other
\catcode`\&=\other
diff --git a/config/srclist.txt b/config/srclist.txt
index d669fd8..a55c95f 100644
--- a/config/srclist.txt
+++ b/config/srclist.txt
@@ -55,7 +55,7 @@ $LIBCSRC include/idx.h lib
#$LIBCSRC malloc/dynarray.h lib/malloc
#$LIBCSRC malloc/dynarray_at_failure.c lib/malloc
#$LIBCSRC malloc/dynarray_emplace_enlarge.c lib/malloc
-$LIBCSRC malloc/dynarray_finalize.c lib/malloc
+#$LIBCSRC malloc/dynarray_finalize.c lib/malloc
#$LIBCSRC malloc/dynarray_resize.c lib/malloc
#$LIBCSRC malloc/dynarray_resize_clear.c lib/malloc
$LIBCSRC include/scratch_buffer.h lib/malloc
diff --git a/doc/INSTALL b/doc/INSTALL
index 8865734..e82fd21 100644
--- a/doc/INSTALL
+++ b/doc/INSTALL
@@ -1,8 +1,8 @@
Installation Instructions
*************************
- Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
-Foundation, Inc.
+ Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
+Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@@ -225,7 +225,7 @@ order to use an ANSI C compiler:
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
- HP-UX 'make' updates targets which have the same time stamps as their
+ HP-UX 'make' updates targets which have the same timestamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
diff --git a/doc/INSTALL.ISO b/doc/INSTALL.ISO
index 8865734..e82fd21 100644
--- a/doc/INSTALL.ISO
+++ b/doc/INSTALL.ISO
@@ -1,8 +1,8 @@
Installation Instructions
*************************
- Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
-Foundation, Inc.
+ Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
+Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@@ -225,7 +225,7 @@ order to use an ANSI C compiler:
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
- HP-UX 'make' updates targets which have the same time stamps as their
+ HP-UX 'make' updates targets which have the same timestamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
diff --git a/doc/INSTALL.UTF-8 b/doc/INSTALL.UTF-8
index 8865734..e82fd21 100644
--- a/doc/INSTALL.UTF-8
+++ b/doc/INSTALL.UTF-8
@@ -1,8 +1,8 @@
Installation Instructions
*************************
- Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
-Foundation, Inc.
+ Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
+Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@@ -225,7 +225,7 @@ order to use an ANSI C compiler:
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
- HP-UX 'make' updates targets which have the same time stamps as their
+ HP-UX 'make' updates targets which have the same timestamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
diff --git a/doc/glibc-functions/sethostname.texi b/doc/glibc-functions/sethostname.texi
index 8294a4a..d34f4a1 100644
--- a/doc/glibc-functions/sethostname.texi
+++ b/doc/glibc-functions/sethostname.texi
@@ -37,5 +37,5 @@ The first parameter is @code{char *} instead of @code{const char *}
on some platforms: Solaris 11 2010-11.
@item
The second parameter is @code{int} instead of @code{size_t}
-on some platforms: Mac OS X 10.12, Solaris 11 2010-11.
+on some platforms: Mac OS X 10.12, MidnightBSD 2.0, Solaris 11 2010-11.
@end itemize
diff --git a/doc/install.texi b/doc/install.texi
index 875b8eb..3bedb4e 100644
--- a/doc/install.texi
+++ b/doc/install.texi
@@ -5,8 +5,8 @@
@unnumbered Installation Instructions
-Copyright @copyright{} 1994-1996, 1999-2002, 2004-2017, 2020 Free
-Software Foundation, Inc.
+Copyright @copyright{} 1994--1996, 1999--2002, 2004--2017, 2020--2021
+Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification, are
permitted in any medium without royalty provided the copyright notice
diff --git a/doc/posix-functions/expl.texi b/doc/posix-functions/expl.texi
index d0810b2..f70589f 100644
--- a/doc/posix-functions/expl.texi
+++ b/doc/posix-functions/expl.texi
@@ -23,7 +23,7 @@ MSVC 14.
@item
This function produces results which are accurate to only 16 digits on some
platforms:
-NetBSD 9.0.
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x, NetBSD 9.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/expm1l.texi b/doc/posix-functions/expm1l.texi
index 4cd58a8..059d5fc 100644
--- a/doc/posix-functions/expm1l.texi
+++ b/doc/posix-functions/expm1l.texi
@@ -17,7 +17,7 @@ IRIX 6.5.
@item
This function produces results which are accurate to only 16 digits on some
platforms:
-Mac OS X 10.5, NetBSD 8.0.
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x, Mac OS X 10.5, NetBSD 8.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/fmaf.texi b/doc/posix-functions/fmaf.texi
index 1e0d34a..3551d19 100644
--- a/doc/posix-functions/fmaf.texi
+++ b/doc/posix-functions/fmaf.texi
@@ -18,4 +18,8 @@ glibc 2.11, Mac OS X 10.5, FreeBSD 6.4/x86, FreeBSD 12.2/arm, Cygwin 1.5, mingw.
Portability problems not fixed by Gnulib:
@itemize
+@item
+This function produces wrong results on some platforms:
+musl libc/powerpc64le when emulated by QEMU 5.0.0.
+@c https://bugs.launchpad.net/qemu/+bug/1912934
@end itemize
diff --git a/doc/posix-functions/getaddrinfo.texi b/doc/posix-functions/getaddrinfo.texi
index eae5b8b..8c2bc7f 100644
--- a/doc/posix-functions/getaddrinfo.texi
+++ b/doc/posix-functions/getaddrinfo.texi
@@ -21,4 +21,7 @@ that is different from @code{cdecl}.
Portability problems not fixed by Gnulib:
@itemize
+@item
+Unlike glibc's implementation, gnulib's replacement does not support
+internationalized domain names (IDN) encoding.
@end itemize
diff --git a/doc/posix-functions/getcwd.texi b/doc/posix-functions/getcwd.texi
index 9ca0ae3..9a4cf1e 100644
--- a/doc/posix-functions/getcwd.texi
+++ b/doc/posix-functions/getcwd.texi
@@ -38,7 +38,7 @@ Portability problems fixed by Gnulib module @code{getcwd}:
@item
This function does not handle long file names (greater than @code{PATH_MAX})
correctly on some platforms:
-glibc on Linux 2.4.20, Mac OS X 10.13, FreeBSD 6.4, NetBSD 9.0, OpenBSD 4.9, AIX 7.1.
+glibc on Linux 2.4.20, musl libc 1.2.2/powerpc64le, Mac OS X 10.13, FreeBSD 6.4, NetBSD 9.0, OpenBSD 6.7, AIX 7.1.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/getlogin_r.texi b/doc/posix-functions/getlogin_r.texi
index d17c541..c70eb32 100644
--- a/doc/posix-functions/getlogin_r.texi
+++ b/doc/posix-functions/getlogin_r.texi
@@ -25,7 +25,7 @@ Portability problems not fixed by Gnulib:
@itemize
@item
This function has an incompatible declaration on some platforms:
-Solaris 11.4 (when @code{_POSIX_PTHREAD_SEMANTICS} is not defined).
+MidnightBSD 2.0, Solaris 11.4 (when @code{_POSIX_PTHREAD_SEMANTICS} is not defined).
@item
This function fails even when standard input is a tty on some platforms:
HP-UX 11.11.
diff --git a/doc/posix-functions/initstate.texi b/doc/posix-functions/initstate.texi
index fa03e99..3346767 100644
--- a/doc/posix-functions/initstate.texi
+++ b/doc/posix-functions/initstate.texi
@@ -18,4 +18,11 @@ Cygwin 1.5.25.
Portability problems not fixed by Gnulib:
@itemize
+@item
+The first parameter is @code{unsigned long} instead of @code{unsigned int} on
+some platforms:
+MidnightBSD 2.0.
+@item
+The third parameter is @code{long} instead of @code{size_t} on some platforms:
+MidnightBSD 2.0.
@end itemize
diff --git a/doc/posix-functions/log10l.texi b/doc/posix-functions/log10l.texi
index 7dd6f49..ffddbcb 100644
--- a/doc/posix-functions/log10l.texi
+++ b/doc/posix-functions/log10l.texi
@@ -26,7 +26,7 @@ IRIX 6.5.
@item
This function produces results which are accurate to only 16 digits on some
platforms:
-NetBSD 9.0.
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x, NetBSD 9.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/log1pl.texi b/doc/posix-functions/log1pl.texi
index 802c2e6..be81d60 100644
--- a/doc/posix-functions/log1pl.texi
+++ b/doc/posix-functions/log1pl.texi
@@ -11,6 +11,10 @@ Portability problems fixed by either Gnulib module @code{log1pl} or @code{log1pl
@item
This function is missing on some platforms:
FreeBSD 6.0, NetBSD 9.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 9, Cygwin 1.7.x, MSVC 9, Android 4.4.
+@item
+This function produces results which are accurate to only 16 digits on some
+platforms:
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x.
@end itemize
Portability problems fixed by Gnulib module @code{log1pl-ieee}:
diff --git a/doc/posix-functions/log2l.texi b/doc/posix-functions/log2l.texi
index 24e367c..563a67e 100644
--- a/doc/posix-functions/log2l.texi
+++ b/doc/posix-functions/log2l.texi
@@ -14,6 +14,13 @@ FreeBSD 6.0, NetBSD 9.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, older IRIX
@item
This function is not declared on some platforms:
IRIX 6.5.
+@item
+This function produces results which are accurate to only 16 digits on some
+platforms:
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x.
+@item
+This function returns Infinity for some large finite arguments on some platforms:
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/logl.texi b/doc/posix-functions/logl.texi
index 1e7918b..e0d04b5 100644
--- a/doc/posix-functions/logl.texi
+++ b/doc/posix-functions/logl.texi
@@ -20,7 +20,7 @@ glibc 2.7 on Linux/SPARC64.
@item
This function produces results which are accurate to only 16 digits on some
platforms:
-NetBSD 9.0.
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x, NetBSD 9.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/open_memstream.texi b/doc/posix-functions/open_memstream.texi
index e287664..479738e 100644
--- a/doc/posix-functions/open_memstream.texi
+++ b/doc/posix-functions/open_memstream.texi
@@ -16,3 +16,6 @@ Portability problems not fixed by Gnulib:
This function is missing on some platforms:
Mac OS X 10.5, FreeBSD 6.0, NetBSD 7.1, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 11.3, Cygwin 1.5.x, mingw, MSVC 14, Android 5.1.
@end itemize
+
+An alternative to the @code{open_memstream} function is the Gnulib module
+@code{string-buffer}.
diff --git a/doc/posix-functions/posix_spawn_file_actions_addclose.texi b/doc/posix-functions/posix_spawn_file_actions_addclose.texi
index 6a1ba1b..db5bcfd 100644
--- a/doc/posix-functions/posix_spawn_file_actions_addclose.texi
+++ b/doc/posix-functions/posix_spawn_file_actions_addclose.texi
@@ -12,8 +12,8 @@ Portability problems fixed by Gnulib:
This function is missing on some platforms:
FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 9, Cygwin 1.7.x, mingw, MSVC 14, Android 8.1.
@item
-This function does not reject a too large file descriptor on some platforms:
-musl libc, Solaris 11.4.
+This function does not reject a negative file descriptor on some platforms:
+musl libc.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/pthread_sigmask.texi b/doc/posix-functions/pthread_sigmask.texi
index 2814662..aefe0a9 100644
--- a/doc/posix-functions/pthread_sigmask.texi
+++ b/doc/posix-functions/pthread_sigmask.texi
@@ -18,7 +18,7 @@ FreeBSD 6.4, OpenBSD 3.8.
@item
This function does nothing and always returns 0 in programs that are not
linked with @code{-lpthread} on some platforms:
-FreeBSD 6.4, HP-UX 11.31, Solaris 9.
+FreeBSD 6.4, MidnightBSD 1.1, HP-UX 11.31, Solaris 9.
@item
When it fails, this functions returns @minus{}1 instead of the error number on
some platforms:
diff --git a/doc/posix-functions/remainderl.texi b/doc/posix-functions/remainderl.texi
index e1b439f..1a8f625 100644
--- a/doc/posix-functions/remainderl.texi
+++ b/doc/posix-functions/remainderl.texi
@@ -17,6 +17,10 @@ IRIX 6.5.
@item
This function returns completely wrong values on some platforms:
OpenBSD 5.1/SPARC.
+@item
+This function produces results which are accurate to only 16 digits on some
+platforms:
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x.
@end itemize
Portability problems fixed by Gnulib module @code{remainderl-ieee}:
diff --git a/doc/posix-functions/srandom.texi b/doc/posix-functions/srandom.texi
index d553373..12df916 100644
--- a/doc/posix-functions/srandom.texi
+++ b/doc/posix-functions/srandom.texi
@@ -22,4 +22,8 @@ Portability problems not fixed by Gnulib:
This function has a slightly incompatible declaration (the return type being
@samp{long} instead of @samp{void}) on some platforms:
Cygwin 1.5.25.
+@item
+The parameter is @code{unsigned long} instead of @code{unsigned int} on some
+platforms:
+MidnightBSD 2.0.
@end itemize
diff --git a/doc/posix-functions/wcwidth.texi b/doc/posix-functions/wcwidth.texi
index 86d2397..0540bb6 100644
--- a/doc/posix-functions/wcwidth.texi
+++ b/doc/posix-functions/wcwidth.texi
@@ -17,7 +17,7 @@ glibc 2.8.
@item
This function handles combining characters in UTF-8 locales incorrectly on some
platforms:
-NetBSD 9.0, OpenBSD 5.8.
+NetBSD 9.0, OpenBSD 5.8, MidnightBSD 1.1.
@item
This function returns 2 for characters with ambiguous east asian width, even in
Western locales, on some platforms:
diff --git a/doc/posix-headers/stddef.texi b/doc/posix-headers/stddef.texi
index dbc0103..ba27fa8 100644
--- a/doc/posix-headers/stddef.texi
+++ b/doc/posix-headers/stddef.texi
@@ -27,6 +27,10 @@ NetBSD 5.0
Some platforms provide a @code{NULL} macro whose value does not have the size
of a pointer:
AIX 7.2 with xlc in 64-bit mode.
+
+@item
+When this header file is provided by TinyCC 0.9.27 on glibc systems, it does
+not fulfil the expectations of other glibc header files.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/relocatable.texi b/doc/relocatable.texi
index fca0ea5..f8eec1e 100644
--- a/doc/relocatable.texi
+++ b/doc/relocatable.texi
@@ -8,7 +8,8 @@ and have it work correctly (including i18n). So many users need to go
through @code{configure; make; make install} with all its
dependencies, options, and hurdles.
-Red Hat, Debian, and similar package systems solve the ``ease of
+Most package management systems, that allow the user to install
+pre-built binaries of the packages, solve the ``ease of
installation'' problem, but they hardwire path names, usually to
@file{/usr} or @file{/usr/local}. This means that users need root
privileges to install a binary package, and prevents installing two
@@ -52,9 +53,7 @@ make install DESTDIR=/tmp/inst$$
Installation with @option{--enable-relocatable} will not work for
setuid or setgid executables, because such executables search only
-system library paths for security reasons. Also, installation with
-@option{--enable-relocatable} might not work on OpenBSD, when the
-package contains shared libraries and libtool versions 1.5.xx are used.
+system library paths for security reasons.
The runtime penalty and size penalty are negligible on GNU/Linux (just
one system call more when an executable is launched), and small on
diff --git a/lib/argp-namefrob.h b/lib/argp-namefrob.h
index f3216d7..de1a26e 100644
--- a/lib/argp-namefrob.h
+++ b/lib/argp-namefrob.h
@@ -95,43 +95,56 @@
#undef __vsnprintf
#define __vsnprintf vsnprintf
-#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
+#if (defined HAVE_DECL_CLEARERR_UNLOCKED && !HAVE_DECL_CLEARERR_UNLOCKED \
+ && !defined clearerr_unlocked)
# define clearerr_unlocked(x) clearerr (x)
#endif
-#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
+#if (defined HAVE_DECL_FEOF_UNLOCKED && !HAVE_DECL_FEOF_UNLOCKED \
+ && !defined feof_unlocked)
# define feof_unlocked(x) feof (x)
#endif
-#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
+#if (defined HAVE_DECL_FERROR_UNLOCKED && !HAVE_DECL_FERROR_UNLOCKED \
+ && !defined ferror_unlocked)
# define ferror_unlocked(x) ferror (x)
#endif
-#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
+#if (defined HAVE_DECL_FFLUSH_UNLOCKED && !HAVE_DECL_FFLUSH_UNLOCKED \
+ && !defined fflush_unlocked)
# define fflush_unlocked(x) fflush (x)
#endif
-#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
+#if (defined HAVE_DECL_FGETS_UNLOCKED && !HAVE_DECL_FGETS_UNLOCKED \
+ && !defined fgets_unlocked)
# define fgets_unlocked(x,y,z) fgets (x,y,z)
#endif
-#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED
+#if (defined HAVE_DECL_FPUTC_UNLOCKED && !HAVE_DECL_FPUTC_UNLOCKED \
+ && !defined fputc_unlocked)
# define fputc_unlocked(x,y) fputc (x,y)
#endif
-#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
+#if (defined HAVE_DECL_FPUTS_UNLOCKED && !HAVE_DECL_FPUTS_UNLOCKED \
+ && !defined fputs_unlocked)
# define fputs_unlocked(x,y) fputs (x,y)
#endif
-#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
+#if (defined HAVE_DECL_FREAD_UNLOCKED && !HAVE_DECL_FREAD_UNLOCKED \
+ && !defined fread_unlocked)
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
#endif
-#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
+#if (defined HAVE_DECL_FWRITE_UNLOCKED && !HAVE_DECL_FWRITE_UNLOCKED \
+ && !defined fwrite_unlocked)
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
#endif
-#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED
+#if (defined HAVE_DECL_GETC_UNLOCKED && !HAVE_DECL_GETC_UNLOCKED \
+ && !defined getc_unlocked)
# define getc_unlocked(x) getc (x)
#endif
-#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED
-# define getchar_unlocked() getchar ()
+#if (defined HAVE_DECL_GETCHAR_UNLOCKED && !HAVE_DECL_GETCHAR_UNLOCKED \
+ && !defined getchar_unlocked)
+# define getchar_unlocked() getchar ()
#endif
-#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED
+#if (defined HAVE_DECL_PUTC_UNLOCKED && !HAVE_DECL_PUTC_UNLOCKED \
+ && !defined putc_unlocked)
# define putc_unlocked(x,y) putc (x,y)
#endif
-#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED
+#if (defined HAVE_DECL_PUTCHAR_UNLOCKED && !HAVE_DECL_PUTCHAR_UNLOCKED \
+ && !defined putchar_unlocked)
# define putchar_unlocked(x) putchar (x)
#endif
diff --git a/lib/asyncsafe-spin.c b/lib/asyncsafe-spin.c
index ba22b9c..d0cdb39 100644
--- a/lib/asyncsafe-spin.c
+++ b/lib/asyncsafe-spin.c
@@ -190,7 +190,7 @@ do_unlock (asyncsafe_spinlock_t *lock)
abort ();
}
-# elif (defined __GNUC__ || defined __clang__ || defined __SUNPRO_C) && (defined __sparc || defined __i386 || defined __x86_64__)
+# elif ((defined __GNUC__ || defined __clang__ || defined __SUNPRO_C) && (defined __sparc || defined __i386 || defined __x86_64__)) || (defined __TINYC__ && (defined __i386 || defined __x86_64__))
/* For older versions of GCC or clang, use inline assembly.
GCC, clang, and the Oracle Studio C 12 compiler understand GCC's extended
asm syntax, but the plain Oracle Studio C 11 compiler understands only
@@ -200,9 +200,14 @@ do_unlock (asyncsafe_spinlock_t *lock)
static void
memory_barrier (void)
{
-# if defined __GNUC__ || defined __clang__ || __SUNPRO_C >= 0x590
+# if defined __GNUC__ || defined __clang__ || __SUNPRO_C >= 0x590 || defined __TINYC__
# if defined __i386 || defined __x86_64__
+# if defined __TINYC__ && defined __i386
+ /* Cannot use the SSE instruction "mfence" with this compiler. */
+ asm volatile ("lock orl $0,(%esp)");
+# else
asm volatile ("mfence");
+# endif
# endif
# if defined __sparc
asm volatile ("membar 2");
@@ -223,7 +228,7 @@ static unsigned int
atomic_compare_and_swap (volatile unsigned int *vp, unsigned int cmp,
unsigned int newval)
{
-# if defined __GNUC__ || defined __clang__ || __SUNPRO_C >= 0x590
+# if defined __GNUC__ || defined __clang__ || __SUNPRO_C >= 0x590 || defined __TINYC__
unsigned int oldval;
# if defined __i386 || defined __x86_64__
asm volatile (" lock\n cmpxchgl %3,(%1)"
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index bf63355..c6fef17 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -21,7 +21,6 @@
optimizes away the name == NULL test below. */
# define _GL_ARG_NONNULL(params)
-# define _GL_USE_STDLIB_ALLOC 1
# include <libc-config.h>
#endif
@@ -76,6 +75,12 @@
# define __rawmemchr rawmemchr
# define __readlink readlink
# define __stat stat
+# if IN_RELOCWRAPPER
+ /* When building the relocatable program wrapper, use the system's memmove
+ function, not the gnulib override, otherwise we would get a link error.
+ */
+# undef memmove
+# endif
#endif
/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
diff --git a/lib/dynarray.h b/lib/dynarray.h
index 6da3e87..37053d0 100644
--- a/lib/dynarray.h
+++ b/lib/dynarray.h
@@ -19,8 +19,6 @@
#ifndef _GL_DYNARRAY_H
#define _GL_DYNARRAY_H
-#include <libc-config.h>
-
#define __libc_dynarray_at_failure gl_dynarray_at_failure
#define __libc_dynarray_emplace_enlarge gl_dynarray_emplace_enlarge
#define __libc_dynarray_finalize gl_dynarray_finalize
diff --git a/lib/free.c b/lib/free.c
index 5c89787..3f5968c 100644
--- a/lib/free.c
+++ b/lib/free.c
@@ -19,15 +19,19 @@
#include <config.h>
+/* Specification. */
#include <stdlib.h>
-#include <errno.h>
+/* A function definition is only needed if HAVE_FREE_POSIX is not defined. */
+#if !HAVE_FREE_POSIX
+
+# include <errno.h>
void
rpl_free (void *p)
-#undef free
+# undef free
{
-#if defined __GNUC__ && !defined __clang__
+# if defined __GNUC__ && !defined __clang__
/* An invalid GCC optimization
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98396>
would optimize away the assignments in the code below, when link-time
@@ -39,9 +43,11 @@ rpl_free (void *p)
errno = 0;
free (p);
errno = err[errno == 0];
-#else
+# else
int err = errno;
free (p);
errno = err;
-#endif
+# endif
}
+
+#endif
diff --git a/lib/glob.c b/lib/glob.c
index 32c88e5..775911e 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -21,7 +21,7 @@
optimizes away the pattern == NULL test below. */
# define _GL_ARG_NONNULL(params)
-# include <config.h>
+# include <libc-config.h>
#endif
diff --git a/lib/glob.in.h b/lib/glob.in.h
index d4270d7..d8b03c5 100644
--- a/lib/glob.in.h
+++ b/lib/glob.in.h
@@ -70,7 +70,9 @@ typedef int (*_gl_glob_errfunc_fn) (const char *, int);
/* Preparations for including the standard GNU C Library header. */
-# include <libc-config.h>
+# ifndef __attribute_maybe_unused__
+# include <libc-config.h>
+# endif
# include <stddef.h>
diff --git a/lib/malloc.c b/lib/malloc.c
index 325064d..887cdde 100644
--- a/lib/malloc.c
+++ b/lib/malloc.c
@@ -30,7 +30,11 @@
#include <stdlib.h>
-#include <errno.h>
+/* A function definition is only needed if NEED_MALLOC_GNU is defined above
+ or if the module 'malloc-posix' requests it. */
+#if NEED_MALLOC_GNU || (GNULIB_MALLOC_POSIX && !HAVE_MALLOC_POSIX)
+
+# include <errno.h>
/* Allocate an N-byte block of memory from the heap.
If N is zero, allocate a 1-byte block. */
@@ -40,17 +44,19 @@ rpl_malloc (size_t n)
{
void *result;
-#if NEED_MALLOC_GNU
+# if NEED_MALLOC_GNU
if (n == 0)
n = 1;
-#endif
+# endif
result = malloc (n);
-#if !HAVE_MALLOC_POSIX
+# if !HAVE_MALLOC_POSIX
if (result == NULL)
errno = ENOMEM;
-#endif
+# endif
return result;
}
+
+#endif
diff --git a/lib/malloc/dynarray_at_failure.c b/lib/malloc/dynarray_at_failure.c
index 0fa12c7..4f840db 100644
--- a/lib/malloc/dynarray_at_failure.c
+++ b/lib/malloc/dynarray_at_failure.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/lib/malloc/dynarray_emplace_enlarge.c b/lib/malloc/dynarray_emplace_enlarge.c
index ddfe306..0f8baf9 100644
--- a/lib/malloc/dynarray_emplace_enlarge.c
+++ b/lib/malloc/dynarray_emplace_enlarge.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <errno.h>
#include <intprops.h>
diff --git a/lib/malloc/dynarray_finalize.c b/lib/malloc/dynarray_finalize.c
index 8ec6ad2..c33da41 100644
--- a/lib/malloc/dynarray_finalize.c
+++ b/lib/malloc/dynarray_finalize.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <stdlib.h>
#include <string.h>
diff --git a/lib/malloc/dynarray_resize.c b/lib/malloc/dynarray_resize.c
index 5c60927..5a57166 100644
--- a/lib/malloc/dynarray_resize.c
+++ b/lib/malloc/dynarray_resize.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <errno.h>
#include <intprops.h>
diff --git a/lib/malloc/dynarray_resize_clear.c b/lib/malloc/dynarray_resize_clear.c
index e893d1d..9c43b00 100644
--- a/lib/malloc/dynarray_resize_clear.c
+++ b/lib/malloc/dynarray_resize_clear.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <string.h>
diff --git a/lib/mbtowc-lock.h b/lib/mbtowc-lock.h
index 696b12c..b7c5ba8 100644
--- a/lib/mbtowc-lock.h
+++ b/lib/mbtowc-lock.h
@@ -32,7 +32,15 @@ mbtowc_unlocked (wchar_t *pwc, const char *p, size_t m)
/* Prohibit renaming this symbol. */
#undef gl_get_mbtowc_lock
-#if defined _WIN32 && !defined __CYGWIN__
+#ifdef USE_UNLOCKED_IO
+
+static int
+mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
+{
+ return mbtowc_unlocked (pwc, p, m);
+}
+
+#elif defined _WIN32 && !defined __CYGWIN__
extern __declspec(dllimport) CRITICAL_SECTION *gl_get_mbtowc_lock (void);
diff --git a/lib/mempcpy.c b/lib/mempcpy.c
index c61132e..6e9500c 100644
--- a/lib/mempcpy.c
+++ b/lib/mempcpy.c
@@ -19,6 +19,9 @@
/* Specification. */
#include <string.h>
+/* A function definition is only needed if HAVE_MEMPCPY is not defined. */
+#if !HAVE_MEMPCPY
+
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
last written byte. */
void *
@@ -26,3 +29,5 @@ mempcpy (void *dest, const void *src, size_t n)
{
return (char *) memcpy (dest, src, n) + n;
}
+
+#endif
diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y
index b8a832f..552fe5c 100644
--- a/lib/parse-datetime.y
+++ b/lib/parse-datetime.y
@@ -221,8 +221,10 @@ typedef struct
idx_t zones_seen;
bool year_seen;
+#ifdef GNULIB_PARSE_DATETIME2
/* Print debugging output to stderr. */
bool parse_datetime_debug;
+#endif
/* Which of the 'seen' parts have been printed when debugging. */
bool debug_dates_seen;
@@ -239,6 +241,16 @@ typedef struct
table local_time_zone_table[3];
} parser_control;
+static bool
+debugging (parser_control const *pc)
+{
+#ifdef GNULIB_PARSE_DATETIME2
+ return pc->parse_datetime_debug;
+#else
+ return false;
+#endif
+}
+
union YYSTYPE;
static int yylex (union YYSTYPE *, parser_control *);
static int yyerror (parser_control const *, char const *);
@@ -421,7 +433,7 @@ debug_print_current_time (char const *item, parser_control *pc)
{
bool space = false;
- if (!pc->parse_datetime_debug)
+ if (!debugging (pc))
return;
/* no newline, more items printed below */
@@ -521,7 +533,7 @@ debug_print_relative_time (char const *item, parser_control const *pc)
{
bool space = false;
- if (!pc->parse_datetime_debug)
+ if (!debugging (pc))
return;
/* no newline, more items printed below */
@@ -802,7 +814,7 @@ date:
you want portability, use the ISO 8601 format. */
if (4 <= $1.digits)
{
- if (pc->parse_datetime_debug)
+ if (debugging (pc))
{
intmax_t digits = $1.digits;
dbg_printf (_("warning: value %"PRIdMAX" has %"PRIdMAX" digits. "
@@ -816,7 +828,7 @@ date:
}
else
{
- if (pc->parse_datetime_debug)
+ if (debugging (pc))
dbg_printf (_("warning: value %"PRIdMAX" has less than 4 digits. "
"Assuming MM/DD/YY[YY]\n"),
$1.value);
@@ -1504,7 +1516,7 @@ yylex (union YYSTYPE *lvalp, parser_control *pc)
tp = lookup_word (pc, buff);
if (! tp)
{
- if (pc->parse_datetime_debug)
+ if (debugging (pc))
dbg_printf (_("error: unknown word '%s'\n"), buff);
return '?';
}
@@ -1651,7 +1663,7 @@ debug_mktime_not_ok (struct tm const *tm0, struct tm const *tm1,
const bool dst_shift = eq_sec && eq_min && !eq_hour
&& eq_mday && eq_month && eq_year;
- if (!pc->parse_datetime_debug)
+ if (!debugging (pc))
return;
dbg_printf (_("error: invalid date/time value:\n"));
@@ -1690,29 +1702,15 @@ debug_mktime_not_ok (struct tm const *tm0, struct tm const *tm1,
: _("missing timezone")));
}
-/* The original interface: run with debug=false and the default timezone. */
-bool
-parse_datetime (struct timespec *result, char const *p,
- struct timespec const *now)
-{
- char const *tzstring = getenv ("TZ");
- timezone_t tz = tzalloc (tzstring);
- if (!tz)
- return false;
- bool ok = parse_datetime2 (result, p, now, 0, tz, tzstring);
- tzfree (tz);
- return ok;
-}
-
/* Parse a date/time string, storing the resulting time value into *RESULT.
The string itself is pointed to by P. Return true if successful.
P can be an incomplete or relative time specification; if so, use
*NOW as the basis for the returned time. Default to timezone
TZDEFAULT, which corresponds to tzalloc (TZSTRING). */
-bool
-parse_datetime2 (struct timespec *result, char const *p,
- struct timespec const *now, unsigned int flags,
- timezone_t tzdefault, char const *tzstring)
+static bool
+parse_datetime_body (struct timespec *result, char const *p,
+ struct timespec const *now, unsigned int flags,
+ timezone_t tzdefault, char const *tzstring)
{
struct tm tm;
struct tm tm0;
@@ -1803,10 +1801,12 @@ parse_datetime2 (struct timespec *result, char const *p,
parser_control pc;
pc.input = p;
+#ifdef GNULIB_PARSE_DATETIME2
pc.parse_datetime_debug = (flags & PARSE_DATETIME_DEBUG) != 0;
+#endif
if (INT_ADD_WRAPV (tmp.tm_year, TM_YEAR_BASE, &pc.year.value))
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: initial year out of range\n"));
goto fail;
}
@@ -1900,7 +1900,7 @@ parse_datetime2 (struct timespec *result, char const *p,
if (yyparse (&pc) != 0)
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf ((input_sentinel <= pc.input
? _("error: parsing failed\n")
: _("error: parsing failed, stopped at '%s'\n")),
@@ -1911,7 +1911,7 @@ parse_datetime2 (struct timespec *result, char const *p,
/* Determine effective timezone source. */
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
{
dbg_printf (_("input timezone: "));
@@ -1953,7 +1953,7 @@ parse_datetime2 (struct timespec *result, char const *p,
if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen
| (pc.local_zones_seen + pc.zones_seen)))
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
{
if (pc.times_seen > 1)
dbg_printf ("error: seen multiple time parts\n");
@@ -1969,11 +1969,11 @@ parse_datetime2 (struct timespec *result, char const *p,
goto fail;
}
- if (! to_tm_year (pc.year, pc.parse_datetime_debug, &tm.tm_year)
+ if (! to_tm_year (pc.year, debugging (&pc), &tm.tm_year)
|| INT_ADD_WRAPV (pc.month, -1, &tm.tm_mon)
|| INT_ADD_WRAPV (pc.day, 0, &tm.tm_mday))
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: year, month, or day overflow\n"));
goto fail;
}
@@ -1984,14 +1984,14 @@ parse_datetime2 (struct timespec *result, char const *p,
{
char const *mrd = (pc.meridian == MERam ? "am"
: pc.meridian == MERpm ?"pm" : "");
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: invalid hour %"PRIdMAX"%s\n"),
pc.hour, mrd);
goto fail;
}
tm.tm_min = pc.minutes;
tm.tm_sec = pc.seconds.tv_sec;
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf ((pc.times_seen
? _("using specified time as starting value: '%s'\n")
: _("using current time as starting value: '%s'\n")),
@@ -2001,7 +2001,7 @@ parse_datetime2 (struct timespec *result, char const *p,
{
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
pc.seconds.tv_nsec = 0;
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf ("warning: using midnight as starting time: 00:00:00\n");
}
@@ -2047,7 +2047,7 @@ parse_datetime2 (struct timespec *result, char const *p,
timezone_t tz2 = tzalloc (tz2buf);
if (!tz2)
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: tzalloc (\"%s\") failed\n"), tz2buf);
goto fail;
}
@@ -2092,7 +2092,7 @@ parse_datetime2 (struct timespec *result, char const *p,
if (Start == (time_t) -1)
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: day '%s' "
"(day ordinal=%"PRIdMAX" number=%d) "
"resulted in an invalid date: '%s'\n"),
@@ -2103,14 +2103,14 @@ parse_datetime2 (struct timespec *result, char const *p,
goto fail;
}
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("new start date: '%s' is '%s'\n"),
str_days (&pc, dbg_ord, sizeof dbg_ord),
debug_strfdatetime (&tm, &pc, dbg_tm, sizeof dbg_tm));
}
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
{
if (!pc.dates_seen && !pc.days_seen)
dbg_printf (_("using current date as starting value: '%s'\n"),
@@ -2128,7 +2128,7 @@ parse_datetime2 (struct timespec *result, char const *p,
/* Add relative date. */
if (pc.rel.year | pc.rel.month | pc.rel.day)
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
{
if ((pc.rel.year != 0 || pc.rel.month != 0) && tm.tm_mday != 15)
dbg_printf (_("warning: when adding relative months/years, "
@@ -2145,7 +2145,7 @@ parse_datetime2 (struct timespec *result, char const *p,
|| INT_ADD_WRAPV (tm.tm_mon, pc.rel.month, &month)
|| INT_ADD_WRAPV (tm.tm_mday, pc.rel.day, &day))
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: %s:%d\n"), __FILE__, __LINE__);
goto fail;
}
@@ -2159,7 +2159,7 @@ parse_datetime2 (struct timespec *result, char const *p,
Start = mktime_z (tz, &tm);
if (Start == (time_t) -1)
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: adding relative date resulted "
"in an invalid date: '%s'\n"),
debug_strfdatetime (&tm, &pc, dbg_tm,
@@ -2167,7 +2167,7 @@ parse_datetime2 (struct timespec *result, char const *p,
goto fail;
}
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
{
dbg_printf (_("after date adjustment "
"(%+"PRIdMAX" years, %+"PRIdMAX" months, "
@@ -2244,7 +2244,7 @@ parse_datetime2 (struct timespec *result, char const *p,
overflow |= INT_SUBTRACT_WRAPV (Start, delta, &t1);
if (overflow)
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: timezone %d caused time_t overflow\n"),
pc.time_zone);
goto fail;
@@ -2252,7 +2252,7 @@ parse_datetime2 (struct timespec *result, char const *p,
Start = t1;
}
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
{
intmax_t Starti = Start;
dbg_printf (_("'%s' = %"PRIdMAX" epoch-seconds\n"),
@@ -2282,7 +2282,7 @@ parse_datetime2 (struct timespec *result, char const *p,
|| INT_ADD_WRAPV (t2, pc.rel.seconds, &t3)
|| INT_ADD_WRAPV (t3, d4, &t4))
{
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
dbg_printf (_("error: adding relative time caused an "
"overflow\n"));
goto fail;
@@ -2291,7 +2291,7 @@ parse_datetime2 (struct timespec *result, char const *p,
result->tv_sec = t4;
result->tv_nsec = normalized_ns;
- if (pc.parse_datetime_debug
+ if (debugging (&pc)
&& (pc.rel.hour | pc.rel.minutes | pc.rel.seconds | pc.rel.ns))
{
dbg_printf (_("after time adjustment (%+"PRIdMAX" hours, "
@@ -2322,7 +2322,7 @@ parse_datetime2 (struct timespec *result, char const *p,
}
}
- if (pc.parse_datetime_debug)
+ if (debugging (&pc))
{
/* Special case: using 'date -u' simply set TZ=UTC0 */
if (! tzstring)
@@ -2373,6 +2373,36 @@ parse_datetime2 (struct timespec *result, char const *p,
return ok;
}
+#ifdef GNULIB_PARSE_DATETIME2
+/* Parse a date/time string, storing the resulting time value into *RESULT.
+ The string itself is pointed to by P. Return true if successful.
+ P can be an incomplete or relative time specification; if so, use
+ *NOW as the basis for the returned time. Default to timezone
+ TZDEFAULT, which corresponds to tzalloc (TZSTRING). */
+bool
+parse_datetime2 (struct timespec *result, char const *p,
+ struct timespec const *now, unsigned int flags,
+ timezone_t tzdefault, char const *tzstring)
+{
+ return parse_datetime_body (result, p, now, flags, tzdefault, tzstring);
+}
+#endif
+
+
+/* The plain interface: run with debug=false and the default timezone. */
+bool
+parse_datetime (struct timespec *result, char const *p,
+ struct timespec const *now)
+{
+ char const *tzstring = getenv ("TZ");
+ timezone_t tz = tzalloc (tzstring);
+ if (!tz)
+ return false;
+ bool ok = parse_datetime_body (result, p, now, 0, tz, tzstring);
+ tzfree (tz);
+ return ok;
+}
+
#if TEST
int
diff --git a/lib/passfd.c b/lib/passfd.c
index ca10ba5..a993f39 100644
--- a/lib/passfd.c
+++ b/lib/passfd.c
@@ -142,19 +142,23 @@ recvfd (int sock, int flags)
cmsg->cmsg_len = CMSG_LEN (sizeof fd);
/* Initialize the payload: */
memcpy (CMSG_DATA (cmsg), &fd, sizeof fd);
- msg.msg_controllen = cmsg->cmsg_len;
+ msg.msg_controllen = CMSG_SPACE (sizeof fd);
len = recvmsg (sock, &msg, flags_recvmsg);
if (len < 0)
return -1;
-
+ if (len == 0)
+ {
+ /* fake errno: at end the file is not available */
+ errno = ENOTCONN;
+ return -1;
+ }
cmsg = CMSG_FIRSTHDR (&msg);
/* be paranoiac */
- if (len == 0 || cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof fd)
+ if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof fd)
|| cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
{
- /* fake errno: at end the file is not available */
- errno = len ? EACCES : ENOTCONN;
+ errno = EACCES;
return -1;
}
diff --git a/lib/rawmemchr.c b/lib/rawmemchr.c
index bbb250f..f4d5030 100644
--- a/lib/rawmemchr.c
+++ b/lib/rawmemchr.c
@@ -19,6 +19,9 @@
/* Specification. */
#include <string.h>
+/* A function definition is only needed if HAVE_RAWMEMCHR is not defined. */
+#if !HAVE_RAWMEMCHR
+
/* Find the first occurrence of C in S. */
void *
rawmemchr (const void *s, int c_in)
@@ -134,3 +137,5 @@ rawmemchr (const void *s, int c_in)
char_ptr++;
return (void *) char_ptr;
}
+
+#endif
diff --git a/lib/realloc.c b/lib/realloc.c
index 35caeab..51d8d21 100644
--- a/lib/realloc.c
+++ b/lib/realloc.c
@@ -37,7 +37,11 @@
#include <stdlib.h>
-#include <errno.h>
+/* A function definition is only needed if NEED_REALLOC_GNU is defined above
+ or if the module 'realloc-posix' requests it. */
+#if NEED_REALLOC_GNU || (GNULIB_REALLOC_POSIX && !HAVE_REALLOC_POSIX)
+
+# include <errno.h>
/* Change the size of an allocated block of memory P to N bytes,
with error checking. If N is zero, change it to 1. If P is NULL,
@@ -48,7 +52,7 @@ rpl_realloc (void *p, size_t n)
{
void *result;
-#if NEED_REALLOC_GNU
+# if NEED_REALLOC_GNU
if (n == 0)
{
n = 1;
@@ -57,23 +61,25 @@ rpl_realloc (void *p, size_t n)
free (p);
p = NULL;
}
-#endif
+# endif
if (p == NULL)
{
-#if GNULIB_REALLOC_GNU && !NEED_REALLOC_GNU && !SYSTEM_MALLOC_GLIBC_COMPATIBLE
+# if GNULIB_REALLOC_GNU && !NEED_REALLOC_GNU && !SYSTEM_MALLOC_GLIBC_COMPATIBLE
if (n == 0)
n = 1;
-#endif
+# endif
result = malloc (n);
}
else
result = realloc (p, n);
-#if !HAVE_REALLOC_POSIX
+# if !HAVE_REALLOC_POSIX
if (result == NULL)
errno = ENOMEM;
-#endif
+# endif
return result;
}
+
+#endif
diff --git a/lib/regcomp.c b/lib/regcomp.c
index d93698a..887e5b5 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -1695,12 +1695,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
reg_errcode_t err;
Idx i;
re_node_set eclosure;
- bool ok;
bool incomplete = false;
err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
if (__glibc_unlikely (err != REG_NOERROR))
return err;
+ /* An epsilon closure includes itself. */
+ eclosure.elems[eclosure.nelem++] = node;
+
/* This indicates that we are calculating this node now.
We reference this value to avoid infinite loop. */
dfa->eclosures[node].nelem = -1;
@@ -1753,10 +1755,6 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
}
}
- /* An epsilon closure includes itself. */
- ok = re_node_set_insert (&eclosure, node);
- if (__glibc_unlikely (! ok))
- return REG_ESPACE;
if (incomplete && !root)
dfa->eclosures[node].nelem = 0;
else
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
index 9dd387e..55f6b66 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -1314,6 +1314,7 @@ re_node_set_insert (re_node_set *set, Idx elem)
{
for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
set->elems[idx] = set->elems[idx - 1];
+ DEBUG_ASSERT (set->elems[idx - 1] < elem);
}
/* Insert the new element. */
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index 3fa2bf1..4b0a3ef 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -32,7 +32,10 @@
#include <stdbool.h>
#include <stdint.h>
-#include <dynarray.h>
+#ifndef _LIBC
+# include <dynarray.h>
+#endif
+
#include <intprops.h>
#include <verify.h>
diff --git a/lib/regexec.c b/lib/regexec.c
index f7b4f9c..6309dea 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -59,7 +59,7 @@ static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
Idx cur_idx, Idx nmatch);
static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
Idx str_idx, Idx dest_node, Idx nregs,
- regmatch_t *regs,
+ regmatch_t *regs, regmatch_t *prevregs,
re_node_set *eps_via_nodes);
static reg_errcode_t set_regs (const regex_t *preg,
const re_match_context_t *mctx,
@@ -186,7 +186,8 @@ static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len);
REG_NOTBOL is set, then ^ does not match at the beginning of the
string; if REG_NOTEOL is set, then $ does not match at the end.
- We return 0 if we find a match and REG_NOMATCH if not. */
+ Return 0 if a match is found, REG_NOMATCH if not, REG_BADPAT if
+ EFLAGS is invalid. */
int
regexec (const regex_t *__restrict preg, const char *__restrict string,
@@ -269,8 +270,8 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
strings.)
On success, re_match* functions return the length of the match, re_search*
- return the position of the start of the match. Return value -1 means no
- match was found and -2 indicates an internal error. */
+ return the position of the start of the match. They return -1 on
+ match failure, -2 on error. */
regoff_t
re_match (struct re_pattern_buffer *bufp, const char *string, Idx length,
@@ -1206,27 +1207,26 @@ check_halt_state_context (const re_match_context_t *mctx,
/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
corresponding to the DFA).
Return the destination node, and update EPS_VIA_NODES;
- return -1 in case of errors. */
+ return -1 on match failure, -2 on error. */
static Idx
proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
+ regmatch_t *prevregs,
Idx *pidx, Idx node, re_node_set *eps_via_nodes,
struct re_fail_stack_t *fs)
{
const re_dfa_t *const dfa = mctx->dfa;
- Idx i;
- bool ok;
if (IS_EPSILON_NODE (dfa->nodes[node].type))
{
re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
re_node_set *edests = &dfa->edests[node];
- Idx dest_node;
- ok = re_node_set_insert (eps_via_nodes, node);
+ bool ok = re_node_set_insert (eps_via_nodes, node);
if (__glibc_unlikely (! ok))
return -2;
- /* Pick up a valid destination, or return -1 if none
- is found. */
- for (dest_node = -1, i = 0; i < edests->nelem; ++i)
+
+ /* Pick a valid destination, or return -1 if none is found. */
+ Idx dest_node = -1;
+ for (Idx i = 0; i < edests->nelem; i++)
{
Idx candidate = edests->elems[i];
if (!re_node_set_contains (cur_nodes, candidate))
@@ -1244,7 +1244,7 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
/* Otherwise, push the second epsilon-transition on the fail stack. */
else if (fs != NULL
&& push_fail_stack (fs, *pidx, candidate, nregs, regs,
- eps_via_nodes))
+ prevregs, eps_via_nodes))
return -2;
/* We know we are going to exit. */
@@ -1288,7 +1288,7 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
if (naccepted == 0)
{
Idx dest_node;
- ok = re_node_set_insert (eps_via_nodes, node);
+ bool ok = re_node_set_insert (eps_via_nodes, node);
if (__glibc_unlikely (! ok))
return -2;
dest_node = dfa->edests[node].elems[0];
@@ -1317,7 +1317,8 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
static reg_errcode_t
__attribute_warn_unused_result__
push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
- Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
+ Idx nregs, regmatch_t *regs, regmatch_t *prevregs,
+ re_node_set *eps_via_nodes)
{
reg_errcode_t err;
Idx num = fs->num++;
@@ -1333,25 +1334,30 @@ push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
}
fs->stack[num].idx = str_idx;
fs->stack[num].node = dest_node;
- fs->stack[num].regs = re_malloc (regmatch_t, nregs);
+ fs->stack[num].regs = re_malloc (regmatch_t, 2 * nregs);
if (fs->stack[num].regs == NULL)
return REG_ESPACE;
memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
+ memcpy (fs->stack[num].regs + nregs, prevregs, sizeof (regmatch_t) * nregs);
err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
return err;
}
static Idx
pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
- regmatch_t *regs, re_node_set *eps_via_nodes)
+ regmatch_t *regs, regmatch_t *prevregs,
+ re_node_set *eps_via_nodes)
{
+ if (fs == NULL || fs->num == 0)
+ return -1;
Idx num = --fs->num;
- DEBUG_ASSERT (num >= 0);
*pidx = fs->stack[num].idx;
memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
+ memcpy (prevregs, fs->stack[num].regs + nregs, sizeof (regmatch_t) * nregs);
re_node_set_free (eps_via_nodes);
re_free (fs->stack[num].regs);
*eps_via_nodes = fs->stack[num].eps_via_nodes;
+ DEBUG_ASSERT (0 <= fs->stack[num].node);
return fs->stack[num].node;
}
@@ -1407,33 +1413,32 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
{
update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
- if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
+ if ((idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
+ || re_node_set_contains (&eps_via_nodes, cur_node))
{
Idx reg_idx;
+ cur_node = -1;
if (fs)
{
for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
- break;
- if (reg_idx == nmatch)
- {
- re_node_set_free (&eps_via_nodes);
- regmatch_list_free (&prev_match);
- return free_fail_stack_return (fs);
- }
- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
- &eps_via_nodes);
+ {
+ cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+ prev_idx_match, &eps_via_nodes);
+ break;
+ }
}
- else
+ if (cur_node < 0)
{
re_node_set_free (&eps_via_nodes);
regmatch_list_free (&prev_match);
- return REG_NOERROR;
+ return free_fail_stack_return (fs);
}
}
/* Proceed to next node. */
- cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,
+ cur_node = proceed_next_node (mctx, nmatch, pmatch, prev_idx_match,
+ &idx, cur_node,
&eps_via_nodes, fs);
if (__glibc_unlikely (cur_node < 0))
@@ -1445,13 +1450,13 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
free_fail_stack_return (fs);
return REG_ESPACE;
}
- if (fs)
- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
- &eps_via_nodes);
- else
+ cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+ prev_idx_match, &eps_via_nodes);
+ if (cur_node < 0)
{
re_node_set_free (&eps_via_nodes);
regmatch_list_free (&prev_match);
+ free_fail_stack_return (fs);
return REG_NOMATCH;
}
}
@@ -1495,10 +1500,10 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
}
else if (type == OP_CLOSE_SUBEXP)
{
+ /* We are at the last node of this sub expression. */
Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
if (reg_num < nmatch)
{
- /* We are at the last node of this sub expression. */
if (pmatch[reg_num].rm_so < cur_idx)
{
pmatch[reg_num].rm_eo = cur_idx;
@@ -2195,6 +2200,7 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
/* Return the next state to which the current state STATE will transit by
accepting the current input byte, and update STATE_LOG if necessary.
+ Return NULL on failure.
If STATE can accept a multibyte char/collating element/back reference
update the destination of STATE_LOG. */
@@ -2395,7 +2401,7 @@ check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
#if 0
/* Return the next state to which the current state STATE will transit by
- accepting the current input byte. */
+ accepting the current input byte. Return NULL on failure. */
static re_dfastate_t *
transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
@@ -2817,7 +2823,8 @@ find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
LAST_NODE at LAST_STR. We record the path onto PATH since it will be
heavily reused.
- Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */
+ Return REG_NOERROR if it can arrive, REG_NOMATCH if it cannot,
+ REG_ESPACE if memory is exhausted. */
static reg_errcode_t
__attribute_warn_unused_result__
@@ -3433,7 +3440,8 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
/* Group all nodes belonging to STATE into several destinations.
Then for all destinations, set the nodes belonging to the destination
to DESTS_NODE[i] and set the characters accepted by the destination
- to DEST_CH[i]. This function return the number of destinations. */
+ to DEST_CH[i]. Return the number of destinations if successful,
+ -1 on internal error. */
static Idx
group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
@@ -4211,7 +4219,8 @@ match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx)
}
/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
- at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */
+ at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.
+ Return the new entry if successful, NULL if memory is exhausted. */
static re_sub_match_last_t *
match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx)
diff --git a/lib/relocwrapper.c b/lib/relocwrapper.c
index 0624bd9..771da89 100644
--- a/lib/relocwrapper.c
+++ b/lib/relocwrapper.c
@@ -29,10 +29,26 @@
-> readlink
-> stat
-> canonicalize-lgpl
+ -> libc-config
+ -> errno
+ -> fcntl-h
+ -> stdbool
+ -> sys_stat
+ -> unistd
+ -> eloop-threshold
-> filename
- -> malloca
- -> lstat
+ -> idx
+ -> intprops
+ -> scratch_buffer
+ -> malloc-posix
+ -> realloc-posix
+ -> free-posix
+ -> pathmax
+ -> mempcpy
+ -> rawmemchr
-> readlink
+ -> stat
+ -> double-slash-root
-> relocatable
-> setenv
-> malloca
diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h
index 603b0d6..f4b5f9e 100644
--- a/lib/scratch_buffer.h
+++ b/lib/scratch_buffer.h
@@ -19,6 +19,97 @@
#ifndef _GL_SCRATCH_BUFFER_H
#define _GL_SCRATCH_BUFFER_H
+/* Scratch buffers with a default stack allocation and fallback to
+ heap allocation. It is expected that this function is used in this
+ way:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ return -1;
+
+ scratch_buffer_free (&tmpbuf);
+ return 0;
+
+ The allocation functions (scratch_buffer_grow,
+ scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+ sure that the heap allocation, if any, is freed, so that the code
+ above does not have a memory leak. The buffer still remains in a
+ state that can be deallocated using scratch_buffer_free, so a loop
+ like this is valid as well:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ break;
+
+ scratch_buffer_free (&tmpbuf);
+
+ scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+ to grow the buffer by at least 512 bytes. This means that when
+ using the scratch buffer as a backing store for a non-character
+ array whose element size, in bytes, is 512 or smaller, the scratch
+ buffer only has to grow once to make room for at least one more
+ element.
+*/
+
+/* Scratch buffer. Must be initialized with scratch_buffer_init
+ before its use. */
+struct scratch_buffer;
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+ and BUFFER->length reflects the available space. */
+#if 0
+extern void scratch_buffer_init (struct scratch_buffer *buffer);
+#endif
+
+/* Deallocates *BUFFER (if it was heap-allocated). */
+#if 0
+extern void scratch_buffer_free (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
+ preserved. Return true on success, false on allocation failure (in
+ which case the old buffer is freed). On success, the new buffer is
+ larger than the previous size. On failure, *BUFFER is deallocated,
+ but remains in a free-able state, and errno is set. */
+#if 0
+extern bool scratch_buffer_grow (struct scratch_buffer *buffer);
+#endif
+
+/* Like scratch_buffer_grow, but preserve the old buffer
+ contents on success, as a prefix of the new buffer. */
+#if 0
+extern bool scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+ bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
+ can be zero. Return true on success, false on allocation failure
+ (in which case the old buffer is freed, but *BUFFER remains in a
+ free-able state, and errno is set). It is unspecified whether this
+ function can reduce the array size. */
+#if 0
+extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size);
+#endif
+
+/* Return a copy of *BUFFER's first SIZE bytes as a heap-allocated block,
+ deallocating *BUFFER if it was heap-allocated. SIZE must be at
+ most *BUFFER's size. Return NULL (setting errno) on memory
+ exhaustion. */
+#if 0
+extern void *scratch_buffer_dupfree (struct scratch_buffer *buffer,
+ size_t size);
+#endif
+
+
+/* The implementation is imported from glibc. */
+
#include <libc-config.h>
#define __libc_scratch_buffer_dupfree gl_scratch_buffer_dupfree
diff --git a/lib/simple-atomic.c b/lib/simple-atomic.c
new file mode 100644
index 0000000..7c4f7e9
--- a/dev/null
+++ b/lib/simple-atomic.c
@@ -0,0 +1,360 @@
+/* Simple atomic operations for multithreading.
+ Copyright (C) 2020-2021 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 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#include <config.h>
+
+/* Specification. */
+#include "simple-atomic.h"
+
+#if defined _WIN32 && ! defined __CYGWIN__
+/* Native Windows. */
+
+# include <windows.h>
+
+void
+memory_barrier (void)
+{
+ /* MemoryBarrier
+ <https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-memorybarrier> */
+ MemoryBarrier ();
+}
+
+unsigned int
+atomic_compare_and_swap (unsigned int volatile *vp,
+ unsigned int cmp,
+ unsigned int newval)
+{
+ /* InterlockedCompareExchange
+ <https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-interlockedcompareexchange> */
+ return InterlockedCompareExchange ((LONG volatile *) vp,
+ (LONG) newval, (LONG) cmp);
+}
+
+uintptr_t
+atomic_compare_and_swap_ptr (uintptr_t volatile *vp,
+ uintptr_t cmp,
+ uintptr_t newval)
+{
+ /* InterlockedCompareExchangePointer
+ <https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-interlockedcompareexchangepointer> */
+ return InterlockedCompareExchangePointer ((void * volatile *) vp,
+ (void *) newval, (void *) cmp);
+}
+
+#elif HAVE_PTHREAD_H
+/* Some other platform that supports multi-threading.
+
+ We don't use the C11 <stdatomic.h> (available in GCC >= 4.9) because it would
+ require to link with -latomic. */
+
+# if (((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) \
+ && !defined __sparc__) \
+ || __clang_major__ >= 3) \
+ && !defined __ibmxl__
+/* Use GCC built-ins (available in GCC >= 4.1, except on SPARC, and
+ clang >= 3.0).
+ Documentation:
+ <https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html> */
+
+void
+memory_barrier (void)
+{
+ __sync_synchronize ();
+}
+
+unsigned int
+atomic_compare_and_swap (unsigned int volatile *vp,
+ unsigned int cmp,
+ unsigned int newval)
+{
+ return __sync_val_compare_and_swap (vp, cmp, newval);
+}
+
+uintptr_t
+atomic_compare_and_swap_ptr (uintptr_t volatile *vp,
+ uintptr_t cmp,
+ uintptr_t newval)
+{
+ return __sync_val_compare_and_swap (vp, cmp, newval);
+}
+
+# elif defined _AIX
+/* AIX */
+/* For older versions of GCC or xlc, use inline assembly.
+ __compare_and_swap and __compare_and_swaplp are not sufficient here. */
+
+void
+memory_barrier (void)
+{
+ asm volatile ("sync");
+}
+
+unsigned int
+atomic_compare_and_swap (unsigned int volatile *vp,
+ unsigned int cmp,
+ unsigned int newval)
+{
+ asm volatile ("sync");
+
+ unsigned int oldval;
+ asm volatile (
+# if defined __GNUC__ || defined __clang__
+ "1: lwarx %0,0,%1\n"
+ " cmpw 0,%0,%2\n"
+ " bne 0,2f\n"
+ " stwcx. %3,0,%1\n"
+ " bne 0,1b\n"
+ "2:"
+# else /* another label syntax */
+ ".L01: lwarx %0,0,%1\n"
+ " cmpw 0,%0,%2\n"
+ " bne 0,.L02\n"
+ " stwcx. %3,0,%1\n"
+ " bne 0,.L01\n"
+ ".L02:"
+# endif
+ : "=&r" (oldval)
+ : "r" (vp), "r" (cmp), "r" (newval)
+ : "cr0");
+
+ asm volatile ("isync");
+ return oldval;
+}
+
+uintptr_t
+atomic_compare_and_swap_ptr (uintptr_t volatile *vp,
+ uintptr_t cmp,
+ uintptr_t newval)
+{
+ asm volatile ("sync");
+
+ uintptr_t oldval;
+ asm volatile (
+# if defined __GNUC__ || defined __clang__
+# if defined __powerpc64__ || defined __LP64__
+ "1: ldarx %0,0,%1\n"
+ " cmpd 0,%0,%2\n"
+ " bne 0,2f\n"
+ " stdcx. %3,0,%1\n"
+ " bne 0,1b\n"
+ "2:"
+# else
+ "1: lwarx %0,0,%1\n"
+ " cmpw 0,%0,%2\n"
+ " bne 0,2f\n"
+ " stwcx. %3,0,%1\n"
+ " bne 0,1b\n"
+ "2:"
+# endif
+# else /* another label syntax */
+# if defined __powerpc64__ || defined __LP64__
+ ".L01: ldarx %0,0,%1\n"
+ " cmpd 0,%0,%2\n"
+ " bne 0,.L02\n"
+ " stdcx. %3,0,%1\n"
+ " bne 0,.L01\n"
+ ".L02:"
+# else
+ ".L01: lwarx %0,0,%1\n"
+ " cmpw 0,%0,%2\n"
+ " bne 0,.L02\n"
+ " stwcx. %3,0,%1\n"
+ " bne 0,.L01\n"
+ ".L02:"
+# endif
+# endif
+ : "=&r" (oldval)
+ : "r" (vp), "r" (cmp), "r" (newval)
+ : "cr0");
+
+ asm volatile ("isync");
+ return oldval;
+}
+
+# elif ((defined __GNUC__ || defined __clang__ || defined __SUNPRO_C) && (defined __sparc || defined __i386 || defined __x86_64__)) || (defined __TINYC__ && (defined __i386 || defined __x86_64__))
+/* For older versions of GCC or clang, use inline assembly.
+ GCC, clang, and the Oracle Studio C 12 compiler understand GCC's extended
+ asm syntax, but the plain Oracle Studio C 11 compiler understands only
+ simple asm. */
+
+void
+memory_barrier (void)
+{
+# if defined __GNUC__ || defined __clang__ || __SUNPRO_C >= 0x590 || defined __TINYC__
+# if defined __i386 || defined __x86_64__
+# if defined __TINYC__ && defined __i386
+ /* Cannot use the SSE instruction "mfence" with this compiler. */
+ asm volatile ("lock orl $0,(%esp)");
+# else
+ asm volatile ("mfence");
+# endif
+# endif
+# if defined __sparc
+ asm volatile ("membar 2");
+# endif
+# else
+# if defined __i386 || defined __x86_64__
+ asm ("mfence");
+# endif
+# if defined __sparc
+ asm ("membar 2");
+# endif
+# endif
+}
+
+unsigned int
+atomic_compare_and_swap (unsigned int volatile *vp,
+ unsigned int cmp,
+ unsigned int newval)
+{
+# if defined __GNUC__ || defined __clang__ || __SUNPRO_C >= 0x590 || defined __TINYC__
+ unsigned int oldval;
+# if defined __i386 || defined __x86_64__
+ asm volatile (" lock\n cmpxchgl %3,(%1)"
+ : "=a" (oldval) : "r" (vp), "a" (cmp), "r" (newval) : "memory");
+# endif
+# if defined __sparc
+ asm volatile (" cas [%1],%2,%3\n"
+ " mov %3,%0"
+ : "=r" (oldval) : "r" (vp), "r" (cmp), "r" (newval) : "memory");
+# endif
+ return oldval;
+# else /* __SUNPRO_C */
+# if defined __x86_64__
+ asm (" movl %esi,%eax\n"
+ " lock\n cmpxchgl %edx,(%rdi)");
+# elif defined __i386
+ asm (" movl 16(%ebp),%ecx\n"
+ " movl 12(%ebp),%eax\n"
+ " movl 8(%ebp),%edx\n"
+ " lock\n cmpxchgl %ecx,(%edx)");
+# endif
+# if defined __sparc
+ asm (" cas [%i0],%i1,%i2\n"
+ " mov %i2,%i0");
+# endif
+# endif
+}
+
+uintptr_t
+atomic_compare_and_swap_ptr (uintptr_t volatile *vp,
+ uintptr_t cmp,
+ uintptr_t newval)
+{
+# if defined __GNUC__ || defined __clang__ || __SUNPRO_C >= 0x590 || defined __TINYC__
+ uintptr_t oldval;
+# if defined __x86_64__
+ asm volatile (" lock\n cmpxchgq %3,(%1)"
+ : "=a" (oldval) : "r" (vp), "a" (cmp), "r" (newval) : "memory");
+# elif defined __i386
+ asm volatile (" lock\n cmpxchgl %3,(%1)"
+ : "=a" (oldval) : "r" (vp), "a" (cmp), "r" (newval) : "memory");
+# endif
+# if defined __sparc && (defined __sparcv9 || defined __arch64__)
+ asm volatile (" casx [%1],%2,%3\n"
+ " mov %3,%0"
+ : "=r" (oldval) : "r" (vp), "r" (cmp), "r" (newval) : "memory");
+# elif defined __sparc
+ asm volatile (" cas [%1],%2,%3\n"
+ " mov %3,%0"
+ : "=r" (oldval) : "r" (vp), "r" (cmp), "r" (newval) : "memory");
+# endif
+ return oldval;
+# else /* __SUNPRO_C */
+# if defined __x86_64__
+ asm (" movl %rsi,%rax\n"
+ " lock\n cmpxchgq %rdx,(%rdi)");
+# elif defined __i386
+ asm (" movl 16(%ebp),%ecx\n"
+ " movl 12(%ebp),%eax\n"
+ " movl 8(%ebp),%edx\n"
+ " lock\n cmpxchgl %ecx,(%edx)");
+# endif
+# if defined __sparc && (defined __sparcv9 || defined __arch64__)
+ asm (" casx [%i0],%i1,%i2\n"
+ " mov %i2,%i0");
+# elif defined __sparc
+ asm (" cas [%i0],%i1,%i2\n"
+ " mov %i2,%i0");
+# endif
+# endif
+}
+
+# else
+/* Fallback code. It has some race conditions. The unit test will fail. */
+
+void
+memory_barrier (void)
+{
+}
+
+unsigned int
+atomic_compare_and_swap (unsigned int volatile *vp,
+ unsigned int cmp,
+ unsigned int newval)
+{
+ unsigned int oldval = *vp;
+ if (oldval == cmp)
+ *vp = newval;
+ return oldval;
+}
+
+uintptr_t
+atomic_compare_and_swap_ptr (uintptr_t volatile *vp,
+ uintptr_t cmp,
+ uintptr_t newval)
+{
+ uintptr_t oldval = *vp;
+ if (oldval == cmp)
+ *vp = newval;
+ return oldval;
+}
+
+# endif
+
+#else
+/* A platform that does not support multi-threading. */
+
+void
+memory_barrier (void)
+{
+}
+
+unsigned int
+atomic_compare_and_swap (unsigned int volatile *vp,
+ unsigned int cmp,
+ unsigned int newval)
+{
+ unsigned int oldval = *vp;
+ if (oldval == cmp)
+ *vp = newval;
+ return oldval;
+}
+
+uintptr_t
+atomic_compare_and_swap_ptr (uintptr_t volatile *vp,
+ uintptr_t cmp,
+ uintptr_t newval)
+{
+ uintptr_t oldval = *vp;
+ if (oldval == cmp)
+ *vp = newval;
+ return oldval;
+}
+
+#endif
diff --git a/lib/simple-atomic.h b/lib/simple-atomic.h
new file mode 100644
index 0000000..5a34e66
--- a/dev/null
+++ b/lib/simple-atomic.h
@@ -0,0 +1,49 @@
+/* Simple atomic operations for multithreading.
+ Copyright (C) 2021 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 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#ifndef _SIMPLE_ATOMIC_H
+#define _SIMPLE_ATOMIC_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Guarantees that memory stores that are in code before this call
+ are finished before this call, and that memory loads that are in code
+ after this call are started after this call. */
+extern void memory_barrier (void);
+
+/* Stores NEWVAL in *VP if the old value *VP is == CMP.
+ Returns the old value. */
+extern unsigned int atomic_compare_and_swap (unsigned int volatile *vp,
+ unsigned int cmp,
+ unsigned int newval);
+
+/* Stores NEWVAL in *VP if the old value *VP is == CMP.
+ Returns the old value. */
+extern uintptr_t atomic_compare_and_swap_ptr (uintptr_t volatile *vp,
+ uintptr_t cmp,
+ uintptr_t newval);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SIMPLE_ATOMIC_H */
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index 5d3e087..590e12c 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -42,6 +42,15 @@
# define _GL_STDDEF_WINT_T
# endif
# @INCLUDE_NEXT@ @NEXT_STDDEF_H@
+ /* On TinyCC, make sure that the macros that indicate the special invocation
+ convention get undefined. */
+# ifdef __TINYC__
+# undef __need_wchar_t
+# undef __need_size_t
+# undef __need_ptrdiff_t
+# undef __need_NULL
+# undef __need_wint_t
+# endif
# endif
#else
@@ -51,7 +60,7 @@
/* On AIX 7.2, with xlc in 64-bit mode, <stddef.h> defines max_align_t to a
type with alignment 4, but 'long' has alignment 8. */
-# if defined _AIX && defined _ARCH_PPC64
+# if defined _AIX && defined __LP64__
# if !GNULIB_defined_max_align_t
# ifdef _MAX_ALIGN_T
/* /usr/include/stddef.h has already defined max_align_t. Override it. */
@@ -109,7 +118,7 @@ typedef long max_align_t;
&& defined __cplusplus
# include <cstddef>
#else
-# if ! (@HAVE_MAX_ALIGN_T@ || defined _GCC_MAX_ALIGN_T)
+# if ! (@HAVE_MAX_ALIGN_T@ || (defined _GCC_MAX_ALIGN_T && !defined __clang__))
# if !GNULIB_defined_max_align_t
/* On the x86, the maximum storage alignment of double, long, etc. is 4,
but GCC's C11 ABI for x86 says that max_align_t has an alignment of 8,
diff --git a/lib/string-buffer.c b/lib/string-buffer.c
new file mode 100644
index 0000000..b5a4009
--- a/dev/null
+++ b/lib/string-buffer.c
@@ -0,0 +1,297 @@
+/* A buffer that accumulates a string by piecewise concatenation.
+ Copyright (C) 2021 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 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#include <config.h>
+
+/* Specification. */
+#include "string-buffer.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void
+sb_init (struct string_buffer *buffer)
+{
+ buffer->data = buffer->space;
+ buffer->length = 0;
+ buffer->allocated = sizeof (buffer->space);
+ buffer->error = false;
+}
+
+/* Ensures that INCREMENT bytes are available beyond the current used length
+ of BUFFER.
+ Returns 0, or -1 in case of out-of-memory error. */
+static int
+sb_ensure_more_bytes (struct string_buffer *buffer, size_t increment)
+{
+ size_t incremented_length = buffer->length + increment;
+ if (incremented_length < increment)
+ /* Overflow. */
+ return -1;
+
+ if (buffer->allocated < incremented_length)
+ {
+ size_t new_allocated = 2 * buffer->allocated;
+ if (new_allocated < buffer->allocated)
+ /* Overflow. */
+ return -1;
+ if (new_allocated < incremented_length)
+ new_allocated = incremented_length;
+
+ char *new_data;
+ if (buffer->data == buffer->space)
+ {
+ new_data = (char *) malloc (new_allocated);
+ if (new_data == NULL)
+ /* Out-of-memory. */
+ return -1;
+ memcpy (new_data, buffer->data, buffer->length);
+ }
+ else
+ {
+ new_data = (char *) realloc (buffer->data, new_allocated);
+ if (new_data == NULL)
+ /* Out-of-memory. */
+ return -1;
+ }
+ buffer->data = new_data;
+ buffer->allocated = new_allocated;
+ }
+ return 0;
+}
+
+int
+sb_append (struct string_buffer *buffer, const char *str)
+{
+ size_t len = strlen (str);
+ if (sb_ensure_more_bytes (buffer, len) < 0)
+ {
+ buffer->error = true;
+ return -1;
+ }
+ memcpy (buffer->data + buffer->length, str, len);
+ buffer->length += len;
+ return 0;
+}
+
+int
+sb_appendvf (struct string_buffer *buffer, const char *formatstring,
+ va_list list)
+{
+ va_list list_copy;
+
+ /* Make a bit of room, so that the probability that the first vsnprintf() call
+ succeeds is high. */
+ size_t room = buffer->allocated - buffer->length;
+ if (room < 64)
+ {
+ if (sb_ensure_more_bytes (buffer, 64) < 0)
+ {
+ buffer->error = true;
+ return -1;
+ }
+ room = buffer->allocated - buffer->length;
+ }
+
+ va_copy (list_copy, list);
+
+ /* First vsnprintf() call. */
+ int ret = vsnprintf (buffer->data + buffer->length, room, formatstring, list);
+ if (ret < 0)
+ {
+ /* Failed. */
+ buffer->error = true;
+ ret = -1;
+ }
+ else
+ {
+ if ((size_t) ret <= room)
+ {
+ /* The result has fit into room bytes. */
+ buffer->length += (size_t) ret;
+ ret = 0;
+ }
+ else
+ {
+ /* The result was truncated. Make more room, for a second vsnprintf()
+ call. */
+ if (sb_ensure_more_bytes (buffer, (size_t) ret) < 0)
+ {
+ buffer->error = true;
+ ret = -1;
+ }
+ else
+ {
+ /* Second vsnprintf() call. */
+ room = buffer->allocated - buffer->length;
+ ret = vsnprintf (buffer->data + buffer->length, room,
+ formatstring, list_copy);
+ if (ret < 0)
+ {
+ /* Failed. */
+ buffer->error = true;
+ ret = -1;
+ }
+ else
+ {
+ if ((size_t) ret <= room)
+ {
+ /* The result has fit into room bytes. */
+ buffer->length += (size_t) ret;
+ ret = 0;
+ }
+ else
+ /* The return values of the vsnprintf() calls are not
+ consistent. */
+ abort ();
+ }
+ }
+ }
+ }
+
+ va_end (list_copy);
+ return ret;
+}
+
+int
+sb_appendf (struct string_buffer *buffer, const char *formatstring, ...)
+{
+ va_list args;
+
+ /* Make a bit of room, so that the probability that the first vsnprintf() call
+ succeeds is high. */
+ size_t room = buffer->allocated - buffer->length;
+ if (room < 64)
+ {
+ if (sb_ensure_more_bytes (buffer, 64) < 0)
+ {
+ buffer->error = true;
+ return -1;
+ }
+ room = buffer->allocated - buffer->length;
+ }
+
+ va_start (args, formatstring);
+
+ /* First vsnprintf() call. */
+ int ret = vsnprintf (buffer->data + buffer->length, room, formatstring, args);
+ if (ret < 0)
+ {
+ /* Failed. */
+ buffer->error = true;
+ ret = -1;
+ }
+ else
+ {
+ if ((size_t) ret <= room)
+ {
+ /* The result has fit into room bytes. */
+ buffer->length += (size_t) ret;
+ ret = 0;
+ }
+ else
+ {
+ /* The result was truncated. Make more room, for a second vsnprintf()
+ call. */
+ if (sb_ensure_more_bytes (buffer, (size_t) ret) < 0)
+ {
+ buffer->error = true;
+ ret = -1;
+ }
+ else
+ {
+ /* Second vsnprintf() call. */
+ room = buffer->allocated - buffer->length;
+ va_end (args);
+ va_start (args, formatstring);
+ ret = vsnprintf (buffer->data + buffer->length, room,
+ formatstring, args);
+ if (ret < 0)
+ {
+ /* Failed. */
+ buffer->error = true;
+ ret = -1;
+ }
+ else
+ {
+ if ((size_t) ret <= room)
+ {
+ /* The result has fit into room bytes. */
+ buffer->length += (size_t) ret;
+ ret = 0;
+ }
+ else
+ /* The return values of the vsnprintf() calls are not
+ consistent. */
+ abort ();
+ }
+ }
+ }
+ }
+
+ va_end (args);
+ return ret;
+}
+
+void
+sb_free (struct string_buffer *buffer)
+{
+ if (buffer->data != buffer->space)
+ free (buffer->data);
+}
+
+/* Returns the contents of BUFFER, and frees all other memory held
+ by BUFFER. Returns NULL upon failure or if there was an error earlier. */
+char *
+sb_dupfree (struct string_buffer *buffer)
+{
+ if (buffer->error)
+ goto fail;
+
+ if (sb_ensure_more_bytes (buffer, 1) < 0)
+ goto fail;
+ buffer->data[buffer->length] = '\0';
+ buffer->length++;
+
+ if (buffer->data == buffer->space)
+ {
+ char *copy = (char *) malloc (buffer->length);
+ if (copy == NULL)
+ goto fail;
+ memcpy (copy, buffer->data, buffer->length);
+ return copy;
+ }
+ else
+ {
+ /* Shrink the string before returning it. */
+ char *contents = buffer->data;
+ if (buffer->length < buffer->allocated)
+ {
+ contents = realloc (contents, buffer->length);
+ if (contents == NULL)
+ goto fail;
+ }
+ return contents;
+ }
+
+ fail:
+ sb_free (buffer);
+ return NULL;
+}
diff --git a/lib/string-buffer.h b/lib/string-buffer.h
new file mode 100644
index 0000000..6beaff5
--- a/dev/null
+++ b/lib/string-buffer.h
@@ -0,0 +1,85 @@
+/* A buffer that accumulates a string by piecewise concatenation.
+ Copyright (C) 2021 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 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#ifndef _STRING_BUFFER_H
+#define _STRING_BUFFER_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "attribute.h"
+
+/* A string buffer type. */
+struct string_buffer
+{
+ char *data;
+ size_t length; /* used bytes, <= allocated */
+ size_t allocated; /* allocated bytes */
+ bool error; /* true if there was an error */
+ char space[1024]; /* stack allocated space */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initializes BUFFER to the empty string. */
+extern void sb_init (struct string_buffer *buffer);
+
+/* Appends the contents of STR to BUFFER.
+ Returns 0, or -1 in case of out-of-memory error. */
+extern int sb_append (struct string_buffer *buffer, const char *str);
+
+/* Appends the result of the printf-compatible FORMATSTRING with the argument
+ list LIST to BUFFER.
+ Returns 0, or -1 in case of error. */
+extern int sb_appendvf (struct string_buffer *buffer,
+ const char *formatstring, va_list list)
+ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+ ATTRIBUTE_FORMAT ((__gnu_printf__, 2, 0))
+ #else
+ ATTRIBUTE_FORMAT ((__printf__, 2, 0))
+ #endif
+ ;
+
+/* Appends the result of the printf-compatible FORMATSTRING with the following
+ arguments to BUFFER.
+ Returns 0, or -1 in case of error. */
+extern int sb_appendf (struct string_buffer *buffer,
+ const char *formatstring, ...)
+ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+ ATTRIBUTE_FORMAT ((__gnu_printf__, 2, 3))
+ #else
+ ATTRIBUTE_FORMAT ((__printf__, 2, 3))
+ #endif
+ ;
+
+/* Frees the memory held by BUFFER. */
+extern void sb_free (struct string_buffer *buffer);
+
+/* Returns the contents of BUFFER, and frees all other memory held
+ by BUFFER. Returns NULL upon failure or if there was an error earlier.
+ It is the responsibility of the caller to free() the result. */
+extern char * sb_dupfree (struct string_buffer *buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STRING_BUFFER_H */
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
index 86b91c1..ca184b3 100644
--- a/lib/unlocked-io.h
+++ b/lib/unlocked-io.h
@@ -33,91 +33,91 @@
# include <stdio.h>
-# if HAVE_DECL_CLEARERR_UNLOCKED
+# if HAVE_DECL_CLEARERR_UNLOCKED || defined clearerr_unlocked
# undef clearerr
# define clearerr(x) clearerr_unlocked (x)
# else
# define clearerr_unlocked(x) clearerr (x)
# endif
-# if HAVE_DECL_FEOF_UNLOCKED
+# if HAVE_DECL_FEOF_UNLOCKED || defined feof_unlocked
# undef feof
# define feof(x) feof_unlocked (x)
# else
# define feof_unlocked(x) feof (x)
# endif
-# if HAVE_DECL_FERROR_UNLOCKED
+# if HAVE_DECL_FERROR_UNLOCKED || defined ferror_unlocked
# undef ferror
# define ferror(x) ferror_unlocked (x)
# else
# define ferror_unlocked(x) ferror (x)
# endif
-# if HAVE_DECL_FFLUSH_UNLOCKED
+# if HAVE_DECL_FFLUSH_UNLOCKED || defined fflush_unlocked
# undef fflush
# define fflush(x) fflush_unlocked (x)
# else
# define fflush_unlocked(x) fflush (x)
# endif
-# if HAVE_DECL_FGETS_UNLOCKED
+# if HAVE_DECL_FGETS_UNLOCKED || defined fgets_unlocked
# undef fgets
# define fgets(x,y,z) fgets_unlocked (x,y,z)
# else
# define fgets_unlocked(x,y,z) fgets (x,y,z)
# endif
-# if HAVE_DECL_FPUTC_UNLOCKED
+# if HAVE_DECL_FPUTC_UNLOCKED || defined fputc_unlocked
# undef fputc
# define fputc(x,y) fputc_unlocked (x,y)
# else
# define fputc_unlocked(x,y) fputc (x,y)
# endif
-# if HAVE_DECL_FPUTS_UNLOCKED
+# if HAVE_DECL_FPUTS_UNLOCKED || defined fputs_unlocked
# undef fputs
# define fputs(x,y) fputs_unlocked (x,y)
# else
# define fputs_unlocked(x,y) fputs (x,y)
# endif
-# if HAVE_DECL_FREAD_UNLOCKED
+# if HAVE_DECL_FREAD_UNLOCKED || defined fread_unlocked
# undef fread
# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
# else
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
# endif
-# if HAVE_DECL_FWRITE_UNLOCKED
+# if HAVE_DECL_FWRITE_UNLOCKED || defined fwrite_unlocked
# undef fwrite
# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
# else
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
# endif
-# if HAVE_DECL_GETC_UNLOCKED
+# if HAVE_DECL_GETC_UNLOCKED || defined get_unlocked
# undef getc
# define getc(x) getc_unlocked (x)
# else
# define getc_unlocked(x) getc (x)
# endif
-# if HAVE_DECL_GETCHAR_UNLOCKED
+# if HAVE_DECL_GETCHAR_UNLOCKED || defined getchar_unlocked
# undef getchar
# define getchar() getchar_unlocked ()
# else
# define getchar_unlocked() getchar ()
# endif
-# if HAVE_DECL_PUTC_UNLOCKED
+# if HAVE_DECL_PUTC_UNLOCKED || defined putc_unlocked
# undef putc
# define putc(x,y) putc_unlocked (x,y)
# else
# define putc_unlocked(x,y) putc (x,y)
# endif
-# if HAVE_DECL_PUTCHAR_UNLOCKED
+# if HAVE_DECL_PUTCHAR_UNLOCKED || defined putchar_unlocked
# undef putchar
# define putchar(x) putchar_unlocked (x)
# else
diff --git a/m4/c-stack.m4 b/m4/c-stack.m4
index e7413a2..df8dc52 100644
--- a/m4/c-stack.m4
+++ b/m4/c-stack.m4
@@ -7,7 +7,7 @@
# Written by Paul Eggert.
-# serial 20
+# serial 21
AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
[
@@ -19,7 +19,7 @@ AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
dnl is accessed, or when the stack overflows.
dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }.
case "$host_os" in
- sunos4* | freebsd* | dragonfly* | openbsd* | mirbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
+ sunos4* | freebsd* | dragonfly* | midnightbsd* | openbsd* | mirbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
FAULT_YIELDS_SIGBUS=1 ;;
hpux*) # HP-UX
FAULT_YIELDS_SIGBUS=1 ;;
diff --git a/m4/expl.m4 b/m4/expl.m4
index 0ed62ab..9e7bfa7 100644
--- a/m4/expl.m4
+++ b/m4/expl.m4
@@ -1,4 +1,4 @@
-# expl.m4 serial 17
+# expl.m4 serial 18
dnl Copyright (C) 2010-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -129,7 +129,7 @@ int main (int argc, char *argv[])
if (isnan (expl (x1)) || isnan (expl (x2)) || isnan (expl (x3)))
result |= 2;
}
- /* This test fails on NetBSD 9.0. */
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x, NetBSD 9.0. */
{
const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
(long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
@@ -150,8 +150,8 @@ int main (int argc, char *argv[])
[case "$host_os" in
# Guess yes on glibc systems.
*-gnu* | gnu*) gl_cv_func_expl_works="guessing yes" ;;
- # Guess yes on musl systems.
- *-musl*) gl_cv_func_expl_works="guessing yes" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_expl_works="guessing no" ;;
# Guess yes on native Windows.
mingw*) gl_cv_func_expl_works="guessing yes" ;;
# If we don't know, obey --enable-cross-guesses.
diff --git a/m4/expm1l.m4 b/m4/expm1l.m4
index 0eaaf84..ec0d907 100644
--- a/m4/expm1l.m4
+++ b/m4/expm1l.m4
@@ -1,4 +1,4 @@
-# expm1l.m4 serial 7
+# expm1l.m4 serial 9
dnl Copyright (C) 2010-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -123,7 +123,8 @@ int main (int argc, char *argv[])
{
long double (* volatile my_expm1l) (long double) = argc ? expm1l : dummy;
int result = 0;
- /* This test fails on Mac OS X 10.5, NetBSD 8.0. */
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x, Mac OS X 10.5,
+ NetBSD 8.0. */
{
const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
(long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
@@ -134,7 +135,8 @@ int main (int argc, char *argv[])
long double x = 11.358L;
long double y = my_expm1l (x);
long double z = my_expm1l (- x);
- long double err = (y + (1.0L + y) * z) * TWO_LDBL_MANT_DIG;
+ volatile long double t = (1.0L + y) * z;
+ long double err = (y + t) * TWO_LDBL_MANT_DIG;
if (!(err >= -100.0L && err <= 100.0L))
result |= 1;
}
@@ -146,8 +148,8 @@ int main (int argc, char *argv[])
[case "$host_os" in
# Guess yes on glibc systems.
*-gnu* | gnu*) gl_cv_func_expm1l_works="guessing yes" ;;
- # Guess yes on musl systems.
- *-musl*) gl_cv_func_expm1l_works="guessing yes" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_expm1l_works="guessing no" ;;
# Guess yes on native Windows.
mingw*) gl_cv_func_expm1l_works="guessing yes" ;;
# If we don't know, obey --enable-cross-guesses.
diff --git a/m4/free.m4 b/m4/free.m4
index d671376..a7923b9 100644
--- a/m4/free.m4
+++ b/m4/free.m4
@@ -1,4 +1,4 @@
-# free.m4 serial 5
+# free.m4 serial 6
# Copyright (C) 2003-2005, 2009-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -40,7 +40,10 @@ AC_DEFUN([gl_FUNC_FREE],
])
case $gl_cv_func_free_preserves_errno in
- *yes) ;;
+ *yes)
+ AC_DEFINE([HAVE_FREE_POSIX], [1],
+ [Define if the 'free' function is guaranteed to preserve errno.])
+ ;;
*) REPLACE_FREE=1 ;;
esac
])
diff --git a/m4/getcwd-abort-bug.m4 b/m4/getcwd-abort-bug.m4
index 89d0689..bd32de1 100644
--- a/m4/getcwd-abort-bug.m4
+++ b/m4/getcwd-abort-bug.m4
@@ -1,4 +1,4 @@
-# serial 15
+# serial 16
# Determine whether getcwd aborts when the length of the working directory
# name is unusually large. Any length between 4k and 16k trigger the bug
# when using glibc-2.4.90-9 or older.
@@ -128,11 +128,12 @@ main ()
]])],
[gl_cv_func_getcwd_succeeds_beyond_4k=yes],
[dnl An abort will provoke an exit code of something like 134 (128 + 6).
- dnl An exit code of 4 can also occur (in OpenBSD 6.7, NetBSD 5.1 for
- dnl example): getcwd (NULL, 0) fails rather than returning a string
- dnl longer than PATH_MAX. This may be POSIX compliant (in some
- dnl interpretations of POSIX). But gnulib's getcwd module wants to
- dnl provide a non-NULL value in this case.
+ dnl An exit code of 4 can also occur (for example in
+ dnl musl libc 1.2.2/powerpc64le, NetBSD 9.0, OpenBSD 6.7:
+ dnl getcwd (NULL, 0) fails rather than returning a string longer than
+ dnl PATH_MAX. This may be POSIX compliant (in some interpretations of
+ dnl POSIX). But gnulib's getcwd module wants to provide a non-NULL
+ dnl value in this case.
ret=$?
if test $ret -ge 128 || test $ret = 4; then
gl_cv_func_getcwd_succeeds_beyond_4k=no
@@ -141,10 +142,8 @@ main ()
fi
],
[case "$host_os" in
- # Guess yes on musl systems.
- *-musl*) gl_cv_func_getcwd_succeeds_beyond_4k="guessing yes" ;;
- # Guess no otherwise, even on glibc systems.
- *) gl_cv_func_getcwd_succeeds_beyond_4k="guessing no"
+ # Guess no otherwise, even on glibc systems and musl systems.
+ *) gl_cv_func_getcwd_succeeds_beyond_4k="guessing no"
esac
])
])
diff --git a/m4/host-cpu-c-abi.m4 b/m4/host-cpu-c-abi.m4
index 7dc830e..64e28b1 100644
--- a/m4/host-cpu-c-abi.m4
+++ b/m4/host-cpu-c-abi.m4
@@ -1,4 +1,4 @@
-# host-cpu-c-abi.m4 serial 13
+# host-cpu-c-abi.m4 serial 14
dnl Copyright (C) 2002-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -211,7 +211,7 @@ changequote([,])dnl
# be generating 64-bit code.
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE(
- [[#if defined __powerpc64__ || defined _ARCH_PPC64
+ [[#if defined __powerpc64__ || defined __LP64__
int ok;
#else
error fail
@@ -605,7 +605,7 @@ changequote([,])dnl
# be generating 64-bit code.
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE(
- [[#if defined __powerpc64__ || defined _ARCH_PPC64
+ [[#if defined __powerpc64__ || defined __LP64__
int ok;
#else
error fail
diff --git a/m4/host-os.m4 b/m4/host-os.m4
index 543473c..813133b 100644
--- a/m4/host-os.m4
+++ b/m4/host-os.m4
@@ -1,4 +1,4 @@
-# serial 10
+# serial 11
# Copyright (C) 2001, 2003-2004, 2006, 2009-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
@@ -41,6 +41,7 @@ AC_DEFUN([gl_HOST_OS],
netbsd*-gnu*) os='GNU/NetBSD';; # NetBSD kernel+libc, GNU userland
netbsd*) os='NetBSD';;
mirbsd*) os='MirBSD';;
+ midnightbsd*) os='MidnightBSD';;
knetbsd*-gnu) os='GNU/kNetBSD';; # NetBSD kernel, GNU libc+userland
kfreebsd*-gnu) os='GNU/kFreeBSD';; # FreeBSD kernel, GNU libc+userland
msdosdjgpp*) os='DJGPP';;
diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4
index aa07cb4..076358d 100644
--- a/m4/lib-ld.m4
+++ b/m4/lib-ld.m4
@@ -1,4 +1,4 @@
-# lib-ld.m4 serial 9
+# lib-ld.m4 serial 10
dnl Copyright (C) 1996-2003, 2009-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -122,7 +122,7 @@ else
*-*-aix*)
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE(
- [[#if defined __powerpc64__ || defined _ARCH_PPC64
+ [[#if defined __powerpc64__ || defined __LP64__
int ok;
#else
error fail
diff --git a/m4/log10l.m4 b/m4/log10l.m4
index c594f6b..57aa1ba 100644
--- a/m4/log10l.m4
+++ b/m4/log10l.m4
@@ -1,4 +1,4 @@
-# log10l.m4 serial 9
+# log10l.m4 serial 10
dnl Copyright (C) 2011-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -126,7 +126,7 @@ int main (int argc, char *argv[])
if (!(gy + gy == gy))
result |= 1;
}
- /* This test fails on NetBSD 9.0. */
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x, NetBSD 9.0. */
{
const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
(long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
@@ -147,8 +147,8 @@ int main (int argc, char *argv[])
[case "$host_os" in
# Guess yes on glibc systems.
*-gnu* | gnu*) gl_cv_func_log10l_works="guessing yes" ;;
- # Guess yes on musl systems.
- *-musl*) gl_cv_func_log10l_works="guessing yes" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_log10l_works="guessing no" ;;
# Guess yes on native Windows.
mingw*) gl_cv_func_log10l_works="guessing yes" ;;
# If we don't know, obey --enable-cross-guesses.
diff --git a/m4/log1pl.m4 b/m4/log1pl.m4
index 7d95aac..bd9d63d 100644
--- a/m4/log1pl.m4
+++ b/m4/log1pl.m4
@@ -1,4 +1,4 @@
-# log1pl.m4 serial 8
+# log1pl.m4 serial 9
dnl Copyright (C) 2012-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -22,6 +22,16 @@ AC_DEFUN([gl_FUNC_LOG1PL],
LIBS="$save_LIBS"
if test $ac_cv_func_log1pl = yes; then
LOG1PL_LIBM="$LOG1P_LIBM"
+
+ save_LIBS="$LIBS"
+ LIBS="$LIBS $LOG1PL_LIBM"
+ gl_FUNC_LOG1PL_WORKS
+ LIBS="$save_LIBS"
+ case "$gl_cv_func_log1pl_works" in
+ *yes) ;;
+ *) REPLACE_LOG1PL=1 ;;
+ esac
+
m4_ifdef([gl_FUNC_LOG1PL_IEEE], [
if test $gl_log1pl_required = ieee && test $REPLACE_LOG1PL = 0; then
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
@@ -99,3 +109,93 @@ int main (int argc, char *argv[])
fi
AC_SUBST([LOG1PL_LIBM])
])
+
+dnl Test whether log1pl() works.
+dnl On musl 1.2.2/{arm64,s390x}, the result is accurate to only 16 digits.
+AC_DEFUN([gl_FUNC_LOG1PL_WORKS],
+[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_CACHE_CHECK([whether log1pl works], [gl_cv_func_log1pl_works],
+ [
+ AC_RUN_IFELSE(
+ [AC_LANG_SOURCE([[
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES 1 /* for glibc */
+#endif
+#include <float.h>
+#include <math.h>
+/* Override the values of <float.h>, like done in float.in.h. */
+#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP 16384
+#endif
+#if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP 16384
+#endif
+#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+#endif
+#if defined __sgi && (LDBL_MANT_DIG >= 106)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 106
+# if defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+# endif
+#endif
+#undef log1pl
+extern
+#ifdef __cplusplus
+"C"
+#endif
+long double log1pl (long double);
+static long double dummy (long double x) { return 0; }
+int main (int argc, char *argv[])
+{
+ long double (* volatile my_log1pl) (long double) = argc ? log1pl : dummy;
+ int result = 0;
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x. */
+ {
+ const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
+ (long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 1) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 2) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 3) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 4) / 5));
+ long double x = 11.358L;
+ long double y = my_log1pl (x);
+ long double z = my_log1pl (- x / (1.0L + x));
+ long double err = (y + z) * TWO_LDBL_MANT_DIG;
+ if (!(err >= -900.0L && err <= 900.0L))
+ result |= 1;
+ }
+
+ return result;
+}
+]])],
+ [gl_cv_func_log1pl_works=yes],
+ [gl_cv_func_log1pl_works=no],
+ [case "$host_os" in
+ # Guess yes on glibc systems.
+ *-gnu* | gnu*) gl_cv_func_log1pl_works="guessing yes" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_log1pl_works="guessing no" ;;
+ # Guess yes on native Windows.
+ mingw*) gl_cv_func_log1pl_works="guessing yes" ;;
+ # If we don't know, obey --enable-cross-guesses.
+ *) gl_cv_func_log1pl_works="$gl_cross_guess_normal" ;;
+ esac
+ ])
+ ])
+])
diff --git a/m4/log2l.m4 b/m4/log2l.m4
index 4776543..cd8e984 100644
--- a/m4/log2l.m4
+++ b/m4/log2l.m4
@@ -1,4 +1,4 @@
-# log2l.m4 serial 2
+# log2l.m4 serial 3
dnl Copyright (C) 2010-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -69,6 +69,7 @@ AC_DEFUN([gl_FUNC_LOG2L],
dnl Test whether log2l() works.
dnl On OSF/1 5.1, log2l(-0.0) is NaN.
+dnl On musl 1.2.2/{arm64,s390x}, the result is accurate to only 16 digits.
AC_DEFUN([gl_FUNC_LOG2L_WORKS],
[
AC_REQUIRE([AC_PROG_CC])
@@ -77,7 +78,40 @@ AC_DEFUN([gl_FUNC_LOG2L_WORKS],
[
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES 1 /* for glibc */
+#endif
+#include <float.h>
#include <math.h>
+/* Override the values of <float.h>, like done in float.in.h. */
+#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP 16384
+#endif
+#if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP 16384
+#endif
+#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+#endif
+#if defined __sgi && (LDBL_MANT_DIG >= 106)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 106
+# if defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+# endif
+#endif
#ifndef log2l /* for AIX */
extern
#ifdef __cplusplus
@@ -85,25 +119,59 @@ extern
#endif
long double log2l (long double);
#endif
-volatile long double x;
-volatile long double y;
-int main ()
+static long double dummy (long double x) { return 0; }
+volatile long double gx;
+volatile long double gy;
+int main (int argc, char *argv[])
{
+ long double (* volatile my_log2l) (long double) = argc ? log2l : dummy;
+ int result = 0;
/* This test fails on OSF/1 5.1. */
- x = -0.0L;
- y = log2l (x);
- if (!(y + y == y))
- return 1;
- return 0;
+ {
+ gx = -0.0L;
+ gy = my_log2l (gx);
+ if (!(gy + gy == gy))
+ result |= 1;
+ }
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x. */
+ {
+ const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
+ (long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 1) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 2) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 3) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 4) / 5));
+ long double x = 11.358L;
+ long double y = my_log2l (x);
+ long double z = my_log2l (1.0L / x);
+ long double err = (y + z) * TWO_LDBL_MANT_DIG;
+ if (!(err >= -10000.0L && err <= 10000.0L))
+ result |= 2;
+ }
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x. */
+ if (DBL_MAX_EXP < LDBL_MAX_EXP)
+ {
+ long double x = ldexpl (1.0L, DBL_MAX_EXP); /* finite! */
+ long double y = my_log2l (x);
+ if (y > 0 && y + y == y) /* infinite? */
+ result |= 4;
+ }
+ return result;
}
]])],
[gl_cv_func_log2l_works=yes],
[gl_cv_func_log2l_works=no],
[case "$host_os" in
- osf*) gl_cv_func_log2l_works="guessing no" ;;
- # Guess yes on native Windows.
- mingw*) gl_cv_func_log2l_works="guessing yes" ;;
- *) gl_cv_func_log2l_works="guessing yes" ;;
+ # Guess yes on glibc systems.
+ *-gnu* | gnu*) gl_cv_func_log2l_works="guessing yes" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_log2l_works="guessing no" ;;
+ # Guess no on OSF/1.
+ osf*) gl_cv_func_log2l_works="guessing no" ;;
+ # Guess yes on native Windows.
+ mingw*) gl_cv_func_log2l_works="guessing yes" ;;
+ # If we don't know, obey --enable-cross-guesses.
+ *) gl_cv_func_log2l_works="$gl_cross_guess_normal" ;;
esac
])
])
diff --git a/m4/logl.m4 b/m4/logl.m4
index 128170a..7dcdac1 100644
--- a/m4/logl.m4
+++ b/m4/logl.m4
@@ -1,4 +1,4 @@
-# logl.m4 serial 14
+# logl.m4 serial 15
dnl Copyright (C) 2010-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -166,7 +166,7 @@ int main (int argc, char *argv[])
if (!(gy + gy == gy))
result |= 1;
}
- /* This test fails on NetBSD 9.0. */
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x, NetBSD 9.0. */
{
const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
(long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
@@ -188,8 +188,8 @@ int main (int argc, char *argv[])
[case "$host_os" in
# Guess yes on glibc systems.
*-gnu* | gnu*) gl_cv_func_logl_works="guessing yes" ;;
- # Guess yes on musl systems.
- *-musl*) gl_cv_func_logl_works="guessing yes" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_logl_works="guessing no" ;;
# Guess yes on native Windows.
mingw*) gl_cv_func_logl_works="guessing yes" ;;
# If we don't know, obey --enable-cross-guesses.
diff --git a/m4/malloc.m4 b/m4/malloc.m4
index 514d19a..32ab42e 100644
--- a/m4/malloc.m4
+++ b/m4/malloc.m4
@@ -1,4 +1,4 @@
-# malloc.m4 serial 21
+# malloc.m4 serial 22
dnl Copyright (C) 2007, 2009-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -24,7 +24,7 @@ AC_DEFUN([_AC_FUNC_MALLOC_IF],
[ac_cv_func_malloc_0_nonnull=no],
[case "$host_os" in
# Guess yes on platforms where we know the result.
- *-gnu* | gnu* | *-musl* | freebsd* | netbsd* | openbsd* \
+ *-gnu* | gnu* | *-musl* | freebsd* | midnightbsd* | netbsd* | openbsd* \
| hpux* | solaris* | cygwin* | mingw*)
ac_cv_func_malloc_0_nonnull="guessing yes" ;;
# If we don't know, obey --enable-cross-guesses.
diff --git a/m4/mbrtoc32.m4 b/m4/mbrtoc32.m4
index 56f09c6..ba0397b 100644
--- a/m4/mbrtoc32.m4
+++ b/m4/mbrtoc32.m4
@@ -1,4 +1,4 @@
-# mbrtoc32.m4 serial 6
+# mbrtoc32.m4 serial 7
dnl Copyright (C) 2014-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -158,7 +158,7 @@ AC_DEFUN([gl_MBRTOC32_SANITYCHECK],
changequote(,)dnl
case "$host_os" in
# Guess no on FreeBSD, Solaris, native Windows.
- freebsd* | solaris* | mingw*)
+ freebsd* | midnightbsd* | solaris* | mingw*)
gl_cv_func_mbrtoc32_sanitycheck="guessing no"
;;
# Guess yes otherwise.
diff --git a/m4/mprotect.m4 b/m4/mprotect.m4
index 13e27e2..9a0bdf9 100644
--- a/m4/mprotect.m4
+++ b/m4/mprotect.m4
@@ -1,4 +1,4 @@
-# mprotect.m4 serial 1
+# mprotect.m4 serial 2
dnl Copyright (C) 1993-2021 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License as published by the Free Software Foundation;
@@ -141,7 +141,7 @@ AC_DEFUN([gl_FUNC_MPROTECT_WORKS],
dnl Guess yes on Linux systems, glibc systems,
dnl macOS, BSD systems, AIX, HP-UX, IRIX, Solaris, Cygwin.
linux-* | linux | *-gnu* | gnu* | \
- darwin* | freebsd* | dragonfly* | netbsd* | openbsd* | \
+ darwin* | freebsd* | dragonfly* | midnightbsd* | netbsd* | openbsd* | \
aix* | hpux* | irix* | solaris* | cygwin*)
gl_cv_func_mprotect_works="guessing yes" ;;
mingw*)
diff --git a/m4/posix_spawn.m4 b/m4/posix_spawn.m4
index 787336d..84b7a13 100644
--- a/m4/posix_spawn.m4
+++ b/m4/posix_spawn.m4
@@ -1,4 +1,4 @@
-# posix_spawn.m4 serial 19
+# posix_spawn.m4 serial 21
dnl Copyright (C) 2008-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -525,7 +525,8 @@ AC_DEFUN([gl_POSIX_SPAWN_SECURE],
*-gnu* | *-musl* | netbsd*)
gl_cv_func_posix_spawnp_secure_exec="guessing yes" ;;
# Guess no on GNU/Hurd, macOS, FreeBSD, OpenBSD, AIX, Solaris, Cygwin.
- gnu* | darwin* | freebsd* | dragonfly* | openbsd* | aix* | solaris* | cygwin*)
+ gnu* | darwin* | freebsd* | dragonfly* | midnightbsd* | openbsd* | \
+ aix* | solaris* | cygwin*)
gl_cv_func_posix_spawnp_secure_exec="guessing no" ;;
# If we don't know, obey --enable-cross-guesses.
*)
@@ -552,8 +553,8 @@ AC_DEFUN([gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE],
if test $REPLACE_POSIX_SPAWN = 1; then
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE=1
else
- dnl On musl libc and Solaris 11.0, posix_spawn_file_actions_addclose
- dnl succeeds even if the fd argument is out of range.
+ dnl On musl libc, posix_spawn_file_actions_addclose succeeds even if the fd
+ dnl argument is negative.
AC_CACHE_CHECK([whether posix_spawn_file_actions_addclose works],
[gl_cv_func_posix_spawn_file_actions_addclose_works],
[AC_RUN_IFELSE(
@@ -564,7 +565,7 @@ int main ()
posix_spawn_file_actions_t actions;
if (posix_spawn_file_actions_init (&actions) != 0)
return 1;
- if (posix_spawn_file_actions_addclose (&actions, 10000000) == 0)
+ if (posix_spawn_file_actions_addclose (&actions, -5) == 0)
return 2;
return 0;
}]])],
diff --git a/m4/printf.m4 b/m4/printf.m4
index c8e74e2..d8b3521 100644
--- a/m4/printf.m4
+++ b/m4/printf.m4
@@ -1,4 +1,4 @@
-# printf.m4 serial 71
+# printf.m4 serial 72
dnl Copyright (C) 2003, 2007-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -67,6 +67,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 5.
freebsd[1-4].*) gl_cv_func_printf_sizes_c99="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_printf_sizes_c99="guessing yes";;
+ midnightbsd*) gl_cv_func_printf_sizes_c99="guessing yes";;
# Guess yes on Mac OS X >= 10.3.
darwin[1-6].*) gl_cv_func_printf_sizes_c99="guessing no";;
darwin*) gl_cv_func_printf_sizes_c99="guessing yes";;
@@ -247,6 +248,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 6.
freebsd[1-5].*) gl_cv_func_printf_infinite="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_printf_infinite="guessing yes";;
+ midnightbsd*) gl_cv_func_printf_infinite="guessing yes";;
# Guess yes on Mac OS X >= 10.3.
darwin[1-6].*) gl_cv_func_printf_infinite="guessing no";;
darwin*) gl_cv_func_printf_infinite="guessing yes";;
@@ -469,6 +471,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 6.
freebsd[1-5].*) gl_cv_func_printf_infinite_long_double="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_printf_infinite_long_double="guessing yes";;
+ midnightbsd*) gl_cv_func_printf_infinite_long_double="guessing yes";;
# Guess yes on HP-UX >= 11.
hpux[7-9]* | hpux10*) gl_cv_func_printf_infinite_long_double="guessing no";;
hpux*) gl_cv_func_printf_infinite_long_double="guessing yes";;
@@ -644,6 +647,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 6.
freebsd[1-5].*) gl_cv_func_printf_directive_f="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_printf_directive_f="guessing yes";;
+ midnightbsd*) gl_cv_func_printf_directive_f="guessing yes";;
# Guess yes on Mac OS X >= 10.3.
darwin[1-6].*) gl_cv_func_printf_directive_f="guessing no";;
darwin*) gl_cv_func_printf_directive_f="guessing yes";;
@@ -1239,6 +1243,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 5.
freebsd[1-4].*) gl_cv_func_snprintf_truncation_c99="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_snprintf_truncation_c99="guessing yes";;
+ midnightbsd*) gl_cv_func_snprintf_truncation_c99="guessing yes";;
# Guess yes on Mac OS X >= 10.3.
darwin[1-6].*) gl_cv_func_snprintf_truncation_c99="guessing no";;
darwin*) gl_cv_func_snprintf_truncation_c99="guessing yes";;
@@ -1343,6 +1348,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 5.
freebsd[1-4].*) gl_cv_func_snprintf_retval_c99="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_snprintf_retval_c99="guessing yes";;
+ midnightbsd*) gl_cv_func_snprintf_retval_c99="guessing yes";;
# Guess yes on Mac OS X >= 10.3.
darwin[1-6].*) gl_cv_func_snprintf_retval_c99="guessing no";;
darwin*) gl_cv_func_snprintf_retval_c99="guessing yes";;
@@ -1445,6 +1451,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 5.
freebsd[1-4].*) gl_cv_func_snprintf_directive_n="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_snprintf_directive_n="guessing yes";;
+ midnightbsd*) gl_cv_func_snprintf_directive_n="guessing yes";;
# Guess yes on Mac OS X >= 10.3.
darwin[1-6].*) gl_cv_func_snprintf_directive_n="guessing no";;
darwin*) gl_cv_func_snprintf_directive_n="guessing yes";;
@@ -1601,6 +1608,7 @@ changequote(,)dnl
# Guess yes on FreeBSD >= 5.
freebsd[1-4].*) gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
freebsd* | kfreebsd*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
+ midnightbsd*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
# Guess yes on Mac OS X >= 10.3.
darwin[1-6].*) gl_cv_func_vsnprintf_zerosize_c99="guessing no";;
darwin*) gl_cv_func_vsnprintf_zerosize_c99="guessing yes";;
diff --git a/m4/pthread_sigmask.m4 b/m4/pthread_sigmask.m4
index eb4c784..7c74415 100644
--- a/m4/pthread_sigmask.m4
+++ b/m4/pthread_sigmask.m4
@@ -1,4 +1,4 @@
-# pthread_sigmask.m4 serial 19
+# pthread_sigmask.m4 serial 20
dnl Copyright (C) 2011-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -111,9 +111,9 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK],
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
- dnl On FreeBSD 6.4, HP-UX 11.31, Solaris 9, in programs that are not linked
- dnl with -lpthread, the pthread_sigmask() function always returns 0 and has
- dnl no effect.
+ dnl On FreeBSD 6.4, MidnightBSD 1.1, HP-UX 11.31, Solaris 9, in programs
+ dnl that are not linked with -lpthread, the pthread_sigmask() function
+ dnl always returns 0 and has no effect.
if test -z "$LIB_PTHREAD_SIGMASK"; then
case " $LIBS " in
*' -pthread '*) ;;
@@ -138,7 +138,7 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK],
[
changequote(,)dnl
case "$host_os" in
- freebsd* | hpux* | solaris | solaris2.[2-9]*)
+ freebsd* | midnightbsd* | hpux* | solaris | solaris2.[2-9]*)
gl_cv_func_pthread_sigmask_in_libc_works="guessing no";;
*)
gl_cv_func_pthread_sigmask_in_libc_works="guessing yes";;
diff --git a/m4/realloc.m4 b/m4/realloc.m4
index 6f4461d..a80a02a 100644
--- a/m4/realloc.m4
+++ b/m4/realloc.m4
@@ -1,4 +1,4 @@
-# realloc.m4 serial 19
+# realloc.m4 serial 20
dnl Copyright (C) 2007, 2009-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -24,7 +24,7 @@ AC_DEFUN([_AC_FUNC_REALLOC_IF],
[ac_cv_func_realloc_0_nonnull=no],
[case "$host_os" in
# Guess yes on platforms where we know the result.
- *-gnu* | gnu* | *-musl* | freebsd* | netbsd* | openbsd* \
+ *-gnu* | gnu* | *-musl* | freebsd* | midnightbsd* | netbsd* | openbsd* \
| hpux* | solaris* | cygwin* | mingw*)
ac_cv_func_realloc_0_nonnull="guessing yes" ;;
# If we don't know, obey --enable-cross-guesses.
diff --git a/m4/relocatable.m4 b/m4/relocatable.m4
index a3bd41e..c11999e 100644
--- a/m4/relocatable.m4
+++ b/m4/relocatable.m4
@@ -1,4 +1,4 @@
-# relocatable.m4 serial 23
+# relocatable.m4 serial 24
dnl Copyright (C) 2003, 2005-2007, 2009-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -68,10 +68,11 @@ AC_DEFUN([gl_RELOCATABLE_BODY],
fi
;;
changequote(,)dnl
- # FreeBSD >= 7.3, DragonFly >= 3.0: yes.
+ # FreeBSD >= 7.3, DragonFly >= 3.0, MidnightBSD >= 1.1: yes.
freebsd | freebsd[1-7] | freebsd[1-6].* | freebsd7.[0-2]) ;;
dragonfly | dragonfly[1-2] | dragonfly[1-2].*) ;;
- freebsd* | dragonfly*) use_elf_origin_trick=yes ;;
+ midnightbsd | midnightbsd0* | midnightbsd1.0*) ;;
+ freebsd* | dragonfly* | midnightbsd*) use_elf_origin_trick=yes ;;
# NetBSD >= 8.0: yes.
netbsd | netbsd[1-7] | netbsd[1-7].*) ;;
netbsdelf | netbsdelf[1-7] | netbsdelf[1-7].*) ;;
diff --git a/m4/remainderl.m4 b/m4/remainderl.m4
index 395ad2a..4867f9c 100644
--- a/m4/remainderl.m4
+++ b/m4/remainderl.m4
@@ -1,4 +1,4 @@
-# remainderl.m4 serial 12
+# remainderl.m4 serial 13
dnl Copyright (C) 2012-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -153,6 +153,7 @@ int main (int argc, char *argv[])
dnl Test whether remainderl() works.
dnl It produces completely wrong values on OpenBSD 5.1/SPARC.
+dnl On musl 1.2.2/{arm64,s390x}, the result is accurate to only 16 digits.
AC_DEFUN([gl_FUNC_REMAINDERL_WORKS],
[
AC_REQUIRE([AC_PROG_CC])
@@ -164,33 +165,90 @@ AC_DEFUN([gl_FUNC_REMAINDERL_WORKS],
#ifndef __NO_MATH_INLINES
# define __NO_MATH_INLINES 1 /* for glibc */
#endif
+#include <float.h>
#include <math.h>
+/* Override the values of <float.h>, like done in float.in.h. */
+#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP 16384
+#endif
+#if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP 16384
+#endif
+#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+#endif
+#if defined __sgi && (LDBL_MANT_DIG >= 106)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 106
+# if defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+# endif
+#endif
extern
#ifdef __cplusplus
"C"
#endif
long double remainderl (long double, long double);
-volatile long double x;
-volatile long double y;
-long double z;
-int main ()
+static long double dummy (long double x, long double y) { return 0; }
+volatile long double gx;
+volatile long double gy;
+long double gz;
+int main (int argc, char *argv[])
{
+ long double (* volatile my_remainderl) (long double, long double) =
+ argc ? remainderl : dummy;
+ int result = 0;
/* This test fails on OpenBSD 5.1/SPARC. */
- x = 9.245907126L;
- y = 3.141592654L;
- z = remainderl (x, y);
- if (z >= 0.0L)
- return 1;
- return 0;
+ {
+ gx = 9.245907126L;
+ gy = 3.141592654L;
+ gz = remainderl (gx, gy);
+ if (gz >= 0.0L)
+ result |= 1;
+ }
+ /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x. */
+ {
+ const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
+ (long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 1) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 2) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 3) / 5))
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 4) / 5));
+ long double x = 11.357996098166760874793827872740874983168L;
+ long double y = 0.486497838502717923110029188864352615388L;
+ long double z = my_remainderl (x, y) - (x - 23 * y);
+ long double err = z * TWO_LDBL_MANT_DIG;
+ if (!(err >= -32.0L && err <= 32.0L))
+ result |= 2;
+ }
+ return result;
}
]])],
[gl_cv_func_remainderl_works=yes],
[gl_cv_func_remainderl_works=no],
[case "$host_os" in
- openbsd*) gl_cv_func_remainderl_works="guessing no" ;;
- # Guess yes on native Windows.
- mingw*) gl_cv_func_remainderl_works="guessing yes" ;;
- *) gl_cv_func_remainderl_works="guessing yes" ;;
+ # Guess yes on glibc systems.
+ *-gnu* | gnu*) gl_cv_func_remainderl_works="guessing yes" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_remainderl_works="guessing no" ;;
+ # Guess no on OpenBSD.
+ openbsd*) gl_cv_func_remainderl_works="guessing no" ;;
+ # Guess yes on native Windows.
+ mingw*) gl_cv_func_remainderl_works="guessing yes" ;;
+ # If we don't know, obey --enable-cross-guesses.
+ *) gl_cv_func_remainderl_works="$gl_cross_guess_normal" ;;
esac
])
])
diff --git a/m4/setlocale_null.m4 b/m4/setlocale_null.m4
index c486ca8..2c958ed 100644
--- a/m4/setlocale_null.m4
+++ b/m4/setlocale_null.m4
@@ -1,4 +1,4 @@
-# setlocale_null.m4 serial 4
+# setlocale_null.m4 serial 5
dnl Copyright (C) 2019-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -14,7 +14,7 @@ AC_DEFUN([gl_FUNC_SETLOCALE_NULL],
[gl_cv_func_setlocale_null_all_mtsafe],
[case "$host_os" in
# Guess no on musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin.
- *-musl* | darwin* | freebsd* | netbsd* | openbsd* | aix* | haiku* | cygwin*)
+ *-musl* | darwin* | freebsd* | midnightbsd* | netbsd* | openbsd* | aix* | haiku* | cygwin*)
gl_cv_func_setlocale_null_all_mtsafe=no ;;
# Guess yes on glibc, HP-UX, IRIX, Solaris, native Windows.
*-gnu* | gnu* | hpux* | irix* | solaris* | mingw*)
@@ -48,7 +48,7 @@ AC_DEFUN([gl_FUNC_SETLOCALE_NULL],
openbsd* | aix*)
gl_cv_func_setlocale_null_one_mtsafe=no ;;
# Guess yes on glibc, musl libc, macOS, FreeBSD, NetBSD, HP-UX, IRIX, Solaris, Haiku, Cygwin, native Windows.
- *-gnu* | gnu* | *-musl* | darwin* | freebsd* | netbsd* | hpux* | irix* | solaris* | haiku* | cygwin* | mingw*)
+ *-gnu* | gnu* | *-musl* | darwin* | freebsd* | midnightbsd* | netbsd* | hpux* | irix* | solaris* | haiku* | cygwin* | mingw*)
gl_cv_func_setlocale_null_one_mtsafe=yes ;;
# If we don't know, obey --enable-cross-guesses.
*)
diff --git a/m4/strfmon_l.m4 b/m4/strfmon_l.m4
index 32a78f0..e79ff97 100644
--- a/m4/strfmon_l.m4
+++ b/m4/strfmon_l.m4
@@ -1,4 +1,4 @@
-# strfmon_l.m4 serial 2
+# strfmon_l.m4 serial 3
dnl Copyright (C) 2017-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -40,7 +40,7 @@ AC_DEFUN([gl_FUNC_STRFMON_L],
[gl_cv_strfmon_l_works="guessing yes"])
;;
# Guess no on FreeBSD and Cygwin.
- freebsd* | cygwin*) gl_cv_strfmon_l_works="guessing no" ;;
+ freebsd* | midnightbsd* | cygwin*) gl_cv_strfmon_l_works="guessing no" ;;
# Guess yes otherwise.
*) gl_cv_strfmon_l_works="guessing yes" ;;
esac
diff --git a/m4/threadlib.m4 b/m4/threadlib.m4
index 20b383a..8fc3dfd 100644
--- a/m4/threadlib.m4
+++ b/m4/threadlib.m4
@@ -1,4 +1,4 @@
-# threadlib.m4 serial 29
+# threadlib.m4 serial 30
dnl Copyright (C) 2005-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -126,7 +126,7 @@ int main ()
case "$gl_cv_have_weak" in
*yes)
case "$host_os" in
- freebsd* | dragonfly*)
+ freebsd* | dragonfly* | midnightbsd*)
: > conftest1.c
$CC $CPPFLAGS $CFLAGS $LDFLAGS -fPIC -shared -o libempty.so conftest1.c -lpthread >&AS_MESSAGE_LOG_FD 2>&1
cat <<EOF > conftest2.c
@@ -488,7 +488,7 @@ AC_DEFUN([gl_THREADLIB_BODY],
LIBTHREAD= LTLIBTHREAD=
else
case "$host_os" in
- freebsd* | dragonfly*)
+ freebsd* | dragonfly* | midnightbsd*)
if test "x$LIBTHREAD" != "x$LIBMULTITHREAD"; then
dnl If weak symbols can't tell whether pthread_create(), pthread_key_create()
dnl etc. will succeed, we need a runtime test.
diff --git a/m4/utime.m4 b/m4/utime.m4
index 03df7b7..4ed4158 100644
--- a/m4/utime.m4
+++ b/m4/utime.m4
@@ -1,4 +1,4 @@
-# utime.m4 serial 3
+# utime.m4 serial 4
dnl Copyright (C) 2017-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -34,7 +34,7 @@ AC_DEFUN([gl_FUNC_UTIME],
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stddef.h>
- #include <time.h>
+ #include <utime.h>
]],
[[int result = 0;
if (!utime ("conftest.tmp/", NULL))
diff --git a/m4/visibility.m4 b/m4/visibility.m4
index 6e4b461..8f27a12 100644
--- a/m4/visibility.m4
+++ b/m4/visibility.m4
@@ -1,4 +1,4 @@
-# visibility.m4 serial 6
+# visibility.m4 serial 7
dnl Copyright (C) 2005, 2008, 2010-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -58,6 +58,7 @@ AC_DEFUN([gl_VISIBILITY],
extern __attribute__((__visibility__("default"))) int exportedvar;
extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
extern __attribute__((__visibility__("default"))) int exportedfunc (void);
+ void dummyfunc (void);
void dummyfunc (void) {}
]],
[[]])],
diff --git a/m4/wcwidth.m4 b/m4/wcwidth.m4
index 40fdea7..2ac2a51 100644
--- a/m4/wcwidth.m4
+++ b/m4/wcwidth.m4
@@ -1,4 +1,4 @@
-# wcwidth.m4 serial 33
+# wcwidth.m4 serial 34
dnl Copyright (C) 2006-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -41,8 +41,10 @@ AC_DEFUN([gl_FUNC_WCWIDTH],
if test $ac_cv_func_wcwidth = yes || test $gl_cv_func_wcwidth_macro = yes; then
HAVE_WCWIDTH=1
dnl On Mac OS X 10.3, wcwidth(0x0301) (COMBINING ACUTE ACCENT) returns 1.
- dnl On NetBSD 9.0, OpenBSD 5.0, wcwidth(0x05B0) (HEBREW POINT SHEVA) returns 1.
- dnl On NetBSD 9.0, OSF/1 5.1, wcwidth(0x200B) (ZERO WIDTH SPACE) returns 1.
+ dnl On NetBSD 9.0, OpenBSD 5.0, MidnightBSD 1.1,
+ dnl wcwidth(0x05B0) (HEBREW POINT SHEVA) returns 1.
+ dnl On NetBSD 9.0, MidnightBSD 1.1, OSF/1 5.1,
+ dnl wcwidth(0x200B) (ZERO WIDTH SPACE) returns 1.
dnl On OpenBSD 5.8, wcwidth(0xFF1A) (FULLWIDTH COLON) returns 0.
dnl This leads to bugs in 'ls' (coreutils).
dnl On Solaris 11.4, wcwidth(0x2202) (PARTIAL DIFFERENTIAL) returns 2,
diff --git a/modules/canonicalize b/modules/canonicalize
index a6cf76f..ddd83bc 100644
--- a/modules/canonicalize
+++ b/modules/canonicalize
@@ -15,7 +15,6 @@ extensions
fcntl-h
file-set
filename
-free-posix
getcwd
hash-triple-simple
idx
@@ -29,7 +28,7 @@ scratch_buffer
stat
stdbool
sys_stat
-xalloc
+unistd
xalloc-die
configure.ac:
diff --git a/modules/canonicalize-lgpl b/modules/canonicalize-lgpl
index b8e87a6..0bc5591 100644
--- a/modules/canonicalize-lgpl
+++ b/modules/canonicalize-lgpl
@@ -16,11 +16,9 @@ eloop-threshold [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONI
errno [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
fcntl-h [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
filename [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
-free-posix [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
idx [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
intprops [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
libc-config [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
-malloc-posix [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
memmove [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
mempcpy [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
pathmax [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
@@ -30,6 +28,7 @@ scratch_buffer [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONI
stat [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
stdbool [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
sys_stat [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
+unistd [test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1]
configure.ac:
gl_CANONICALIZE_LGPL
diff --git a/modules/linked-list-tests b/modules/linked-list-tests
index c34e49e..bf21bee 100644
--- a/modules/linked-list-tests
+++ b/modules/linked-list-tests
@@ -1,12 +1,20 @@
Files:
tests/test-linked_list.c
+tests/test-asyncsafe-linked_list.sh
+tests/test-asyncsafe-linked_list.c
tests/macros.h
Depends-on:
array-list
+thread
+yield
+nanosleep
+sigaction
+sigprocmask
configure.ac:
Makefile.am:
-TESTS += test-linked_list
-check_PROGRAMS += test-linked_list
+TESTS += test-linked_list test-asyncsafe-linked_list.sh
+check_PROGRAMS += test-linked_list test-asyncsafe-linked_list
+test_asyncsafe_linked_list_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
diff --git a/modules/malloc-posix b/modules/malloc-posix
index b5ab594..1a2d72c 100644
--- a/modules/malloc-posix
+++ b/modules/malloc-posix
@@ -14,6 +14,7 @@ if test $REPLACE_MALLOC = 1; then
AC_LIBOBJ([malloc])
fi
gl_STDLIB_MODULE_INDICATOR([malloc-posix])
+gl_MODULE_INDICATOR([malloc-posix])
Makefile.am:
diff --git a/modules/parse-datetime b/modules/parse-datetime
index 820bc6c..8a2d050 100644
--- a/modules/parse-datetime
+++ b/modules/parse-datetime
@@ -38,7 +38,7 @@ Makefile.am:
# and by the GNU Coding Standards
# <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>
# the file should be generated in the source directory.
-# - The #line numbers in the .c file refer to a nonexistent file once it
+# - The #line directives in the .c file refer to a nonexistent file once it
# has been moved from the build directory to the source directory. This
# leads to error if 'lcov' is used later.
# Additionally, here we assume GNU Bison and therefore don't need the ylwrap
diff --git a/modules/parse-datetime2 b/modules/parse-datetime2
new file mode 100644
index 0000000..b4771dc
--- a/dev/null
+++ b/modules/parse-datetime2
@@ -0,0 +1,21 @@
+Description:
+Convert a date/time string to linear time, with debugging.
+
+Files:
+
+Depends-on:
+parse-datetime
+
+configure.ac:
+AC_DEFINE([GNULIB_PARSE_DATETIME2], [1], [Define to support parse_datetime2.])
+
+Makefile.am:
+
+Include:
+"parse-datetime.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+Paul Eggert
diff --git a/modules/posix_spawn_file_actions_addchdir-tests b/modules/posix_spawn_file_actions_addchdir-tests
index 1c56b1c..e554138 100644
--- a/modules/posix_spawn_file_actions_addchdir-tests
+++ b/modules/posix_spawn_file_actions_addchdir-tests
@@ -6,6 +6,7 @@ tests/macros.h
Depends-on:
posix_spawn_file_actions_init
+posix_spawn_file_actions_destroy
posix_spawnp-tests
findprog
diff --git a/modules/posix_spawn_file_actions_addclose-tests b/modules/posix_spawn_file_actions_addclose-tests
index 848acce..b115e3d 100644
--- a/modules/posix_spawn_file_actions_addclose-tests
+++ b/modules/posix_spawn_file_actions_addclose-tests
@@ -6,6 +6,7 @@ tests/macros.h
Depends-on:
getdtablesize
posix_spawn_file_actions_init
+posix_spawn_file_actions_destroy
configure.ac:
diff --git a/modules/posix_spawn_file_actions_adddup2-tests b/modules/posix_spawn_file_actions_adddup2-tests
index f504892..5e25990 100644
--- a/modules/posix_spawn_file_actions_adddup2-tests
+++ b/modules/posix_spawn_file_actions_adddup2-tests
@@ -6,6 +6,7 @@ tests/macros.h
Depends-on:
getdtablesize
posix_spawn_file_actions_init
+posix_spawn_file_actions_destroy
configure.ac:
diff --git a/modules/posix_spawn_file_actions_addfchdir-tests b/modules/posix_spawn_file_actions_addfchdir-tests
index 45f4230..2f09934 100644
--- a/modules/posix_spawn_file_actions_addfchdir-tests
+++ b/modules/posix_spawn_file_actions_addfchdir-tests
@@ -6,6 +6,7 @@ tests/macros.h
Depends-on:
posix_spawn_file_actions_init
+posix_spawn_file_actions_destroy
posix_spawnp-tests
findprog
diff --git a/modules/posix_spawn_file_actions_addopen-tests b/modules/posix_spawn_file_actions_addopen-tests
index fbe7943..8f0de9e 100644
--- a/modules/posix_spawn_file_actions_addopen-tests
+++ b/modules/posix_spawn_file_actions_addopen-tests
@@ -6,6 +6,7 @@ tests/macros.h
Depends-on:
getdtablesize
posix_spawn_file_actions_init
+posix_spawn_file_actions_destroy
configure.ac:
diff --git a/modules/realloc-posix b/modules/realloc-posix
index 8e4924d..7f48110 100644
--- a/modules/realloc-posix
+++ b/modules/realloc-posix
@@ -15,6 +15,7 @@ if test $REPLACE_REALLOC = 1; then
AC_LIBOBJ([realloc])
fi
gl_STDLIB_MODULE_INDICATOR([realloc-posix])
+gl_MODULE_INDICATOR([realloc-posix])
Makefile.am:
diff --git a/modules/relocatable-prog-wrapper b/modules/relocatable-prog-wrapper
index f97fdae..da9ad30 100644
--- a/modules/relocatable-prog-wrapper
+++ b/modules/relocatable-prog-wrapper
@@ -17,9 +17,19 @@ lib/allocator.c
lib/readlink.c
lib/stat.c
lib/canonicalize-lgpl.c
+lib/scratch_buffer.h
+lib/malloc/scratch_buffer.h
+lib/malloc/scratch_buffer_dupfree.c
+lib/malloc/scratch_buffer_grow.c
+lib/malloc/scratch_buffer_grow_preserve.c
+lib/malloc/scratch_buffer_set_array_size.c
+lib/malloc.c
+lib/realloc.c
+lib/free.c
+lib/mempcpy.c
+lib/rawmemchr.c
lib/malloca.h
lib/malloca.c
-lib/lstat.c
lib/relocatable.h
lib/relocatable.c
lib/setenv.c
@@ -28,6 +38,7 @@ lib/c-ctype.c
m4/largefile.m4
m4/malloca.m4
m4/canonicalize.m4
+m4/lstat.m4
m4/eealloc.m4
m4/environ.m4
m4/readlink.m4
@@ -35,19 +46,26 @@ m4/relocatable-lib.m4
m4/setenv.m4
Depends-on:
-alloca-opt
+c99
double-slash-root
+eloop-threshold
+environ
errno
+fcntl-h
filename
+idx
+intprops
largefile
+libc-config
pathmax
ssize_t
stdbool
+stddef
stdint
stdlib
-unistd
-environ
string
+sys_stat
+unistd
verify
xalloc-oversized
@@ -58,6 +76,11 @@ configure.ac:
AC_REQUIRE([AC_C_RESTRICT])
gl_FUNC_READLINK_SEPARATE
gl_CANONICALIZE_LGPL_SEPARATE
+gl_FUNC_MALLOC_POSIX
+gl_FUNC_REALLOC_POSIX
+gl_FUNC_FREE
+gl_FUNC_MEMPCPY
+gl_FUNC_RAWMEMCHR
gl_MALLOCA
gl_RELOCATABLE_LIBRARY
gl_FUNC_SETENV_SEPARATE
diff --git a/modules/scratch_buffer b/modules/scratch_buffer
index 7eedae7..cf83ab5 100644
--- a/modules/scratch_buffer
+++ b/modules/scratch_buffer
@@ -14,6 +14,9 @@ c99
libc-config
stdbool
stddef
+malloc-posix
+realloc-posix
+free-posix
configure.ac:
diff --git a/modules/simple-atomic b/modules/simple-atomic
new file mode 100644
index 0000000..5f3f63d
--- a/dev/null
+++ b/modules/simple-atomic
@@ -0,0 +1,25 @@
+Description:
+Simple atomic operations for multithreading.
+
+Files:
+lib/simple-atomic.h
+lib/simple-atomic.c
+
+Depends-on:
+stdint
+sparcv8+
+
+configure.ac:
+AC_CHECK_HEADERS_ONCE([pthread.h])
+
+Makefile.am:
+lib_SOURCES += simple-atomic.c
+
+Include:
+"simple-atomic.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/simple-atomic-tests b/modules/simple-atomic-tests
new file mode 100644
index 0000000..a57b9fc
--- a/dev/null
+++ b/modules/simple-atomic-tests
@@ -0,0 +1,14 @@
+Files:
+tests/test-simple-atomic.c
+tests/macros.h
+
+Depends-on:
+thread
+yield
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-simple-atomic
+check_PROGRAMS += test-simple-atomic
+test_simple_atomic_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
diff --git a/modules/string-buffer b/modules/string-buffer
new file mode 100644
index 0000000..54da1db
--- a/dev/null
+++ b/modules/string-buffer
@@ -0,0 +1,26 @@
+Description:
+A buffer that accumulates a string by piecewise concatenation.
+
+Files:
+lib/string-buffer.h
+lib/string-buffer.c
+
+Depends-on:
+stdbool
+attribute
+stdarg
+vsnprintf-posix
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += string-buffer.c
+
+Include:
+"string-buffer.h"
+
+License:
+LGPL
+
+Maintainer:
+all
diff --git a/modules/string-buffer-tests b/modules/string-buffer-tests
new file mode 100644
index 0000000..38473fd
--- a/dev/null
+++ b/modules/string-buffer-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-string-buffer.c
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-string-buffer
+check_PROGRAMS += test-string-buffer
diff --git a/tests/test-asyncsafe-linked_list.c b/tests/test-asyncsafe-linked_list.c
new file mode 100644
index 0000000..56e76bb
--- a/dev/null
+++ b/tests/test-asyncsafe-linked_list.c
@@ -0,0 +1,322 @@
+/* Test of async-safe sequential list data type implementation.
+ Copyright (C) 2021 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#include <config.h>
+
+/* Work around GCC bug 44511. */
+#if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
+# pragma GCC diagnostic ignored "-Wreturn-type"
+#endif
+
+#include "gl_linked_list.h"
+
+#if SIGNAL_SAFE_LIST
+
+# if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS /* || USE_WINDOWS_THREADS */
+/* This test works only with POSIX compatible threads.
+ With Windows threads, send_signal() has to be implemented as
+ raise (SIGINT);
+ hence only test == 2 tests anything, and in fact only 5 signals arrive.
+ This small test is not able to detect a buggy implementation. Therefore
+ mark the test as skipped in this case. */
+
+# include <signal.h>
+# include <stdint.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <time.h>
+
+# include "glthread/thread.h"
+# include "glthread/yield.h"
+
+# include "macros.h"
+
+# define RANDOM(n) (rand () % (n))
+# define RANDOM_OBJECT() ((void *) (uintptr_t) RANDOM (10000))
+
+/* test == 1: signals are executed in an idle thread.
+ test == 2: signals are executed in the signal-sending thread.
+ test == 3: signals are executed in the mutator thread. */
+static int volatile test;
+
+static uintptr_t volatile sum_before_current_operation;
+static uintptr_t volatile sum_after_current_operation;
+
+static gl_list_t volatile list1;
+
+static gl_thread_t volatile signal_target;
+
+/* Statistics. */
+static unsigned int volatile num_mutations;
+static unsigned int volatile num_signals_sent;
+static unsigned int volatile num_signals_arrived;
+
+/* Blocks the SIGINT signal in the current thread. */
+static void
+block_sigint (void)
+{
+ sigset_t mask;
+
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGINT);
+ sigprocmask (SIG_BLOCK, &mask, NULL); /* equivalent to pthread_sigmask */
+}
+
+/* This thread is idle. */
+static void *
+idle_thread (void *arg)
+{
+ for (;;)
+ gl_thread_yield ();
+
+ /*NOTREACHED*/
+}
+
+/* The signal handler iterates through the list and verifies that the sum of
+ all elements in the list is one of the two allowed values. */
+static _GL_ASYNC_SAFE void
+sigint_handler (int signo)
+{
+ num_signals_arrived++;
+
+ uintptr_t sum = 0;
+ {
+ gl_list_iterator_t iter = gl_list_iterator (list1);
+ const void *elt;
+
+ while (gl_list_iterator_next (&iter, &elt, NULL))
+ sum += (uintptr_t) elt;
+ gl_list_iterator_free (&iter);
+ }
+ if (!(sum == sum_before_current_operation
+ || sum == sum_after_current_operation))
+ {
+ /* POSIX does not allow uses of stdio from within a signal handler, but
+ it should work here, because the rest of the program does not use
+ stdio. */
+ fprintf (stderr, "sum = %lu, expected %lu or %lu\n",
+ (unsigned long) sum,
+ (unsigned long) sum_before_current_operation,
+ (unsigned long) sum_after_current_operation);
+ fflush (stderr);
+ abort ();
+ }
+}
+
+/* Sends a SIGINT signal to the current process. */
+static void
+send_signal (void)
+{
+#if 0
+ /* This does not work for test != 2, because raise() sends the signal to the
+ current thread always, and if test != 2 the signal is eternally blocked
+ in the current thread; thus it will never get delivered. */
+ raise (SIGINT);
+#else
+ /* This works: Either
+ kill (getpid (), SIGINT);
+ or
+ pthread_kill (signal_target, SIGINT);
+ The difference is that for kill(), the OS determines the (only) thread that
+ has not blocked the signal, whereas for pthread_kill() we have manually
+ determined this thread. */
+ kill (getpid (), SIGINT);
+#endif
+}
+
+/* This thread permanently sends SIGINT signals. */
+static void *
+signal_sending_thread (void *arg)
+{
+ if (test != 2)
+ block_sigint ();
+
+ int repeat;
+
+ for (repeat = 1000; repeat > 0; repeat--)
+ {
+ num_signals_sent++; send_signal ();
+ num_signals_sent++; send_signal ();
+ num_signals_sent++; send_signal ();
+ num_signals_sent++; send_signal ();
+ num_signals_sent++; send_signal ();
+ {
+ struct timespec ts;
+ ts.tv_sec = 0; ts.tv_nsec = 1000000;
+ nanosleep (&ts, NULL);
+ }
+ gl_thread_yield ();
+ }
+
+ printf ("Sent %u signals. Received %u signals. Done after %u mutations.\n",
+ num_signals_sent, num_signals_arrived, num_mutations);
+
+ exit (0);
+
+ /*NOTREACHED*/
+}
+
+/* This thread repeatedly adds and removes objects from the list. */
+static void *
+mutator_thread (void *arg)
+{
+ if (test != 3)
+ block_sigint ();
+
+ gl_list_t list2 = (gl_list_t) arg;
+
+ for (num_mutations = 0; ; num_mutations++)
+ {
+ unsigned int operation = RANDOM (2);
+ switch (operation)
+ {
+ case 0: /* Add an element. */
+ {
+ const void *obj = RANDOM_OBJECT ();
+ ASSERT (gl_list_nx_add_first (list2, obj) != NULL);
+ sum_after_current_operation =
+ sum_before_current_operation + (uintptr_t) obj;
+ ASSERT (gl_list_nx_add_first (list1, obj) != NULL);
+ sum_before_current_operation = sum_after_current_operation;
+ }
+ break;
+ case 1: /* Remove an element. */
+ if (gl_list_size (list2) > 0)
+ {
+ size_t index = RANDOM (gl_list_size (list2));
+ const void *obj = gl_list_get_at (list2, index);
+ ASSERT (gl_list_remove (list2, obj));
+ sum_after_current_operation =
+ sum_before_current_operation - (uintptr_t) obj;
+ ASSERT (gl_list_remove (list1, obj));
+ sum_before_current_operation = sum_after_current_operation;
+ }
+ break;
+ }
+ }
+
+ /*NOTREACHED*/
+}
+
+int
+main (int argc, char *argv[])
+{
+ test = atoi (argv[1]);
+
+ /* Allow the user to provide a non-default random seed on the command line. */
+ if (argc > 2)
+ srand (atoi (argv[2]));
+
+ gl_list_t list2;
+ /* Initialize list1 and list2. */
+ {
+ size_t initial_size = RANDOM (50);
+ const void **contents =
+ (const void **) malloc (initial_size * sizeof (const void *));
+ size_t i;
+
+ for (i = 0; i < initial_size; i++)
+ contents[i] = RANDOM_OBJECT ();
+
+ list1 = gl_list_nx_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
+ ASSERT (list1 != NULL);
+ for (i = 0; i < initial_size; i++)
+ ASSERT (gl_list_nx_add_first (list1, contents[i]) != NULL);
+
+ list2 = gl_list_nx_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
+ ASSERT (list2 != NULL);
+ for (i = 0; i < initial_size; i++)
+ ASSERT (gl_list_nx_add_last (list2, contents[i]) != NULL);
+
+ uintptr_t initial_sum = 0;
+ for (i = 0; i < initial_size; i++)
+ initial_sum += (uintptr_t) contents[i];
+ sum_before_current_operation = initial_sum;
+ sum_after_current_operation = initial_sum;
+ }
+
+ /* Install the signal handler.
+ It needs to be done with sigaction(), not signal(), otherwise on Solaris
+ and AIX the program crashes at the second incoming SIGINT. */
+ #if 0
+ signal (SIGINT, sigint_handler);
+ #else
+ {
+ struct sigaction action;
+ action.sa_handler = sigint_handler;
+ action.sa_flags = SA_RESTART | SA_NODEFER;
+ sigemptyset (&action.sa_mask);
+ ASSERT (sigaction (SIGINT, &action, NULL) == 0);
+ }
+ #endif
+
+ /* Launch the threads. */
+ switch (test)
+ {
+ case 1:
+ {
+ signal_target = gl_thread_create (idle_thread, NULL);
+ gl_thread_create (mutator_thread, list2);
+ signal_sending_thread (NULL);
+ abort ();
+ }
+
+ case 2:
+ {
+ gl_thread_create (mutator_thread, list2);
+ signal_target = gl_thread_self (); signal_sending_thread (NULL);
+ abort ();
+ }
+
+ case 3:
+ {
+ signal_target = gl_thread_create (mutator_thread, list2);
+ signal_sending_thread (NULL);
+ abort ();
+ }
+
+ default:
+ ASSERT (false);
+ }
+}
+
+# else
+
+# include <stdio.h>
+
+int
+main ()
+{
+ fputs ("Skipping test: POSIX compatible multithreading not enabled\n", stderr);
+ return 77;
+}
+
+# endif
+
+#else
+
+# include <stdio.h>
+
+int
+main ()
+{
+ fputs ("Skipping test: signal-safety of linked lists is not enabled\n", stderr);
+ return 77;
+}
+
+#endif
diff --git a/tests/test-asyncsafe-linked_list.sh b/tests/test-asyncsafe-linked_list.sh
new file mode 100755
index 0000000..c2ad176
--- a/dev/null
+++ b/tests/test-asyncsafe-linked_list.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+st=0
+for i in 1 2 3 ; do
+ ${CHECKER} ./test-asyncsafe-linked_list${EXEEXT} $i
+ result=$?
+ if test $result = 77; then
+ st=77
+ break
+ fi
+ if test $result != 0; then
+ echo test-asyncsafe-linked_list.sh: test case $i failed >&2
+ st=1
+ fi
+done
+exit $st
diff --git a/tests/test-c32isalnum.c b/tests/test-c32isalnum.c
index 3720810..8f61ad9 100644
--- a/tests/test-c32isalnum.c
+++ b/tests/test-c32isalnum.c
@@ -149,7 +149,7 @@ main (int argc, char *argv[])
/* U+00D7 MULTIPLICATION SIGN */
is = for_character ("\241\337", 2);
ASSERT (is == 0);
- #if !(defined __APPLE__ && defined __MACH__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__)
/* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
is = for_character ("\217\251\254", 3);
ASSERT (is != 0);
@@ -165,7 +165,7 @@ main (int argc, char *argv[])
is = for_character ("\243\261", 2);
ASSERT (is != 0);
#endif
- #if !((defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__)
/* U+FF4D FULLWIDTH LATIN SMALL LETTER M */
is = for_character ("\243\355", 2);
ASSERT (is != 0);
diff --git a/tests/test-c32isalpha.c b/tests/test-c32isalpha.c
index 5be0178..9b07186 100644
--- a/tests/test-c32isalpha.c
+++ b/tests/test-c32isalpha.c
@@ -147,7 +147,7 @@ main (int argc, char *argv[])
/* U+00D7 MULTIPLICATION SIGN */
is = for_character ("\241\337", 2);
ASSERT (is == 0);
- #if !(defined __APPLE__ && defined __MACH__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__)
/* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
is = for_character ("\217\251\254", 3);
ASSERT (is != 0);
@@ -163,7 +163,7 @@ main (int argc, char *argv[])
is = for_character ("\243\261", 2);
ASSERT (is == 0);
#endif
- #if !((defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__)
/* U+FF4D FULLWIDTH LATIN SMALL LETTER M */
is = for_character ("\243\355", 2);
ASSERT (is != 0);
diff --git a/tests/test-c32isblank.c b/tests/test-c32isblank.c
index 984d0d8..a615388 100644
--- a/tests/test-c32isblank.c
+++ b/tests/test-c32isblank.c
@@ -74,7 +74,7 @@ main (int argc, char *argv[])
switch (c)
{
case '\t':
- #if !defined __NetBSD__
+ #if !(defined __FreeBSD__ || defined __NetBSD__)
case '\v':
#endif
case '\f':
diff --git a/tests/test-c32islower.c b/tests/test-c32islower.c
index 8bcffaf..0b811fd 100644
--- a/tests/test-c32islower.c
+++ b/tests/test-c32islower.c
@@ -156,12 +156,12 @@ main (int argc, char *argv[])
/* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */
is = for_character ("\217\252\261", 3);
ASSERT (is == 0);
- #if !((defined __APPLE__ && defined __MACH__) || defined __NetBSD__ || defined __CYGWIN__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__ || defined __CYGWIN__)
/* U+00DF LATIN SMALL LETTER SHARP S */
is = for_character ("\217\251\316", 3);
ASSERT (is != 0);
#endif
- #if !((defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__)
/* U+00E9 LATIN SMALL LETTER E WITH ACUTE */
is = for_character ("\217\253\261", 3);
ASSERT (is != 0);
@@ -172,7 +172,7 @@ main (int argc, char *argv[])
/* U+0141 LATIN CAPITAL LETTER L WITH STROKE */
is = for_character ("\217\251\250", 3);
ASSERT (is == 0);
- #if !((defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__)
/* U+0142 LATIN SMALL LETTER L WITH STROKE */
is = for_character ("\217\251\310", 3);
ASSERT (is != 0);
@@ -269,7 +269,7 @@ main (int argc, char *argv[])
/* U+00B2 SUPERSCRIPT TWO */
is = for_character ("\201\060\205\065", 4);
ASSERT (is == 0);
- #if !(defined __GLIBC__ || (defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
+ #if !(defined __GLIBC__ || (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__)
/* U+00B5 MICRO SIGN */
is = for_character ("\201\060\205\070", 4);
ASSERT (is == 0);
diff --git a/tests/test-c32isupper.c b/tests/test-c32isupper.c
index 05b969d..5604a8f 100644
--- a/tests/test-c32isupper.c
+++ b/tests/test-c32isupper.c
@@ -151,7 +151,7 @@ main (int argc, char *argv[])
case '2':
/* Locale encoding is EUC-JP. */
{
- #if !((defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__)
/* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */
is = for_character ("\217\252\261", 3);
ASSERT (is != 0);
@@ -165,7 +165,7 @@ main (int argc, char *argv[])
/* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
is = for_character ("\217\253\363", 3);
ASSERT (is == 0);
- #if !((defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
+ #if !((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __NetBSD__)
/* U+0141 LATIN CAPITAL LETTER L WITH STROKE */
is = for_character ("\217\251\250", 3);
ASSERT (is != 0);
diff --git a/tests/test-immutable.c b/tests/test-immutable.c
index 4bee1f2..18ccf9d 100644
--- a/tests/test-immutable.c
+++ b/tests/test-immutable.c
@@ -45,7 +45,7 @@ static void
install_segv_handler (void)
{
signal (SIGSEGV, segv_handler);
-# if defined __APPLE__ && defined __MACH__
+# if (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__
signal (SIGBUS, segv_handler);
# endif
}
diff --git a/tests/test-posix_spawn_file_actions_addclose.c b/tests/test-posix_spawn_file_actions_addclose.c
index 3aca333..2c910ea 100644
--- a/tests/test-posix_spawn_file_actions_addclose.c
+++ b/tests/test-posix_spawn_file_actions_addclose.c
@@ -54,6 +54,8 @@ main (void)
errno = 0;
ASSERT (posix_spawn_file_actions_addclose (&actions, -1) == EBADF);
}
+ /* This behaviour is not mandated by POSIX, but happens to pass on all
+ platforms. */
{
int bad_fd = big_fd ();
errno = 0;
diff --git a/tests/test-posixtm.c b/tests/test-posixtm.c
index ea20564..b07e0c5 100644
--- a/tests/test-posixtm.c
+++ b/tests/test-posixtm.c
@@ -178,7 +178,7 @@ main (void)
if (t_out != t_exp)
{
printf ("%s mismatch (-: actual; +:expected)\n-%12ld\n+%12ld\n",
- T[i].in, t_out, t_exp);
+ T[i].in, (long) t_out, (long) t_exp);
fail = 1;
}
}
diff --git a/tests/test-regex.c b/tests/test-regex.c
index 4a4ff39..adccf21 100644
--- a/tests/test-regex.c
+++ b/tests/test-regex.c
@@ -55,6 +55,111 @@ really_utf8 (void)
return strcmp (locale_charset (), "UTF-8") == 0;
}
+/* Tests supposed to match; copied from glibc posix/bug-regex11.c. */
+static struct
+{
+ const char *pattern;
+ const char *string;
+ int flags, nmatch;
+ regmatch_t rm[5];
+} const tests[] = {
+ /* Test for newline handling in regex. */
+ { "[^~]*~", "\nx~y", 0, 2, { { 0, 3 }, { -1, -1 } } },
+ /* Other tests. */
+ { "a(.*)b", "a b", REG_EXTENDED, 2, { { 0, 3 }, { 1, 2 } } },
+ { ".*|\\([KIO]\\)\\([^|]*\\).*|?[KIO]", "10~.~|P|K0|I10|O16|?KSb", 0, 3,
+ { { 0, 21 }, { 15, 16 }, { 16, 18 } } },
+ { ".*|\\([KIO]\\)\\([^|]*\\).*|?\\1", "10~.~|P|K0|I10|O16|?KSb", 0, 3,
+ { { 0, 21 }, { 8, 9 }, { 9, 10 } } },
+ { "^\\(a*\\)\\1\\{9\\}\\(a\\{0,9\\}\\)\\([0-9]*;.*[^a]\\2\\([0-9]\\)\\)",
+ "a1;;0a1aa2aaa3aaaa4aaaaa5aaaaaa6aaaaaaa7aaaaaaaa8aaaaaaaaa9aa2aa1a0", 0,
+ 5, { { 0, 67 }, { 0, 0 }, { 0, 1 }, { 1, 67 }, { 66, 67 } } },
+ /* Test for BRE expression anchoring. POSIX says just that this may match;
+ in glibc regex it always matched, so avoid changing it. */
+ { "\\(^\\|foo\\)bar", "bar", 0, 2, { { 0, 3 }, { -1, -1 } } },
+ { "\\(foo\\|^\\)bar", "bar", 0, 2, { { 0, 3 }, { -1, -1 } } },
+ /* In ERE this must be treated as an anchor. */
+ { "(^|foo)bar", "bar", REG_EXTENDED, 2, { { 0, 3 }, { -1, -1 } } },
+ { "(foo|^)bar", "bar", REG_EXTENDED, 2, { { 0, 3 }, { -1, -1 } } },
+ /* Here ^ cannot be treated as an anchor according to POSIX. */
+ { "(^|foo)bar", "(^|foo)bar", 0, 2, { { 0, 10 }, { -1, -1 } } },
+ { "(foo|^)bar", "(foo|^)bar", 0, 2, { { 0, 10 }, { -1, -1 } } },
+ /* More tests on backreferences. */
+ { "()\\1", "x", REG_EXTENDED, 2, { { 0, 0 }, { 0, 0 } } },
+ { "()x\\1", "x", REG_EXTENDED, 2, { { 0, 1 }, { 0, 0 } } },
+ { "()\\1*\\1*", "", REG_EXTENDED, 2, { { 0, 0 }, { 0, 0 } } },
+ { "([0-9]).*\\1(a*)", "7;7a6", REG_EXTENDED, 3, { { 0, 4 }, { 0, 1 }, { 3, 4 } } },
+ { "([0-9]).*\\1(a*)", "7;7a", REG_EXTENDED, 3, { { 0, 4 }, { 0, 1 }, { 3, 4 } } },
+ { "(b)()c\\1", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 1 }, { 1, 1 } } },
+ { "()(b)c\\2", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 0 }, { 0, 1 } } },
+ { "a(b)()c\\1", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 2 }, { 2, 2 } } },
+ { "a()(b)c\\2", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 1 }, { 1, 2 } } },
+ { "()(b)\\1c\\2", "bcb", REG_EXTENDED, 3, { { 0, 3 }, { 0, 0 }, { 0, 1 } } },
+ { "(b())\\2\\1", "bbbb", REG_EXTENDED, 3, { { 0, 2 }, { 0, 1 }, { 1, 1 } } },
+ { "a()(b)\\1c\\2", "abcb", REG_EXTENDED, 3, { { 0, 4 }, { 1, 1 }, { 1, 2 } } },
+ { "a()d(b)\\1c\\2", "adbcb", REG_EXTENDED, 3, { { 0, 5 }, { 1, 1 }, { 2, 3 } } },
+ { "a(b())\\2\\1", "abbbb", REG_EXTENDED, 3, { { 0, 3 }, { 1, 2 }, { 2, 2 } } },
+ { "(bb())\\2\\1", "bbbb", REG_EXTENDED, 3, { { 0, 4 }, { 0, 2 }, { 2, 2 } } },
+ { "^([^,]*),\\1,\\1$", "a,a,a", REG_EXTENDED, 2, { { 0, 5 }, { 0, 1 } } },
+ { "^([^,]*),\\1,\\1$", "ab,ab,ab", REG_EXTENDED, 2, { { 0, 8 }, { 0, 2 } } },
+ { "^([^,]*),\\1,\\1,\\1$", "abc,abc,abc,abc", REG_EXTENDED, 2,
+ { { 0, 15 }, { 0, 3 } } },
+ { "^(.?)(.?)(.?)(.?)(.?).?\\5\\4\\3\\2\\1$",
+ "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } },
+ { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$",
+ "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } },
+ { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$",
+ "abcdedcba", REG_EXTENDED, 1, { { 0, 9 } } },
+ /* XXX Not used since they fail so far. */
+ { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$|^.?$",
+ "ababababa", REG_EXTENDED, 1, { { 0, 9 } } },
+ { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$",
+ "level", REG_NOSUB | REG_EXTENDED, 0, { { -1, -1 } } },
+ { "^(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\\9\\8\\7\\6\\5\\4\\3\\2\\1$",
+ "ababababa", REG_EXTENDED, 1, { { 0, 9 } } },
+};
+
+static void
+bug_regex11 (void)
+{
+ regex_t re;
+ regmatch_t rm[5];
+ size_t i;
+ int n;
+
+ for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+ {
+ n = regcomp (&re, tests[i].pattern, tests[i].flags);
+ if (n != 0)
+ {
+ char buf[500];
+ regerror (n, &re, buf, sizeof (buf));
+ report_error ("%s: regcomp %zd failed: %s", tests[i].pattern, i, buf);
+ continue;
+ }
+
+ if (regexec (&re, tests[i].string, tests[i].nmatch, rm, 0))
+ {
+ report_error ("%s: regexec %zd failed", tests[i].pattern, i);
+ regfree (&re);
+ continue;
+ }
+
+ for (n = 0; n < tests[i].nmatch; ++n)
+ if (rm[n].rm_so != tests[i].rm[n].rm_so
+ || rm[n].rm_eo != tests[i].rm[n].rm_eo)
+ {
+ if (tests[i].rm[n].rm_so == -1 && tests[i].rm[n].rm_eo == -1)
+ break;
+ report_error ("%s: regexec %zd match failure rm[%d] %d..%d",
+ tests[i].pattern, i, n, rm[n].rm_so, rm[n].rm_eo);
+ break;
+ }
+
+ regfree (&re);
+ }
+}
+
int
main (void)
{
@@ -65,11 +170,15 @@ main (void)
struct re_registers regs;
#if HAVE_DECL_ALARM
- /* Some builds of glibc go into an infinite loop on this test. */
- int alarm_value = 2;
+ /* In case a bug causes glibc to go into an infinite loop.
+ The tests should take less than 10 s on a reasonably modern CPU. */
+ int alarm_value = 1000;
signal (SIGALRM, SIG_DFL);
alarm (alarm_value);
#endif
+
+ bug_regex11 ();
+
if (setlocale (LC_ALL, "en_US.UTF-8"))
{
{
@@ -290,13 +399,43 @@ main (void)
{
memset (&regs, 0, sizeof regs);
static char const data[] = "WXY";
- if (re_search (&regex, data, sizeof data - 1, 0, 3, &regs) < 0)
+ i = re_search (&regex, data, sizeof data - 1, 0, 3, &regs);
+ if (i < 0)
report_error ("re_search '%s' on '%s' returned %d", pat_x, data, i);
regfree (&regex);
free (regs.start);
free (regs.end);
}
+ /* glibc bug 11053. */
+ re_set_syntax (RE_SYNTAX_POSIX_BASIC);
+ memset (&regex, 0, sizeof regex);
+ static char const pat_sub2[] = "\\(a*\\)*a*\\1";
+ s = re_compile_pattern (pat_sub2, sizeof pat_sub2 - 1, &regex);
+ if (s)
+ report_error ("%s: %s", pat_sub2, s);
+ else
+ {
+ memset (&regs, 0, sizeof regs);
+ static char const data[] = "a";
+ int datalen = sizeof data - 1;
+ i = re_search (&regex, data, datalen, 0, datalen, &regs);
+ if (i != 0)
+ report_error ("re_search '%s' on '%s' returned %d", pat_sub2, data, i);
+ else if (regs.num_regs < 2)
+ report_error ("re_search '%s' on '%s' returned only %d registers",
+ pat_sub2, data, (int) regs.num_regs);
+ else if (! (regs.start[0] == 0 && regs.end[0] == 1))
+ report_error ("re_search '%s' on '%s' returned wrong match [%d,%d)",
+ pat_sub2, data, (int) regs.start[0], (int) regs.end[0]);
+ else if (! (regs.start[1] == 0 && regs.end[1] == 0))
+ report_error ("re_search '%s' on '%s' returned wrong submatch [%d,%d)",
+ pat_sub2, data, regs.start[1], regs.end[1]);
+ regfree (&regex);
+ free (regs.start);
+ free (regs.end);
+ }
+
/* Catch a bug reported by Vin Shelton in
https://lists.gnu.org/r/bug-coreutils/2007-06/msg00089.html
*/
diff --git a/tests/test-simple-atomic.c b/tests/test-simple-atomic.c
new file mode 100644
index 0000000..04baf05
--- a/dev/null
+++ b/tests/test-simple-atomic.c
@@ -0,0 +1,234 @@
+/* Test of simple atomic operations for multithreading.
+ Copyright (C) 2021 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#include <config.h>
+
+#include "simple-atomic.h"
+
+#if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
+
+/* Whether to help the scheduler through explicit yield().
+ Uncomment this to see if the operating system has a fair scheduler. */
+#define EXPLICIT_YIELD 1
+
+/* Number of simultaneous threads. */
+#define THREAD_COUNT 4
+
+/* Number of operations performed in each thread.
+ With a smaller count, say 100, we often get an "OK" result even with the racy
+ implementation. */
+#define REPEAT_COUNT 1000
+
+#if EXPLICIT_YIELD
+# define yield() gl_thread_yield ()
+#else
+# define yield()
+#endif
+
+#include "glthread/thread.h"
+#include "glthread/yield.h"
+
+#include "macros.h"
+
+/* Counters for each thread. */
+static unsigned int counter[THREAD_COUNT][5];
+
+/* A variable of type 'unsigned int'. */
+static unsigned int int_variable;
+
+static void *
+int_mutator_thread (void *arg)
+{
+ int *pcounter = (int *) arg;
+ int repeat;
+
+ for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
+ {
+ if (atomic_compare_and_swap (&int_variable, 0, 10) == 0)
+ pcounter[0]++;
+ yield ();
+
+ if (atomic_compare_and_swap (&int_variable, 14, 17) == 14)
+ pcounter[1]++;
+ yield ();
+
+ if (atomic_compare_and_swap (&int_variable, 20, 0) == 20)
+ pcounter[2]++;
+ yield ();
+
+ if (atomic_compare_and_swap (&int_variable, 10, 14) == 10)
+ pcounter[3]++;
+ yield ();
+
+ if (atomic_compare_and_swap (&int_variable, 17, 20) == 17)
+ pcounter[4]++;
+ yield ();
+ }
+
+ return NULL;
+}
+
+/* A variable of type 'uintptr_t'. */
+static uintptr_t ptr_variable;
+
+static void *
+ptr_mutator_thread (void *arg)
+{
+ int *pcounter = (int *) arg;
+ int repeat;
+
+ for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
+ {
+ if (atomic_compare_and_swap_ptr (&ptr_variable, 0, 10) == 0)
+ pcounter[0]++;
+ yield ();
+
+ if (atomic_compare_and_swap_ptr (&ptr_variable, 14, 17) == 14)
+ pcounter[1]++;
+ yield ();
+
+ if (atomic_compare_and_swap_ptr (&ptr_variable, 20, 0) == 20)
+ pcounter[2]++;
+ yield ();
+
+ if (atomic_compare_and_swap_ptr (&ptr_variable, 10, 14) == 10)
+ pcounter[3]++;
+ yield ();
+
+ if (atomic_compare_and_swap_ptr (&ptr_variable, 17, 20) == 17)
+ pcounter[4]++;
+ yield ();
+ }
+
+ return NULL;
+}
+
+int
+main ()
+{
+ /* Check simple uses of atomic_compare_and_swap. */
+ {
+ unsigned int x[3] = { 0xDEADBEEFU, 11, 0xDEADBEEFU };
+
+ ASSERT (atomic_compare_and_swap (&x[1], 0, 17) == 11);
+ ASSERT (x[1] == 11);
+
+ ASSERT (atomic_compare_and_swap (&x[1], 4, 11) == 11);
+ ASSERT (x[1] == 11);
+
+ ASSERT (atomic_compare_and_swap (&x[1], 11, 15) == 11);
+ ASSERT (x[1] == 15);
+
+ ASSERT (x[0] == 0xDEADBEEFU);
+ ASSERT (x[2] == 0xDEADBEEFU);
+ }
+
+ /* Check simple uses of atomic_compare_and_swap_ptr. */
+ {
+ uintptr_t v1 = ~(uintptr_t)0 / 3;
+ uintptr_t v2 = ~(uintptr_t)0 / 5 * 4;
+ uintptr_t v3 = ~(uintptr_t)0 / 7 * 3;
+ uintptr_t x[3] = { 0xDEADBEEFU, v1, 0xDEADBEEFU };
+
+ ASSERT (atomic_compare_and_swap_ptr (&x[1], 0, v3) == v1);
+ ASSERT (x[1] == v1);
+
+ ASSERT (atomic_compare_and_swap_ptr (&x[1], 4, v1) == v1);
+ ASSERT (x[1] == v1);
+
+ ASSERT (atomic_compare_and_swap_ptr (&x[1], v1, v2) == v1);
+ ASSERT (x[1] == v2);
+
+ ASSERT (x[0] == 0xDEADBEEFU);
+ ASSERT (x[2] == 0xDEADBEEFU);
+ }
+
+ /* Check atomicity of atomic_compare_and_swap. */
+ {
+ void * (*funcs[2]) (void *) = { int_mutator_thread, ptr_mutator_thread };
+ int f;
+ for (f = 0; f < 2; f++)
+ {
+ void * (*func) (void *) = funcs[f];
+ int i, j;
+ gl_thread_t threads[THREAD_COUNT];
+
+ /* Initialization. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ for (j = 0; j < 5; j++)
+ counter[i][j] = 0;
+
+ /* Spawn the threads. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ threads[i] = gl_thread_create (func, &counter[i][0]);
+
+ /* Wait for the threads to terminate. */
+ for (i = 0; i < THREAD_COUNT; i++)
+ gl_thread_join (threads[i], NULL);
+
+ /* Sum up the work that the threads have done. */
+ unsigned int sum[5];
+ for (j = 0; j < 5; j++)
+ {
+ sum[j] = 0;
+ for (i = 0; i < THREAD_COUNT; i++)
+ sum[j] += counter[i][j];
+ }
+
+ /* If things went atomically, the threads have moved the variable's
+ value through the cycle 0 -> 10 -> 14 -> 17 -> 20 -> 0 ... a large
+ number of times.
+ sum[0] is the number of transitions 0 -> 10.
+ sum[3] is the number of transitions 10 -> 14.
+ sum[1] is the number of transitions 14 -> 17.
+ sum[4] is the number of transitions 17 -> 20.
+ sum[2] is the number of transitions 20 -> 0.
+ Since the cycle started at 0 and ends anywhere (namely, when all
+ threads when through their loop REPEAT_COUNT times), the sequence
+ sum[0], sum[3], sum[1], sum[4], sum[2], sum[0] - 1
+ must be monotonically decreasing.
+
+ If things did not go atomically, the counters don't exhibit this
+ pattern. */
+ printf ("Counters: %u %u %u %u %u\n",
+ sum[0], sum[3], sum[1], sum[4], sum[2]);
+ ASSERT ((sum[0] == sum[3] || sum[0] == sum[3] + 1)
+ && (sum[3] == sum[1] || sum[3] == sum[1] + 1)
+ && (sum[1] == sum[4] || sum[1] == sum[4] + 1)
+ && (sum[4] == sum[2] || sum[4] == sum[2] + 1)
+ && (sum[2] + 1 == sum[0] || sum[2] == sum[0]));
+ }
+ }
+
+ 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/tests/test-string-buffer.c b/tests/test-string-buffer.c
new file mode 100644
index 0000000..ecf5160
--- a/dev/null
+++ b/tests/test-string-buffer.c
@@ -0,0 +1,115 @@
+/* Test of buffer that accumulates a string by piecewise concatenation.
+ Copyright (C) 2021 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 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2021. */
+
+#include <config.h>
+
+#include "string-buffer.h"
+
+#include <string.h>
+
+#include "macros.h"
+
+static int
+my_appendf (struct string_buffer *buffer, const char *formatstring, ...)
+{
+ va_list args;
+
+ va_start (args, formatstring);
+ int ret = sb_appendvf (buffer, formatstring, args);
+ va_end (args);
+
+ return ret;
+}
+
+char invalid_format_string_1[] = "%&";
+char invalid_format_string_2[] = "%^";
+
+int
+main ()
+{
+ /* Test simple string concatenation. */
+ {
+ struct string_buffer buffer;
+
+ sb_init (&buffer);
+ char *s = sb_dupfree (&buffer);
+ ASSERT (s != NULL && strcmp (s, "") == 0);
+ free (s);
+ }
+
+ {
+ struct string_buffer buffer;
+
+ sb_init (&buffer);
+ sb_append (&buffer, "abc");
+ sb_append (&buffer, "");
+ sb_append (&buffer, "defg");
+ char *s = sb_dupfree (&buffer);
+ ASSERT (s != NULL && strcmp (s, "abcdefg") == 0);
+ free (s);
+ }
+
+ /* Test printf-like formatting. */
+ {
+ struct string_buffer buffer;
+
+ sb_init (&buffer);
+ sb_append (&buffer, "<");
+ sb_appendf (&buffer, "%x", 3735928559U);
+ sb_append (&buffer, ">");
+ char *s = sb_dupfree (&buffer);
+ ASSERT (s != NULL && strcmp (s, "<deadbeef>") == 0);
+ free (s);
+ }
+
+ /* Test vprintf-like formatting. */
+ {
+ struct string_buffer buffer;
+
+ sb_init (&buffer);
+ sb_append (&buffer, "<");
+ my_appendf (&buffer, "%x", 3735928559U);
+ sb_append (&buffer, ">");
+ char *s = sb_dupfree (&buffer);
+ ASSERT (s != NULL && strcmp (s, "<deadbeef>") == 0);
+ free (s);
+ }
+
+ /* Test printf-like formatting failure.
+ On all systems except AIX, trying to convert the wide-character 0x76543210
+ to a multibyte string (in the "C" locale) fails.
+ On all systems where REPLACE_VSNPRINTF=1 (this includes AIX), i.e. where
+ the Gnulib implementation of vsnprintf() is used), invalid format
+ directives make the *printf call fail. */
+ {
+ struct string_buffer buffer;
+
+ sb_init (&buffer);
+ sb_append (&buffer, "<");
+ sb_appendf (&buffer, "%lc", 0x76543210);
+ sb_append (&buffer, "|");
+ sb_appendf (&buffer, invalid_format_string_1, 1);
+ sb_append (&buffer, "|");
+ sb_appendf (&buffer, invalid_format_string_2, 2);
+ sb_append (&buffer, ">");
+ char *s = sb_dupfree (&buffer);
+ ASSERT (s == NULL);
+ }
+
+ return 0;
+}
diff --git a/top/maint.mk b/top/maint.mk
index 934f23d..ae3a817 100644
--- a/top/maint.mk
+++ b/top/maint.mk
@@ -64,7 +64,11 @@ VC_LIST = $(srcdir)/$(_build-aux)/vc-list-files -C $(srcdir)
# You can override this variable in cfg.mk if your gnulib submodule lives
# in a different location.
-gnulib_dir ?= $(srcdir)/gnulib
+gnulib_dir ?= $(shell if test -d $(srcdir)/gnulib; then \
+ echo $(srcdir)/gnulib; \
+ else \
+ echo ${GNULIB_SRCDIR}; \
+ fi)
# You can override this variable in cfg.mk to set your own regexp
# matching files to ignore.

Return to:

Send suggestions and report system problems to the System administrator.