From 50a5971be27ff11061776afc8014bbff22870b7c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 5 Mar 2021 15:52:33 -0800 Subject: [PATCH] RISC-V Freertos support (#582) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support reading names/status of all threads, as well as all registers that are stored on the stack. Limited to RV32, no FPU. --- * WIP Change-Id: I09417c2e45748504be449d74c39ae0b6b311e277 * WIP Change-Id: I975fa2cabbf43ccf64f5162337c394f9c8e3017f * Import rbtreehash-list from gnulib. The main change to get this to build was to remove 3 includes from config.h (actual code change in configure.ac) because lib/Makefile.am doesn't contain the correct flags to find the files referenced there. Instead I sprinkled necessary includes throughout the source code. This feels like less of a hack regardless, so hopefully that's OK. I'm not actually using the new library. Just got it to build. Change-Id: I824000d8be0b6f58b6f2036498b37c33f453515a * Actually use linkedhash_map. Moved some files around to get it to link. Also note I'm using a different module than before. This is the one I want (I think right now). Change-Id: I6161bffd4b5f916602c33c1930be6e061cefe982 * Properly track TCB/threadid mappings. Change-Id: I725abb96f880745d78c5634d5faff7385c2773e1 * OpenOCD no longer crashes reading rv32 freertos regs Change-Id: Ia84502dbf007145995d4fba8661153ab7f58f26f * WIP The register values reported for threads that aren't the current thread look believable to me. Change-Id: I94b109565c8cc2029fa77657a7fc10291bcb36e3 * Correctly mark the current thread. Change-Id: Id94ababb55a222292090e6465e47ebf92ca26291 * Try to make the build pass. Change-Id: I0fddd10fe22c013464f9a1e106cd21470fa7afe1 Signed-off-by: Tim Newsome * Exclude new gnulib files. Change-Id: I8b95615908034124f2236422771b5079f3304e37 Signed-off-by: Tim Newsome * Style fixes. Change-Id: I4aef0b1d0b0e366893c740ab89756fe8ea033ddb Signed-off-by: Tim Newsome * Don't include string.h. It breaks the i686-w64-mingw32-gcc build, which complains: error: incompatible implicit declaration of built-in function ‘strndup’ Change-Id: I8d758fe092efa503e015f71f34721f2c44632516 Signed-off-by: Tim Newsome * Hopefully fix mingw32 build. Change-Id: I8703b834b5679588b3aa6602ae4add7258dbd879 Signed-off-by: Tim Newsome * Include winsock2 in replacements. Change-Id: I77cfc90736c771a3cdefb39062e6c5b59de52cd5 Signed-off-by: Tim Newsome * Zero now gets the correct value. Change-Id: Ia7da043439a82081629b8a5991ed8cbc382d5ac8 Signed-off-by: Tim Newsome * Accommodate non-general regs on the stack. Also refactor FreeRTOS a little to separate out target-specific code from target-indepent code. Change-Id: Icc74d85b24f35d069be091e32e23144573560e9f * All registers now read sane values. It appears that FreeRTOS wastes a space on the stack, where x0 would be saved. Am I missing something? Correctly read mstatus as it is saved on the stack as well. This same mechanism should also work for FPU registers, although there's more work to be done before we get there. Change-Id: Iabacc3af2ab368aa7b9090c1ff719451a087b5ed Signed-off-by: Tim Newsome --- .travis.yml | 3 +- Makefile.am | 2 + bootstrap | 2 +- configure.ac | 9 +- src/Makefile.am | 4 + src/flash/common.h | 1 + src/flash/nor/bluenrg-x.c | 1 + src/gnulib/Makefile.am | 237 +++++ src/gnulib/attribute.h | 218 +++++ src/gnulib/gl_anyhash1.h | 31 + src/gnulib/gl_anyhash2.h | 82 ++ src/gnulib/gl_anyhash_primes.h | 87 ++ src/gnulib/gl_linkedhash_map.c | 330 +++++++ src/gnulib/gl_linkedhash_map.h | 34 + src/gnulib/gl_map.c | 3 + src/gnulib/gl_map.h | 370 ++++++++ src/gnulib/limits.in.h | 121 +++ src/gnulib/size_max.h | 30 + src/gnulib/stdbool.in.h | 132 +++ src/gnulib/stdint.in.h | 740 ++++++++++++++++ src/gnulib/sys_types.in.h | 106 +++ src/gnulib/xsize.c | 3 + src/gnulib/xsize.h | 108 +++ src/helper/binarybuffer.c | 1 + src/helper/bits.h | 1 + src/helper/configuration.c | 2 + src/helper/fileio.c | 1 + src/helper/fileio.h | 2 + src/helper/log.c | 1 + src/helper/options.c | 1 + src/helper/replacements.c | 1 + src/helper/replacements.h | 1 + src/helper/time_support.h | 1 + src/jtag/adapter.c | 4 - src/jtag/aice/aice_pipe.c | 1 + src/jtag/aice/aice_transport.c | 1 + src/jtag/aice/aice_usb.c | 1 + src/jtag/core.c | 1 + src/jtag/drivers/arm-jtag-ew.c | 1 + src/jtag/drivers/cmsis_dap.c | 1 + src/jtag/drivers/cmsis_dap_usb_bulk.c | 1 + src/jtag/drivers/jlink.c | 1 + src/jtag/drivers/jtag_usb_common.c | 1 + src/jtag/drivers/jtag_usb_common.h | 3 + src/jtag/drivers/jtag_vpi.c | 2 +- src/jtag/drivers/mpsse.c | 1 + src/jtag/drivers/remote_bitbang.c | 2 + src/jtag/drivers/rlink.c | 1 + src/jtag/drivers/rlink.h | 1 + src/jtag/drivers/stlink_usb.c | 1 + src/jtag/drivers/ulink.c | 1 + .../usb_blaster/ublast2_access_libusb.c | 1 + src/jtag/drivers/usb_blaster/usb_blaster.c | 1 + src/jtag/jtag.h | 1 + src/m4/00gnulib.m4 | 85 ++ src/m4/absolute-header.m4 | 100 +++ src/m4/extern-inline.m4 | 114 +++ src/m4/gnulib-cache.m4 | 57 ++ src/m4/gnulib-common.m4 | 727 +++++++++++++++ src/m4/gnulib-comp.m4 | 261 ++++++ src/m4/gnulib-tool.m4 | 57 ++ src/m4/include_next.m4 | 224 +++++ src/m4/limits-h.m4 | 43 + src/m4/multiarch.m4 | 65 ++ src/m4/off_t.m4 | 18 + src/m4/pid_t.m4 | 38 + src/m4/size_max.m4 | 75 ++ src/m4/ssize_t.m4 | 23 + src/m4/std-gnu11.m4 | 829 ++++++++++++++++++ src/m4/stdbool.m4 | 122 +++ src/m4/stdint.m4 | 533 +++++++++++ src/m4/sys_types_h.m4 | 58 ++ src/m4/wint_t.m4 | 57 ++ src/m4/xsize.m4 | 12 + src/m4/zzgnulib.m4 | 23 + src/main.c | 1 + src/pld/pld.c | 1 + src/pld/xilinx_bit.c | 2 +- src/pld/xilinx_bit.h | 2 + src/rtos/FreeRTOS.c | 352 +++++--- src/rtos/ThreadX.c | 18 +- src/rtos/nuttx.c | 18 +- src/rtos/rtos.c | 58 +- src/rtos/rtos.h | 21 +- src/rtos/rtos_chibios_stackings.c | 18 +- src/rtos/rtos_ecos_stackings.c | 10 +- src/rtos/rtos_embkernel_stackings.c | 10 +- src/rtos/rtos_mqx_stackings.c | 9 +- src/rtos/rtos_riot_stackings.c | 20 +- src/rtos/rtos_standard_stackings.c | 101 ++- src/rtos/rtos_standard_stackings.h | 2 + src/rtos/rtos_ucos_iii_stackings.c | 19 +- src/server/gdb_server.c | 3 +- src/server/server.h | 1 + src/svf/svf.c | 1 + src/target/algorithm.h | 3 + src/target/armv4_5_cache.h | 2 + src/target/breakpoints.h | 2 + src/target/image.h | 1 + src/target/nds32_edm.h | 2 + src/target/register.h | 3 + src/target/semihosting_common.h | 1 + src/target/target.h | 2 + src/target/trace.h | 2 + src/transport/transport.c | 1 + src/xsvf/xsvf.c | 1 + 106 files changed, 6686 insertions(+), 216 deletions(-) create mode 100644 src/gnulib/Makefile.am create mode 100644 src/gnulib/attribute.h create mode 100644 src/gnulib/gl_anyhash1.h create mode 100644 src/gnulib/gl_anyhash2.h create mode 100644 src/gnulib/gl_anyhash_primes.h create mode 100644 src/gnulib/gl_linkedhash_map.c create mode 100644 src/gnulib/gl_linkedhash_map.h create mode 100644 src/gnulib/gl_map.c create mode 100644 src/gnulib/gl_map.h create mode 100644 src/gnulib/limits.in.h create mode 100644 src/gnulib/size_max.h create mode 100644 src/gnulib/stdbool.in.h create mode 100644 src/gnulib/stdint.in.h create mode 100644 src/gnulib/sys_types.in.h create mode 100644 src/gnulib/xsize.c create mode 100644 src/gnulib/xsize.h create mode 100644 src/m4/00gnulib.m4 create mode 100644 src/m4/absolute-header.m4 create mode 100644 src/m4/extern-inline.m4 create mode 100644 src/m4/gnulib-cache.m4 create mode 100644 src/m4/gnulib-common.m4 create mode 100644 src/m4/gnulib-comp.m4 create mode 100644 src/m4/gnulib-tool.m4 create mode 100644 src/m4/include_next.m4 create mode 100644 src/m4/limits-h.m4 create mode 100644 src/m4/multiarch.m4 create mode 100644 src/m4/off_t.m4 create mode 100644 src/m4/pid_t.m4 create mode 100644 src/m4/size_max.m4 create mode 100644 src/m4/ssize_t.m4 create mode 100644 src/m4/std-gnu11.m4 create mode 100644 src/m4/stdbool.m4 create mode 100644 src/m4/stdint.m4 create mode 100644 src/m4/sys_types_h.m4 create mode 100644 src/m4/wint_t.m4 create mode 100644 src/m4/xsize.m4 create mode 100644 src/m4/zzgnulib.m4 diff --git a/.travis.yml b/.travis.yml index bbf2319b2..d0bc8f261 100644 --- a/.travis.yml +++ b/.travis.yml @@ -69,7 +69,8 @@ script: # so this should work fine most of the time, and be a lot better than not # checking at all. - git diff -U20 HEAD~40 | - filterdiff -x "a/src/jtag/drivers/libjaylink/*" -x "a/tools/git2cl/*" | + filterdiff -x "a/src/jtag/drivers/libjaylink/*" -x "a/tools/git2cl/*" + -x "b/src/gnulib/*" | ./tools/scripts/checkpatch.pl --no-signoff - - ./bootstrap && ./configure --enable-remote-bitbang --enable-jtag_vpi $CONFIGURE_ARGS && make - file src/$EXECUTABLE diff --git a/Makefile.am b/Makefile.am index 9c068db36..5d699b934 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,6 +28,8 @@ SUBDIRS += jimtcl DIST_SUBDIRS += jimtcl endif +ACLOCAL_AMFLAGS = -I m4 + # common flags used in openocd build AM_CFLAGS = $(GCC_WARNINGS) diff --git a/bootstrap b/bootstrap index e81ba4d02..8edb17220 100755 --- a/bootstrap +++ b/bootstrap @@ -24,7 +24,7 @@ fi # bootstrap the autotools ( set -x -aclocal --warnings=all +aclocal --warnings=all -I src/m4 # Apparently, not all versions of libtoolize support option --warnings=all . ${libtoolize} --automake --copy autoconf --warnings=all diff --git a/configure.ac b/configure.ac index 19bece082..955b1b0e9 100644 --- a/configure.ac +++ b/configure.ac @@ -17,14 +17,10 @@ AC_SUBST([MAKEINFO]) AM_INIT_AUTOMAKE([-Wall -Wno-portability dist-bzip2 dist-zip subdir-objects]) AC_CONFIG_HEADERS([config.h]) -AH_BOTTOM([ -#include -#include -#include -]) AC_LANG([C]) AC_PROG_CC +gl_EARLY # autoconf 2.70 obsoletes AC_PROG_CC_C99 and includes it in AC_PROG_CC m4_version_prereq([2.70],[],[AC_PROG_CC_C99]) AM_PROG_CC_C_O @@ -91,6 +87,8 @@ AC_CHECK_FUNCS([usleep]) AC_CHECK_FUNCS([vasprintf]) AC_CHECK_FUNCS([realpath]) +gl_INIT + # guess-rev.sh only exists in the repository, not in the released archives AC_MSG_CHECKING([whether to build a release]) AS_IF([test -x "$srcdir/guess-rev.sh"], [ @@ -857,6 +855,7 @@ AS_IF([test "x$gcc_warnings" = "xyes"], [ AC_CONFIG_FILES([ Makefile + src/gnulib/Makefile ]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 781c1e74f..41153fb61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,5 @@ +SUBDIRS += src/gnulib + noinst_LTLIBRARIES += %D%/libopenocd.la bin_PROGRAMS += %D%/openocd @@ -19,6 +21,7 @@ else endif %C%_libopenocd_la_CPPFLAGS = +%C%_openocd_LDADD += src/gnulib/libgnu.a # banner output includes RELSTR appended to $VERSION from the configure script # guess-rev.sh returns either a repository version ID or "-snapshot" @@ -60,6 +63,7 @@ BIN2C = $(srcdir)/%D%/helper/bin2char.sh STARTUP_TCL_SRCS = EXTRA_DIST += $(STARTUP_TCL_SRCS) +EXTRA_DIST += m4/gnulib-cache.m4 BUILT_SOURCES += %D%/startup_tcl.inc diff --git a/src/flash/common.h b/src/flash/common.h index 4244f1360..69f60d9a3 100644 --- a/src/flash/common.h +++ b/src/flash/common.h @@ -19,6 +19,7 @@ #define OPENOCD_FLASH_COMMON_H #include +#include /** * Parses the optional '.index' portion of a flash bank identifier. diff --git a/src/flash/nor/bluenrg-x.c b/src/flash/nor/bluenrg-x.c index 57aebc597..cf968cb8c 100644 --- a/src/flash/nor/bluenrg-x.c +++ b/src/flash/nor/bluenrg-x.c @@ -20,6 +20,7 @@ #include "config.h" #endif +#include "helper/types.h" #include #include #include diff --git a/src/gnulib/Makefile.am b/src/gnulib/Makefile.am new file mode 100644 index 000000000..62accdfe2 --- /dev/null +++ b/src/gnulib/Makefile.am @@ -0,0 +1,237 @@ +## DO NOT EDIT! GENERATED AUTOMATICALLY! +## Process this file with automake to produce Makefile.in. +# Copyright (C) 2002-2021 Free Software Foundation, Inc. +# +# 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 +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# Reproduce by: +# gnulib-tool --import \ +# --lib=libgnu \ +# --source-base=src/gnulib \ +# --m4-base=src/m4 \ +# --doc-base=doc \ +# --tests-base=tests \ +# --aux-dir=. \ +# --no-conditional-dependencies \ +# --no-libtool \ +# --macro-prefix=gl \ +# linkedhash-map + +AUTOMAKE_OPTIONS = 1.11 gnits + +SUBDIRS = +noinst_HEADERS = +noinst_LIBRARIES = +noinst_LTLIBRARIES = +EXTRA_DIST = +BUILT_SOURCES = +SUFFIXES = +MOSTLYCLEANFILES = core *.stackdump +MOSTLYCLEANDIRS = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = +# No GNU Make output. + +AM_CPPFLAGS = +AM_CFLAGS = + +noinst_LIBRARIES += libgnu.a + +libgnu_a_SOURCES = +libgnu_a_LIBADD = $(gl_LIBOBJS) +libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) +EXTRA_libgnu_a_SOURCES = + +## begin gnulib module absolute-header + +# Use this preprocessor expression to decide whether #include_next works. +# Do not rely on a 'configure'-time test for this, since the expression +# might appear in an installed header, which is used by some other compiler. +HAVE_INCLUDE_NEXT = (__GNUC__ || __clang__ || 60000000 <= __DECC_VER) + +## end gnulib module absolute-header + +## begin gnulib module attribute + + +EXTRA_DIST += attribute.h + +## end gnulib module attribute + +## begin gnulib module limits-h + +BUILT_SOURCES += $(LIMITS_H) + +# We need the following in order to create when the system +# doesn't have one that is compatible with GNU. +if GL_GENERATE_LIMITS_H +limits.h: limits.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LIMITS_H''@|$(NEXT_LIMITS_H)|g' \ + < $(srcdir)/limits.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +limits.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += limits.h limits.h-t + +EXTRA_DIST += limits.in.h + +## end gnulib module limits-h + +## begin gnulib module linkedhash-map + +libgnu_a_SOURCES += gl_linkedhash_map.h gl_linkedhash_map.c gl_anyhash1.h gl_anyhash2.h gl_anyhash_primes.h + +## end gnulib module linkedhash-map + +## begin gnulib module map + +libgnu_a_SOURCES += gl_map.h gl_map.c + +## end gnulib module map + +## begin gnulib module size_max + +libgnu_a_SOURCES += size_max.h + +## end gnulib module size_max + +## begin gnulib module stdbool + +BUILT_SOURCES += $(STDBOOL_H) + +# We need the following in order to create when the system +# doesn't have one that works. +if GL_GENERATE_STDBOOL_H +stdbool.h: stdbool.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdbool.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdbool.h stdbool.h-t + +EXTRA_DIST += stdbool.in.h + +## end gnulib module stdbool + +## begin gnulib module stdint + +BUILT_SOURCES += $(STDINT_H) + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_STDINT_H +stdint.h: stdint.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \ + -e 's/@''HAVE_C99_STDINT_H''@/$(HAVE_C99_STDINT_H)/g' \ + -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ + -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ + -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ + -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ + -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \ + -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \ + -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ + -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ + -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ + -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ + -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ + -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ + -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ + -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ + -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ + -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \ + < $(srcdir)/stdint.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdint.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdint.h stdint.h-t + +EXTRA_DIST += stdint.in.h + +## end gnulib module stdint + +## begin gnulib module sys_types + +BUILT_SOURCES += sys/types.h + +# We need the following in order to create when the system +# doesn't have one that works with the given compiler. +sys/types.h: sys_types.in.h $(top_builddir)/config.status + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \ + < $(srcdir)/sys_types.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/types.h sys/types.h-t + +EXTRA_DIST += sys_types.in.h + +## end gnulib module sys_types + +## begin gnulib module xsize + +libgnu_a_SOURCES += xsize.h xsize.c + +## end gnulib module xsize + + +mostlyclean-local: mostlyclean-generic + @for dir in '' $(MOSTLYCLEANDIRS); do \ + if test -n "$$dir" && test -d $$dir; then \ + echo "rmdir $$dir"; rmdir $$dir; \ + fi; \ + done; \ + : diff --git a/src/gnulib/attribute.h b/src/gnulib/attribute.h new file mode 100644 index 000000000..82245279e --- /dev/null +++ b/src/gnulib/attribute.h @@ -0,0 +1,218 @@ +/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers + + Copyright 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 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 . */ + +/* Written by Paul Eggert. */ + +/* Provide public ATTRIBUTE_* names for the private _GL_ATTRIBUTE_* + macros used within Gnulib. */ + +/* These attributes can be placed in two ways: + - At the start of a declaration (i.e. even before storage-class + specifiers!); then they apply to all entities that are declared + by the declaration. + - Immediately after the name of an entity being declared by the + declaration; then they apply to that entity only. */ + +#ifndef _GL_ATTRIBUTE_H +#define _GL_ATTRIBUTE_H + + +/* This file defines two types of attributes: + * C2X standard attributes. These have macro names that do not begin with + 'ATTRIBUTE_'. + * Selected GCC attributes; see: + https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html + https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html + https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html + These names begin with 'ATTRIBUTE_' to avoid name clashes. */ + + +/* =============== Attributes for specific kinds of functions =============== */ + +/* Attributes for functions that should not be used. */ + +/* Warn if the entity is used. */ +/* Applies to: + - function, variable, + - struct, union, struct/union member, + - enumeration, enumeration item, + - typedef, + in C++ also: namespace, class, template specialization. */ +#define DEPRECATED _GL_ATTRIBUTE_DEPRECATED + +/* If a function call is not optimized way, warn with MSG. */ +/* Applies to: functions. */ +#define ATTRIBUTE_WARNING(msg) _GL_ATTRIBUTE_WARNING (msg) + +/* If a function call is not optimized way, report an error with MSG. */ +/* Applies to: functions. */ +#define ATTRIBUTE_ERROR(msg) _GL_ATTRIBUTE_ERROR (msg) + + +/* Attributes for memory-allocating functions. */ + +/* The function returns a pointer to freshly allocated memory. */ +/* Applies to: functions. */ +#define ATTRIBUTE_MALLOC _GL_ATTRIBUTE_MALLOC + +/* ATTRIBUTE_ALLOC_SIZE ((N)) - The Nth argument of the function + is the size of the returned memory block. + ATTRIBUTE_ALLOC_SIZE ((M, N)) - Multiply the Mth and Nth arguments + to determine the size of the returned memory block. */ +/* Applies to: function, pointer to function, function types. */ +#define ATTRIBUTE_ALLOC_SIZE(args) _GL_ATTRIBUTE_ALLOC_SIZE (args) + + +/* Attributes for variadic functions. */ + +/* The variadic function expects a trailing NULL argument. + ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99). + ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */ +/* Applies to: functions. */ +#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos) + + +/* ================== Attributes for compiler diagnostics ================== */ + +/* Attributes that help the compiler diagnose programmer mistakes. + Some of them may also help for some compiler optimizations. */ + +/* ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) - + The STRING-INDEXth function argument is a format string of style + ARCHETYPE, which is one of: + printf, gnu_printf + scanf, gnu_scanf, + strftime, gnu_strftime, + strfmon, + or the same thing prefixed and suffixed with '__'. + If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK + are suitable for the format string. */ +/* Applies to: functions. */ +#define ATTRIBUTE_FORMAT(spec) _GL_ATTRIBUTE_FORMAT (spec) + +/* ATTRIBUTE_NONNULL ((N1, N2,...)) - Arguments N1, N2,... must not be NULL. + ATTRIBUTE_NONNULL () - All pointer arguments must not be null. */ +/* Applies to: functions. */ +#define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args) + +/* The function's return value is a non-NULL pointer. */ +/* Applies to: functions. */ +#define ATTRIBUTE_RETURNS_NONNULL _GL_ATTRIBUTE_RETURNS_NONNULL + +/* Warn if the caller does not use the return value, + unless the caller uses something like ignore_value. */ +/* Applies to: function, enumeration, class. */ +#define NODISCARD _GL_ATTRIBUTE_NODISCARD + + +/* Attributes that disable false alarms when the compiler diagnoses + programmer "mistakes". */ + +/* Do not warn if the entity is not used. */ +/* Applies to: + - function, variable, + - struct, union, struct/union member, + - enumeration, enumeration item, + - typedef, + in C++ also: class. */ +#define MAYBE_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED + +/* The contents of a character array is not meant to be NUL-terminated. */ +/* Applies to: struct/union members and variables that are arrays of element + type '[[un]signed] char'. */ +#define ATTRIBUTE_NONSTRING _GL_ATTRIBUTE_NONSTRING + +/* Do not warn if control flow falls through to the immediately + following 'case' or 'default' label. */ +/* Applies to: Empty statement (;), inside a 'switch' statement. */ +#define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH + + +/* ================== Attributes for debugging information ================== */ + +/* Attributes regarding debugging information emitted by the compiler. */ + +/* Omit the function from stack traces when debugging. */ +/* Applies to: function. */ +#define ATTRIBUTE_ARTIFICIAL _GL_ATTRIBUTE_ARTIFICIAL + +/* Make the entity visible to debuggers etc., even with '-fwhole-program'. */ +/* Applies to: functions, variables. */ +#define ATTRIBUTE_EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE + + +/* ========== Attributes that mainly direct compiler optimizations ========== */ + +/* The function does not throw exceptions. */ +/* Applies to: functions. */ +#define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW + +/* Do not inline the function. */ +/* Applies to: functions. */ +#define ATTRIBUTE_NOINLINE _GL_ATTRIBUTE_NOINLINE + +/* Always inline the function, and report an error if the compiler + cannot inline. */ +/* Applies to: function. */ +#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE + +/* It is OK for a compiler to omit duplicate calls with the same arguments. + This attribute is safe for a function that neither depends on + nor affects observable state, and always returns exactly once - + e.g., does not loop forever, and does not call longjmp. + (This attribute is stricter than ATTRIBUTE_PURE.) */ +/* Applies to: functions. */ +#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST + +/* It is OK for a compiler to omit duplicate calls with the same + arguments if observable state is not changed between calls. + This attribute is safe for a function that does not affect + observable state, and always returns exactly once. + (This attribute is looser than ATTRIBUTE_CONST.) */ +/* Applies to: functions. */ +#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE + +/* The function is rarely executed. */ +/* Applies to: functions. */ +#define ATTRIBUTE_COLD _GL_ATTRIBUTE_COLD + +/* If called from some other compilation unit, the function executes + code from that unit only by return or by exception handling, + letting the compiler optimize that unit more aggressively. */ +/* Applies to: functions. */ +#define ATTRIBUTE_LEAF _GL_ATTRIBUTE_LEAF + +/* For struct members: The member has the smallest possible alignment. + For struct, union, class: All members have the smallest possible alignment, + minimizing the memory required. */ +/* Applies to: struct members, struct, union, + in C++ also: class. */ +#define ATTRIBUTE_PACKED _GL_ATTRIBUTE_PACKED + + +/* ================ Attributes that make invalid code valid ================ */ + +/* Attributes that prevent fatal compiler optimizations for code that is not + fully ISO C compliant. */ + +/* Pointers to the type may point to the same storage as pointers to + other types, thus disabling strict aliasing optimization. */ +/* Applies to: types. */ +#define ATTRIBUTE_MAY_ALIAS _GL_ATTRIBUTE_MAY_ALIAS + + +#endif /* _GL_ATTRIBUTE_H */ diff --git a/src/gnulib/gl_anyhash1.h b/src/gnulib/gl_anyhash1.h new file mode 100644 index 000000000..3253673bd --- /dev/null +++ b/src/gnulib/gl_anyhash1.h @@ -0,0 +1,31 @@ +/* Hash table for sequential list, set, and map data type. + Copyright (C) 2006, 2009-2021 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + 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 . */ + +/* Common code of + gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c, + gl_linkedhash_set.c, gl_hash_set.c, + gl_linkedhash_map.c, gl_hash_map.c. */ + +/* Hash table entry. */ +struct gl_hash_entry +{ + struct gl_hash_entry *hash_next; /* chain of entries in same bucket */ + size_t hashcode; /* cache of the hash code of + - the key (for map data type) or + - the value (for list, set data types) */ +}; +typedef struct gl_hash_entry * gl_hash_entry_t; diff --git a/src/gnulib/gl_anyhash2.h b/src/gnulib/gl_anyhash2.h new file mode 100644 index 000000000..d8b5fb051 --- /dev/null +++ b/src/gnulib/gl_anyhash2.h @@ -0,0 +1,82 @@ +/* Hash table for sequential list, set, and map data type. + Copyright (C) 2006, 2009-2021 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + 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 . */ + +/* Common code of + gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c, + gl_linkedhash_set.c, gl_hash_set.c, + gl_linkedhash_map.c, gl_hash_map.c. */ + +#include "gl_anyhash_primes.h" + +/* Resizes the hash table with a new estimated size. */ +static void +hash_resize (CONTAINER_T container, size_t estimate) +{ + size_t new_size = next_prime (estimate); + + if (new_size > container->table_size) + { + gl_hash_entry_t *old_table = container->table; + /* Allocate the new table. */ + gl_hash_entry_t *new_table; + size_t i; + + if (size_overflow_p (xtimes (new_size, sizeof (gl_hash_entry_t)))) + goto fail; + new_table = + (gl_hash_entry_t *) calloc (new_size, sizeof (gl_hash_entry_t)); + if (new_table == NULL) + goto fail; + + /* Iterate through the entries of the old table. */ + for (i = container->table_size; i > 0; ) + { + gl_hash_entry_t node = old_table[--i]; + + while (node != NULL) + { + gl_hash_entry_t next = node->hash_next; + /* Add the entry to the new table. */ + size_t bucket = node->hashcode % new_size; + node->hash_next = new_table[bucket]; + new_table[bucket] = node; + + node = next; + } + } + + container->table = new_table; + container->table_size = new_size; + free (old_table); + } + return; + + fail: + /* Just continue without resizing the table. */ + return; +} + +/* Resizes the hash table if needed, after CONTAINER_COUNT (container) was + incremented. */ +static void +hash_resize_after_add (CONTAINER_T container) +{ + size_t count = CONTAINER_COUNT (container); + size_t estimate = xsum (count, count / 2); /* 1.5 * count */ + if (estimate > container->table_size) + hash_resize (container, estimate); +} diff --git a/src/gnulib/gl_anyhash_primes.h b/src/gnulib/gl_anyhash_primes.h new file mode 100644 index 000000000..b723e6494 --- /dev/null +++ b/src/gnulib/gl_anyhash_primes.h @@ -0,0 +1,87 @@ +/* Table of primes, for use by hash tables. + Copyright (C) 2006, 2009-2021 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + 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 . */ + +/* Array of primes, approximately in steps of factor 1.2. + This table was computed by executing the Common Lisp expression + (dotimes (i 244) (format t "nextprime(~D)~%" (ceiling (expt 1.2d0 i)))) + and feeding the result to PARI/gp. */ +static const size_t primes[] = + { + 11, 13, 17, 19, 23, 29, 37, 41, 47, 59, 67, 83, 97, 127, 139, 167, 199, + 239, 293, 347, 419, 499, 593, 709, 853, 1021, 1229, 1471, 1777, 2129, 2543, + 3049, 3659, 4391, 5273, 6323, 7589, 9103, 10937, 13109, 15727, 18899, + 22651, 27179, 32609, 39133, 46957, 56359, 67619, 81157, 97369, 116849, + 140221, 168253, 201907, 242309, 290761, 348889, 418667, 502409, 602887, + 723467, 868151, 1041779, 1250141, 1500181, 1800191, 2160233, 2592277, + 3110741, 3732887, 4479463, 5375371, 6450413, 7740517, 9288589, 11146307, + 13375573, 16050689, 19260817, 23112977, 27735583, 33282701, 39939233, + 47927081, 57512503, 69014987, 82818011, 99381577, 119257891, 143109469, + 171731387, 206077643, 247293161, 296751781, 356102141, 427322587, + 512787097, 615344489, 738413383, 886096061, 1063315271, 1275978331, + 1531174013, 1837408799, 2204890543UL, 2645868653UL, 3175042391UL, + 3810050851UL, +#if SIZE_MAX > 4294967295UL + 4572061027UL, 5486473229UL, 6583767889UL, 7900521449UL, 9480625733UL, + 11376750877UL, 13652101063UL, 16382521261UL, 19659025513UL, 23590830631UL, + 28308996763UL, 33970796089UL, 40764955463UL, 48917946377UL, 58701535657UL, + 70441842749UL, 84530211301UL, 101436253561UL, 121723504277UL, + 146068205131UL, 175281846149UL, 210338215379UL, 252405858521UL, + 302887030151UL, 363464436191UL, 436157323417UL, 523388788231UL, + 628066545713UL, 753679854847UL, 904415825857UL, 1085298991109UL, + 1302358789181UL, 1562830547009UL, 1875396656429UL, 2250475987709UL, + 2700571185239UL, 3240685422287UL, 3888822506759UL, 4666587008147UL, + 5599904409713UL, 6719885291641UL, 8063862349969UL, 9676634819959UL, + 11611961783951UL, 13934354140769UL, 16721224968907UL, 20065469962669UL, + 24078563955191UL, 28894276746229UL, 34673132095507UL, 41607758514593UL, + 49929310217531UL, 59915172260971UL, 71898206713183UL, 86277848055823UL, + 103533417666967UL, 124240101200359UL, 149088121440451UL, 178905745728529UL, + 214686894874223UL, 257624273849081UL, 309149128618903UL, 370978954342639UL, + 445174745211143UL, 534209694253381UL, 641051633104063UL, 769261959724877UL, + 923114351670013UL, 1107737222003791UL, 1329284666404567UL, + 1595141599685509UL, 1914169919622551UL, 2297003903547091UL, + 2756404684256459UL, 3307685621107757UL, 3969222745329323UL, + 4763067294395177UL, 5715680753274209UL, 6858816903929113UL, + 8230580284714831UL, 9876696341657791UL, 11852035609989371UL, + 14222442731987227UL, 17066931278384657UL, 20480317534061597UL, + 24576381040873903UL, 29491657249048679UL, 35389988698858471UL, + 42467986438630267UL, 50961583726356109UL, 61153900471627387UL, + 73384680565952851UL, 88061616679143347UL, 105673940014972061UL, + 126808728017966413UL, 152170473621559703UL, 182604568345871671UL, + 219125482015045997UL, 262950578418055169UL, 315540694101666193UL, + 378648832921999397UL, 454378599506399233UL, 545254319407679131UL, + 654305183289214771UL, 785166219947057701UL, 942199463936469157UL, + 1130639356723763129UL, 1356767228068515623UL, 1628120673682218619UL, + 1953744808418662409UL, 2344493770102394881UL, 2813392524122873857UL, + 3376071028947448339UL, 4051285234736937517UL, 4861542281684325481UL, + 5833850738021191727UL, 7000620885625427969UL, 8400745062750513217UL, + 10080894075300616261UL, 12097072890360739951UL, 14516487468432885797UL, + 17419784962119465179UL, +#endif + SIZE_MAX /* sentinel, to ensure the search terminates */ + }; + +/* Returns a suitable prime >= ESTIMATE. */ +static size_t +next_prime (size_t estimate) +{ + size_t i; + + for (i = 0; i < sizeof (primes) / sizeof (primes[0]); i++) + if (primes[i] >= estimate) + return primes[i]; + return SIZE_MAX; /* not a prime, but better than nothing */ +} diff --git a/src/gnulib/gl_linkedhash_map.c b/src/gnulib/gl_linkedhash_map.c new file mode 100644 index 000000000..e2cf9fbf1 --- /dev/null +++ b/src/gnulib/gl_linkedhash_map.c @@ -0,0 +1,330 @@ +/* Map data type implemented by a hash table with a linked list. + Copyright (C) 2006, 2008-2021 Free Software Foundation, Inc. + Written by Bruno Haible , 2018. + + 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 . */ + +#include + +/* Specification. */ +#include "gl_linkedhash_map.h" + +#include /* for uintptr_t, SIZE_MAX */ +#include + +#include "xsize.h" + +/* --------------------------- gl_map_t Data Type --------------------------- */ + +#include "gl_anyhash1.h" + +/* Concrete list node implementation, valid for this file only. */ +struct gl_list_node_impl +{ + struct gl_hash_entry h; /* hash table entry fields; must be first */ + struct gl_list_node_impl *next; + struct gl_list_node_impl *prev; + const void *key; + const void *value; +}; +typedef struct gl_list_node_impl * gl_list_node_t; + +/* Concrete gl_map_impl type, valid for this file only. */ +struct gl_map_impl +{ + struct gl_map_impl_base base; + gl_mapkey_hashcode_fn hashcode_fn; + /* A hash table: managed as an array of collision lists. */ + struct gl_hash_entry **table; + size_t table_size; + /* A circular list anchored at root. + The first node is = root.next, the last node is = root.prev. + The root's value is unused. */ + struct gl_list_node_impl root; + /* Number of list nodes, excluding the root. */ + size_t count; +}; + +#define CONTAINER_T gl_map_t +#define CONTAINER_COUNT(map) (map)->count +#include "gl_anyhash2.h" + +/* If the symbol SIGNAL_SAFE_MAP is defined, the code is compiled in such + a way that a gl_map_t data structure may be used from within a signal + handler. The operations allowed in the signal handler are: + gl_map_iterator, gl_map_iterator_next, gl_map_iterator_free. + The map and node fields that are therefore accessed from the signal handler + are: + map->root, node->next, node->value. + We are careful to make modifications to these fields only in an order + that maintains the consistency of the list data structure at any moment, + and we use 'volatile' assignments to prevent the compiler from reordering + such assignments. */ +#ifdef SIGNAL_SAFE_MAP +# define ASYNCSAFE(type) *(type volatile *)& +#else +# define ASYNCSAFE(type) +#endif + +/* --------------------------- gl_map_t Data Type --------------------------- */ + +static gl_map_t +gl_linkedhash_nx_create_empty (gl_map_implementation_t implementation, + gl_mapkey_equals_fn equals_fn, + gl_mapkey_hashcode_fn hashcode_fn, + gl_mapkey_dispose_fn kdispose_fn, + gl_mapvalue_dispose_fn vdispose_fn) +{ + struct gl_map_impl *map = + (struct gl_map_impl *) malloc (sizeof (struct gl_map_impl)); + + if (map == NULL) + return NULL; + + map->base.vtable = implementation; + map->base.equals_fn = equals_fn; + map->base.kdispose_fn = kdispose_fn; + map->base.vdispose_fn = vdispose_fn; + map->hashcode_fn = hashcode_fn; + map->table_size = 11; + map->table = + (gl_hash_entry_t *) calloc (map->table_size, sizeof (gl_hash_entry_t)); + if (map->table == NULL) + goto fail; + map->root.next = &map->root; + map->root.prev = &map->root; + map->count = 0; + + return map; + + fail: + free (map); + return NULL; +} + +static size_t _GL_ATTRIBUTE_PURE +gl_linkedhash_size (gl_map_t map) +{ + return map->count; +} + +static bool _GL_ATTRIBUTE_PURE +gl_linkedhash_search (gl_map_t map, const void *key, const void **valuep) +{ + size_t hashcode = + (map->hashcode_fn != NULL + ? map->hashcode_fn (key) + : (size_t)(uintptr_t) key); + size_t bucket = hashcode % map->table_size; + gl_mapkey_equals_fn equals = map->base.equals_fn; + + /* Look for a match in the hash bucket. */ + gl_list_node_t node; + + for (node = (gl_list_node_t) map->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (key, node->key) + : key == node->key)) + { + *valuep = node->value; + return true; + } + return false; +} + +static int +gl_linkedhash_nx_getput (gl_map_t map, const void *key, const void *value, + const void **oldvaluep) +{ + size_t hashcode = + (map->hashcode_fn != NULL + ? map->hashcode_fn (key) + : (size_t)(uintptr_t) key); + size_t bucket = hashcode % map->table_size; + gl_mapkey_equals_fn equals = map->base.equals_fn; + + /* Look for a match in the hash bucket. */ + { + gl_list_node_t node; + + for (node = (gl_list_node_t) map->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (key, node->key) + : key == node->key)) + { + *oldvaluep = node->value; + node->value = value; + return 0; + } + } + + /* Allocate a new node. */ + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (node == NULL) + return -1; + + ASYNCSAFE(const void *) node->key = key; + ASYNCSAFE(const void *) node->value = value; + node->h.hashcode = hashcode; + + /* Add node to the hash table. */ + node->h.hash_next = map->table[bucket]; + map->table[bucket] = &node->h; + + /* Add node to the map. */ + ASYNCSAFE(gl_list_node_t) node->next = &map->root; + node->prev = map->root.prev; + ASYNCSAFE(gl_list_node_t) node->prev->next = node; + map->root.prev = node; + map->count++; + + hash_resize_after_add (map); + + return 1; +} + +static bool +gl_linkedhash_getremove (gl_map_t map, const void *key, const void **oldvaluep) +{ + size_t hashcode = + (map->hashcode_fn != NULL + ? map->hashcode_fn (key) + : (size_t)(uintptr_t) key); + size_t bucket = hashcode % map->table_size; + gl_mapkey_equals_fn equals = map->base.equals_fn; + + /* Look for the first match in the hash bucket. */ + gl_list_node_t *nodep; + + for (nodep = (gl_list_node_t *) &map->table[bucket]; + *nodep != NULL; + nodep = (gl_list_node_t *) &(*nodep)->h.hash_next) + { + gl_list_node_t node = *nodep; + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (key, node->key) + : key == node->key)) + { + *oldvaluep = node->value; + + /* Remove node from the hash table. */ + *nodep = (gl_list_node_t) node->h.hash_next; + + /* Remove node from the list. */ + { + gl_list_node_t prev = node->prev; + gl_list_node_t next = node->next; + + ASYNCSAFE(gl_list_node_t) prev->next = next; + next->prev = prev; + } + map->count--; + + if (map->base.kdispose_fn != NULL) + map->base.kdispose_fn (node->key); + free (node); + return true; + } + } + + return false; +} + +static void +gl_linkedhash_free (gl_map_t map) +{ + gl_mapkey_dispose_fn kdispose = map->base.kdispose_fn; + gl_mapvalue_dispose_fn vdispose = map->base.vdispose_fn; + gl_list_node_t node; + + for (node = map->root.next; node != &map->root; ) + { + gl_list_node_t next = node->next; + if (vdispose != NULL) + vdispose (node->value); + if (kdispose != NULL) + kdispose (node->key); + free (node); + node = next; + } + free (map->table); + free (map); +} + +/* ---------------------- gl_map_iterator_t Data Type ---------------------- */ + +/* Iterate through the list, not through the hash buckets, so that the order + in which the pairs are returned is predictable. */ + +static gl_map_iterator_t +gl_linkedhash_iterator (gl_map_t map) +{ + gl_map_iterator_t result; + + result.vtable = map->base.vtable; + result.map = map; + result.p = map->root.next; + result.q = &map->root; +#if defined GCC_LINT || defined lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static bool +gl_linkedhash_iterator_next (gl_map_iterator_t *iterator, + const void **keyp, const void **valuep) +{ + if (iterator->p != iterator->q) + { + gl_list_node_t node = (gl_list_node_t) iterator->p; + *keyp = node->key; + *valuep = node->value; + iterator->p = node->next; + return true; + } + else + return false; +} + +static void +gl_linkedhash_iterator_free (gl_map_iterator_t *iterator) +{ +} + + +const struct gl_map_implementation gl_linkedhash_map_implementation = + { + gl_linkedhash_nx_create_empty, + gl_linkedhash_size, + gl_linkedhash_search, + gl_linkedhash_nx_getput, + gl_linkedhash_getremove, + gl_linkedhash_free, + gl_linkedhash_iterator, + gl_linkedhash_iterator_next, + gl_linkedhash_iterator_free + }; diff --git a/src/gnulib/gl_linkedhash_map.h b/src/gnulib/gl_linkedhash_map.h new file mode 100644 index 000000000..56c2f3df1 --- /dev/null +++ b/src/gnulib/gl_linkedhash_map.h @@ -0,0 +1,34 @@ +/* Map data type implemented by a hash table with a linked list. + Copyright (C) 2006, 2009-2021 Free Software Foundation, Inc. + Written by Bruno Haible , 2018. + + 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 . */ + +#ifndef _GL_LINKEDHASH_MAP_H +#define _GL_LINKEDHASH_MAP_H + +#include "gl_map.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const struct gl_map_implementation gl_linkedhash_map_implementation; +#define GL_LINKEDHASH_MAP &gl_linkedhash_map_implementation + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_LINKEDHASH_MAP_H */ diff --git a/src/gnulib/gl_map.c b/src/gnulib/gl_map.c new file mode 100644 index 000000000..758a65f3d --- /dev/null +++ b/src/gnulib/gl_map.c @@ -0,0 +1,3 @@ +#include +#define GL_MAP_INLINE _GL_EXTERN_INLINE +#include "gl_map.h" diff --git a/src/gnulib/gl_map.h b/src/gnulib/gl_map.h new file mode 100644 index 000000000..051ec5944 --- /dev/null +++ b/src/gnulib/gl_map.h @@ -0,0 +1,370 @@ +/* Abstract map data type. + Copyright (C) 2006-2007, 2009-2021 Free Software Foundation, Inc. + Written by Bruno Haible , 2018. + + 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 . */ + +#ifndef _GL_MAP_H +#define _GL_MAP_H + +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef GL_MAP_INLINE +# define GL_MAP_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* gl_map is an abstract map data type. It can contain any number of + (key, value) pairs, where + - keys and values are objects ('void *' or 'const void *' pointers), + - There are no (key, value1) and (key, value2) pairs with the same key + (in the sense of a given comparator function). + + There are several implementations of this map datatype, optimized for + different operations or for memory. You can start using the simplest map + implementation, GL_ARRAY_MAP, and switch to a different implementation + later, when you realize which operations are performed the most frequently. + The API of the different implementations is exactly the same; when switching + to a different implementation, you only have to change the gl_map_create + call. + + The implementations are: + GL_ARRAY_MAP a growable array + GL_LINKEDHASH_MAP a hash table with a linked list + GL_HASH_MAP a hash table + + The memory consumption is asymptotically the same: O(1) for every pair + in the map. When looking more closely at the average memory consumed + for an object, GL_ARRAY_MAP is the most compact representation, then comes + GL_HASH_MAP, and GL_LINKEDHASH_MAP needs the most memory. + + The guaranteed average performance of the operations is, for a map of + n pairs: + + Operation ARRAY LINKEDHASH + HASH + + gl_map_size O(1) O(1) + gl_map_get O(n) O(1) + gl_map_put O(n) O(1) + gl_map_remove O(n) O(1) + gl_map_search O(n) O(1) + gl_map_iterator O(1) O(1) + gl_map_iterator_next O(1) O(1) + */ + +/* --------------------------- gl_map_t Data Type --------------------------- */ + +/* Type of function used to compare two keys. + NULL denotes pointer comparison. */ +typedef bool (*gl_mapkey_equals_fn) (const void *key1, const void *key2); + +/* Type of function used to compute a hash code. + NULL denotes a function that depends only on the pointer itself. */ +typedef size_t (*gl_mapkey_hashcode_fn) (const void *key); + +#ifndef _GL_MAP_DISPOSE_FNS_DEFINED + +/* Type of function used to dispose a key once a (key, value) pair is removed + from a map. NULL denotes a no-op. */ +typedef void (*gl_mapkey_dispose_fn) (const void *key); + +/* Type of function used to dispose a value once a (key, value) pair is removed + from a map. NULL denotes a no-op. */ +typedef void (*gl_mapvalue_dispose_fn) (const void *value); + +# define _GL_MAP_DISPOSE_FNS_DEFINED 1 +#endif + +struct gl_map_impl; +/* Type representing an entire map. */ +typedef struct gl_map_impl * gl_map_t; + +struct gl_map_implementation; +/* Type representing a map datatype implementation. */ +typedef const struct gl_map_implementation * gl_map_implementation_t; + +#if 0 /* Unless otherwise specified, these are defined inline below. */ + +/* Creates an empty map. + IMPLEMENTATION is one of GL_ARRAY_MAP, GL_LINKEDHASH_MAP, GL_HASH_MAP. + EQUALS_FN is a key comparison function or NULL. + HASHCODE_FN is a key hash code function or NULL. + KDISPOSE_FN is a key disposal function or NULL. + VDISPOSE_FN is a value disposal function or NULL. */ +/* declared in gl_xmap.h */ +extern gl_map_t gl_map_create_empty (gl_map_implementation_t implementation, + gl_mapkey_equals_fn equals_fn, + gl_mapkey_hashcode_fn hashcode_fn, + gl_mapkey_dispose_fn kdispose_fn, + gl_mapvalue_dispose_fn vdispose_fn); +/* Likewise. Returns NULL upon out-of-memory. */ +extern gl_map_t gl_map_nx_create_empty (gl_map_implementation_t implementation, + gl_mapkey_equals_fn equals_fn, + gl_mapkey_hashcode_fn hashcode_fn, + gl_mapkey_dispose_fn kdispose_fn, + gl_mapvalue_dispose_fn vdispose_fn); + +/* Returns the current number of pairs in a map. */ +extern size_t gl_map_size (gl_map_t map); + +/* Searches whether a pair with the given key is already in the map. + Returns the value if found, or NULL if not present in the map. */ +extern const void * gl_map_get (gl_map_t map, const void *key); + +/* Searches whether a pair with the given key is already in the map. + Returns true and sets *VALUEP to the value if found. + Returns false if not present in the map. */ +extern bool gl_map_search (gl_map_t map, const void *key, const void **valuep); + +/* Adds a pair to a map. + Returns true if a pair with the given key was not already in the map and so + this pair was added. + Returns false if a pair with the given key was already in the map and only + its value was replaced. */ +/* declared in gl_xmap.h */ +extern bool gl_map_put (gl_map_t map, const void *key, const void *value); +/* Likewise. Returns -1 upon out-of-memory. */ +extern int gl_map_nx_put (gl_map_t map, const void *key, const void *value) + _GL_ATTRIBUTE_NODISCARD; + +/* Adds a pair to a map and retrieves the previous value. + Returns true if a pair with the given key was not already in the map and so + this pair was added. + Returns false and sets *OLDVALUEP to the previous value, if a pair with the + given key was already in the map and only its value was replaced. */ +/* declared in gl_xmap.h */ +extern bool gl_map_getput (gl_map_t map, const void *key, const void *value, + const void **oldvaluep); +/* Likewise. Returns -1 upon out-of-memory. */ +extern int gl_map_nx_getput (gl_map_t map, const void *key, const void *value, + const void **oldvaluep) + _GL_ATTRIBUTE_NODISCARD; + +/* Removes a pair from a map. + Returns true if the key was found and its pair removed. + Returns false otherwise. */ +extern bool gl_map_remove (gl_map_t map, const void *key); + +/* Removes a pair from a map and retrieves the previous value. + Returns true and sets *OLDVALUEP to the previous value, if the key was found + and its pair removed. + Returns false otherwise. */ +extern bool gl_map_getremove (gl_map_t map, const void *key, + const void **oldvaluep); + +/* Frees an entire map. + (But this call does not free the keys and values of the pairs in the map. + It only invokes the KDISPOSE_FN on each key and the VDISPOSE_FN on each value + of the pairs in the map.) */ +extern void gl_map_free (gl_map_t map); + +#endif /* End of inline and gl_xmap.h-defined functions. */ + +/* ---------------------- gl_map_iterator_t Data Type ---------------------- */ + +/* Functions for iterating through a map. + Note: Iterating through a map of type GL_HASH_MAP returns the pairs in an + unpredictable order. If you need a predictable order, use GL_LINKEDHASH_MAP + instead of GL_HASH_MAP. */ + +/* Type of an iterator that traverses a map. + This is a fixed-size struct, so that creation of an iterator doesn't need + memory allocation on the heap. */ +typedef struct +{ + /* For fast dispatch of gl_map_iterator_next. */ + const struct gl_map_implementation *vtable; + /* For detecting whether the last returned pair was removed. */ + gl_map_t map; + size_t count; + /* Other, implementation-private fields. */ + void *p; void *q; + size_t i; size_t j; +} gl_map_iterator_t; + +#if 0 /* These are defined inline below. */ + +/* Creates an iterator traversing a map. + The map's contents must not be modified while the iterator is in use, + except for modifying the value of the last returned key or removing the + last returned pair. */ +extern gl_map_iterator_t gl_map_iterator (gl_map_t map); + +/* If there is a next pair, stores the next pair in *KEYP and *VALUEP, advances + the iterator, and returns true. Otherwise, returns false. */ +extern bool gl_map_iterator_next (gl_map_iterator_t *iterator, + const void **keyp, const void **valuep); + +/* Frees an iterator. */ +extern void gl_map_iterator_free (gl_map_iterator_t *iterator); + +#endif /* End of inline functions. */ + +/* ------------------------- Implementation Details ------------------------- */ + +struct gl_map_implementation +{ + /* gl_map_t functions. */ + gl_map_t (*nx_create_empty) (gl_map_implementation_t implementation, + gl_mapkey_equals_fn equals_fn, + gl_mapkey_hashcode_fn hashcode_fn, + gl_mapkey_dispose_fn kdispose_fn, + gl_mapvalue_dispose_fn vdispose_fn); + size_t (*size) (gl_map_t map); + bool (*search) (gl_map_t map, const void *key, const void **valuep); + int (*nx_getput) (gl_map_t map, const void *key, const void *value, + const void **oldvaluep); + bool (*getremove) (gl_map_t map, const void *key, const void **oldvaluep); + void (*map_free) (gl_map_t map); + /* gl_map_iterator_t functions. */ + gl_map_iterator_t (*iterator) (gl_map_t map); + bool (*iterator_next) (gl_map_iterator_t *iterator, + const void **keyp, const void **valuep); + void (*iterator_free) (gl_map_iterator_t *iterator); +}; + +struct gl_map_impl_base +{ + const struct gl_map_implementation *vtable; + gl_mapkey_equals_fn equals_fn; + gl_mapkey_dispose_fn kdispose_fn; + gl_mapvalue_dispose_fn vdispose_fn; +}; + +/* Define most functions of this file as accesses to the + struct gl_map_implementation. */ + +GL_MAP_INLINE gl_map_t +gl_map_nx_create_empty (gl_map_implementation_t implementation, + gl_mapkey_equals_fn equals_fn, + gl_mapkey_hashcode_fn hashcode_fn, + gl_mapkey_dispose_fn kdispose_fn, + gl_mapvalue_dispose_fn vdispose_fn) +{ + return implementation->nx_create_empty (implementation, + equals_fn, hashcode_fn, + kdispose_fn, vdispose_fn); +} + +GL_MAP_INLINE size_t +gl_map_size (gl_map_t map) +{ + return ((const struct gl_map_impl_base *) map)->vtable->size (map); +} + +GL_MAP_INLINE bool +gl_map_search (gl_map_t map, const void *key, const void **valuep) +{ + return ((const struct gl_map_impl_base *) map)->vtable + ->search (map, key, valuep); +} + +GL_MAP_INLINE _GL_ATTRIBUTE_NODISCARD int +gl_map_nx_getput (gl_map_t map, const void *key, const void *value, + const void **oldvaluep) +{ + return ((const struct gl_map_impl_base *) map)->vtable + ->nx_getput (map, key, value, oldvaluep); +} + +GL_MAP_INLINE bool +gl_map_getremove (gl_map_t map, const void *key, const void **oldvaluep) +{ + return ((const struct gl_map_impl_base *) map)->vtable + ->getremove (map, key, oldvaluep); +} + +GL_MAP_INLINE void +gl_map_free (gl_map_t map) +{ + ((const struct gl_map_impl_base *) map)->vtable->map_free (map); +} + +GL_MAP_INLINE gl_map_iterator_t +gl_map_iterator (gl_map_t map) +{ + return ((const struct gl_map_impl_base *) map)->vtable->iterator (map); +} + +GL_MAP_INLINE bool +gl_map_iterator_next (gl_map_iterator_t *iterator, + const void **keyp, const void **valuep) +{ + return iterator->vtable->iterator_next (iterator, keyp, valuep); +} + +GL_MAP_INLINE void +gl_map_iterator_free (gl_map_iterator_t *iterator) +{ + iterator->vtable->iterator_free (iterator); +} + +/* Define the convenience functions, that is, the functions that are independent + of the implementation. */ + +GL_MAP_INLINE const void * +gl_map_get (gl_map_t map, const void *key) +{ + const void *value = NULL; + gl_map_search (map, key, &value); + return value; +} + +GL_MAP_INLINE _GL_ATTRIBUTE_NODISCARD int +gl_map_nx_put (gl_map_t map, const void *key, const void *value) +{ + const void *oldvalue; + int result = gl_map_nx_getput (map, key, value, &oldvalue); + if (result == 0) + { + gl_mapvalue_dispose_fn vdispose_fn = + ((const struct gl_map_impl_base *) map)->vdispose_fn; + if (vdispose_fn != NULL) + vdispose_fn (oldvalue); + } + return result; +} + +GL_MAP_INLINE bool +gl_map_remove (gl_map_t map, const void *key) +{ + const void *oldvalue; + bool result = gl_map_getremove (map, key, &oldvalue); + if (result) + { + gl_mapvalue_dispose_fn vdispose_fn = + ((const struct gl_map_impl_base *) map)->vdispose_fn; + if (vdispose_fn != NULL) + vdispose_fn (oldvalue); + } + return result; +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* _GL_MAP_H */ diff --git a/src/gnulib/limits.in.h b/src/gnulib/limits.in.h new file mode 100644 index 000000000..076ab9ef5 --- /dev/null +++ b/src/gnulib/limits.in.h @@ -0,0 +1,121 @@ +/* A GNU-like . + + Copyright 2016-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, 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 . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined _GL_ALREADY_INCLUDING_LIMITS_H +/* Special invocation convention: + On Haiku/x86_64, we have a sequence of nested includes + -> -> . + In this situation, LONG_MAX and INT_MAX are not yet defined, + therefore we should not attempt to define LONG_BIT. */ + +#@INCLUDE_NEXT@ @NEXT_LIMITS_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_LIMITS_H + +# define _GL_ALREADY_INCLUDING_LIMITS_H + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_LIMITS_H@ + +# undef _GL_ALREADY_INCLUDING_LIMITS_H + +#ifndef _@GUARD_PREFIX@_LIMITS_H +#define _@GUARD_PREFIX@_LIMITS_H + +#ifndef LLONG_MIN +# if defined LONG_LONG_MIN /* HP-UX 11.31 */ +# define LLONG_MIN LONG_LONG_MIN +# elif defined LONGLONG_MIN /* IRIX 6.5 */ +# define LLONG_MIN LONGLONG_MIN +# elif defined __GNUC__ +# define LLONG_MIN (- __LONG_LONG_MAX__ - 1LL) +# endif +#endif +#ifndef LLONG_MAX +# if defined LONG_LONG_MAX /* HP-UX 11.31 */ +# define LLONG_MAX LONG_LONG_MAX +# elif defined LONGLONG_MAX /* IRIX 6.5 */ +# define LLONG_MAX LONGLONG_MAX +# elif defined __GNUC__ +# define LLONG_MAX __LONG_LONG_MAX__ +# endif +#endif +#ifndef ULLONG_MAX +# if defined ULONG_LONG_MAX /* HP-UX 11.31 */ +# define ULLONG_MAX ULONG_LONG_MAX +# elif defined ULONGLONG_MAX /* IRIX 6.5 */ +# define ULLONG_MAX ULONGLONG_MAX +# elif defined __GNUC__ +# define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL) +# endif +#endif + +/* The number of usable bits in an unsigned or signed integer type + with minimum value MIN and maximum value MAX, as an int expression + suitable in #if. Cover all known practical hosts. This + implementation exploits the fact that MAX is 1 less than a power of + 2, and merely counts the number of 1 bits in MAX; "COBn" means + "count the number of 1 bits in the low-order n bits"). */ +#define _GL_INTEGER_WIDTH(min, max) (((min) < 0) + _GL_COB128 (max)) +#define _GL_COB128(n) (_GL_COB64 ((n) >> 31 >> 31 >> 2) + _GL_COB64 (n)) +#define _GL_COB64(n) (_GL_COB32 ((n) >> 31 >> 1) + _GL_COB32 (n)) +#define _GL_COB32(n) (_GL_COB16 ((n) >> 16) + _GL_COB16 (n)) +#define _GL_COB16(n) (_GL_COB8 ((n) >> 8) + _GL_COB8 (n)) +#define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n)) +#define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1)) + +#ifndef WORD_BIT +/* Assume 'int' is 32 bits wide. */ +# define WORD_BIT 32 +#endif +#ifndef LONG_BIT +/* Assume 'long' is 32 or 64 bits wide. */ +# if LONG_MAX == INT_MAX +# define LONG_BIT 32 +# else +# define LONG_BIT 64 +# endif +#endif + +/* Macros specified by ISO/IEC TS 18661-1:2014. */ + +#if (! defined ULLONG_WIDTH \ + && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__)) +# define CHAR_WIDTH _GL_INTEGER_WIDTH (CHAR_MIN, CHAR_MAX) +# define SCHAR_WIDTH _GL_INTEGER_WIDTH (SCHAR_MIN, SCHAR_MAX) +# define UCHAR_WIDTH _GL_INTEGER_WIDTH (0, UCHAR_MAX) +# define SHRT_WIDTH _GL_INTEGER_WIDTH (SHRT_MIN, SHRT_MAX) +# define USHRT_WIDTH _GL_INTEGER_WIDTH (0, USHRT_MAX) +# define INT_WIDTH _GL_INTEGER_WIDTH (INT_MIN, INT_MAX) +# define UINT_WIDTH _GL_INTEGER_WIDTH (0, UINT_MAX) +# define LONG_WIDTH _GL_INTEGER_WIDTH (LONG_MIN, LONG_MAX) +# define ULONG_WIDTH _GL_INTEGER_WIDTH (0, ULONG_MAX) +# define LLONG_WIDTH _GL_INTEGER_WIDTH (LLONG_MIN, LLONG_MAX) +# define ULLONG_WIDTH _GL_INTEGER_WIDTH (0, ULLONG_MAX) +#endif /* !ULLONG_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */ + +#endif /* _@GUARD_PREFIX@_LIMITS_H */ +#endif /* _@GUARD_PREFIX@_LIMITS_H */ +#endif diff --git a/src/gnulib/size_max.h b/src/gnulib/size_max.h new file mode 100644 index 000000000..16cfa0968 --- /dev/null +++ b/src/gnulib/size_max.h @@ -0,0 +1,30 @@ +/* size_max.h -- declare SIZE_MAX through system headers + Copyright (C) 2005-2006, 2009-2021 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, 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 . */ + +#ifndef GNULIB_SIZE_MAX_H +#define GNULIB_SIZE_MAX_H + +/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */ +# include +/* Get SIZE_MAX declaration on systems like glibc 2. */ +# if HAVE_STDINT_H +# include +# endif +/* On systems where these include files don't define it, SIZE_MAX is defined + in config.h. */ + +#endif /* GNULIB_SIZE_MAX_H */ diff --git a/src/gnulib/stdbool.in.h b/src/gnulib/stdbool.in.h new file mode 100644 index 000000000..28e0a5355 --- /dev/null +++ b/src/gnulib/stdbool.in.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2001-2003, 2006-2021 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _GL_STDBOOL_H +#define _GL_STDBOOL_H + +/* ISO C 99 for platforms that lack it. */ + +/* Usage suggestions: + + Programs that use should be aware of some limitations + and standards compliance issues. + + Standards compliance: + + - must be #included before 'bool', 'false', 'true' + can be used. + + - You cannot assume that sizeof (bool) == 1. + + - Programs should not undefine the macros bool, true, and false, + as C99 lists that as an "obsolescent feature". + + Limitations of this substitute, when used in a C89 environment: + + - must be #included before the '_Bool' type can be used. + + - You cannot assume that _Bool is a typedef; it might be a macro. + + - Bit-fields of type 'bool' are not supported. Portable code + should use 'unsigned int foo : 1;' rather than 'bool foo : 1;'. + + - In C99, casts and automatic conversions to '_Bool' or 'bool' are + performed in such a way that every nonzero value gets converted + to 'true', and zero gets converted to 'false'. This doesn't work + with this substitute. With this substitute, only the values 0 and 1 + give the expected result when converted to _Bool' or 'bool'. + + - C99 allows the use of (_Bool)0.0 in constant expressions, but + this substitute cannot always provide this property. + + Also, it is suggested that programs use 'bool' rather than '_Bool'; + this isn't required, but 'bool' is more common. */ + + +/* 7.16. Boolean type and values */ + +/* BeOS already #defines false 0, true 1. We use the same + definitions below, but temporarily we have to #undef them. */ +#if defined __BEOS__ && !defined __HAIKU__ +# include /* defines bool but not _Bool */ +# undef false +# undef true +#endif + +#ifdef __cplusplus +# define _Bool bool +# define bool bool +#else +# if defined __BEOS__ && !defined __HAIKU__ + /* A compiler known to have 'bool'. */ + /* If the compiler already has both 'bool' and '_Bool', we can assume they + are the same types. */ +# if !@HAVE__BOOL@ +typedef bool _Bool; +# endif +# else +# if !defined __GNUC__ + /* If @HAVE__BOOL@: + Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when + the built-in _Bool type is used. See + https://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + https://lists.gnu.org/r/bug-coreutils/2005-11/msg00161.html + https://lists.gnu.org/r/bug-coreutils/2005-10/msg00086.html + Similar bugs are likely with other compilers as well; this file + wouldn't be used if was working. + So we override the _Bool type. + If !@HAVE__BOOL@: + Need to define _Bool ourselves. As 'signed char' or as an enum type? + Use of a typedef, with SunPRO C, leads to a stupid + "warning: _Bool is a keyword in ISO C99". + Use of an enum type, with IRIX cc, leads to a stupid + "warning(1185): enumerated type mixed with another type". + Even the existence of an enum type, without a typedef, + "Invalid enumerator. (badenum)" with HP-UX cc on Tru64. + The only benefit of the enum, debuggability, is not important + with these compilers. So use 'signed char' and no enum. */ +# define _Bool signed char +# else + /* With this compiler, trust the _Bool type if the compiler has it. */ +# if !@HAVE__BOOL@ + /* For the sake of symbolic names in gdb, define true and false as + enum constants, not only as macros. + It is tempting to write + typedef enum { false = 0, true = 1 } _Bool; + so that gdb prints values of type 'bool' symbolically. But then + values of type '_Bool' might promote to 'int' or 'unsigned int' + (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int' + (see ISO C 99 6.3.1.1.(2)). So add a negative value to the + enum; this ensures that '_Bool' promotes to 'int'. */ +typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; +# endif +# endif +# endif +# define bool _Bool +#endif + +/* The other macros must be usable in preprocessor directives. */ +#ifdef __cplusplus +# define false false +# define true true +#else +# define false 0 +# define true 1 +#endif + +#define __bool_true_false_are_defined 1 + +#endif /* _GL_STDBOOL_H */ diff --git a/src/gnulib/stdint.in.h b/src/gnulib/stdint.in.h new file mode 100644 index 000000000..7a8f27cef --- /dev/null +++ b/src/gnulib/stdint.in.h @@ -0,0 +1,740 @@ +/* Copyright (C) 2001-2002, 2004-2021 Free Software Foundation, Inc. + Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. + This file is part of gnulib. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +/* + * ISO C 99 for platforms that lack it. + * + */ + +#ifndef _@GUARD_PREFIX@_STDINT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* When including a system file that in turn includes , + use the system , not our substitute. This avoids + problems with (for example) VMS, whose includes + . */ +#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* On Android (Bionic libc), includes this file before + having defined 'time_t'. Therefore in this case avoid including + other system header files; just include the system's . + Ideally we should test __BIONIC__ here, but it is only defined after + has been included; hence test __ANDROID__ instead. */ +#if defined __ANDROID__ && defined _GL_INCLUDING_SYS_TYPES_H +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#else + +/* Get those types that are already defined in other system include + files, so that we can "#define int8_t signed char" below without + worrying about a later system include file containing a "typedef + signed char int8_t;" that will get messed up by our macro. Our + macros should all be consistent with the system versions, except + for the "fast" types and macros, which we recommend against using + in public interfaces due to compiler differences. */ + +#if @HAVE_STDINT_H@ +# if defined __sgi && ! defined __c99 + /* Bypass IRIX's if in C89 mode, since it merely annoys users + with "This header file is to be used only for c99 mode compilations" + diagnostics. */ +# define __STDINT_H__ +# endif + + /* Some pre-C++11 implementations need this. */ +# ifdef __cplusplus +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS 1 +# endif +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +# endif +# endif + + /* Other systems may have an incomplete or buggy . + Include it before , since any "#include " + in would reinclude us, skipping our contents because + _@GUARD_PREFIX@_STDINT_H is defined. + The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#endif + +#if ! defined _@GUARD_PREFIX@_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H +#define _@GUARD_PREFIX@_STDINT_H + +/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX, + LONG_MIN, LONG_MAX, ULONG_MAX, _GL_INTEGER_WIDTH. */ +#include + +/* Override WINT_MIN and WINT_MAX if gnulib's or overrides + wint_t. */ +#if @GNULIB_OVERRIDES_WINT_T@ +# undef WINT_MIN +# undef WINT_MAX +# define WINT_MIN 0x0U +# define WINT_MAX 0xffffffffU +#endif + +#if ! @HAVE_C99_STDINT_H@ + +/* defines some of the stdint.h types as well, on glibc, + IRIX 6.5, and OpenBSD 3.8 (via ). + AIX 5.2 isn't needed and causes troubles. + Mac OS X 10.4.6 includes (which is us), but + relies on the system definitions, so include + after @NEXT_STDINT_H@. */ +# if @HAVE_SYS_TYPES_H@ && ! defined _AIX +# include +# endif + +# if @HAVE_INTTYPES_H@ + /* In OpenBSD 3.8, includes , which defines + int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. + also defines intptr_t and uintptr_t. */ +# include +# elif @HAVE_SYS_INTTYPES_H@ + /* Solaris 7 has the types except the *_fast*_t types, and + the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ +# include +# endif + +# if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ + /* Linux libc4 >= 4.6.7 and libc5 have a that defines + int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is + included by . */ +# include +# endif + +# undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* Minimum and maximum values for an integer type under the usual assumption. + Return an unspecified value if BITS == 0, adding a check to pacify + picky compilers. */ + +/* These are separate macros, because if you try to merge these macros into + a single one, HP-UX cc rejects the resulting expression in constant + expressions. */ +# define _STDINT_UNSIGNED_MIN(bits, zero) \ + (zero) +# define _STDINT_SIGNED_MIN(bits, zero) \ + (~ _STDINT_MAX (1, bits, zero)) + +# define _STDINT_MAX(signed, bits, zero) \ + (((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) + +#if !GNULIB_defined_stdint_types + +/* 7.18.1.1. Exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +# undef int8_t +# undef uint8_t +typedef signed char gl_int8_t; +typedef unsigned char gl_uint8_t; +# define int8_t gl_int8_t +# define uint8_t gl_uint8_t + +# undef int16_t +# undef uint16_t +typedef short int gl_int16_t; +typedef unsigned short int gl_uint16_t; +# define int16_t gl_int16_t +# define uint16_t gl_uint16_t + +# undef int32_t +# undef uint32_t +typedef int gl_int32_t; +typedef unsigned int gl_uint32_t; +# define int32_t gl_int32_t +# define uint32_t gl_uint32_t + +/* If the system defines INT64_MAX, assume int64_t works. That way, + if the underlying platform defines int64_t to be a 64-bit long long + int, the code below won't mistakenly define it to be a 64-bit long + int, which would mess up C++ name mangling. We must use #ifdef + rather than #if, to avoid an error with HP-UX 10.20 cc. */ + +# ifdef INT64_MAX +# define GL_INT64_T +# else +/* Do not undefine int64_t if gnulib is not being used with 64-bit + types, since otherwise it breaks platforms like Tandem/NSK. */ +# if LONG_MAX >> 31 >> 31 == 1 +# undef int64_t +typedef long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# elif defined _MSC_VER +# undef int64_t +typedef __int64 gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# else +# undef int64_t +typedef long long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# endif +# endif + +# ifdef UINT64_MAX +# define GL_UINT64_T +# else +# if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# undef uint64_t +typedef unsigned long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# elif defined _MSC_VER +# undef uint64_t +typedef unsigned __int64 gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# else +# undef uint64_t +typedef unsigned long long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# endif +# endif + +/* Avoid collision with Solaris 2.5.1 etc. */ +# define _UINT8_T +# define _UINT32_T +# define _UINT64_T + + +/* 7.18.1.2. Minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +# undef int_least8_t +# undef uint_least8_t +# undef int_least16_t +# undef uint_least16_t +# undef int_least32_t +# undef uint_least32_t +# undef int_least64_t +# undef uint_least64_t +# define int_least8_t int8_t +# define uint_least8_t uint8_t +# define int_least16_t int16_t +# define uint_least16_t uint16_t +# define int_least32_t int32_t +# define uint_least32_t uint32_t +# ifdef GL_INT64_T +# define int_least64_t int64_t +# endif +# ifdef GL_UINT64_T +# define uint_least64_t uint64_t +# endif + +/* 7.18.1.3. Fastest minimum-width integer types */ + +/* Note: Other substitutes may define these types differently. + It is not recommended to use these types in public header files. */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. The following code normally + uses types consistent with glibc, as that lessens the chance of + incompatibility with older GNU hosts. */ + +# undef int_fast8_t +# undef uint_fast8_t +# undef int_fast16_t +# undef uint_fast16_t +# undef int_fast32_t +# undef uint_fast32_t +# undef int_fast64_t +# undef uint_fast64_t +typedef signed char gl_int_fast8_t; +typedef unsigned char gl_uint_fast8_t; + +# ifdef __sun +/* Define types compatible with SunOS 5.10, so that code compiled under + earlier SunOS versions works with code compiled under SunOS 5.10. */ +typedef int gl_int_fast32_t; +typedef unsigned int gl_uint_fast32_t; +# else +typedef long int gl_int_fast32_t; +typedef unsigned long int gl_uint_fast32_t; +# endif +typedef gl_int_fast32_t gl_int_fast16_t; +typedef gl_uint_fast32_t gl_uint_fast16_t; + +# define int_fast8_t gl_int_fast8_t +# define uint_fast8_t gl_uint_fast8_t +# define int_fast16_t gl_int_fast16_t +# define uint_fast16_t gl_uint_fast16_t +# define int_fast32_t gl_int_fast32_t +# define uint_fast32_t gl_uint_fast32_t +# ifdef GL_INT64_T +# define int_fast64_t int64_t +# endif +# ifdef GL_UINT64_T +# define uint_fast64_t uint64_t +# endif + +/* 7.18.1.4. Integer types capable of holding object pointers */ + +/* kLIBC's defines _INTPTR_T_DECLARED and needs its own + definitions of intptr_t and uintptr_t (which use int and unsigned) + to avoid clashes with declarations of system functions like sbrk. + Similarly, MinGW WSL-5.4.1 needs its own intptr_t and + uintptr_t to avoid conflicting declarations of system functions like + _findclose in . */ +# if !((defined __KLIBC__ && defined _INTPTR_T_DECLARED) \ + || defined __MINGW32__) +# undef intptr_t +# undef uintptr_t +# ifdef _WIN64 +typedef long long int gl_intptr_t; +typedef unsigned long long int gl_uintptr_t; +# else +typedef long int gl_intptr_t; +typedef unsigned long int gl_uintptr_t; +# endif +# define intptr_t gl_intptr_t +# define uintptr_t gl_uintptr_t +# endif + +/* 7.18.1.5. Greatest-width integer types */ + +/* Note: These types are compiler dependent. It may be unwise to use them in + public header files. */ + +/* If the system defines INTMAX_MAX, assume that intmax_t works, and + similarly for UINTMAX_MAX and uintmax_t. This avoids problems with + assuming one type where another is used by the system. */ + +# ifndef INTMAX_MAX +# undef INTMAX_C +# undef intmax_t +# if LONG_MAX >> 30 == 1 +typedef long long int gl_intmax_t; +# define intmax_t gl_intmax_t +# elif defined GL_INT64_T +# define intmax_t int64_t +# else +typedef long int gl_intmax_t; +# define intmax_t gl_intmax_t +# endif +# endif + +# ifndef UINTMAX_MAX +# undef UINTMAX_C +# undef uintmax_t +# if ULONG_MAX >> 31 == 1 +typedef unsigned long long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# elif defined GL_UINT64_T +# define uintmax_t uint64_t +# else +typedef unsigned long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# endif +# endif + +/* Verify that intmax_t and uintmax_t have the same size. Too much code + breaks if this is not the case. If this check fails, the reason is likely + to be found in the autoconf macros. */ +typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) + ? 1 : -1]; + +# define GNULIB_defined_stdint_types 1 +# endif /* !GNULIB_defined_stdint_types */ + +/* 7.18.2. Limits of specified-width integer types */ + +/* 7.18.2.1. Limits of exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +# undef INT8_MIN +# undef INT8_MAX +# undef UINT8_MAX +# define INT8_MIN (~ INT8_MAX) +# define INT8_MAX 127 +# define UINT8_MAX 255 + +# undef INT16_MIN +# undef INT16_MAX +# undef UINT16_MAX +# define INT16_MIN (~ INT16_MAX) +# define INT16_MAX 32767 +# define UINT16_MAX 65535 + +# undef INT32_MIN +# undef INT32_MAX +# undef UINT32_MAX +# define INT32_MIN (~ INT32_MAX) +# define INT32_MAX 2147483647 +# define UINT32_MAX 4294967295U + +# if defined GL_INT64_T && ! defined INT64_MAX +/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0 + evaluates the latter incorrectly in preprocessor expressions. */ +# define INT64_MIN (- INTMAX_C (1) << 63) +# define INT64_MAX INTMAX_C (9223372036854775807) +# endif + +# if defined GL_UINT64_T && ! defined UINT64_MAX +# define UINT64_MAX UINTMAX_C (18446744073709551615) +# endif + +/* 7.18.2.2. Limits of minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +# undef INT_LEAST8_MIN +# undef INT_LEAST8_MAX +# undef UINT_LEAST8_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST8_MAX UINT8_MAX + +# undef INT_LEAST16_MIN +# undef INT_LEAST16_MAX +# undef UINT_LEAST16_MAX +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST16_MAX UINT16_MAX + +# undef INT_LEAST32_MIN +# undef INT_LEAST32_MAX +# undef UINT_LEAST32_MAX +# define INT_LEAST32_MIN INT32_MIN +# define INT_LEAST32_MAX INT32_MAX +# define UINT_LEAST32_MAX UINT32_MAX + +# undef INT_LEAST64_MIN +# undef INT_LEAST64_MAX +# ifdef GL_INT64_T +# define INT_LEAST64_MIN INT64_MIN +# define INT_LEAST64_MAX INT64_MAX +# endif + +# undef UINT_LEAST64_MAX +# ifdef GL_UINT64_T +# define UINT_LEAST64_MAX UINT64_MAX +# endif + +/* 7.18.2.3. Limits of fastest minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. */ + +# undef INT_FAST8_MIN +# undef INT_FAST8_MAX +# undef UINT_FAST8_MAX +# define INT_FAST8_MIN SCHAR_MIN +# define INT_FAST8_MAX SCHAR_MAX +# define UINT_FAST8_MAX UCHAR_MAX + +# undef INT_FAST16_MIN +# undef INT_FAST16_MAX +# undef UINT_FAST16_MAX +# define INT_FAST16_MIN INT_FAST32_MIN +# define INT_FAST16_MAX INT_FAST32_MAX +# define UINT_FAST16_MAX UINT_FAST32_MAX + +# undef INT_FAST32_MIN +# undef INT_FAST32_MAX +# undef UINT_FAST32_MAX +# ifdef __sun +# define INT_FAST32_MIN INT_MIN +# define INT_FAST32_MAX INT_MAX +# define UINT_FAST32_MAX UINT_MAX +# else +# define INT_FAST32_MIN LONG_MIN +# define INT_FAST32_MAX LONG_MAX +# define UINT_FAST32_MAX ULONG_MAX +# endif + +# undef INT_FAST64_MIN +# undef INT_FAST64_MAX +# ifdef GL_INT64_T +# define INT_FAST64_MIN INT64_MIN +# define INT_FAST64_MAX INT64_MAX +# endif + +# undef UINT_FAST64_MAX +# ifdef GL_UINT64_T +# define UINT_FAST64_MAX UINT64_MAX +# endif + +/* 7.18.2.4. Limits of integer types capable of holding object pointers */ + +# undef INTPTR_MIN +# undef INTPTR_MAX +# undef UINTPTR_MAX +# ifdef _WIN64 +# define INTPTR_MIN LLONG_MIN +# define INTPTR_MAX LLONG_MAX +# define UINTPTR_MAX ULLONG_MAX +# else +# define INTPTR_MIN LONG_MIN +# define INTPTR_MAX LONG_MAX +# define UINTPTR_MAX ULONG_MAX +# endif + +/* 7.18.2.5. Limits of greatest-width integer types */ + +# ifndef INTMAX_MAX +# undef INTMAX_MIN +# ifdef INT64_MAX +# define INTMAX_MIN INT64_MIN +# define INTMAX_MAX INT64_MAX +# else +# define INTMAX_MIN INT32_MIN +# define INTMAX_MAX INT32_MAX +# endif +# endif + +# ifndef UINTMAX_MAX +# ifdef UINT64_MAX +# define UINTMAX_MAX UINT64_MAX +# else +# define UINTMAX_MAX UINT32_MAX +# endif +# endif + +/* 7.18.3. Limits of other integer types */ + +/* ptrdiff_t limits */ +# undef PTRDIFF_MIN +# undef PTRDIFF_MAX +# if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (64, 0l) +# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l) +# else +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (32, 0) +# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0) +# endif +# else +# define PTRDIFF_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +# define PTRDIFF_MAX \ + _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +# endif + +/* sig_atomic_t limits */ +# undef SIG_ATOMIC_MIN +# undef SIG_ATOMIC_MAX +# if @HAVE_SIGNED_SIG_ATOMIC_T@ +# define SIG_ATOMIC_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# else +# define SIG_ATOMIC_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# endif +# define SIG_ATOMIC_MAX \ + _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ + 0@SIG_ATOMIC_T_SUFFIX@) + + +/* size_t limit */ +# undef SIZE_MAX +# if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define SIZE_MAX _STDINT_MAX (0, 64, 0ul) +# else +# define SIZE_MAX _STDINT_MAX (0, 32, 0ul) +# endif +# else +# define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) +# endif + +/* wchar_t limits */ +/* Get WCHAR_MIN, WCHAR_MAX. + This include is not on the top, above, because on OSF/1 4.0 we have a + sequence of nested includes + -> -> -> , and the latter includes + and assumes its types are already defined. */ +# if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX) +# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +# include +# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +# endif +# undef WCHAR_MIN +# undef WCHAR_MAX +# if @HAVE_SIGNED_WCHAR_T@ +# define WCHAR_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# else +# define WCHAR_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# endif +# define WCHAR_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) + +/* wint_t limits */ +/* If gnulib's or overrides wint_t, @WINT_T_SUFFIX@ is not + accurate, therefore use the definitions from above. */ +# if !@GNULIB_OVERRIDES_WINT_T@ +# undef WINT_MIN +# undef WINT_MAX +# if @HAVE_SIGNED_WINT_T@ +# define WINT_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# else +# define WINT_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# endif +# define WINT_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# endif + +/* 7.18.4. Macros for integer constants */ + +/* 7.18.4.1. Macros for minimum-width integer constants */ +/* According to ISO C 99 Technical Corrigendum 1 */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ + +# undef INT8_C +# undef UINT8_C +# define INT8_C(x) x +# define UINT8_C(x) x + +# undef INT16_C +# undef UINT16_C +# define INT16_C(x) x +# define UINT16_C(x) x + +# undef INT32_C +# undef UINT32_C +# define INT32_C(x) x +# define UINT32_C(x) x ## U + +# undef INT64_C +# undef UINT64_C +# if LONG_MAX >> 31 >> 31 == 1 +# define INT64_C(x) x##L +# elif defined _MSC_VER +# define INT64_C(x) x##i64 +# else +# define INT64_C(x) x##LL +# endif +# if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# define UINT64_C(x) x##UL +# elif defined _MSC_VER +# define UINT64_C(x) x##ui64 +# else +# define UINT64_C(x) x##ULL +# endif + +/* 7.18.4.2. Macros for greatest-width integer constants */ + +# ifndef INTMAX_C +# if LONG_MAX >> 30 == 1 +# define INTMAX_C(x) x##LL +# elif defined GL_INT64_T +# define INTMAX_C(x) INT64_C(x) +# else +# define INTMAX_C(x) x##L +# endif +# endif + +# ifndef UINTMAX_C +# if ULONG_MAX >> 31 == 1 +# define UINTMAX_C(x) x##ULL +# elif defined GL_UINT64_T +# define UINTMAX_C(x) UINT64_C(x) +# else +# define UINTMAX_C(x) x##UL +# endif +# endif + +#endif /* !@HAVE_C99_STDINT_H@ */ + +/* Macros specified by ISO/IEC TS 18661-1:2014. */ + +#if (!defined UINTMAX_WIDTH \ + && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__)) +# ifdef INT8_MAX +# define INT8_WIDTH _GL_INTEGER_WIDTH (INT8_MIN, INT8_MAX) +# endif +# ifdef UINT8_MAX +# define UINT8_WIDTH _GL_INTEGER_WIDTH (0, UINT8_MAX) +# endif +# ifdef INT16_MAX +# define INT16_WIDTH _GL_INTEGER_WIDTH (INT16_MIN, INT16_MAX) +# endif +# ifdef UINT16_MAX +# define UINT16_WIDTH _GL_INTEGER_WIDTH (0, UINT16_MAX) +# endif +# ifdef INT32_MAX +# define INT32_WIDTH _GL_INTEGER_WIDTH (INT32_MIN, INT32_MAX) +# endif +# ifdef UINT32_MAX +# define UINT32_WIDTH _GL_INTEGER_WIDTH (0, UINT32_MAX) +# endif +# ifdef INT64_MAX +# define INT64_WIDTH _GL_INTEGER_WIDTH (INT64_MIN, INT64_MAX) +# endif +# ifdef UINT64_MAX +# define UINT64_WIDTH _GL_INTEGER_WIDTH (0, UINT64_MAX) +# endif +# define INT_LEAST8_WIDTH _GL_INTEGER_WIDTH (INT_LEAST8_MIN, INT_LEAST8_MAX) +# define UINT_LEAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST8_MAX) +# define INT_LEAST16_WIDTH _GL_INTEGER_WIDTH (INT_LEAST16_MIN, INT_LEAST16_MAX) +# define UINT_LEAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST16_MAX) +# define INT_LEAST32_WIDTH _GL_INTEGER_WIDTH (INT_LEAST32_MIN, INT_LEAST32_MAX) +# define UINT_LEAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST32_MAX) +# define INT_LEAST64_WIDTH _GL_INTEGER_WIDTH (INT_LEAST64_MIN, INT_LEAST64_MAX) +# define UINT_LEAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST64_MAX) +# define INT_FAST8_WIDTH _GL_INTEGER_WIDTH (INT_FAST8_MIN, INT_FAST8_MAX) +# define UINT_FAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST8_MAX) +# define INT_FAST16_WIDTH _GL_INTEGER_WIDTH (INT_FAST16_MIN, INT_FAST16_MAX) +# define UINT_FAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST16_MAX) +# define INT_FAST32_WIDTH _GL_INTEGER_WIDTH (INT_FAST32_MIN, INT_FAST32_MAX) +# define UINT_FAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST32_MAX) +# define INT_FAST64_WIDTH _GL_INTEGER_WIDTH (INT_FAST64_MIN, INT_FAST64_MAX) +# define UINT_FAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST64_MAX) +# define INTPTR_WIDTH _GL_INTEGER_WIDTH (INTPTR_MIN, INTPTR_MAX) +# define UINTPTR_WIDTH _GL_INTEGER_WIDTH (0, UINTPTR_MAX) +# define INTMAX_WIDTH _GL_INTEGER_WIDTH (INTMAX_MIN, INTMAX_MAX) +# define UINTMAX_WIDTH _GL_INTEGER_WIDTH (0, UINTMAX_MAX) +# define PTRDIFF_WIDTH _GL_INTEGER_WIDTH (PTRDIFF_MIN, PTRDIFF_MAX) +# define SIZE_WIDTH _GL_INTEGER_WIDTH (0, SIZE_MAX) +# define WCHAR_WIDTH _GL_INTEGER_WIDTH (WCHAR_MIN, WCHAR_MAX) +# ifdef WINT_MAX +# define WINT_WIDTH _GL_INTEGER_WIDTH (WINT_MIN, WINT_MAX) +# endif +# ifdef SIG_ATOMIC_MAX +# define SIG_ATOMIC_WIDTH _GL_INTEGER_WIDTH (SIG_ATOMIC_MIN, SIG_ATOMIC_MAX) +# endif +#endif /* !WINT_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */ + +#endif /* _@GUARD_PREFIX@_STDINT_H */ +#endif /* !(defined __ANDROID__ && ...) */ +#endif /* !defined _@GUARD_PREFIX@_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ diff --git a/src/gnulib/sys_types.in.h b/src/gnulib/sys_types.in.h new file mode 100644 index 000000000..654e80335 --- /dev/null +++ b/src/gnulib/sys_types.in.h @@ -0,0 +1,106 @@ +/* Provide a more complete sys/types.h. + + Copyright (C) 2011-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, 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 . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined _WIN32 && !defined __CYGWIN__ \ + && (defined __need_off_t || defined __need___off64_t \ + || defined __need_ssize_t || defined __need_time_t) + +/* Special invocation convention inside mingw header files. */ + +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H + +/* The include_next requires a split double-inclusion guard. */ +# define _GL_INCLUDING_SYS_TYPES_H +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ +# undef _GL_INCLUDING_SYS_TYPES_H + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H +#define _@GUARD_PREFIX@_SYS_TYPES_H + +/* Override off_t if Large File Support is requested on native Windows. */ +#if @WINDOWS_64_BIT_OFF_T@ +/* Same as int64_t in . */ +# if defined _MSC_VER +# define off_t __int64 +# else +# define off_t long long int +# endif +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_64_BIT_OFF_T 1 +#endif + +/* Override dev_t and ino_t if distinguishable inodes support is requested + on native Windows. */ +#if @WINDOWS_STAT_INODES@ + +# if @WINDOWS_STAT_INODES@ == 2 +/* Experimental, not useful in Windows 10. */ + +/* Define dev_t to a 64-bit type. */ +# if !defined GNULIB_defined_dev_t +typedef unsigned long long int rpl_dev_t; +# undef dev_t +# define dev_t rpl_dev_t +# define GNULIB_defined_dev_t 1 +# endif + +/* Define ino_t to a 128-bit type. */ +# if !defined GNULIB_defined_ino_t +/* MSVC does not have a 128-bit integer type. + GCC has a 128-bit integer type __int128, but only on 64-bit targets. */ +typedef struct { unsigned long long int _gl_ino[2]; } rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# else /* @WINDOWS_STAT_INODES@ == 1 */ + +/* Define ino_t to a 64-bit type. */ +# if !defined GNULIB_defined_ino_t +typedef unsigned long long int rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# endif + +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_INODES @WINDOWS_STAT_INODES@ + +#endif + +/* MSVC 9 defines size_t in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if (defined _WIN32 && ! defined __CYGWIN__) && ! defined __GLIBC__ +# include +#endif + +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* __need_XXX */ diff --git a/src/gnulib/xsize.c b/src/gnulib/xsize.c new file mode 100644 index 000000000..4b4914c2c --- /dev/null +++ b/src/gnulib/xsize.c @@ -0,0 +1,3 @@ +#include +#define XSIZE_INLINE _GL_EXTERN_INLINE +#include "xsize.h" diff --git a/src/gnulib/xsize.h b/src/gnulib/xsize.h new file mode 100644 index 000000000..b69bafc3a --- /dev/null +++ b/src/gnulib/xsize.h @@ -0,0 +1,108 @@ +/* xsize.h -- Checked size_t computations. + + Copyright (C) 2003, 2008-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, 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 . */ + +#ifndef _XSIZE_H +#define _XSIZE_H + +/* Get size_t. */ +#include + +/* Get SIZE_MAX. */ +#include +#if HAVE_STDINT_H +# include +#endif + +/* Get ATTRIBUTE_PURE. */ +#include "attribute.h" + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef XSIZE_INLINE +# define XSIZE_INLINE _GL_INLINE +#endif + +/* The size of memory objects is often computed through expressions of + type size_t. Example: + void* p = malloc (header_size + n * element_size). + These computations can lead to overflow. When this happens, malloc() + returns a piece of memory that is way too small, and the program then + crashes while attempting to fill the memory. + To avoid this, the functions and macros in this file check for overflow. + The convention is that SIZE_MAX represents overflow. + malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc + implementation that uses mmap --, it's recommended to use size_overflow_p() + or size_in_bounds_p() before invoking malloc(). + The example thus becomes: + size_t size = xsum (header_size, xtimes (n, element_size)); + void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); +*/ + +/* Convert an arbitrary value >= 0 to type size_t. */ +#define xcast_size_t(N) \ + ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) + +/* Sum of two sizes, with overflow check. */ +XSIZE_INLINE size_t ATTRIBUTE_PURE +xsum (size_t size1, size_t size2) +{ + size_t sum = size1 + size2; + return (sum >= size1 ? sum : SIZE_MAX); +} + +/* Sum of three sizes, with overflow check. */ +XSIZE_INLINE size_t ATTRIBUTE_PURE +xsum3 (size_t size1, size_t size2, size_t size3) +{ + return xsum (xsum (size1, size2), size3); +} + +/* Sum of four sizes, with overflow check. */ +XSIZE_INLINE size_t ATTRIBUTE_PURE +xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) +{ + return xsum (xsum (xsum (size1, size2), size3), size4); +} + +/* Maximum of two sizes, with overflow check. */ +XSIZE_INLINE size_t ATTRIBUTE_PURE +xmax (size_t size1, size_t size2) +{ + /* No explicit check is needed here, because for any n: + max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ + return (size1 >= size2 ? size1 : size2); +} + +/* Multiplication of a count with an element size, with overflow check. + The count must be >= 0 and the element size must be > 0. + This is a macro, not a function, so that it works correctly even + when N is of a wider type and N > SIZE_MAX. */ +#define xtimes(N, ELSIZE) \ + ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) + +/* Check for overflow. */ +#define size_overflow_p(SIZE) \ + ((SIZE) == SIZE_MAX) +/* Check against overflow. */ +#define size_in_bounds_p(SIZE) \ + ((SIZE) != SIZE_MAX) + +_GL_INLINE_HEADER_END + +#endif /* _XSIZE_H */ diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 44d139f58..3d35702ac 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -23,6 +23,7 @@ #include "config.h" #endif +#include "helper/replacements.h" #include "log.h" #include "binarybuffer.h" diff --git a/src/helper/bits.h b/src/helper/bits.h index cdcac9eaf..00d3c0270 100644 --- a/src/helper/bits.h +++ b/src/helper/bits.h @@ -24,6 +24,7 @@ #ifndef OPENOCD_HELPER_BITS_H #define OPENOCD_HELPER_BITS_H +#include #include #define BIT(nr) (1UL << (nr)) diff --git a/src/helper/configuration.c b/src/helper/configuration.c index 114ad2c6c..8f4f11833 100644 --- a/src/helper/configuration.c +++ b/src/helper/configuration.c @@ -18,12 +18,14 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "configuration.h" #include "log.h" +#include "replacements.h" static size_t num_config_files; static char **config_file_names; diff --git a/src/helper/fileio.c b/src/helper/fileio.c index 9dd57e72a..b6f1f4e2c 100644 --- a/src/helper/fileio.c +++ b/src/helper/fileio.c @@ -29,6 +29,7 @@ #include "log.h" #include "configuration.h" #include "fileio.h" +#include "replacements.h" struct fileio { char *url; diff --git a/src/helper/fileio.h b/src/helper/fileio.h index 02592e28d..16c104657 100644 --- a/src/helper/fileio.h +++ b/src/helper/fileio.h @@ -25,6 +25,8 @@ #ifndef OPENOCD_HELPER_FILEIO_H #define OPENOCD_HELPER_FILEIO_H +#include "types.h" + #define FILEIO_MAX_ERROR_STRING (128) enum fileio_type { diff --git a/src/helper/log.c b/src/helper/log.c index 7440b70f6..f5a80623f 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -28,6 +28,7 @@ #include "log.h" #include "command.h" +#include "replacements.h" #include "time_support.h" #include diff --git a/src/helper/options.c b/src/helper/options.c index 0ccbf5642..246c6a8b5 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -31,6 +31,7 @@ #include #include +#include #if IS_DARWIN #include #endif diff --git a/src/helper/replacements.c b/src/helper/replacements.c index b4bb94f06..f4ecb8dfc 100644 --- a/src/helper/replacements.c +++ b/src/helper/replacements.c @@ -62,6 +62,7 @@ void *fill_malloc(size_t size) #ifdef _WIN32 #include +#include #endif /* replacements for gettimeofday */ diff --git a/src/helper/replacements.h b/src/helper/replacements.h index ac5009549..1b6e5bdb8 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -26,6 +26,7 @@ #define OPENOCD_HELPER_REPLACEMENTS_H #include +#include /* MIN,MAX macros */ #ifndef MIN diff --git a/src/helper/time_support.h b/src/helper/time_support.h index a9f2dffad..3c7d4255b 100644 --- a/src/helper/time_support.h +++ b/src/helper/time_support.h @@ -26,6 +26,7 @@ #define OPENOCD_HELPER_TIME_SUPPORT_H #include +#include "types.h" #ifdef HAVE_SYS_TIME_H #include diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index af75917a3..13368ab4a 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -37,10 +37,6 @@ #include #include -#ifdef HAVE_STRINGS_H -#include -#endif - /** * @file * Holds support for configuring debug adapters from TCl scripts. diff --git a/src/jtag/aice/aice_pipe.c b/src/jtag/aice/aice_pipe.c index c0e532c9d..2dd24b93f 100644 --- a/src/jtag/aice/aice_pipe.c +++ b/src/jtag/aice/aice_pipe.c @@ -27,6 +27,7 @@ #include #include +#include #include "aice_port.h" #include "aice_pipe.h" diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c index ea710ad25..0c9f30302 100644 --- a/src/jtag/aice/aice_transport.c +++ b/src/jtag/aice/aice_transport.c @@ -27,6 +27,7 @@ #include #include #include +#include /* */ static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi, diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index 7688aeaab..c5a0eb7b7 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/src/jtag/core.c b/src/jtag/core.c index 5abf832f8..ac589063b 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -35,6 +35,7 @@ #include "interface.h" #include #include +#include "helper/system.h" #ifdef HAVE_STRINGS_H #include diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index 40d52acb9..754f93767 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -22,6 +22,7 @@ #include #include +#include "helper/system.h" #include #include "usb_common.h" diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 16480ae1e..e2762e1a3 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -36,6 +36,7 @@ #endif #include +#include "helper/replacements.h" #include #include #include diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index 0134c0376..9c7644947 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -37,6 +37,7 @@ #include #include +#include #include "cmsis_dap.h" diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 15d252cfb..8c1a8116d 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/src/jtag/drivers/jtag_usb_common.c b/src/jtag/drivers/jtag_usb_common.c index 969ea8406..f18ea54a2 100644 --- a/src/jtag/drivers/jtag_usb_common.c +++ b/src/jtag/drivers/jtag_usb_common.c @@ -4,6 +4,7 @@ */ #include +#include #include "jtag_usb_common.h" diff --git a/src/jtag/drivers/jtag_usb_common.h b/src/jtag/drivers/jtag_usb_common.h index 8c03742e9..c4c28cc91 100644 --- a/src/jtag/drivers/jtag_usb_common.h +++ b/src/jtag/drivers/jtag_usb_common.h @@ -6,6 +6,9 @@ #ifndef OPENOCD_JTAG_USB_COMMON_H #define OPENOCD_JTAG_USB_COMMON_H +#include +#include + void jtag_usb_set_location(const char *location); const char *jtag_usb_get_location(void); bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path, diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index c5ffe83ba..aeed6a56c 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -33,7 +33,7 @@ #include #endif -#include +#include "helper/replacements.h" #define NO_TAP_SHIFT 0 #define TAP_SHIFT 1 diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index fe8b6b82c..39c49e7b4 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -22,6 +22,7 @@ #include "mpsse.h" #include "helper/log.h" +#include "helper/replacements.h" #include "helper/time_support.h" #include diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 663795296..ef27056c7 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -24,6 +24,8 @@ #include #include #endif +#include "helper/system.h" +#include "helper/replacements.h" #include #include "bitbang.h" diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index be4ad08bf..d15dba750 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -29,6 +29,7 @@ /* project specific includes */ #include #include +#include "helper/replacements.h" #include "rlink.h" #include "rlink_st7.h" #include "rlink_ep1_cmd.h" diff --git a/src/jtag/drivers/rlink.h b/src/jtag/drivers/rlink.h index 74b62580c..0c15a3223 100644 --- a/src/jtag/drivers/rlink.h +++ b/src/jtag/drivers/rlink.h @@ -19,6 +19,7 @@ #ifndef OPENOCD_JTAG_DRIVERS_RLINK_H #define OPENOCD_JTAG_DRIVERS_RLINK_H +#include "helper/types.h" struct rlink_speed_table { uint8_t const *dtc; uint16_t dtc_size; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 4545bcba0..a6d7c3a1b 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -32,6 +32,7 @@ /* project specific includes */ #include #include +#include #include #include #include diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index ccc023fb8..1b773fa62 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -21,6 +21,7 @@ #endif #include +#include "helper/system.h" #include #include #include diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index 6f15fa70a..15028b7ea 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -23,6 +23,7 @@ #endif #include #include +#include "helper/system.h" #include #include diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 5002a5f53..c312468b4 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -77,6 +77,7 @@ #include #include #include +#include #include "ublast_access.h" /* system includes */ diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 2fa580223..cc403df46 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -24,6 +24,7 @@ #include #include +#include #ifndef DEBUG_JTAG_IOZ #define DEBUG_JTAG_IOZ 64 diff --git a/src/m4/00gnulib.m4 b/src/m4/00gnulib.m4 new file mode 100644 index 000000000..9ba1743e6 --- /dev/null +++ b/src/m4/00gnulib.m4 @@ -0,0 +1,85 @@ +# 00gnulib.m4 serial 8 +dnl Copyright (C) 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, +dnl with or without modifications, as long as this notice is preserved. + +dnl This file must be named something that sorts before all other +dnl gnulib-provided .m4 files. It is needed until the clang fix has +dnl been included in Autoconf. + +# The following definitions arrange to use a compiler option +# -Werror=implicit-function-declaration in AC_CHECK_DECL, when the +# compiler is clang. Without it, clang implicitly declares "known" +# library functions in C mode, but not in C++ mode, which would cause +# Gnulib to omit a declaration and thus later produce an error in C++ +# mode. As of clang 9.0, these "known" functions are identified through +# LIBBUILTIN invocations in the LLVM source file +# llvm/tools/clang/include/clang/Basic/Builtins.def. +# It's not possible to AC_REQUIRE the extra tests from AC_CHECK_DECL, +# because AC_CHECK_DECL, like other Autoconf built-ins, is not supposed +# to AC_REQUIRE anything: some configure.ac files have their first +# AC_CHECK_DECL executed conditionally. Therefore append the extra tests +# to AC_PROG_CC. +AC_DEFUN([gl_COMPILER_CLANG], +[ +dnl AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([whether the compiler is clang], + [gl_cv_compiler_clang], + [dnl Use _AC_COMPILE_IFELSE instead of AC_EGREP_CPP, to avoid error + dnl "circular dependency of AC_LANG_COMPILER(C)" if AC_PROG_CC has + dnl not yet been invoked. + _AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #ifdef __clang__ + barfbarf + #endif + ]],[[]]) + ], + [gl_cv_compiler_clang=no], + [gl_cv_compiler_clang=yes]) + ]) +]) +AC_DEFUN([gl_COMPILER_PREPARE_CHECK_DECL], +[ +dnl AC_REQUIRE([AC_PROG_CC]) +dnl AC_REQUIRE([gl_COMPILER_CLANG]) + AC_CACHE_CHECK([for compiler option needed when checking for declarations], + [gl_cv_compiler_check_decl_option], + [if test $gl_cv_compiler_clang = yes; then + dnl Test whether the compiler supports the option + dnl '-Werror=implicit-function-declaration'. + save_ac_compile="$ac_compile" + ac_compile="$ac_compile -Werror=implicit-function-declaration" + dnl Use _AC_COMPILE_IFELSE instead of AC_COMPILE_IFELSE, to avoid a + dnl warning "AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS". + _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [gl_cv_compiler_check_decl_option='-Werror=implicit-function-declaration'], + [gl_cv_compiler_check_decl_option=none]) + ac_compile="$save_ac_compile" + else + gl_cv_compiler_check_decl_option=none + fi + ]) + if test "x$gl_cv_compiler_check_decl_option" != xnone; then + ac_compile_for_check_decl="$ac_compile $gl_cv_compiler_check_decl_option" + else + ac_compile_for_check_decl="$ac_compile" + fi +]) +dnl Redefine _AC_CHECK_DECL_BODY so that it references ac_compile_for_check_decl +dnl instead of ac_compile. If, for whatever reason, the override of AC_PROG_CC +dnl in zzgnulib.m4 is inactive, use the original ac_compile. +m4_define([_AC_CHECK_DECL_BODY], +[ ac_save_ac_compile="$ac_compile" + if test -n "$ac_compile_for_check_decl"; then + ac_compile="$ac_compile_for_check_decl" + fi] +m4_defn([_AC_CHECK_DECL_BODY])[ ac_compile="$ac_save_ac_compile" +]) + +# gl_00GNULIB +# ----------- +# Witness macro that this file has been included. Needed to force +# Automake to include this file prior to all other gnulib .m4 files. +AC_DEFUN([gl_00GNULIB]) diff --git a/src/m4/absolute-header.m4 b/src/m4/absolute-header.m4 new file mode 100644 index 000000000..52d80d042 --- /dev/null +++ b/src/m4/absolute-header.m4 @@ -0,0 +1,100 @@ +# absolute-header.m4 serial 17 +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, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Derek Price. + +# gl_ABSOLUTE_HEADER(HEADER1 HEADER2 ...) +# --------------------------------------- +# Find the absolute name of a header file, testing first if the header exists. +# If the header were sys/inttypes.h, this macro would define +# ABSOLUTE_SYS_INTTYPES_H to the '""' quoted absolute name of sys/inttypes.h +# in config.h +# (e.g. '#define ABSOLUTE_SYS_INTTYPES_H "///usr/include/sys/inttypes.h"'). +# The three "///" are to pacify Sun C 5.8, which otherwise would say +# "warning: #include of /usr/include/... may be non-portable". +# Use '""', not '<>', so that the /// cannot be confused with a C99 comment. +# Note: This macro assumes that the header file is not empty after +# preprocessing, i.e. it does not only define preprocessor macros but also +# provides some type/enum definitions or function/variable declarations. +AC_DEFUN([gl_ABSOLUTE_HEADER], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_PREPROC_REQUIRE()dnl +m4_foreach_w([gl_HEADER_NAME], [$1], + [AS_VAR_PUSHDEF([gl_absolute_header], + [gl_cv_absolute_]m4_defn([gl_HEADER_NAME]))dnl + AC_CACHE_CHECK([absolute name of <]m4_defn([gl_HEADER_NAME])[>], + [gl_absolute_header], + [AS_VAR_PUSHDEF([ac_header_exists], + [ac_cv_header_]m4_defn([gl_HEADER_NAME]))dnl + AC_CHECK_HEADERS_ONCE(m4_defn([gl_HEADER_NAME]))dnl + if test AS_VAR_GET([ac_header_exists]) = yes; then + gl_ABSOLUTE_HEADER_ONE(m4_defn([gl_HEADER_NAME])) + fi + AS_VAR_POPDEF([ac_header_exists])dnl + ])dnl + AC_DEFINE_UNQUOTED(AS_TR_CPP([ABSOLUTE_]m4_defn([gl_HEADER_NAME])), + ["AS_VAR_GET([gl_absolute_header])"], + [Define this to an absolute name of <]m4_defn([gl_HEADER_NAME])[>.]) + AS_VAR_POPDEF([gl_absolute_header])dnl +])dnl +])# gl_ABSOLUTE_HEADER + +# gl_ABSOLUTE_HEADER_ONE(HEADER) +# ------------------------------ +# Like gl_ABSOLUTE_HEADER, except that: +# - it assumes that the header exists, +# - it uses the current CPPFLAGS, +# - it does not cache the result, +# - it is silent. +AC_DEFUN([gl_ABSOLUTE_HEADER_ONE], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_LANG_CONFTEST([AC_LANG_SOURCE([[#include <]]m4_dquote([$1])[[>]])]) + dnl AIX "xlc -E" and "cc -E" omit #line directives for header files + dnl that contain only a #include of other header files and no + dnl non-comment tokens of their own. This leads to a failure to + dnl detect the absolute name of , , + dnl and others. The workaround is to force preservation of comments + dnl through option -C. This ensures all necessary #line directives + dnl are present. GCC supports option -C as well. + case "$host_os" in + aix*) gl_absname_cpp="$ac_cpp -C" ;; + *) gl_absname_cpp="$ac_cpp" ;; + esac +changequote(,) + case "$host_os" in + mingw*) + dnl For the sake of native Windows compilers (excluding gcc), + dnl treat backslash as a directory separator, like /. + dnl Actually, these compilers use a double-backslash as + dnl directory separator, inside the + dnl # line "filename" + dnl directives. + gl_dirsep_regex='[/\\]' + ;; + *) + gl_dirsep_regex='\/' + ;; + esac + dnl A sed expression that turns a string into a basic regular + dnl expression, for use within "/.../". + gl_make_literal_regex_sed='s,[]$^\\.*/[],\\&,g' + gl_header_literal_regex=`echo '$1' \ + | sed -e "$gl_make_literal_regex_sed"` + gl_absolute_header_sed="/${gl_dirsep_regex}${gl_header_literal_regex}/"'{ + s/.*"\(.*'"${gl_dirsep_regex}${gl_header_literal_regex}"'\)".*/\1/ + s|^/[^/]|//&| + p + q + }' +changequote([,]) + dnl eval is necessary to expand gl_absname_cpp. + dnl Ultrix and Pyramid sh refuse to redirect output of eval, + dnl so use subshell. + AS_VAR_SET([gl_cv_absolute_]AS_TR_SH([[$1]]), +[`(eval "$gl_absname_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + sed -n "$gl_absolute_header_sed"`]) +]) diff --git a/src/m4/extern-inline.m4 b/src/m4/extern-inline.m4 new file mode 100644 index 000000000..a2acf126c --- /dev/null +++ b/src/m4/extern-inline.m4 @@ -0,0 +1,114 @@ +dnl 'extern inline' a la ISO C99. + +dnl Copyright 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, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_EXTERN_INLINE], +[ + AH_VERBATIM([extern_inline], +[/* Please see the Gnulib manual for how to use these macros. + + Suppress extern inline with HP-UX cc, as it appears to be broken; see + . + + Suppress extern inline with Sun C in standards-conformance mode, as it + mishandles inline functions that call each other. E.g., for 'inline void f + (void) { } inline void g (void) { f (); }', c99 incorrectly complains + 'reference to static identifier "f" in extern inline function'. + This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16. + + Suppress extern inline (with or without __attribute__ ((__gnu_inline__))) + on configurations that mistakenly use 'static inline' to implement + functions or macros in standard C headers like . For example, + if isdigit is mistakenly implemented via a static inline function, + a program containing an extern inline function that calls isdigit + may not work since the C standard prohibits extern inline functions + from calling static functions (ISO C 99 section 6.7.4.(3). + This bug is known to occur on: + + OS X 10.8 and earlier; see: + https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html + + DragonFly; see + http://muscles.dragonflybsd.org/bulk/clang-master-potential/20141111_102002/logs/ah-tty-0.3.12.log + + FreeBSD; see: + https://lists.gnu.org/r/bug-gnulib/2014-07/msg00104.html + + OS X 10.9 has a macro __header_inline indicating the bug is fixed for C and + for clang but remains for g++; see . + Assume DragonFly and FreeBSD will be similar. + + GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. It defines a macro + __GNUC_STDC_INLINE__ to indicate this situation or a macro + __GNUC_GNU_INLINE__ to indicate the opposite situation. + GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline + semantics but warns, unless -fgnu89-inline is used: + warning: C99 inline functions are not supported; using GNU89 + warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute + It defines a macro __GNUC_GNU_INLINE__ to indicate this situation. + */ +#if (((defined __APPLE__ && defined __MACH__) \ + || defined __DragonFly__ || defined __FreeBSD__) \ + && (defined __header_inline \ + ? (defined __cplusplus && defined __GNUC_STDC_INLINE__ \ + && ! defined __clang__) \ + : ((! defined _DONT_USE_CTYPE_INLINE_ \ + && (defined __GNUC__ || defined __cplusplus)) \ + || (defined _FORTIFY_SOURCE && 0 < _FORTIFY_SOURCE \ + && defined __GNUC__ && ! defined __cplusplus)))) +# define _GL_EXTERN_INLINE_STDHEADER_BUG +#endif +#if ((__GNUC__ \ + ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \ + : (199901L <= __STDC_VERSION__ \ + && !defined __HP_cc \ + && !defined __PGI \ + && !(defined __SUNPRO_C && __STDC__))) \ + && !defined _GL_EXTERN_INLINE_STDHEADER_BUG) +# define _GL_INLINE inline +# define _GL_EXTERN_INLINE extern inline +# define _GL_EXTERN_INLINE_IN_USE +#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \ + && !defined _GL_EXTERN_INLINE_STDHEADER_BUG) +# if defined __GNUC_GNU_INLINE__ && __GNUC_GNU_INLINE__ + /* __gnu_inline__ suppresses a GCC 4.2 diagnostic. */ +# define _GL_INLINE extern inline __attribute__ ((__gnu_inline__)) +# else +# define _GL_INLINE extern inline +# endif +# define _GL_EXTERN_INLINE extern +# define _GL_EXTERN_INLINE_IN_USE +#else +# define _GL_INLINE static _GL_UNUSED +# define _GL_EXTERN_INLINE static _GL_UNUSED +#endif + +/* In GCC 4.6 (inclusive) to 5.1 (exclusive), + suppress bogus "no previous prototype for 'FOO'" + and "no previous declaration for 'FOO'" diagnostics, + when FOO is an inline function in the header; see + and + . */ +#if __GNUC__ == 4 && 6 <= __GNUC_MINOR__ +# if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ +# define _GL_INLINE_HEADER_CONST_PRAGMA +# else +# define _GL_INLINE_HEADER_CONST_PRAGMA \ + _Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") +# endif +# define _GL_INLINE_HEADER_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wmissing-prototypes\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmissing-declarations\"") \ + _GL_INLINE_HEADER_CONST_PRAGMA +# define _GL_INLINE_HEADER_END \ + _Pragma ("GCC diagnostic pop") +#else +# define _GL_INLINE_HEADER_BEGIN +# define _GL_INLINE_HEADER_END +#endif]) +]) diff --git a/src/m4/gnulib-cache.m4 b/src/m4/gnulib-cache.m4 new file mode 100644 index 000000000..c9777fede --- /dev/null +++ b/src/m4/gnulib-cache.m4 @@ -0,0 +1,57 @@ +# Copyright (C) 2002-2021 Free Software Foundation, Inc. +# +# 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 +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# +# This file represents the specification of how gnulib-tool is used. +# It acts as a cache: It is written and read by gnulib-tool. +# In projects that use version control, this file is meant to be put under +# version control, like the configure.ac and various Makefile.am files. + + +# Specification in the form of a command-line invocation: +# gnulib-tool --import \ +# --lib=libgnu \ +# --source-base=src/gnulib \ +# --m4-base=src/m4 \ +# --doc-base=doc \ +# --tests-base=tests \ +# --aux-dir=. \ +# --no-conditional-dependencies \ +# --no-libtool \ +# --macro-prefix=gl \ +# linkedhash-map + +# Specification in the form of a few gnulib-tool.m4 macro invocations: +gl_LOCAL_DIR([]) +gl_MODULES([ + linkedhash-map +]) +gl_AVOID([]) +gl_SOURCE_BASE([src/gnulib]) +gl_M4_BASE([src/m4]) +gl_PO_BASE([]) +gl_DOC_BASE([doc]) +gl_TESTS_BASE([tests]) +gl_LIB([libgnu]) +gl_MAKEFILE_NAME([]) +gl_MACRO_PREFIX([gl]) +gl_PO_DOMAIN([]) +gl_WITNESS_C_MACRO([]) diff --git a/src/m4/gnulib-common.m4 b/src/m4/gnulib-common.m4 new file mode 100644 index 000000000..f2eff10de --- /dev/null +++ b/src/m4/gnulib-common.m4 @@ -0,0 +1,727 @@ +# gnulib-common.m4 serial 63 +dnl Copyright (C) 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, +dnl with or without modifications, as long as this notice is preserved. + +AC_PREREQ([2.62]) + +# gl_COMMON +# is expanded unconditionally through gnulib-tool magic. +AC_DEFUN([gl_COMMON], [ + dnl Use AC_REQUIRE here, so that the code is expanded once only. + AC_REQUIRE([gl_00GNULIB]) + AC_REQUIRE([gl_COMMON_BODY]) + AC_REQUIRE([gl_ZZGNULIB]) +]) +AC_DEFUN([gl_COMMON_BODY], [ + AH_VERBATIM([_GL_GNUC_PREREQ], +[/* True if the compiler says it groks GNU C version MAJOR.MINOR. */ +#if defined __GNUC__ && defined __GNUC_MINOR__ +# define _GL_GNUC_PREREQ(major, minor) \ + ((major) < __GNUC__ + ((minor) <= __GNUC_MINOR__)) +#else +# define _GL_GNUC_PREREQ(major, minor) 0 +#endif +]) + AH_VERBATIM([_Noreturn], +[/* The _Noreturn keyword of C11. */ +#ifndef _Noreturn +# if (defined __cplusplus \ + && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \ + || (defined _MSC_VER && 1900 <= _MSC_VER)) \ + && 0) + /* [[noreturn]] is not practically usable, because with it the syntax + extern _Noreturn void func (...); + would not be valid; such a declaration would only be valid with 'extern' + and '_Noreturn' swapped, or without the 'extern' keyword. However, some + AIX system header files and several gnulib header files use precisely + this syntax with 'extern'. */ +# define _Noreturn [[noreturn]] +# elif ((!defined __cplusplus || defined __clang__) \ + && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \ + || (!defined __STRICT_ANSI__ \ + && (_GL_GNUC_PREREQ (4, 7) \ + || (defined __apple_build_version__ \ + ? 6000000 <= __apple_build_version__ \ + : 3 < __clang_major__ + (5 <= __clang_minor__)))))) + /* _Noreturn works as-is. */ +# elif _GL_GNUC_PREREQ (2, 8) || defined __clang__ || 0x5110 <= __SUNPRO_C +# define _Noreturn __attribute__ ((__noreturn__)) +# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0) +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn +# endif +#endif +]) + AH_VERBATIM([isoc99_inline], +[/* Work around a bug in Apple GCC 4.0.1 build 5465: In C99 mode, it supports + the ISO C 99 semantics of 'extern inline' (unlike the GNU C semantics of + earlier versions), but does not display it by setting __GNUC_STDC_INLINE__. + __APPLE__ && __MACH__ test for Mac OS X. + __APPLE_CC__ tests for the Apple compiler and its version. + __STDC_VERSION__ tests for the C99 mode. */ +#if defined __APPLE__ && defined __MACH__ && __APPLE_CC__ >= 5465 && !defined __cplusplus && __STDC_VERSION__ >= 199901L && !defined __GNUC_STDC_INLINE__ +# define __GNUC_STDC_INLINE__ 1 +#endif]) + AH_VERBATIM([attribute], +[/* Attributes. */ +#if (defined __has_attribute \ + && (!defined __clang_minor__ \ + || 3 < __clang_major__ + (5 <= __clang_minor__))) +# define _GL_HAS_ATTRIBUTE(attr) __has_attribute (__##attr##__) +#else +# define _GL_HAS_ATTRIBUTE(attr) _GL_ATTR_##attr +# define _GL_ATTR_alloc_size _GL_GNUC_PREREQ (4, 3) +# define _GL_ATTR_always_inline _GL_GNUC_PREREQ (3, 2) +# define _GL_ATTR_artificial _GL_GNUC_PREREQ (4, 3) +# define _GL_ATTR_cold _GL_GNUC_PREREQ (4, 3) +# define _GL_ATTR_const _GL_GNUC_PREREQ (2, 95) +# define _GL_ATTR_deprecated _GL_GNUC_PREREQ (3, 1) +# define _GL_ATTR_diagnose_if 0 +# define _GL_ATTR_error _GL_GNUC_PREREQ (4, 3) +# define _GL_ATTR_externally_visible _GL_GNUC_PREREQ (4, 1) +# define _GL_ATTR_fallthrough _GL_GNUC_PREREQ (7, 0) +# define _GL_ATTR_format _GL_GNUC_PREREQ (2, 7) +# define _GL_ATTR_leaf _GL_GNUC_PREREQ (4, 6) +# ifdef _ICC +# define _GL_ATTR_may_alias 0 +# else +# define _GL_ATTR_may_alias _GL_GNUC_PREREQ (3, 3) +# endif +# define _GL_ATTR_malloc _GL_GNUC_PREREQ (3, 0) +# define _GL_ATTR_noinline _GL_GNUC_PREREQ (3, 1) +# define _GL_ATTR_nonnull _GL_GNUC_PREREQ (3, 3) +# define _GL_ATTR_nonstring _GL_GNUC_PREREQ (8, 0) +# define _GL_ATTR_nothrow _GL_GNUC_PREREQ (3, 3) +# define _GL_ATTR_packed _GL_GNUC_PREREQ (2, 7) +# define _GL_ATTR_pure _GL_GNUC_PREREQ (2, 96) +# define _GL_ATTR_returns_nonnull _GL_GNUC_PREREQ (4, 9) +# define _GL_ATTR_sentinel _GL_GNUC_PREREQ (4, 0) +# define _GL_ATTR_unused _GL_GNUC_PREREQ (2, 7) +# define _GL_ATTR_warn_unused_result _GL_GNUC_PREREQ (3, 4) +#endif + +]dnl There is no _GL_ATTRIBUTE_ALIGNED; use stdalign's _Alignas instead. +[ +#if _GL_HAS_ATTRIBUTE (alloc_size) +# define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args)) +#else +# define _GL_ATTRIBUTE_ALLOC_SIZE(args) +#endif + +#if _GL_HAS_ATTRIBUTE (always_inline) +# define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__)) +#else +# define _GL_ATTRIBUTE_ALWAYS_INLINE +#endif + +#if _GL_HAS_ATTRIBUTE (artificial) +# define _GL_ATTRIBUTE_ARTIFICIAL __attribute__ ((__artificial__)) +#else +# define _GL_ATTRIBUTE_ARTIFICIAL +#endif + +/* Avoid __attribute__ ((cold)) on MinGW; see thread starting at + . + Also, Oracle Studio 12.6 requires 'cold' not '__cold__'. */ +#if _GL_HAS_ATTRIBUTE (cold) && !defined __MINGW32__ +# ifndef __SUNPRO_C +# define _GL_ATTRIBUTE_COLD __attribute__ ((__cold__)) +# else +# define _GL_ATTRIBUTE_COLD __attribute__ ((cold)) +# endif +#else +# define _GL_ATTRIBUTE_COLD +#endif + +#if _GL_HAS_ATTRIBUTE (const) +# define _GL_ATTRIBUTE_CONST __attribute__ ((__const__)) +#else +# define _GL_ATTRIBUTE_CONST +#endif + +#if 201710L < __STDC_VERSION__ +# define _GL_ATTRIBUTE_DEPRECATED [[__deprecated__]] +#elif _GL_HAS_ATTRIBUTE (deprecated) +# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) +#else +# define _GL_ATTRIBUTE_DEPRECATED +#endif + +#if _GL_HAS_ATTRIBUTE (error) +# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg))) +# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg))) +#elif _GL_HAS_ATTRIBUTE (diagnose_if) +# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__diagnose_if__ (1, msg, "error"))) +# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__diagnose_if__ (1, msg, "warning"))) +#else +# define _GL_ATTRIBUTE_ERROR(msg) +# define _GL_ATTRIBUTE_WARNING(msg) +#endif + +#if _GL_HAS_ATTRIBUTE (externally_visible) +# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE __attribute__ ((externally_visible)) +#else +# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE +#endif + +/* FALLTHROUGH is special, because it always expands to something. */ +#if 201710L < __STDC_VERSION__ +# define _GL_ATTRIBUTE_FALLTHROUGH [[__fallthrough__]] +#elif _GL_HAS_ATTRIBUTE (fallthrough) +# define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__)) +#else +# define _GL_ATTRIBUTE_FALLTHROUGH ((void) 0) +#endif + +#if _GL_HAS_ATTRIBUTE (format) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) +#endif + +#if _GL_HAS_ATTRIBUTE (leaf) +# define _GL_ATTRIBUTE_LEAF __attribute__ ((__leaf__)) +#else +# define _GL_ATTRIBUTE_LEAF +#endif + +/* Oracle Studio 12.6 mishandles may_alias despite __has_attribute OK. */ +#if _GL_HAS_ATTRIBUTE (may_alias) && !defined __SUNPRO_C +# define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__)) +#else +# define _GL_ATTRIBUTE_MAY_ALIAS +#endif + +#if 201710L < __STDC_VERSION__ +# define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]] +#elif _GL_HAS_ATTRIBUTE (unused) +# define _GL_ATTRIBUTE_MAYBE_UNUSED __attribute__ ((__unused__)) +#else +# define _GL_ATTRIBUTE_MAYBE_UNUSED +#endif +/* Earlier spellings of this macro. */ +#define _GL_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED +#define _UNUSED_PARAMETER_ _GL_ATTRIBUTE_MAYBE_UNUSED + +#if _GL_HAS_ATTRIBUTE (malloc) +# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +#else +# define _GL_ATTRIBUTE_MALLOC +#endif + +#if 201710L < __STDC_VERSION__ +# define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]] +#elif _GL_HAS_ATTRIBUTE (warn_unused_result) +# define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__)) +#else +# define _GL_ATTRIBUTE_NODISCARD +#endif + +#if _GL_HAS_ATTRIBUTE (noinline) +# define _GL_ATTRIBUTE_NOINLINE __attribute__ ((__noinline__)) +#else +# define _GL_ATTRIBUTE_NOINLINE +#endif + +#if _GL_HAS_ATTRIBUTE (nonnull) +# define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args)) +#else +# define _GL_ATTRIBUTE_NONNULL(args) +#endif + +#if _GL_HAS_ATTRIBUTE (nonstring) +# define _GL_ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__)) +#else +# define _GL_ATTRIBUTE_NONSTRING +#endif + +/* There is no _GL_ATTRIBUTE_NORETURN; use _Noreturn instead. */ + +#if _GL_HAS_ATTRIBUTE (nothrow) && !defined __cplusplus +# define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__)) +#else +# define _GL_ATTRIBUTE_NOTHROW +#endif + +#if _GL_HAS_ATTRIBUTE (packed) +# define _GL_ATTRIBUTE_PACKED __attribute__ ((__packed__)) +#else +# define _GL_ATTRIBUTE_PACKED +#endif + +#if _GL_HAS_ATTRIBUTE (pure) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE +#endif + +#if _GL_HAS_ATTRIBUTE (returns_nonnull) +# define _GL_ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__)) +#else +# define _GL_ATTRIBUTE_RETURNS_NONNULL +#endif + +#if _GL_HAS_ATTRIBUTE (sentinel) +# define _GL_ATTRIBUTE_SENTINEL(pos) __attribute__ ((__sentinel__ pos)) +#else +# define _GL_ATTRIBUTE_SENTINEL(pos) +#endif + +]dnl There is no _GL_ATTRIBUTE_VISIBILITY; see m4/visibility.m4 instead. +[ +/* To support C++ as well as C, use _GL_UNUSED_LABEL with trailing ';'. */ +#if !defined __cplusplus || _GL_GNUC_PREREQ (4, 5) +# define _GL_UNUSED_LABEL _GL_ATTRIBUTE_MAYBE_UNUSED +#else +# define _GL_UNUSED_LABEL +#endif +]) + AH_VERBATIM([async_safe], +[/* The _GL_ASYNC_SAFE marker should be attached to functions that are + signal handlers (for signals other than SIGABRT, SIGPIPE) or can be + invoked from such signal handlers. Such functions have some restrictions: + * All functions that it calls should be marked _GL_ASYNC_SAFE as well, + or should be listed as async-signal-safe in POSIX + + section 2.4.3. Note that malloc(), sprintf(), and fwrite(), in + particular, are NOT async-signal-safe. + * All memory locations (variables and struct fields) that these functions + access must be marked 'volatile'. This holds for both read and write + accesses. Otherwise the compiler might optimize away stores to and + reads from such locations that occur in the program, depending on its + data flow analysis. For example, when the program contains a loop + that is intended to inspect a variable set from within a signal handler + while (!signal_occurred) + ; + the compiler is allowed to transform this into an endless loop if the + variable 'signal_occurred' is not declared 'volatile'. + Additionally, recall that: + * A signal handler should not modify errno (except if it is a handler + for a fatal signal and ends by raising the same signal again, thus + provoking the termination of the process). If it invokes a function + that may clobber errno, it needs to save and restore the value of + errno. */ +#define _GL_ASYNC_SAFE +]) + AH_VERBATIM([micro_optimizations], +[/* _GL_CMP (n1, n2) performs a three-valued comparison on n1 vs. n2, where + n1 and n2 are expressions without side effects, that evaluate to real + numbers (excluding NaN). + It returns + 1 if n1 > n2 + 0 if n1 == n2 + -1 if n1 < n2 + The naïve code (n1 > n2 ? 1 : n1 < n2 ? -1 : 0) produces a conditional + jump with nearly all GCC versions up to GCC 10. + This variant (n1 < n2 ? -1 : n1 > n2) produces a conditional with many + GCC versions up to GCC 9. + The better code (n1 > n2) - (n1 < n2) from Hacker's Delight § 2-9 + avoids conditional jumps in all GCC versions >= 3.4. */ +#define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2))) +]) + dnl Hint which direction to take regarding cross-compilation guesses: + dnl When a user installs a program on a platform they are not intimately + dnl familiar with, --enable-cross-guesses=conservative is the appropriate + dnl choice. It implements the "If we don't know, assume the worst" principle. + dnl However, when an operating system developer (on a platform which is not + dnl yet known to gnulib) builds packages for their platform, they want to + dnl expose, not hide, possible platform bugs; in this case, + dnl --enable-cross-guesses=risky is the appropriate choice. + dnl Sets the variables + dnl gl_cross_guess_normal (to be used when 'yes' is good and 'no' is bad), + dnl gl_cross_guess_inverted (to be used when 'no' is good and 'yes' is bad). + AC_ARG_ENABLE([cross-guesses], + [AS_HELP_STRING([--enable-cross-guesses={conservative|risky}], + [specify policy for cross-compilation guesses])], + [if test "x$enableval" != xconservative && test "x$enableval" != xrisky; then + AC_MSG_WARN([invalid argument supplied to --enable-cross-guesses]) + enableval=conservative + fi + gl_cross_guesses="$enableval"], + [gl_cross_guesses=conservative]) + if test $gl_cross_guesses = risky; then + gl_cross_guess_normal="guessing yes" + gl_cross_guess_inverted="guessing no" + else + gl_cross_guess_normal="guessing no" + gl_cross_guess_inverted="guessing yes" + fi + dnl Preparation for running test programs: + dnl Tell glibc to write diagnostics from -D_FORTIFY_SOURCE=2 to stderr, not + dnl to /dev/tty, so they can be redirected to log files. Such diagnostics + dnl arise e.g., in the macros gl_PRINTF_DIRECTIVE_N, gl_SNPRINTF_DIRECTIVE_N. + LIBC_FATAL_STDERR_=1 + export LIBC_FATAL_STDERR_ +]) + +# gl_MODULE_INDICATOR_CONDITION +# expands to a C preprocessor expression that evaluates to 1 or 0, depending +# whether a gnulib module that has been requested shall be considered present +# or not. +m4_define([gl_MODULE_INDICATOR_CONDITION], [1]) + +# gl_MODULE_INDICATOR_SET_VARIABLE([modulename]) +# sets the shell variable that indicates the presence of the given module to +# a C preprocessor expression that will evaluate to 1. +AC_DEFUN([gl_MODULE_INDICATOR_SET_VARIABLE], +[ + gl_MODULE_INDICATOR_SET_VARIABLE_AUX( + [GNULIB_[]m4_translit([[$1]], + [abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])], + [gl_MODULE_INDICATOR_CONDITION]) +]) + +# gl_MODULE_INDICATOR_SET_VARIABLE_AUX([variable]) +# modifies the shell variable to include the gl_MODULE_INDICATOR_CONDITION. +# The shell variable's value is a C preprocessor expression that evaluates +# to 0 or 1. +AC_DEFUN([gl_MODULE_INDICATOR_SET_VARIABLE_AUX], +[ + m4_if(m4_defn([gl_MODULE_INDICATOR_CONDITION]), [1], + [ + dnl Simplify the expression VALUE || 1 to 1. + $1=1 + ], + [gl_MODULE_INDICATOR_SET_VARIABLE_AUX_OR([$1], + [gl_MODULE_INDICATOR_CONDITION])]) +]) + +# gl_MODULE_INDICATOR_SET_VARIABLE_AUX_OR([variable], [condition]) +# modifies the shell variable to include the given condition. The shell +# variable's value is a C preprocessor expression that evaluates to 0 or 1. +AC_DEFUN([gl_MODULE_INDICATOR_SET_VARIABLE_AUX_OR], +[ + dnl Simplify the expression 1 || CONDITION to 1. + if test "$[]$1" != 1; then + dnl Simplify the expression 0 || CONDITION to CONDITION. + if test "$[]$1" = 0; then + $1=$2 + else + $1="($[]$1 || $2)" + fi + fi +]) + +# gl_MODULE_INDICATOR([modulename]) +# defines a C macro indicating the presence of the given module +# in a location where it can be used. +# | Value | Value | +# | in lib/ | in tests/ | +# --------------------------------------------+---------+-----------+ +# Module present among main modules: | 1 | 1 | +# --------------------------------------------+---------+-----------+ +# Module present among tests-related modules: | 0 | 1 | +# --------------------------------------------+---------+-----------+ +# Module not present at all: | 0 | 0 | +# --------------------------------------------+---------+-----------+ +AC_DEFUN([gl_MODULE_INDICATOR], +[ + AC_DEFINE_UNQUOTED([GNULIB_]m4_translit([[$1]], + [abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___]), + [gl_MODULE_INDICATOR_CONDITION], + [Define to a C preprocessor expression that evaluates to 1 or 0, + depending whether the gnulib module $1 shall be considered present.]) +]) + +# gl_MODULE_INDICATOR_FOR_TESTS([modulename]) +# defines a C macro indicating the presence of the given module +# in lib or tests. This is useful to determine whether the module +# should be tested. +# | Value | Value | +# | in lib/ | in tests/ | +# --------------------------------------------+---------+-----------+ +# Module present among main modules: | 1 | 1 | +# --------------------------------------------+---------+-----------+ +# Module present among tests-related modules: | 1 | 1 | +# --------------------------------------------+---------+-----------+ +# Module not present at all: | 0 | 0 | +# --------------------------------------------+---------+-----------+ +AC_DEFUN([gl_MODULE_INDICATOR_FOR_TESTS], +[ + AC_DEFINE([GNULIB_TEST_]m4_translit([[$1]], + [abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___]), [1], + [Define to 1 when the gnulib module $1 should be tested.]) +]) + +# gl_ASSERT_NO_GNULIB_POSIXCHECK +# asserts that there will never be a need to #define GNULIB_POSIXCHECK. +# and thereby enables an optimization of configure and config.h. +# Used by Emacs. +AC_DEFUN([gl_ASSERT_NO_GNULIB_POSIXCHECK], +[ + dnl Override gl_WARN_ON_USE_PREPARE. + dnl But hide this definition from 'aclocal'. + AC_DEFUN([gl_W][ARN_ON_USE_PREPARE], []) +]) + +# gl_ASSERT_NO_GNULIB_TESTS +# asserts that there will be no gnulib tests in the scope of the configure.ac +# and thereby enables an optimization of config.h. +# Used by Emacs. +AC_DEFUN([gl_ASSERT_NO_GNULIB_TESTS], +[ + dnl Override gl_MODULE_INDICATOR_FOR_TESTS. + AC_DEFUN([gl_MODULE_INDICATOR_FOR_TESTS], []) +]) + +# Test whether exists. +# Set HAVE_FEATURES_H. +AC_DEFUN([gl_FEATURES_H], +[ + AC_CHECK_HEADERS_ONCE([features.h]) + if test $ac_cv_header_features_h = yes; then + HAVE_FEATURES_H=1 + else + HAVE_FEATURES_H=0 + fi + AC_SUBST([HAVE_FEATURES_H]) +]) + +# gl_PROG_CC_C99 +# Modifies the value of the shell variable CC in an attempt to make $CC +# understand ISO C99 source code. +AC_DEFUN([gl_PROG_CC_C99], +[ + dnl Just use AC_PROG_CC_C99. + dnl When AC_PROG_CC_C99 and AC_PROG_CC_STDC are used together, the substituted + dnl value of CC will contain the C99 enabling options twice. But this is only + dnl a cosmetic problem. + dnl With Autoconf >= 2.70, use AC_PROG_CC since it implies AC_PROG_CC_C99; + dnl this avoids a "warning: The macro `AC_PROG_CC_C99' is obsolete." + m4_version_prereq([2.70], + [AC_REQUIRE([AC_PROG_CC])], + [AC_REQUIRE([AC_PROG_CC_C99])]) +]) + +# gl_PROG_AR_RANLIB +# Determines the values for AR, ARFLAGS, RANLIB that fit with the compiler. +# The user can set the variables AR, ARFLAGS, RANLIB if he wants to override +# the values. +AC_DEFUN([gl_PROG_AR_RANLIB], +[ + dnl Minix 3 comes with two toolchains: The Amsterdam Compiler Kit compiler + dnl as "cc", and GCC as "gcc". They have different object file formats and + dnl library formats. In particular, the GNU binutils programs ar and ranlib + dnl produce libraries that work only with gcc, not with cc. + AC_REQUIRE([AC_PROG_CC]) + dnl The '][' hides this use from 'aclocal'. + AC_BEFORE([$0], [A][M_PROG_AR]) + AC_CACHE_CHECK([for Minix Amsterdam compiler], [gl_cv_c_amsterdam_compiler], + [ + AC_EGREP_CPP([Amsterdam], + [ +#ifdef __ACK__ +Amsterdam +#endif + ], + [gl_cv_c_amsterdam_compiler=yes], + [gl_cv_c_amsterdam_compiler=no]) + ]) + + dnl Don't compete with AM_PROG_AR's decision about AR/ARFLAGS if we are not + dnl building with __ACK__. + if test $gl_cv_c_amsterdam_compiler = yes; then + if test -z "$AR"; then + AR='cc -c.a' + fi + if test -z "$ARFLAGS"; then + ARFLAGS='-o' + fi + else + dnl AM_PROG_AR was added in automake v1.11.2. AM_PROG_AR does not AC_SUBST + dnl ARFLAGS variable (it is filed into Makefile.in directly by automake + dnl script on-demand, if not specified by ./configure of course). + dnl Don't AC_REQUIRE the AM_PROG_AR otherwise the code for __ACK__ above + dnl will be ignored. Also, pay attention to call AM_PROG_AR in else block + dnl because AM_PROG_AR is written so it could re-set AR variable even for + dnl __ACK__. It may seem like its easier to avoid calling the macro here, + dnl but we need to AC_SUBST both AR/ARFLAGS (thus those must have some good + dnl default value and automake should usually know them). + dnl + dnl The '][' hides this use from 'aclocal'. + m4_ifdef([A][M_PROG_AR], [A][M_PROG_AR], [:]) + fi + + dnl In case the code above has not helped with setting AR/ARFLAGS, use + dnl Automake-documented default values for AR and ARFLAGS, but prefer + dnl ${host}-ar over ar (useful for cross-compiling). + AC_CHECK_TOOL([AR], [ar], [ar]) + if test -z "$ARFLAGS"; then + ARFLAGS='cr' + fi + + AC_SUBST([AR]) + AC_SUBST([ARFLAGS]) + if test -z "$RANLIB"; then + if test $gl_cv_c_amsterdam_compiler = yes; then + RANLIB=':' + else + dnl Use the ranlib program if it is available. + AC_PROG_RANLIB + fi + fi + AC_SUBST([RANLIB]) +]) + +# AC_C_RESTRICT +# This definition is copied from post-2.70 Autoconf and overrides the +# AC_C_RESTRICT macro from autoconf 2.60..2.70. +m4_version_prereq([2.70.1], [], [ +AC_DEFUN([AC_C_RESTRICT], +[AC_CACHE_CHECK([for C/C++ restrict keyword], [ac_cv_c_restrict], + [ac_cv_c_restrict=no + # Put '__restrict__' first, to avoid problems with glibc and non-GCC; see: + # https://lists.gnu.org/archive/html/bug-autoconf/2016-02/msg00006.html + # Put 'restrict' last, because C++ lacks it. + for ac_kw in __restrict__ __restrict _Restrict restrict; do + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[typedef int *int_ptr; + int foo (int_ptr $ac_kw ip) { return ip[0]; } + int bar (int [$ac_kw]); /* Catch GCC bug 14050. */ + int bar (int ip[$ac_kw]) { return ip[0]; } + ]], + [[int s[1]; + int *$ac_kw t = s; + t[0] = 0; + return foo (t) + bar (t); + ]])], + [ac_cv_c_restrict=$ac_kw]) + test "$ac_cv_c_restrict" != no && break + done + ]) + AH_VERBATIM([restrict], +[/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported only directly. */ +#undef restrict +/* Work around a bug in older versions of Sun C++, which did not + #define __restrict__ or support _Restrict or __restrict__ + even though the corresponding Sun C compiler ended up with + "#define restrict _Restrict" or "#define restrict __restrict__" + in the previous line. This workaround can be removed once + we assume Oracle Developer Studio 12.5 (2016) or later. */ +#if defined __SUNPRO_CC && !defined __RESTRICT && !defined __restrict__ +# define _Restrict +# define __restrict__ +#endif]) + case $ac_cv_c_restrict in + restrict) ;; + no) AC_DEFINE([restrict], []) ;; + *) AC_DEFINE_UNQUOTED([restrict], [$ac_cv_c_restrict]) ;; + esac +])# AC_C_RESTRICT +]) + +# gl_BIGENDIAN +# is like AC_C_BIGENDIAN, except that it can be AC_REQUIREd. +# Note that AC_REQUIRE([AC_C_BIGENDIAN]) does not work reliably because some +# macros invoke AC_C_BIGENDIAN with arguments. +AC_DEFUN([gl_BIGENDIAN], +[ + AC_C_BIGENDIAN +]) + +# A temporary file descriptor. +# Must be less than 10, because dash 0.5.8 does not support redirections +# with multi-digit file descriptors. +m4_define([GL_TMP_FD], 9) + +# gl_SILENT(command) +# executes command, but without the normal configure output. +# This is useful when you want to invoke AC_CACHE_CHECK (or AC_CHECK_FUNC etc.) +# inside another AC_CACHE_CHECK. +AC_DEFUN([gl_SILENT], +[ + exec GL_TMP_FD>&AS_MESSAGE_FD AS_MESSAGE_FD>/dev/null + $1 + exec AS_MESSAGE_FD>&GL_TMP_FD GL_TMP_FD>&- +]) + +# gl_CACHE_VAL_SILENT(cache-id, command-to-set-it) +# is like AC_CACHE_VAL(cache-id, command-to-set-it), except that it does not +# output a spurious "(cached)" mark in the midst of other configure output. +# This macro should be used instead of AC_CACHE_VAL when it is not surrounded +# by an AC_MSG_CHECKING/AC_MSG_RESULT pair. +AC_DEFUN([gl_CACHE_VAL_SILENT], +[ + gl_SILENT([ + AC_CACHE_VAL([$1], [$2]) + ]) +]) + +dnl Expands to some code for use in .c programs that, on native Windows, defines +dnl the Microsoft deprecated alias function names to the underscore-prefixed +dnl actual function names. With this macro, these function names are available +dnl without linking with '-loldnames' and without generating warnings. +dnl Usage: Use it after all system header files are included. +dnl #include <...> +dnl #include <...> +dnl ]GL_MDA_DEFINES[ +dnl ... +AC_DEFUN([GL_MDA_DEFINES],[ +AC_REQUIRE([_GL_MDA_DEFINES]) +[$gl_mda_defines] +]) +AC_DEFUN([_GL_MDA_DEFINES], +[gl_mda_defines=' +#if defined _WIN32 && !defined __CYGWIN__ +#define access _access +#define chdir _chdir +#define chmod _chmod +#define close _close +#define creat _creat +#define dup _dup +#define dup2 _dup2 +#define ecvt _ecvt +#define execl _execl +#define execle _execle +#define execlp _execlp +#define execv _execv +#define execve _execve +#define execvp _execvp +#define execvpe _execvpe +#define fcloseall _fcloseall +#define fcvt _fcvt +#define fdopen _fdopen +#define fileno _fileno +#define gcvt _gcvt +#define getcwd _getcwd +#define getpid _getpid +#define getw _getw +#define isatty _isatty +#define j0 _j0 +#define j1 _j1 +#define jn _jn +#define lfind _lfind +#define lsearch _lsearch +#define lseek _lseek +#define memccpy _memccpy +#define mkdir _mkdir +#define mktemp _mktemp +#define open _open +#define putenv _putenv +#define putw _putw +#define read _read +#define rmdir _rmdir +#define strdup _strdup +#define swab _swab +#define tempnam _tempnam +#define tzset _tzset +#define umask _umask +#define unlink _unlink +#define utime _utime +#define wcsdup _wcsdup +#define write _write +#define y0 _y0 +#define y1 _y1 +#define yn _yn +#endif +' +]) diff --git a/src/m4/gnulib-comp.m4 b/src/m4/gnulib-comp.m4 new file mode 100644 index 000000000..4534c72a1 --- /dev/null +++ b/src/m4/gnulib-comp.m4 @@ -0,0 +1,261 @@ +# DO NOT EDIT! GENERATED AUTOMATICALLY! +# Copyright (C) 2002-2021 Free Software Foundation, Inc. +# +# 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 +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file 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 file. If not, see . +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# +# This file represents the compiled summary of the specification in +# gnulib-cache.m4. It lists the computed macro invocations that need +# to be invoked from configure.ac. +# In projects that use version control, this file can be treated like +# other built files. + + +# This macro should be invoked from ./configure.ac, in the section +# "Checks for programs", right after AC_PROG_CC, and certainly before +# any checks for libraries, header files, types and library functions. +AC_DEFUN([gl_EARLY], +[ + m4_pattern_forbid([^gl_[A-Z]])dnl the gnulib macro namespace + m4_pattern_allow([^gl_ES$])dnl a valid locale name + m4_pattern_allow([^gl_LIBOBJS$])dnl a variable + m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable + + # Pre-early section. + AC_REQUIRE([gl_PROG_AR_RANLIB]) + + # Code from module absolute-header: + # Code from module attribute: + # Code from module c99: + # Code from module extern-inline: + # Code from module include_next: + # Code from module limits-h: + # Code from module linkedhash-map: + # Code from module map: + # Code from module multiarch: + # Code from module size_max: + # Code from module ssize_t: + # Code from module std-gnu11: + # Code from module stdbool: + # Code from module stdint: + # Code from module sys_types: + # Code from module xsize: +]) + +# This macro should be invoked from ./configure.ac, in the section +# "Check for header files, types and library functions". +AC_DEFUN([gl_INIT], +[ + AM_CONDITIONAL([GL_COND_LIBTOOL], [false]) + gl_cond_libtool=false + gl_libdeps= + gl_ltlibdeps= + gl_m4_base='src/m4' + m4_pushdef([AC_LIBOBJ], m4_defn([gl_LIBOBJ])) + m4_pushdef([AC_REPLACE_FUNCS], m4_defn([gl_REPLACE_FUNCS])) + m4_pushdef([AC_LIBSOURCES], m4_defn([gl_LIBSOURCES])) + m4_pushdef([gl_LIBSOURCES_LIST], []) + m4_pushdef([gl_LIBSOURCES_DIR], []) + gl_COMMON + gl_source_base='src/gnulib' + AC_REQUIRE([gl_EXTERN_INLINE]) + gl_LIMITS_H + gl_MULTIARCH + gl_SIZE_MAX + gt_TYPE_SSIZE_T + AM_STDBOOL_H + gl_STDINT_H + gl_SYS_TYPES_H + AC_PROG_MKDIR_P + gl_XSIZE + # End of code from modules + m4_ifval(gl_LIBSOURCES_LIST, [ + m4_syscmd([test ! -d ]m4_defn([gl_LIBSOURCES_DIR])[ || + for gl_file in ]gl_LIBSOURCES_LIST[ ; do + if test ! -r ]m4_defn([gl_LIBSOURCES_DIR])[/$gl_file ; then + echo "missing file ]m4_defn([gl_LIBSOURCES_DIR])[/$gl_file" >&2 + exit 1 + fi + done])dnl + m4_if(m4_sysval, [0], [], + [AC_FATAL([expected source file, required through AC_LIBSOURCES, not found])]) + ]) + m4_popdef([gl_LIBSOURCES_DIR]) + m4_popdef([gl_LIBSOURCES_LIST]) + m4_popdef([AC_LIBSOURCES]) + m4_popdef([AC_REPLACE_FUNCS]) + m4_popdef([AC_LIBOBJ]) + AC_CONFIG_COMMANDS_PRE([ + gl_libobjs= + gl_ltlibobjs= + if test -n "$gl_LIBOBJS"; then + # Remove the extension. + sed_drop_objext='s/\.o$//;s/\.obj$//' + for i in `for i in $gl_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do + gl_libobjs="$gl_libobjs $i.$ac_objext" + gl_ltlibobjs="$gl_ltlibobjs $i.lo" + done + fi + AC_SUBST([gl_LIBOBJS], [$gl_libobjs]) + AC_SUBST([gl_LTLIBOBJS], [$gl_ltlibobjs]) + ]) + gltests_libdeps= + gltests_ltlibdeps= + m4_pushdef([AC_LIBOBJ], m4_defn([gltests_LIBOBJ])) + m4_pushdef([AC_REPLACE_FUNCS], m4_defn([gltests_REPLACE_FUNCS])) + m4_pushdef([AC_LIBSOURCES], m4_defn([gltests_LIBSOURCES])) + m4_pushdef([gltests_LIBSOURCES_LIST], []) + m4_pushdef([gltests_LIBSOURCES_DIR], []) + gl_COMMON + gl_source_base='tests' +changequote(,)dnl + gltests_WITNESS=IN_`echo "${PACKAGE-$PACKAGE_TARNAME}" | LC_ALL=C tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | LC_ALL=C sed -e 's/[^A-Z0-9_]/_/g'`_GNULIB_TESTS +changequote([, ])dnl + AC_SUBST([gltests_WITNESS]) + gl_module_indicator_condition=$gltests_WITNESS + m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [$gl_module_indicator_condition]) + m4_popdef([gl_MODULE_INDICATOR_CONDITION]) + m4_ifval(gltests_LIBSOURCES_LIST, [ + m4_syscmd([test ! -d ]m4_defn([gltests_LIBSOURCES_DIR])[ || + for gl_file in ]gltests_LIBSOURCES_LIST[ ; do + if test ! -r ]m4_defn([gltests_LIBSOURCES_DIR])[/$gl_file ; then + echo "missing file ]m4_defn([gltests_LIBSOURCES_DIR])[/$gl_file" >&2 + exit 1 + fi + done])dnl + m4_if(m4_sysval, [0], [], + [AC_FATAL([expected source file, required through AC_LIBSOURCES, not found])]) + ]) + m4_popdef([gltests_LIBSOURCES_DIR]) + m4_popdef([gltests_LIBSOURCES_LIST]) + m4_popdef([AC_LIBSOURCES]) + m4_popdef([AC_REPLACE_FUNCS]) + m4_popdef([AC_LIBOBJ]) + AC_CONFIG_COMMANDS_PRE([ + gltests_libobjs= + gltests_ltlibobjs= + if test -n "$gltests_LIBOBJS"; then + # Remove the extension. + sed_drop_objext='s/\.o$//;s/\.obj$//' + for i in `for i in $gltests_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do + gltests_libobjs="$gltests_libobjs $i.$ac_objext" + gltests_ltlibobjs="$gltests_ltlibobjs $i.lo" + done + fi + AC_SUBST([gltests_LIBOBJS], [$gltests_libobjs]) + AC_SUBST([gltests_LTLIBOBJS], [$gltests_ltlibobjs]) + ]) + LIBGNU_LIBDEPS="$gl_libdeps" + AC_SUBST([LIBGNU_LIBDEPS]) + LIBGNU_LTLIBDEPS="$gl_ltlibdeps" + AC_SUBST([LIBGNU_LTLIBDEPS]) +]) + +# Like AC_LIBOBJ, except that the module name goes +# into gl_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gl_LIBOBJ], [ + AS_LITERAL_IF([$1], [gl_LIBSOURCES([$1.c])])dnl + gl_LIBOBJS="$gl_LIBOBJS $1.$ac_objext" +]) + +# Like AC_REPLACE_FUNCS, except that the module name goes +# into gl_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gl_REPLACE_FUNCS], [ + m4_foreach_w([gl_NAME], [$1], [AC_LIBSOURCES(gl_NAME[.c])])dnl + AC_CHECK_FUNCS([$1], , [gl_LIBOBJ($ac_func)]) +]) + +# Like AC_LIBSOURCES, except the directory where the source file is +# expected is derived from the gnulib-tool parameterization, +# and alloca is special cased (for the alloca-opt module). +# We could also entirely rely on EXTRA_lib..._SOURCES. +AC_DEFUN([gl_LIBSOURCES], [ + m4_foreach([_gl_NAME], [$1], [ + m4_if(_gl_NAME, [alloca.c], [], [ + m4_define([gl_LIBSOURCES_DIR], [src/gnulib]) + m4_append([gl_LIBSOURCES_LIST], _gl_NAME, [ ]) + ]) + ]) +]) + +# Like AC_LIBOBJ, except that the module name goes +# into gltests_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gltests_LIBOBJ], [ + AS_LITERAL_IF([$1], [gltests_LIBSOURCES([$1.c])])dnl + gltests_LIBOBJS="$gltests_LIBOBJS $1.$ac_objext" +]) + +# Like AC_REPLACE_FUNCS, except that the module name goes +# into gltests_LIBOBJS instead of into LIBOBJS. +AC_DEFUN([gltests_REPLACE_FUNCS], [ + m4_foreach_w([gl_NAME], [$1], [AC_LIBSOURCES(gl_NAME[.c])])dnl + AC_CHECK_FUNCS([$1], , [gltests_LIBOBJ($ac_func)]) +]) + +# Like AC_LIBSOURCES, except the directory where the source file is +# expected is derived from the gnulib-tool parameterization, +# and alloca is special cased (for the alloca-opt module). +# We could also entirely rely on EXTRA_lib..._SOURCES. +AC_DEFUN([gltests_LIBSOURCES], [ + m4_foreach([_gl_NAME], [$1], [ + m4_if(_gl_NAME, [alloca.c], [], [ + m4_define([gltests_LIBSOURCES_DIR], [tests]) + m4_append([gltests_LIBSOURCES_LIST], _gl_NAME, [ ]) + ]) + ]) +]) + +# This macro records the list of files which have been installed by +# gnulib-tool and may be removed by future gnulib-tool invocations. +AC_DEFUN([gl_FILE_LIST], [ + lib/attribute.h + lib/gl_anyhash1.h + lib/gl_anyhash2.h + lib/gl_anyhash_primes.h + lib/gl_linkedhash_map.c + lib/gl_linkedhash_map.h + lib/gl_map.c + lib/gl_map.h + lib/limits.in.h + lib/size_max.h + lib/stdbool.in.h + lib/stdint.in.h + lib/sys_types.in.h + lib/xsize.c + lib/xsize.h + m4/00gnulib.m4 + m4/absolute-header.m4 + m4/extern-inline.m4 + m4/gnulib-common.m4 + m4/include_next.m4 + m4/limits-h.m4 + m4/multiarch.m4 + m4/off_t.m4 + m4/pid_t.m4 + m4/size_max.m4 + m4/ssize_t.m4 + m4/std-gnu11.m4 + m4/stdbool.m4 + m4/stdint.m4 + m4/sys_types_h.m4 + m4/wint_t.m4 + m4/xsize.m4 + m4/zzgnulib.m4 +]) diff --git a/src/m4/gnulib-tool.m4 b/src/m4/gnulib-tool.m4 new file mode 100644 index 000000000..3d56d83f1 --- /dev/null +++ b/src/m4/gnulib-tool.m4 @@ -0,0 +1,57 @@ +# gnulib-tool.m4 serial 2 +dnl Copyright (C) 2004-2005, 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, +dnl with or without modifications, as long as this notice is preserved. + +dnl The following macros need not be invoked explicitly. +dnl Invoking them does nothing except to declare default arguments +dnl for "gnulib-tool --import". + +dnl Usage: gl_LOCAL_DIR([DIR]) +AC_DEFUN([gl_LOCAL_DIR], []) + +dnl Usage: gl_MODULES([module1 module2 ...]) +AC_DEFUN([gl_MODULES], []) + +dnl Usage: gl_AVOID([module1 module2 ...]) +AC_DEFUN([gl_AVOID], []) + +dnl Usage: gl_SOURCE_BASE([DIR]) +AC_DEFUN([gl_SOURCE_BASE], []) + +dnl Usage: gl_M4_BASE([DIR]) +AC_DEFUN([gl_M4_BASE], []) + +dnl Usage: gl_PO_BASE([DIR]) +AC_DEFUN([gl_PO_BASE], []) + +dnl Usage: gl_DOC_BASE([DIR]) +AC_DEFUN([gl_DOC_BASE], []) + +dnl Usage: gl_TESTS_BASE([DIR]) +AC_DEFUN([gl_TESTS_BASE], []) + +dnl Usage: gl_WITH_TESTS +AC_DEFUN([gl_WITH_TESTS], []) + +dnl Usage: gl_LIB([LIBNAME]) +AC_DEFUN([gl_LIB], []) + +dnl Usage: gl_LGPL or gl_LGPL([VERSION]) +AC_DEFUN([gl_LGPL], []) + +dnl Usage: gl_MAKEFILE_NAME([FILENAME]) +AC_DEFUN([gl_MAKEFILE_NAME], []) + +dnl Usage: gl_LIBTOOL +AC_DEFUN([gl_LIBTOOL], []) + +dnl Usage: gl_MACRO_PREFIX([PREFIX]) +AC_DEFUN([gl_MACRO_PREFIX], []) + +dnl Usage: gl_PO_DOMAIN([DOMAIN]) +AC_DEFUN([gl_PO_DOMAIN], []) + +dnl Usage: gl_VC_FILES([BOOLEAN]) +AC_DEFUN([gl_VC_FILES], []) diff --git a/src/m4/include_next.m4 b/src/m4/include_next.m4 new file mode 100644 index 000000000..bdd542bc6 --- /dev/null +++ b/src/m4/include_next.m4 @@ -0,0 +1,224 @@ +# include_next.m4 serial 26 +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, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert and Derek Price. + +dnl Sets INCLUDE_NEXT, INCLUDE_NEXT_AS_FIRST_DIRECTIVE, PRAGMA_SYSTEM_HEADER, +dnl and PRAGMA_COLUMNS. +dnl +dnl INCLUDE_NEXT expands to 'include_next' if the compiler supports it, or to +dnl 'include' otherwise. +dnl +dnl INCLUDE_NEXT_AS_FIRST_DIRECTIVE expands to 'include_next' if the compiler +dnl supports it in the special case that it is the first include directive in +dnl the given file, or to 'include' otherwise. +dnl +dnl PRAGMA_SYSTEM_HEADER can be used in files that contain #include_next, +dnl so as to avoid GCC warnings when the gcc option -pedantic is used. +dnl '#pragma GCC system_header' has the same effect as if the file was found +dnl through the include search path specified with '-isystem' options (as +dnl opposed to the search path specified with '-I' options). Namely, gcc +dnl does not warn about some things, and on some systems (Solaris and Interix) +dnl __STDC__ evaluates to 0 instead of to 1. The latter is an undesired side +dnl effect; we are therefore careful to use 'defined __STDC__' or '1' instead +dnl of plain '__STDC__'. +dnl +dnl PRAGMA_COLUMNS can be used in files that override system header files, so +dnl as to avoid compilation errors on HP NonStop systems when the gnulib file +dnl is included by a system header file that does a "#pragma COLUMNS 80" (which +dnl has the effect of truncating the lines of that file and all files that it +dnl includes to 80 columns) and the gnulib file has lines longer than 80 +dnl columns. + +AC_DEFUN([gl_INCLUDE_NEXT], +[ + AC_LANG_PREPROC_REQUIRE() + AC_CACHE_CHECK([whether the preprocessor supports include_next], + [gl_cv_have_include_next], + [rm -rf conftestd1a conftestd1b conftestd2 + mkdir conftestd1a conftestd1b conftestd2 + dnl IBM C 9.0, 10.1 (original versions, prior to the 2009-01 updates) on + dnl AIX 6.1 support include_next when used as first preprocessor directive + dnl in a file, but not when preceded by another include directive. Check + dnl for this bug by including . + dnl Additionally, with this same compiler, include_next is a no-op when + dnl used in a header file that was included by specifying its absolute + dnl file name. Despite these two bugs, include_next is used in the + dnl compiler's . By virtue of the second bug, we need to use + dnl include_next as well in this case. + cat < conftestd1a/conftest.h +#define DEFINED_IN_CONFTESTD1 +#include_next +#ifdef DEFINED_IN_CONFTESTD2 +int foo; +#else +#error "include_next doesn't work" +#endif +EOF + cat < conftestd1b/conftest.h +#define DEFINED_IN_CONFTESTD1 +#include +#include_next +#ifdef DEFINED_IN_CONFTESTD2 +int foo; +#else +#error "include_next doesn't work" +#endif +EOF + cat < conftestd2/conftest.h +#ifndef DEFINED_IN_CONFTESTD1 +#error "include_next test doesn't work" +#endif +#define DEFINED_IN_CONFTESTD2 +EOF + gl_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1b -Iconftestd2" +dnl We intentionally avoid using AC_LANG_SOURCE here. + AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include ]], + [gl_cv_have_include_next=yes], + [CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1a -Iconftestd2" + AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include ]], + [gl_cv_have_include_next=buggy], + [gl_cv_have_include_next=no]) + ]) + CPPFLAGS="$gl_save_CPPFLAGS" + rm -rf conftestd1a conftestd1b conftestd2 + ]) + PRAGMA_SYSTEM_HEADER= + if test $gl_cv_have_include_next = yes; then + INCLUDE_NEXT=include_next + INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include_next + if test -n "$GCC"; then + PRAGMA_SYSTEM_HEADER='#pragma GCC system_header' + fi + else + if test $gl_cv_have_include_next = buggy; then + INCLUDE_NEXT=include + INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include_next + else + INCLUDE_NEXT=include + INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include + fi + fi + AC_SUBST([INCLUDE_NEXT]) + AC_SUBST([INCLUDE_NEXT_AS_FIRST_DIRECTIVE]) + AC_SUBST([PRAGMA_SYSTEM_HEADER]) + + dnl HP NonStop systems, which define __TANDEM, limit the line length + dnl after including some system header files. + AC_CACHE_CHECK([whether source code line length is unlimited], + [gl_cv_source_line_length_unlimited], + [AC_EGREP_CPP([choke me], + [ +#ifdef __TANDEM +choke me +#endif + ], + [gl_cv_source_line_length_unlimited=no], + [gl_cv_source_line_length_unlimited=yes]) + ]) + if test $gl_cv_source_line_length_unlimited = no; then + PRAGMA_COLUMNS="#pragma COLUMNS 10000" + else + PRAGMA_COLUMNS= + fi + AC_SUBST([PRAGMA_COLUMNS]) +]) + +# gl_CHECK_NEXT_HEADERS(HEADER1 HEADER2 ...) +# ------------------------------------------ +# For each arg foo.h, if #include_next works, define NEXT_FOO_H to be +# ''; otherwise define it to be +# '"///usr/include/foo.h"', or whatever other absolute file name is suitable. +# Also, if #include_next works as first preprocessing directive in a file, +# define NEXT_AS_FIRST_DIRECTIVE_FOO_H to be ''; otherwise define it to +# be +# '"///usr/include/foo.h"', or whatever other absolute file name is suitable. +# That way, a header file with the following line: +# #@INCLUDE_NEXT@ @NEXT_FOO_H@ +# or +# #@INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ @NEXT_AS_FIRST_DIRECTIVE_FOO_H@ +# behaves (after sed substitution) as if it contained +# #include_next +# even if the compiler does not support include_next. +# The three "///" are to pacify Sun C 5.8, which otherwise would say +# "warning: #include of /usr/include/... may be non-portable". +# Use '""', not '<>', so that the /// cannot be confused with a C99 comment. +# Note: This macro assumes that the header file is not empty after +# preprocessing, i.e. it does not only define preprocessor macros but also +# provides some type/enum definitions or function/variable declarations. +# +# This macro also checks whether each header exists, by invoking +# AC_CHECK_HEADERS_ONCE or AC_CHECK_HEADERS on each argument. +AC_DEFUN([gl_CHECK_NEXT_HEADERS], +[ + gl_NEXT_HEADERS_INTERNAL([$1], [check]) +]) + +# gl_NEXT_HEADERS(HEADER1 HEADER2 ...) +# ------------------------------------ +# Like gl_CHECK_NEXT_HEADERS, except do not check whether the headers exist. +# This is suitable for headers like that are standardized by C89 +# and therefore can be assumed to exist. +AC_DEFUN([gl_NEXT_HEADERS], +[ + gl_NEXT_HEADERS_INTERNAL([$1], [assume]) +]) + +# The guts of gl_CHECK_NEXT_HEADERS and gl_NEXT_HEADERS. +AC_DEFUN([gl_NEXT_HEADERS_INTERNAL], +[ + AC_REQUIRE([gl_INCLUDE_NEXT]) + AC_REQUIRE([AC_CANONICAL_HOST]) + + m4_if([$2], [check], + [AC_CHECK_HEADERS_ONCE([$1]) + ]) + + m4_foreach_w([gl_HEADER_NAME], [$1], + [AS_VAR_PUSHDEF([gl_next_header], + [gl_cv_next_]m4_defn([gl_HEADER_NAME])) + if test $gl_cv_have_include_next = yes; then + AS_VAR_SET([gl_next_header], ['<'gl_HEADER_NAME'>']) + else + AC_CACHE_CHECK( + [absolute name of <]m4_defn([gl_HEADER_NAME])[>], + [gl_next_header], + [m4_if([$2], [check], + [AS_VAR_PUSHDEF([gl_header_exists], + [ac_cv_header_]m4_defn([gl_HEADER_NAME])) + if test AS_VAR_GET([gl_header_exists]) = yes; then + AS_VAR_POPDEF([gl_header_exists]) + ]) + gl_ABSOLUTE_HEADER_ONE(gl_HEADER_NAME) + AS_VAR_COPY([gl_header], [gl_cv_absolute_]AS_TR_SH(gl_HEADER_NAME)) + AS_VAR_SET([gl_next_header], ['"'$gl_header'"']) + m4_if([$2], [check], + [else + AS_VAR_SET([gl_next_header], ['<'gl_HEADER_NAME'>']) + fi + ]) + ]) + fi + AC_SUBST( + AS_TR_CPP([NEXT_]m4_defn([gl_HEADER_NAME])), + [AS_VAR_GET([gl_next_header])]) + if test $gl_cv_have_include_next = yes || test $gl_cv_have_include_next = buggy; then + # INCLUDE_NEXT_AS_FIRST_DIRECTIVE='include_next' + gl_next_as_first_directive='<'gl_HEADER_NAME'>' + else + # INCLUDE_NEXT_AS_FIRST_DIRECTIVE='include' + gl_next_as_first_directive=AS_VAR_GET([gl_next_header]) + fi + AC_SUBST( + AS_TR_CPP([NEXT_AS_FIRST_DIRECTIVE_]m4_defn([gl_HEADER_NAME])), + [$gl_next_as_first_directive]) + AS_VAR_POPDEF([gl_next_header])]) +]) + +# Autoconf 2.68 added warnings for our use of AC_COMPILE_IFELSE; +# this fallback is safe for all earlier autoconf versions. +m4_define_default([AC_LANG_DEFINES_PROVIDED]) diff --git a/src/m4/limits-h.m4 b/src/m4/limits-h.m4 new file mode 100644 index 000000000..70dbb7dcf --- /dev/null +++ b/src/m4/limits-h.m4 @@ -0,0 +1,43 @@ +dnl Check whether limits.h has needed features. + +dnl Copyright 2016-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, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_DEFUN_ONCE([gl_LIMITS_H], +[ + gl_CHECK_NEXT_HEADERS([limits.h]) + + AC_CACHE_CHECK([whether limits.h has LLONG_MAX, WORD_BIT, ULLONG_WIDTH etc.], + [gl_cv_header_limits_width], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ + #define __STDC_WANT_IEC_60559_BFP_EXT__ 1 + #endif + #include + long long llm = LLONG_MAX; + int wb = WORD_BIT; + int ullw = ULLONG_WIDTH; + ]])], + [gl_cv_header_limits_width=yes], + [gl_cv_header_limits_width=no])]) + if test "$gl_cv_header_limits_width" = yes; then + LIMITS_H= + else + LIMITS_H=limits.h + fi + AC_SUBST([LIMITS_H]) + AM_CONDITIONAL([GL_GENERATE_LIMITS_H], [test -n "$LIMITS_H"]) +]) + +dnl Unconditionally enables the replacement of . +AC_DEFUN([gl_REPLACE_LIMITS_H], +[ + AC_REQUIRE([gl_LIMITS_H]) + LIMITS_H='limits.h' + AM_CONDITIONAL([GL_GENERATE_LIMITS_H], [test -n "$LIMITS_H"]) +]) diff --git a/src/m4/multiarch.m4 b/src/m4/multiarch.m4 new file mode 100644 index 000000000..f1678d9f6 --- /dev/null +++ b/src/m4/multiarch.m4 @@ -0,0 +1,65 @@ +# multiarch.m4 serial 9 +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, +dnl with or without modifications, as long as this notice is preserved. + +# Determine whether the compiler is or may be producing universal binaries. +# +# On Mac OS X 10.5 and later systems, the user can create libraries and +# executables that work on multiple system types--known as "fat" or +# "universal" binaries--by specifying multiple '-arch' options to the +# compiler but only a single '-arch' option to the preprocessor. Like +# this: +# +# ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ +# CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ +# CPP="gcc -E" CXXCPP="g++ -E" +# +# Detect this situation and set APPLE_UNIVERSAL_BUILD accordingly. + +AC_DEFUN_ONCE([gl_MULTIARCH], +[ + dnl Code similar to autoconf-2.63 AC_C_BIGENDIAN. + AC_CACHE_CHECK([whether the compiler produces multi-arch binaries], + [gl_cv_c_multiarch], + [gl_cv_c_multiarch=no + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + ]])], + [ + dnl Check for potential -arch flags. It is not universal unless + dnl there are at least two -arch flags with different values. + arch= + prev= + for word in ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}; do + if test -n "$prev"; then + case $word in + i?86 | x86_64 | ppc | ppc64 | arm | arm64) + if test -z "$arch" || test "$arch" = "$word"; then + arch="$word" + else + gl_cv_c_multiarch=yes + fi + ;; + esac + prev= + else + if test "x$word" = "x-arch"; then + prev=arch + fi + fi + done + ]) + ]) + if test $gl_cv_c_multiarch = yes; then + APPLE_UNIVERSAL_BUILD=1 + else + APPLE_UNIVERSAL_BUILD=0 + fi + AC_SUBST([APPLE_UNIVERSAL_BUILD]) +]) diff --git a/src/m4/off_t.m4 b/src/m4/off_t.m4 new file mode 100644 index 000000000..bdec43c80 --- /dev/null +++ b/src/m4/off_t.m4 @@ -0,0 +1,18 @@ +# off_t.m4 serial 1 +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, +dnl with or without modifications, as long as this notice is preserved. + +dnl Check whether to override the 'off_t' type. +dnl Set WINDOWS_64_BIT_OFF_T. + +AC_DEFUN([gl_TYPE_OFF_T], +[ + m4_ifdef([gl_LARGEFILE], [ + AC_REQUIRE([gl_LARGEFILE]) + ], [ + WINDOWS_64_BIT_OFF_T=0 + ]) + AC_SUBST([WINDOWS_64_BIT_OFF_T]) +]) diff --git a/src/m4/pid_t.m4 b/src/m4/pid_t.m4 new file mode 100644 index 000000000..b7650a10f --- /dev/null +++ b/src/m4/pid_t.m4 @@ -0,0 +1,38 @@ +# pid_t.m4 serial 4 +dnl Copyright (C) 2020-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, +dnl with or without modifications, as long as this notice is preserved. + +# The following implementation works around a problem in autoconf <= 2.69. +m4_version_prereq([2.70], [], [ + +dnl Define pid_t if the headers don't define it. +AC_DEFUN([AC_TYPE_PID_T], +[ + AC_CHECK_TYPE([pid_t], + [], + [dnl On 64-bit native Windows, define it to the equivalent of 'intptr_t' + dnl (= 'long long' = '__int64'), because that is the return type + dnl of the _spawnv* functions + dnl + dnl and the argument type of the _cwait function + dnl . + dnl Otherwise (on 32-bit Windows and on old Unix platforms), define it + dnl to 'int'. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #if defined _WIN64 && !defined __CYGWIN__ + LLP64 + #endif + ]]) + ], + [gl_pid_type='int'], + [gl_pid_type='__int64']) + AC_DEFINE_UNQUOTED([pid_t], [$gl_pid_type], + [Define as a signed integer type capable of holding a process identifier.]) + ], + [AC_INCLUDES_DEFAULT]) +]) + +])# m4_version_prereq 2.70 diff --git a/src/m4/size_max.m4 b/src/m4/size_max.m4 new file mode 100644 index 000000000..1d41ce9ab --- /dev/null +++ b/src/m4/size_max.m4 @@ -0,0 +1,75 @@ +# size_max.m4 serial 12 +dnl Copyright (C) 2003, 2005-2006, 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, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.61]) + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS([stdint.h]) + dnl First test whether the system already has SIZE_MAX. + AC_CACHE_CHECK([for SIZE_MAX], [gl_cv_size_max], [ + gl_cv_size_max=no + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], [gl_cv_size_max=yes]) + if test $gl_cv_size_max != yes; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1], + [#include +#include ], [size_t_bits_minus_1=]) + AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)], + [#include ], [fits_in_uint=]) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + extern size_t foo; + extern unsigned long foo; + ]], + [[]])], + [fits_in_uint=0]) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + ]) + if test "$gl_cv_size_max" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi + dnl Don't redefine SIZE_MAX in config.h if config.h is re-included after + dnl . Remember that the #undef in AH_VERBATIM gets replaced with + dnl #define by AC_DEFINE_UNQUOTED. + AH_VERBATIM([SIZE_MAX], +[/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +#ifndef SIZE_MAX +# undef SIZE_MAX +#endif]) +]) diff --git a/src/m4/ssize_t.m4 b/src/m4/ssize_t.m4 new file mode 100644 index 000000000..f0ed509fc --- /dev/null +++ b/src/m4/ssize_t.m4 @@ -0,0 +1,23 @@ +# ssize_t.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2001-2003, 2006, 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, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether ssize_t is defined. + +AC_DEFUN([gt_TYPE_SSIZE_T], +[ + AC_CACHE_CHECK([for ssize_t], [gt_cv_ssize_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[int x = sizeof (ssize_t *) + sizeof (ssize_t); + return !x;]])], + [gt_cv_ssize_t=yes], [gt_cv_ssize_t=no])]) + if test $gt_cv_ssize_t = no; then + AC_DEFINE([ssize_t], [int], + [Define as a signed type of the same size as size_t.]) + fi +]) diff --git a/src/m4/std-gnu11.m4 b/src/m4/std-gnu11.m4 new file mode 100644 index 000000000..7b1a042af --- /dev/null +++ b/src/m4/std-gnu11.m4 @@ -0,0 +1,829 @@ +# Prefer GNU C11 and C++11 to earlier versions. -*- coding: utf-8 -*- + +# This implementation is taken from GNU Autoconf lib/autoconf/c.m4 +# commit 017d5ddd82854911f0119691d91ea8a1438824d6 +# dated Sun Apr 3 13:57:17 2016 -0700 +# This implementation will be obsolete once we can assume Autoconf 2.70 +# or later is installed everywhere a Gnulib program might be developed. + +m4_version_prereq([2.70], [], [ + + +# Copyright (C) 2001-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 . + +# Written by David MacKenzie, with help from +# Akim Demaille, Paul Eggert, +# François Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor, +# Roland McGrath, Noah Friedman, david d zuhn, and many others. + + +# AC_PROG_CC([COMPILER ...]) +# -------------------------- +# COMPILER ... is a space separated list of C compilers to search for. +# This just gives the user an opportunity to specify an alternative +# search list for the C compiler. +AC_DEFUN_ONCE([AC_PROG_CC], +[AC_LANG_PUSH(C)dnl +AC_ARG_VAR([CC], [C compiler command])dnl +AC_ARG_VAR([CFLAGS], [C compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +_AC_ARG_VAR_LIBS()dnl +_AC_ARG_VAR_CPPFLAGS()dnl +m4_ifval([$1], + [AC_CHECK_TOOLS(CC, [$1])], +[AC_CHECK_TOOL(CC, gcc) +if test -z "$CC"; then + dnl Here we want: + dnl AC_CHECK_TOOL(CC, cc) + dnl but without the check for a tool without the prefix. + dnl Until the check is removed from there, copy the code: + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(CC, [${ac_tool_prefix}cc], [${ac_tool_prefix}cc]) + fi +fi +if test -z "$CC"; then + AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc) +fi +if test -z "$CC"; then + AC_CHECK_TOOLS(CC, cl.exe) +fi +if test -z "$CC"; then + AC_CHECK_TOOL(CC, clang) +fi +]) + +test -z "$CC" && AC_MSG_FAILURE([no acceptable C compiler found in \$PATH]) + +# Provide some information about the compiler. +_AS_ECHO_LOG([checking for _AC_LANG compiler version]) +set X $ac_compile +ac_compiler=$[2] +for ac_option in --version -v -V -qversion -version; do + _AC_DO_LIMIT([$ac_compiler $ac_option >&AS_MESSAGE_LOG_FD]) +done + +m4_expand_once([_AC_COMPILER_EXEEXT])[]dnl +m4_expand_once([_AC_COMPILER_OBJEXT])[]dnl +_AC_LANG_COMPILER_GNU +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +_AC_PROG_CC_G +dnl +dnl Set ac_prog_cc_stdc to the supported C version. +dnl Also set the documented variable ac_cv_prog_cc_stdc; +dnl its name was chosen when it was cached, but it is no longer cached. +_AC_PROG_CC_C11([ac_prog_cc_stdc=c11 + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11], + [_AC_PROG_CC_C99([ac_prog_cc_stdc=c99 + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99], + [_AC_PROG_CC_C89([ac_prog_cc_stdc=c89 + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89], + [ac_prog_cc_stdc=no + ac_cv_prog_cc_stdc=no])])]) +dnl +AC_LANG_POP(C)dnl +])# AC_PROG_CC + + + +# AC_PROG_CXX([LIST-OF-COMPILERS]) +# -------------------------------- +# LIST-OF-COMPILERS is a space separated list of C++ compilers to search +# for (if not specified, a default list is used). This just gives the +# user an opportunity to specify an alternative search list for the C++ +# compiler. +# aCC HP-UX C++ compiler much better than `CC', so test before. +# FCC Fujitsu C++ compiler +# KCC KAI C++ compiler +# RCC Rational C++ +# xlC_r AIX C Set++ (with support for reentrant code) +# xlC AIX C Set++ +AC_DEFUN([AC_PROG_CXX], +[AC_LANG_PUSH(C++)dnl +AC_ARG_VAR([CXX], [C++ compiler command])dnl +AC_ARG_VAR([CXXFLAGS], [C++ compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +_AC_ARG_VAR_LIBS()dnl +_AC_ARG_VAR_CPPFLAGS()dnl +_AC_ARG_VAR_PRECIOUS([CCC])dnl +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + AC_CHECK_TOOLS(CXX, + [m4_default([$1], + [g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++])], + g++) + fi +fi +# Provide some information about the compiler. +_AS_ECHO_LOG([checking for _AC_LANG compiler version]) +set X $ac_compile +ac_compiler=$[2] +for ac_option in --version -v -V -qversion; do + _AC_DO_LIMIT([$ac_compiler $ac_option >&AS_MESSAGE_LOG_FD]) +done + +m4_expand_once([_AC_COMPILER_EXEEXT])[]dnl +m4_expand_once([_AC_COMPILER_OBJEXT])[]dnl +_AC_LANG_COMPILER_GNU +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +_AC_PROG_CXX_G +_AC_PROG_CXX_CXX11([ac_prog_cxx_stdcxx=cxx11 + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 + ac_cv_prog_cxx_cxx98=$ac_cv_prog_cxx_cxx11], + [_AC_PROG_CXX_CXX98([ac_prog_cxx_stdcxx=cxx98 + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98], + [ac_prog_cxx_stdcxx=no + ac_cv_prog_cxx_stdcxx=no])]) +AC_LANG_POP(C++)dnl +])# AC_PROG_CXX + + +# _AC_C_STD_TRY(STANDARD, TEST-PROLOGUE, TEST-BODY, OPTION-LIST, +# ACTION-IF-AVAILABLE, ACTION-IF-UNAVAILABLE) +# -------------------------------------------------------------- +# Check whether the C compiler accepts features of STANDARD (e.g `c89', `c99') +# by trying to compile a program of TEST-PROLOGUE and TEST-BODY. If this fails, +# try again with each compiler option in the space-separated OPTION-LIST; if one +# helps, append it to CC. If eventually successful, run ACTION-IF-AVAILABLE, +# else ACTION-IF-UNAVAILABLE. +AC_DEFUN([_AC_C_STD_TRY], +[AC_MSG_CHECKING([for $CC option to enable ]m4_translit($1, [c], [C])[ features]) +AC_CACHE_VAL(ac_cv_prog_cc_$1, +[ac_cv_prog_cc_$1=no +ac_save_CC=$CC +AC_LANG_CONFTEST([AC_LANG_PROGRAM([$2], [$3])]) +for ac_arg in '' $4 +do + CC="$ac_save_CC $ac_arg" + _AC_COMPILE_IFELSE([], [ac_cv_prog_cc_$1=$ac_arg]) + test "x$ac_cv_prog_cc_$1" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +])# AC_CACHE_VAL +ac_prog_cc_stdc_options= +case "x$ac_cv_prog_cc_$1" in + x) + AC_MSG_RESULT([none needed]) ;; + xno) + AC_MSG_RESULT([unsupported]) ;; + *) + ac_prog_cc_stdc_options=" $ac_cv_prog_cc_$1" + CC=$CC$ac_prog_cc_stdc_options + AC_MSG_RESULT([$ac_cv_prog_cc_$1]) ;; +esac +AS_IF([test "x$ac_cv_prog_cc_$1" != xno], [$5], [$6]) +])# _AC_C_STD_TRY + +# _AC_C_C99_TEST_HEADER +# --------------------- +# A C header suitable for testing for C99. +AC_DEFUN([_AC_C_C99_TEST_HEADER], +[[#include +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static bool +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str = ""; + int number = 0; + float fnumber = 0; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); + + return *str && number && fnumber; +}]])# _AC_C_C99_TEST_HEADER + +# _AC_C_C99_TEST_BODY +# ------------------- +# A C body suitable for testing for C99, assuming the corresponding header. +AC_DEFUN([_AC_C_C99_TEST_BODY], +[[ + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + success &= test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); +]]) + +# _AC_PROG_CC_C99 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE]) +# ---------------------------------------------------------------- +# If the C compiler is not in ISO C99 mode by default, try to add an +# option to output variable CC to make it so. This macro tries +# various options that select ISO C99 on some system or another. It +# considers the compiler to be in ISO C99 mode if it handles _Bool, +# // comments, flexible array members, inline, long long int, mixed +# code and declarations, named initialization of structs, restrict, +# va_copy, varargs macros, variable declarations in for loops and +# variable length arrays. +AC_DEFUN([_AC_PROG_CC_C99], +[_AC_C_STD_TRY([c99], +[_AC_C_C99_TEST_HEADER], +[_AC_C_C99_TEST_BODY], +dnl Try +dnl GCC -std=gnu99 (unused restrictive modes: -std=c99 -std=iso9899:1999) +dnl IBM XL C -qlanglvl=extc1x (V12.1; does not pass C11 test) +dnl IBM XL C -qlanglvl=extc99 +dnl (pre-V12.1; unused restrictive mode: -qlanglvl=stdc99) +dnl HP cc -AC99 +dnl Intel ICC -std=c99, -c99 (deprecated) +dnl IRIX -c99 +dnl Solaris -D_STDC_C99= +dnl cc's -xc99 option uses linker magic to define the external +dnl symbol __xpg4 as if by "int __xpg4 = 1;", which enables C99 +dnl behavior for C library functions. This is not wanted here, +dnl because it means that a single module compiled with -xc99 +dnl alters C runtime behavior for the entire program, not for +dnl just the module. Instead, define the (private) symbol +dnl _STDC_C99, which suppresses a bogus failure in . +dnl The resulting compiler passes the test case here, and that's +dnl good enough. For more, please see the thread starting at: +dnl https://lists.gnu.org/r/autoconf/2010-12/msg00059.html +dnl Tru64 -c99 +dnl with extended modes being tried first. +[[-std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc1x -qlanglvl=extc99]], [$1], [$2])[]dnl +])# _AC_PROG_CC_C99 + + +# _AC_PROG_CC_C11 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE]) +# ---------------------------------------------------------------- +# If the C compiler is not in ISO C11 mode by default, try to add an +# option to output variable CC to make it so. This macro tries +# various options that select ISO C11 on some system or another. It +# considers the compiler to be in ISO C11 mode if it handles _Alignas, +# _Alignof, _Noreturn, _Static_assert, UTF-8 string literals, +# duplicate typedefs, and anonymous structures and unions. +AC_DEFUN([_AC_PROG_CC_C11], +[_AC_C_STD_TRY([c11], +[_AC_C_C99_TEST_HEADER[ +// Check _Alignas. +char _Alignas (double) aligned_as_double; +char _Alignas (0) no_special_alignment; +extern char aligned_as_int; +char _Alignas (0) _Alignas (int) aligned_as_int; + +// Check _Alignof. +enum +{ + int_alignment = _Alignof (int), + int_array_alignment = _Alignof (int[100]), + char_alignment = _Alignof (char) +}; +_Static_assert (0 < -_Alignof (int), "_Alignof is signed"); + +// Check _Noreturn. +int _Noreturn does_not_return (void) { for (;;) continue; } + +// Check _Static_assert. +struct test_static_assert +{ + int x; + _Static_assert (sizeof (int) <= sizeof (long int), + "_Static_assert does not work in struct"); + long int y; +}; + +// Check UTF-8 literals. +#define u8 syntax error! +char const utf8_literal[] = u8"happens to be ASCII" "another string"; + +// Check duplicate typedefs. +typedef long *long_ptr; +typedef long int *long_ptr; +typedef long_ptr long_ptr; + +// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. +struct anonymous +{ + union { + struct { int i; int j; }; + struct { int k; long int l; } w; + }; + int m; +} v1; +]], +[_AC_C_C99_TEST_BODY[ + v1.i = 2; + v1.w.k = 5; + _Static_assert ((offsetof (struct anonymous, i) + == offsetof (struct anonymous, w.k)), + "Anonymous union alignment botch"); +]], +dnl Try +dnl GCC -std=gnu11 (unused restrictive mode: -std=c11) +dnl with extended modes being tried first. +dnl +dnl Do not try -qlanglvl=extc1x, because IBM XL C V12.1 (the latest version as +dnl of September 2012) does not pass the C11 test. For now, try extc1x when +dnl compiling the C99 test instead, since it enables _Static_assert and +dnl _Noreturn, which is a win. If -qlanglvl=extc11 or -qlanglvl=extc1x passes +dnl the C11 test in some future version of IBM XL C, we'll add it here, +dnl preferably extc11. +[[-std=gnu11]], [$1], [$2])[]dnl +])# _AC_PROG_CC_C11 + + +# AC_PROG_CC_C89 +# -------------- +# Do not use AU_ALIAS here and in AC_PROG_CC_C99 and AC_PROG_CC_STDC, +# as that'd be incompatible with how Automake redefines AC_PROG_CC. See +# . +AU_DEFUN([AC_PROG_CC_C89], + [AC_REQUIRE([AC_PROG_CC])], + [$0 is obsolete; use AC_PROG_CC] +) + +# AC_PROG_CC_C99 +# -------------- +AU_DEFUN([AC_PROG_CC_C99], + [AC_REQUIRE([AC_PROG_CC])], + [$0 is obsolete; use AC_PROG_CC] +) + +# AC_PROG_CC_STDC +# --------------- +AU_DEFUN([AC_PROG_CC_STDC], + [AC_REQUIRE([AC_PROG_CC])], + [$0 is obsolete; use AC_PROG_CC] +) + + +# AC_C_PROTOTYPES +# --------------- +# Check if the C compiler supports prototypes, included if it needs +# options. +AC_DEFUN([AC_C_PROTOTYPES], +[AC_REQUIRE([AC_PROG_CC])dnl +if test "$ac_prog_cc_stdc" != no; then + AC_DEFINE(PROTOTYPES, 1, + [Define to 1 if the C compiler supports function prototypes.]) + AC_DEFINE(__PROTOTYPES, 1, + [Define like PROTOTYPES; this can be used by system headers.]) +fi +])# AC_C_PROTOTYPES + + +# _AC_CXX_STD_TRY(STANDARD, TEST-PROLOGUE, TEST-BODY, OPTION-LIST, +# ACTION-IF-AVAILABLE, ACTION-IF-UNAVAILABLE) +# ---------------------------------------------------------------- +# Check whether the C++ compiler accepts features of STANDARD (e.g +# `cxx98', `cxx11') by trying to compile a program of TEST-PROLOGUE +# and TEST-BODY. If this fails, try again with each compiler option +# in the space-separated OPTION-LIST; if one helps, append it to CXX. +# If eventually successful, run ACTION-IF-AVAILABLE, else +# ACTION-IF-UNAVAILABLE. +AC_DEFUN([_AC_CXX_STD_TRY], +[AC_MSG_CHECKING([for $CXX option to enable ]m4_translit(m4_translit($1, [x], [+]), [a-z], [A-Z])[ features]) +AC_LANG_PUSH(C++)dnl +AC_CACHE_VAL(ac_cv_prog_cxx_$1, +[ac_cv_prog_cxx_$1=no +ac_save_CXX=$CXX +AC_LANG_CONFTEST([AC_LANG_PROGRAM([$2], [$3])]) +for ac_arg in '' $4 +do + CXX="$ac_save_CXX $ac_arg" + _AC_COMPILE_IFELSE([], [ac_cv_prog_cxx_$1=$ac_arg]) + test "x$ac_cv_prog_cxx_$1" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +])# AC_CACHE_VAL +ac_prog_cxx_stdcxx_options= +case "x$ac_cv_prog_cxx_$1" in + x) + AC_MSG_RESULT([none needed]) ;; + xno) + AC_MSG_RESULT([unsupported]) ;; + *) + ac_prog_cxx_stdcxx_options=" $ac_cv_prog_cxx_$1" + CXX=$CXX$ac_prog_cxx_stdcxx_options + AC_MSG_RESULT([$ac_cv_prog_cxx_$1]) ;; +esac +AC_LANG_POP(C++)dnl +AS_IF([test "x$ac_cv_prog_cxx_$1" != xno], [$5], [$6]) +])# _AC_CXX_STD_TRY + +# _AC_CXX_CXX98_TEST_HEADER +# ------------------------- +# A C++ header suitable for testing for CXX98. +AC_DEFUN([_AC_CXX_CXX98_TEST_HEADER], +[[ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace test { + typedef std::vector string_vec; + typedef std::pair map_value; + typedef std::map map_type; + typedef std::set set_type; + + template + class printer { + public: + printer(std::ostringstream& os): os(os) {} + void operator() (T elem) { os << elem << std::endl; } + private: + std::ostringstream& os; + }; +} +]])# _AC_CXX_CXX98_TEST_HEADER + +# _AC_CXX_CXX98_TEST_BODY +# ----------------------- +# A C++ body suitable for testing for CXX98, assuming the corresponding header. +AC_DEFUN([_AC_CXX_CXX98_TEST_BODY], +[[ + +try { + // Basic string. + std::string teststr("ASCII text"); + teststr += " string"; + + // Simple vector. + test::string_vec testvec; + testvec.push_back(teststr); + testvec.push_back("foo"); + testvec.push_back("bar"); + if (testvec.size() != 3) { + throw std::runtime_error("vector size is not 1"); + } + + // Dump vector into stringstream and obtain string. + std::ostringstream os; + for (test::string_vec::const_iterator i = testvec.begin(); + i != testvec.end(); ++i) { + if (i + 1 != testvec.end()) { + os << teststr << '\n'; + } + } + // Check algorithms work. + std::for_each(testvec.begin(), testvec.end(), test::printer(os)); + std::string os_out = os.str(); + + // Test pair and map. + test::map_type testmap; + testmap.insert(std::make_pair(std::string("key"), + std::make_pair(53,false))); + + // Test set. + int values[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; + test::set_type testset(values, values + sizeof(values)/sizeof(values[0])); + std::list testlist(testset.begin(), testset.end()); + std::copy(testset.begin(), testset.end(), std::back_inserter(testlist)); +} catch (const std::exception& e) { + std::cerr << "Caught exception: " << e.what() << std::endl; + + // Test fstream + std::ofstream of("test.txt"); + of << "Test ASCII text\n" << std::flush; + of << "N= " << std::hex << std::setw(8) << std::left << 534 << std::endl; + of.close(); +} +std::exit(0); +]]) + +# _AC_CXX_CXX11_TEST_HEADER +# ------------------------- +# A C++ header suitable for testing for CXX11. +AC_DEFUN([_AC_CXX_CXX11_TEST_HEADER], +[[ +#include +#include +#include +#include +#include +#include +#include + +namespace cxx11test +{ + typedef std::shared_ptr sptr; + typedef std::weak_ptr wptr; + + typedef std::tuple tp; + typedef std::array int_array; + + constexpr int get_val() { return 20; } + + struct testinit + { + int i; + double d; + }; + + class delegate { + public: + delegate(int n) : n(n) {} + delegate(): delegate(2354) {} + + virtual int getval() { return this->n; }; + protected: + int n; + }; + + class overridden : public delegate { + public: + overridden(int n): delegate(n) {} + virtual int getval() override final { return this->n * 2; } + }; + + class nocopy { + public: + nocopy(int i): i(i) {} + nocopy() = default; + nocopy(const nocopy&) = delete; + nocopy & operator=(const nocopy&) = delete; + private: + int i; + }; +} +]])# _AC_CXX_CXX11_TEST_HEADER + +# _AC_CXX_CXX11_TEST_BODY +# ----------------------- +# A C++ body suitable for testing for CXX11, assuming the corresponding header. +AC_DEFUN([_AC_CXX_CXX11_TEST_BODY], +[[ +{ + // Test auto and decltype + std::deque d; + d.push_front(43); + d.push_front(484); + d.push_front(3); + d.push_front(844); + int total = 0; + for (auto i = d.begin(); i != d.end(); ++i) { total += *i; } + + auto a1 = 6538; + auto a2 = 48573953.4; + auto a3 = "String literal"; + + decltype(a2) a4 = 34895.034; +} +{ + // Test constexpr + short sa[cxx11test::get_val()] = { 0 }; +} +{ + // Test initializer lists + cxx11test::testinit il = { 4323, 435234.23544 }; +} +{ + // Test range-based for and lambda + cxx11test::int_array array = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; + for (int &x : array) { x += 23; } + std::for_each(array.begin(), array.end(), [](int v1){ std::cout << v1; }); +} +{ + using cxx11test::sptr; + using cxx11test::wptr; + + sptr sp(new std::string("ASCII string")); + wptr wp(sp); + sptr sp2(wp); +} +{ + cxx11test::tp tuple("test", 54, 45.53434); + double d = std::get<2>(tuple); + std::string s; + int i; + std::tie(s,i,d) = tuple; +} +{ + static std::regex filename_regex("^_?([a-z0-9_.]+-)+[a-z0-9]+$"); + std::string testmatch("Test if this string matches"); + bool match = std::regex_search(testmatch, filename_regex); +} +{ + cxx11test::int_array array = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; + cxx11test::int_array::size_type size = array.size(); +} +{ + // Test constructor delegation + cxx11test::delegate d1; + cxx11test::delegate d2(); + cxx11test::delegate d3(45); +} +{ + // Test override and final + cxx11test::overridden o1(55464); +} +{ + // Test nullptr + char *c = nullptr; +} +{ + // Test template brackets + std::vector> v1; +} +{ + // Unicode literals + char const *utf8 = u8"UTF-8 string \u2500"; + char16_t const *utf16 = u"UTF-8 string \u2500"; + char32_t const *utf32 = U"UTF-32 string \u2500"; +} +]]) + +# _AC_PROG_CXX_CXX98 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE]) +# ------------------------------------------------------------------- + +# If the C++ compiler is not in ISO C++98 mode by default, try to add +# an option to output variable CXX to make it so. This macro tries +# various options that select ISO C++98 on some system or another. It +# considers the compiler to be in ISO C++98 mode if it handles basic +# features of the std namespace including: string, containers (list, +# map, set, vector), streams (fstreams, iostreams, stringstreams, +# iomanip), pair, exceptions and algorithms. + + +AC_DEFUN([_AC_PROG_CXX_CXX98], +[_AC_CXX_STD_TRY([cxx98], +[_AC_CXX_CXX98_TEST_HEADER], +[_AC_CXX_CXX98_TEST_BODY], +dnl Try +dnl GCC -std=gnu++98 (unused restrictive mode: -std=c++98) +dnl IBM XL C -qlanglvl=extended +dnl HP aC++ -AA +dnl Intel ICC -std=gnu++98 +dnl Solaris N/A (default) +dnl Tru64 N/A (default, but -std gnu could be used) +dnl with extended modes being tried first. +[[-std=gnu++98 -std=c++98 -qlanglvl=extended -AA]], [$1], [$2])[]dnl +])# _AC_PROG_CXX_CXX98 + +# _AC_PROG_CXX_CXX11 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE]) +# ------------------------------------------------------------------- +# If the C++ compiler is not in ISO CXX11 mode by default, try to add +# an option to output variable CXX to make it so. This macro tries +# various options that select ISO C++11 on some system or another. It +# considers the compiler to be in ISO C++11 mode if it handles all the +# tests from the C++98 checks, plus the following: Language features +# (auto, constexpr, decltype, default/deleted constructors, delegate +# constructors, final, initializer lists, lambda functions, nullptr, +# override, range-based for loops, template brackets without spaces, +# unicode literals) and library features (array, memory (shared_ptr, +# weak_ptr), regex and tuple types). +AC_DEFUN([_AC_PROG_CXX_CXX11], +[_AC_CXX_STD_TRY([cxx11], +[_AC_CXX_CXX11_TEST_HEADER +_AC_CXX_CXX98_TEST_HEADER], +[_AC_CXX_CXX11_TEST_BODY +_AC_CXX_CXX98_TEST_BODY], +dnl Try +dnl GCC -std=gnu++11 (unused restrictive mode: -std=c++11) [and 0x variants] +dnl IBM XL C -qlanglvl=extended0x +dnl (pre-V12.1; unused restrictive mode: -qlanglvl=stdcxx11) +dnl HP aC++ -AA +dnl Intel ICC -std=c++11 -std=c++0x +dnl Solaris N/A (no support) +dnl Tru64 N/A (no support) +dnl with extended modes being tried first. +[[-std=gnu++11 -std=c++11 -std=gnu++0x -std=c++0x -qlanglvl=extended0x -AA]], [$1], [$2])[]dnl +])# _AC_PROG_CXX_CXX11 + + +])# m4_version_prereq diff --git a/src/m4/stdbool.m4 b/src/m4/stdbool.m4 new file mode 100644 index 000000000..3169779d4 --- /dev/null +++ b/src/m4/stdbool.m4 @@ -0,0 +1,122 @@ +# Check for stdbool.h that conforms to C99. + +dnl Copyright (C) 2002-2006, 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, +dnl with or without modifications, as long as this notice is preserved. + +#serial 8 + +# Prepare for substituting if it is not supported. + +AC_DEFUN([AM_STDBOOL_H], +[ + AC_REQUIRE([AC_CHECK_HEADER_STDBOOL]) + AC_REQUIRE([AC_CANONICAL_HOST]) + + dnl On some platforms, does not exist or does not conform to C99. + dnl On Solaris 10 with CC=cc CXX=CC, exists but is not usable + dnl in C++ mode (and no exists). In this case, we use our + dnl replacement, also in C mode (for binary compatibility between C and C++). + if test "$ac_cv_header_stdbool_h" = yes; then + case "$host_os" in + solaris*) + if test -z "$GCC"; then + STDBOOL_H='stdbool.h' + else + STDBOOL_H='' + fi + ;; + *) + STDBOOL_H='' + ;; + esac + else + STDBOOL_H='stdbool.h' + fi + AC_SUBST([STDBOOL_H]) + AM_CONDITIONAL([GL_GENERATE_STDBOOL_H], [test -n "$STDBOOL_H"]) + + if test "$ac_cv_type__Bool" = yes; then + HAVE__BOOL=1 + else + HAVE__BOOL=0 + fi + AC_SUBST([HAVE__BOOL]) +]) + +# AM_STDBOOL_H will be renamed to gl_STDBOOL_H in the future. +AC_DEFUN([gl_STDBOOL_H], [AM_STDBOOL_H]) + +# This version of the macro is needed in autoconf <= 2.68. + +AC_DEFUN([AC_CHECK_HEADER_STDBOOL], + [AC_CACHE_CHECK([for stdbool.h that conforms to C99], + [ac_cv_header_stdbool_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ + #include + + #ifdef __cplusplus + typedef bool Bool; + #else + typedef _Bool Bool; + #ifndef bool + "error: bool is not defined" + #endif + #ifndef false + "error: false is not defined" + #endif + #if false + "error: false is not 0" + #endif + #ifndef true + "error: true is not defined" + #endif + #if true != 1 + "error: true is not 1" + #endif + #endif + + #ifndef __bool_true_false_are_defined + "error: __bool_true_false_are_defined is not defined" + #endif + + struct s { Bool s: 1; Bool t; bool u: 1; bool v; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) 0.5 == true ? 1 : -1]; + /* See body of main program for 'e'. */ + char f[(Bool) 0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (Bool)]; + char i[sizeof s.t]; + enum { j = false, k = true, l = false * true, m = true * 256 }; + /* The following fails for + HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ + Bool n[m]; + char o[sizeof n == m * sizeof n[0] ? 1 : -1]; + char p[-1 - (Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; + /* Catch a bug in an HP-UX C compiler. See + https://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + https://lists.gnu.org/r/bug-coreutils/2005-11/msg00161.html + */ + Bool q = true; + Bool *pq = &q; + bool *qq = &q; + ]], + [[ + bool e = &s; + *pq |= q; *pq |= ! q; + *qq |= q; *qq |= ! q; + /* Refer to every declared value, to avoid compiler optimizations. */ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + + !m + !n + !o + !p + !q + !pq + !qq); + ]])], + [ac_cv_header_stdbool_h=yes], + [ac_cv_header_stdbool_h=no])]) + AC_CHECK_TYPES([_Bool]) +]) diff --git a/src/m4/stdint.m4 b/src/m4/stdint.m4 new file mode 100644 index 000000000..a785b44ed --- /dev/null +++ b/src/m4/stdint.m4 @@ -0,0 +1,533 @@ +# stdint.m4 serial 58 +dnl Copyright (C) 2001-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, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert and Bruno Haible. +dnl Test whether is supported or must be substituted. + +AC_PREREQ([2.61]) + +AC_DEFUN_ONCE([gl_STDINT_H], +[ + AC_PREREQ([2.59])dnl + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + AC_REQUIRE([gl_LIMITS_H]) + AC_REQUIRE([gt_TYPE_WINT_T]) + + dnl For backward compatibility. Some packages may still be testing these + dnl macros. + AC_DEFINE([HAVE_LONG_LONG_INT], [1], + [Define to 1 if the system has the type 'long long int'.]) + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1], + [Define to 1 if the system has the type 'unsigned long long int'.]) + + dnl Check for , in the same way as gl_WCHAR_H does. + AC_CHECK_HEADERS_ONCE([wchar.h]) + if test $ac_cv_header_wchar_h = yes; then + HAVE_WCHAR_H=1 + else + HAVE_WCHAR_H=0 + fi + AC_SUBST([HAVE_WCHAR_H]) + + dnl Check for . + AC_CHECK_HEADERS_ONCE([inttypes.h]) + if test $ac_cv_header_inttypes_h = yes; then + HAVE_INTTYPES_H=1 + else + HAVE_INTTYPES_H=0 + fi + AC_SUBST([HAVE_INTTYPES_H]) + + dnl Check for . + AC_CHECK_HEADERS_ONCE([sys/types.h]) + if test $ac_cv_header_sys_types_h = yes; then + HAVE_SYS_TYPES_H=1 + else + HAVE_SYS_TYPES_H=0 + fi + AC_SUBST([HAVE_SYS_TYPES_H]) + + gl_CHECK_NEXT_HEADERS([stdint.h]) + if test $ac_cv_header_stdint_h = yes; then + HAVE_STDINT_H=1 + else + HAVE_STDINT_H=0 + fi + AC_SUBST([HAVE_STDINT_H]) + + dnl Now see whether we need a substitute . + if test $ac_cv_header_stdint_h = yes; then + AC_CACHE_CHECK([whether stdint.h conforms to C99], + [gl_cv_header_working_stdint_h], + [gl_cv_header_working_stdint_h=no + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */ +#define __STDC_CONSTANT_MACROS 1 +#define __STDC_LIMIT_MACROS 1 +#include +/* Dragonfly defines WCHAR_MIN, WCHAR_MAX only in . */ +#if !(defined WCHAR_MIN && defined WCHAR_MAX) +#error "WCHAR_MIN, WCHAR_MAX not defined in " +#endif +] +gl_STDINT_INCLUDES +[ +#ifdef INT8_MAX +int8_t a1 = INT8_MAX; +int8_t a1min = INT8_MIN; +#endif +#ifdef INT16_MAX +int16_t a2 = INT16_MAX; +int16_t a2min = INT16_MIN; +#endif +#ifdef INT32_MAX +int32_t a3 = INT32_MAX; +int32_t a3min = INT32_MIN; +#endif +#ifdef INT64_MAX +int64_t a4 = INT64_MAX; +int64_t a4min = INT64_MIN; +#endif +#ifdef UINT8_MAX +uint8_t b1 = UINT8_MAX; +#else +typedef int b1[(unsigned char) -1 != 255 ? 1 : -1]; +#endif +#ifdef UINT16_MAX +uint16_t b2 = UINT16_MAX; +#endif +#ifdef UINT32_MAX +uint32_t b3 = UINT32_MAX; +#endif +#ifdef UINT64_MAX +uint64_t b4 = UINT64_MAX; +#endif +int_least8_t c1 = INT8_C (0x7f); +int_least8_t c1max = INT_LEAST8_MAX; +int_least8_t c1min = INT_LEAST8_MIN; +int_least16_t c2 = INT16_C (0x7fff); +int_least16_t c2max = INT_LEAST16_MAX; +int_least16_t c2min = INT_LEAST16_MIN; +int_least32_t c3 = INT32_C (0x7fffffff); +int_least32_t c3max = INT_LEAST32_MAX; +int_least32_t c3min = INT_LEAST32_MIN; +int_least64_t c4 = INT64_C (0x7fffffffffffffff); +int_least64_t c4max = INT_LEAST64_MAX; +int_least64_t c4min = INT_LEAST64_MIN; +uint_least8_t d1 = UINT8_C (0xff); +uint_least8_t d1max = UINT_LEAST8_MAX; +uint_least16_t d2 = UINT16_C (0xffff); +uint_least16_t d2max = UINT_LEAST16_MAX; +uint_least32_t d3 = UINT32_C (0xffffffff); +uint_least32_t d3max = UINT_LEAST32_MAX; +uint_least64_t d4 = UINT64_C (0xffffffffffffffff); +uint_least64_t d4max = UINT_LEAST64_MAX; +int_fast8_t e1 = INT_FAST8_MAX; +int_fast8_t e1min = INT_FAST8_MIN; +int_fast16_t e2 = INT_FAST16_MAX; +int_fast16_t e2min = INT_FAST16_MIN; +int_fast32_t e3 = INT_FAST32_MAX; +int_fast32_t e3min = INT_FAST32_MIN; +int_fast64_t e4 = INT_FAST64_MAX; +int_fast64_t e4min = INT_FAST64_MIN; +uint_fast8_t f1 = UINT_FAST8_MAX; +uint_fast16_t f2 = UINT_FAST16_MAX; +uint_fast32_t f3 = UINT_FAST32_MAX; +uint_fast64_t f4 = UINT_FAST64_MAX; +#ifdef INTPTR_MAX +intptr_t g = INTPTR_MAX; +intptr_t gmin = INTPTR_MIN; +#endif +#ifdef UINTPTR_MAX +uintptr_t h = UINTPTR_MAX; +#endif +intmax_t i = INTMAX_MAX; +uintmax_t j = UINTMAX_MAX; + +/* Check that SIZE_MAX has the correct type, if possible. */ +#if 201112 <= __STDC_VERSION__ +int k = _Generic (SIZE_MAX, size_t: 0); +#elif (2 <= __GNUC__ || 4 <= __clang_major__ || defined __IBM__TYPEOF__ \ + || (0x5110 <= __SUNPRO_C && !__STDC__)) +extern size_t k; +extern __typeof__ (SIZE_MAX) k; +#endif + +#include /* for CHAR_BIT */ +#define TYPE_MINIMUM(t) \ + ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ TYPE_MAXIMUM (t))) +#define TYPE_MAXIMUM(t) \ + ((t) ((t) 0 < (t) -1 \ + ? (t) -1 \ + : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) +struct s { + int check_PTRDIFF: + PTRDIFF_MIN == TYPE_MINIMUM (ptrdiff_t) + && PTRDIFF_MAX == TYPE_MAXIMUM (ptrdiff_t) + ? 1 : -1; + /* Detect bug in FreeBSD 6.0 / ia64. */ + int check_SIG_ATOMIC: + SIG_ATOMIC_MIN == TYPE_MINIMUM (sig_atomic_t) + && SIG_ATOMIC_MAX == TYPE_MAXIMUM (sig_atomic_t) + ? 1 : -1; + int check_SIZE: SIZE_MAX == TYPE_MAXIMUM (size_t) ? 1 : -1; + int check_WCHAR: + WCHAR_MIN == TYPE_MINIMUM (wchar_t) + && WCHAR_MAX == TYPE_MAXIMUM (wchar_t) + ? 1 : -1; + /* Detect bug in mingw. */ + int check_WINT: + WINT_MIN == TYPE_MINIMUM (wint_t) + && WINT_MAX == TYPE_MAXIMUM (wint_t) + ? 1 : -1; + + /* Detect bugs in glibc 2.4 and Solaris 10 stdint.h, among others. */ + int check_UINT8_C: + (-1 < UINT8_C (0)) == (-1 < (uint_least8_t) 0) ? 1 : -1; + int check_UINT16_C: + (-1 < UINT16_C (0)) == (-1 < (uint_least16_t) 0) ? 1 : -1; + + /* Detect bugs in OpenBSD 3.9 stdint.h. */ +#ifdef UINT8_MAX + int check_uint8: (uint8_t) -1 == UINT8_MAX ? 1 : -1; +#endif +#ifdef UINT16_MAX + int check_uint16: (uint16_t) -1 == UINT16_MAX ? 1 : -1; +#endif +#ifdef UINT32_MAX + int check_uint32: (uint32_t) -1 == UINT32_MAX ? 1 : -1; +#endif +#ifdef UINT64_MAX + int check_uint64: (uint64_t) -1 == UINT64_MAX ? 1 : -1; +#endif + int check_uint_least8: (uint_least8_t) -1 == UINT_LEAST8_MAX ? 1 : -1; + int check_uint_least16: (uint_least16_t) -1 == UINT_LEAST16_MAX ? 1 : -1; + int check_uint_least32: (uint_least32_t) -1 == UINT_LEAST32_MAX ? 1 : -1; + int check_uint_least64: (uint_least64_t) -1 == UINT_LEAST64_MAX ? 1 : -1; + int check_uint_fast8: (uint_fast8_t) -1 == UINT_FAST8_MAX ? 1 : -1; + int check_uint_fast16: (uint_fast16_t) -1 == UINT_FAST16_MAX ? 1 : -1; + int check_uint_fast32: (uint_fast32_t) -1 == UINT_FAST32_MAX ? 1 : -1; + int check_uint_fast64: (uint_fast64_t) -1 == UINT_FAST64_MAX ? 1 : -1; + int check_uintptr: (uintptr_t) -1 == UINTPTR_MAX ? 1 : -1; + int check_uintmax: (uintmax_t) -1 == UINTMAX_MAX ? 1 : -1; + int check_size: (size_t) -1 == SIZE_MAX ? 1 : -1; +}; + ]])], + [dnl Determine whether the various *_MIN, *_MAX macros are usable + dnl in preprocessor expression. We could do it by compiling a test + dnl program for each of these macros. It is faster to run a program + dnl that inspects the macro expansion. + dnl This detects a bug on HP-UX 11.23/ia64. + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */ +#define __STDC_CONSTANT_MACROS 1 +#define __STDC_LIMIT_MACROS 1 +#include +] +gl_STDINT_INCLUDES +[ +#include +#include +#define MVAL(macro) MVAL1(macro) +#define MVAL1(expression) #expression +static const char *macro_values[] = + { +#ifdef INT8_MAX + MVAL (INT8_MAX), +#endif +#ifdef INT16_MAX + MVAL (INT16_MAX), +#endif +#ifdef INT32_MAX + MVAL (INT32_MAX), +#endif +#ifdef INT64_MAX + MVAL (INT64_MAX), +#endif +#ifdef UINT8_MAX + MVAL (UINT8_MAX), +#endif +#ifdef UINT16_MAX + MVAL (UINT16_MAX), +#endif +#ifdef UINT32_MAX + MVAL (UINT32_MAX), +#endif +#ifdef UINT64_MAX + MVAL (UINT64_MAX), +#endif + NULL + }; +]], [[ + const char **mv; + for (mv = macro_values; *mv != NULL; mv++) + { + const char *value = *mv; + /* Test whether it looks like a cast expression. */ + if (strncmp (value, "((unsigned int)"/*)*/, 15) == 0 + || strncmp (value, "((unsigned short)"/*)*/, 17) == 0 + || strncmp (value, "((unsigned char)"/*)*/, 16) == 0 + || strncmp (value, "((int)"/*)*/, 6) == 0 + || strncmp (value, "((signed short)"/*)*/, 15) == 0 + || strncmp (value, "((signed char)"/*)*/, 14) == 0) + return mv - macro_values + 1; + } + return 0; +]])], + [gl_cv_header_working_stdint_h=yes], + [], + [case "$host_os" in + # Guess yes on native Windows. + mingw*) gl_cv_header_working_stdint_h="guessing yes" ;; + # In general, assume it works. + *) gl_cv_header_working_stdint_h="guessing yes" ;; + esac + ]) + ]) + ]) + fi + + HAVE_C99_STDINT_H=0 + HAVE_SYS_BITYPES_H=0 + HAVE_SYS_INTTYPES_H=0 + STDINT_H=stdint.h + case "$gl_cv_header_working_stdint_h" in + *yes) + HAVE_C99_STDINT_H=1 + dnl Now see whether the system works without + dnl __STDC_CONSTANT_MACROS/__STDC_LIMIT_MACROS defined. + dnl If not, there would be problems when stdint.h is included from C++. + AC_CACHE_CHECK([whether stdint.h works without ISO C predefines], + [gl_cv_header_stdint_without_STDC_macros], + [gl_cv_header_stdint_without_STDC_macros=no + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */ +#include +] +gl_STDINT_INCLUDES +[ +intmax_t im = INTMAX_MAX; +int32_t i32 = INT32_C (0x7fffffff); + ]])], + [gl_cv_header_stdint_without_STDC_macros=yes]) + ]) + + if test $gl_cv_header_stdint_without_STDC_macros = no; then + AC_DEFINE([__STDC_CONSTANT_MACROS], [1], + [Define to 1 if the system predates C++11.]) + AC_DEFINE([__STDC_LIMIT_MACROS], [1], + [Define to 1 if the system predates C++11.]) + fi + AC_CACHE_CHECK([whether stdint.h has UINTMAX_WIDTH etc.], + [gl_cv_header_stdint_width], + [gl_cv_header_stdint_width=no + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + /* Work if build is not clean. */ + #define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 + #ifndef __STDC_WANT_IEC_60559_BFP_EXT__ + #define __STDC_WANT_IEC_60559_BFP_EXT__ 1 + #endif + #include + ]gl_STDINT_INCLUDES[ + int iw = UINTMAX_WIDTH; + ]])], + [gl_cv_header_stdint_width=yes])]) + if test "$gl_cv_header_stdint_width" = yes; then + STDINT_H= + fi + ;; + *) + dnl Check for , and for + dnl (used in Linux libc4 >= 4.6.7 and libc5). + AC_CHECK_HEADERS([sys/inttypes.h sys/bitypes.h]) + if test $ac_cv_header_sys_inttypes_h = yes; then + HAVE_SYS_INTTYPES_H=1 + fi + if test $ac_cv_header_sys_bitypes_h = yes; then + HAVE_SYS_BITYPES_H=1 + fi + gl_STDINT_TYPE_PROPERTIES + ;; + esac + + dnl The substitute stdint.h needs the substitute limit.h's _GL_INTEGER_WIDTH. + gl_REPLACE_LIMITS_H + + AC_SUBST([HAVE_C99_STDINT_H]) + AC_SUBST([HAVE_SYS_BITYPES_H]) + AC_SUBST([HAVE_SYS_INTTYPES_H]) + AC_SUBST([STDINT_H]) + AM_CONDITIONAL([GL_GENERATE_STDINT_H], [test -n "$STDINT_H"]) +]) + +dnl gl_STDINT_BITSIZEOF(TYPES, INCLUDES) +dnl Determine the size of each of the given types in bits. +AC_DEFUN([gl_STDINT_BITSIZEOF], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + m4_foreach_w([gltype], [$1], + [AH_TEMPLATE([BITSIZEOF_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [Define to the number of bits in type ']gltype['.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([for bit size of $gltype], [gl_cv_bitsizeof_${gltype}], + [AC_COMPUTE_INT([result], [sizeof ($gltype) * CHAR_BIT], + [$2 +#include ], [result=unknown]) + eval gl_cv_bitsizeof_${gltype}=\$result + ]) + eval result=\$gl_cv_bitsizeof_${gltype} + if test $result = unknown; then + dnl Use a nonempty default, because some compilers, such as IRIX 5 cc, + dnl do a syntax check even on unused #if conditions and give an error + dnl on valid C code like this: + dnl #if 0 + dnl # if > 32 + dnl # endif + dnl #endif + result=0 + fi + GLTYPE=`echo "$gltype" | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + AC_DEFINE_UNQUOTED([BITSIZEOF_${GLTYPE}], [$result]) + eval BITSIZEOF_${GLTYPE}=\$result + done + m4_foreach_w([gltype], [$1], + [AC_SUBST([BITSIZEOF_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) +]) + +dnl gl_CHECK_TYPES_SIGNED(TYPES, INCLUDES) +dnl Determine the signedness of each of the given types. +dnl Define HAVE_SIGNED_TYPE if type is signed. +AC_DEFUN([gl_CHECK_TYPES_SIGNED], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + m4_foreach_w([gltype], [$1], + [AH_TEMPLATE([HAVE_SIGNED_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]), + [Define to 1 if ']gltype[' is a signed integer type.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([whether $gltype is signed], [gl_cv_type_${gltype}_signed], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([$2[ + int verify[2 * (($gltype) -1 < ($gltype) 0) - 1];]])], + result=yes, result=no) + eval gl_cv_type_${gltype}_signed=\$result + ]) + eval result=\$gl_cv_type_${gltype}_signed + GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + if test "$result" = yes; then + AC_DEFINE_UNQUOTED([HAVE_SIGNED_${GLTYPE}], [1]) + eval HAVE_SIGNED_${GLTYPE}=1 + else + eval HAVE_SIGNED_${GLTYPE}=0 + fi + done + m4_foreach_w([gltype], [$1], + [AC_SUBST([HAVE_SIGNED_]m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))]) +]) + +dnl gl_INTEGER_TYPE_SUFFIX(TYPES, INCLUDES) +dnl Determine the suffix to use for integer constants of the given types. +dnl Define t_SUFFIX for each such type. +AC_DEFUN([gl_INTEGER_TYPE_SUFFIX], +[ + dnl Use a shell loop, to avoid bloating configure, and + dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into + dnl config.h.in, + dnl - extra AC_SUBST calls, so that the right substitutions are made. + m4_foreach_w([gltype], [$1], + [AH_TEMPLATE(m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX], + [Define to l, ll, u, ul, ull, etc., as suitable for + constants of type ']gltype['.])]) + for gltype in $1 ; do + AC_CACHE_CHECK([for $gltype integer literal suffix], + [gl_cv_type_${gltype}_suffix], + [eval gl_cv_type_${gltype}_suffix=no + eval result=\$gl_cv_type_${gltype}_signed + if test "$result" = yes; then + glsufu= + else + glsufu=u + fi + for glsuf in "$glsufu" ${glsufu}l ${glsufu}ll ${glsufu}i64; do + case $glsuf in + '') gltype1='int';; + l) gltype1='long int';; + ll) gltype1='long long int';; + i64) gltype1='__int64';; + u) gltype1='unsigned int';; + ul) gltype1='unsigned long int';; + ull) gltype1='unsigned long long int';; + ui64)gltype1='unsigned __int64';; + esac + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([$2[ + extern $gltype foo; + extern $gltype1 foo;]])], + [eval gl_cv_type_${gltype}_suffix=\$glsuf]) + eval result=\$gl_cv_type_${gltype}_suffix + test "$result" != no && break + done]) + GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + eval result=\$gl_cv_type_${gltype}_suffix + test "$result" = no && result= + eval ${GLTYPE}_SUFFIX=\$result + AC_DEFINE_UNQUOTED([${GLTYPE}_SUFFIX], [$result]) + done + m4_foreach_w([gltype], [$1], + [AC_SUBST(m4_translit(gltype,[abcdefghijklmnopqrstuvwxyz ],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX])]) +]) + +dnl gl_STDINT_INCLUDES +AC_DEFUN([gl_STDINT_INCLUDES], +[[ + #include + #include + #if HAVE_WCHAR_H + # include + #endif +]]) + +dnl gl_STDINT_TYPE_PROPERTIES +dnl Compute HAVE_SIGNED_t, BITSIZEOF_t and t_SUFFIX, for all the types t +dnl of interest to stdint.in.h. +AC_DEFUN([gl_STDINT_TYPE_PROPERTIES], +[ + AC_REQUIRE([gl_MULTIARCH]) + if test $APPLE_UNIVERSAL_BUILD = 0; then + gl_STDINT_BITSIZEOF([ptrdiff_t size_t], + [gl_STDINT_INCLUDES]) + fi + gl_STDINT_BITSIZEOF([sig_atomic_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) + gl_CHECK_TYPES_SIGNED([sig_atomic_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) + gl_cv_type_ptrdiff_t_signed=yes + gl_cv_type_size_t_signed=no + if test $APPLE_UNIVERSAL_BUILD = 0; then + gl_INTEGER_TYPE_SUFFIX([ptrdiff_t size_t], + [gl_STDINT_INCLUDES]) + fi + gl_INTEGER_TYPE_SUFFIX([sig_atomic_t wchar_t wint_t], + [gl_STDINT_INCLUDES]) + + dnl If wint_t is smaller than 'int', it cannot satisfy the ISO C 99 + dnl requirement that wint_t is "unchanged by default argument promotions". + dnl In this case gnulib's and override wint_t. + dnl Set the variable BITSIZEOF_WINT_T accordingly. + if test $GNULIB_OVERRIDES_WINT_T = 1; then + BITSIZEOF_WINT_T=32 + fi +]) diff --git a/src/m4/sys_types_h.m4 b/src/m4/sys_types_h.m4 new file mode 100644 index 000000000..2172c836d --- /dev/null +++ b/src/m4/sys_types_h.m4 @@ -0,0 +1,58 @@ +# sys_types_h.m4 serial 11 +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, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN_ONCE([gl_SYS_TYPES_H], +[ + dnl Use sane struct stat types in OpenVMS 8.2 and later. + AC_DEFINE([_USE_STD_STAT], 1, [For standard stat data types on VMS.]) + + AC_REQUIRE([gl_SYS_TYPES_H_DEFAULTS]) + gl_NEXT_HEADERS([sys/types.h]) + + dnl Ensure the type pid_t gets defined. + AC_REQUIRE([AC_TYPE_PID_T]) + + dnl Ensure the type mode_t gets defined. + AC_REQUIRE([AC_TYPE_MODE_T]) + + dnl Whether to override the 'off_t' type. + AC_REQUIRE([gl_TYPE_OFF_T]) + + dnl Whether to override the 'dev_t' and 'ino_t' types. + m4_ifdef([gl_WINDOWS_STAT_INODES], [ + AC_REQUIRE([gl_WINDOWS_STAT_INODES]) + ], [ + WINDOWS_STAT_INODES=0 + ]) + AC_SUBST([WINDOWS_STAT_INODES]) +]) + +AC_DEFUN([gl_SYS_TYPES_H_DEFAULTS], +[ +]) + +# This works around a buggy version in autoconf <= 2.69. +# See +# The 2.70 version isn't quoted properly, so override it too. + +m4_version_prereq([2.70.1], [], [ + +m4_undefine([AC_HEADER_MAJOR]) +AC_DEFUN([AC_HEADER_MAJOR], +[AC_CHECK_HEADERS_ONCE([sys/types.h]) +AC_CHECK_HEADER([sys/mkdev.h], + [AC_DEFINE([MAJOR_IN_MKDEV], [1], + [Define to 1 if `major', `minor', and `makedev' are + declared in .])]) +if test $ac_cv_header_sys_mkdev_h = no; then + AC_CHECK_HEADER([sys/sysmacros.h], + [AC_DEFINE([MAJOR_IN_SYSMACROS], [1], + [Define to 1 if `major', `minor', and `makedev' + are declared in .])]) +fi +])# AC_HEADER_MAJOR + +]) diff --git a/src/m4/wint_t.m4 b/src/m4/wint_t.m4 new file mode 100644 index 000000000..2fc7467f4 --- /dev/null +++ b/src/m4/wint_t.m4 @@ -0,0 +1,57 @@ +# wint_t.m4 serial 10 +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, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wint_t' type and whether gnulib's +dnl or would, if present, override 'wint_t'. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + wint_t foo = (wchar_t)'\0';]], + [[]])], + [gt_cv_c_wint_t=yes], + [gt_cv_c_wint_t=no])]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE([HAVE_WINT_T], [1], [Define if you have the 'wint_t' type.]) + + dnl Determine whether gnulib's or would, if present, + dnl override 'wint_t'. + AC_CACHE_CHECK([whether wint_t is large enough], + [gl_cv_type_wint_t_large_enough], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + int verify[sizeof (wint_t) < sizeof (int) ? -1 : 1]; + ]])], + [gl_cv_type_wint_t_large_enough=yes], + [gl_cv_type_wint_t_large_enough=no])]) + if test $gl_cv_type_wint_t_large_enough = no; then + GNULIB_OVERRIDES_WINT_T=1 + else + GNULIB_OVERRIDES_WINT_T=0 + fi + else + GNULIB_OVERRIDES_WINT_T=0 + fi + AC_SUBST([GNULIB_OVERRIDES_WINT_T]) +]) + +dnl Prerequisites of the 'wint_t' override. +AC_DEFUN([gl_TYPE_WINT_T_PREREQ], +[ + AC_CHECK_HEADERS_ONCE([crtdefs.h]) + if test $ac_cv_header_crtdefs_h = yes; then + HAVE_CRTDEFS_H=1 + else + HAVE_CRTDEFS_H=0 + fi + AC_SUBST([HAVE_CRTDEFS_H]) +]) diff --git a/src/m4/xsize.m4 b/src/m4/xsize.m4 new file mode 100644 index 000000000..64e8a4f45 --- /dev/null +++ b/src/m4/xsize.m4 @@ -0,0 +1,12 @@ +# xsize.m4 serial 5 +dnl Copyright (C) 2003-2004, 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, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_CHECK_HEADERS([stdint.h]) +]) diff --git a/src/m4/zzgnulib.m4 b/src/m4/zzgnulib.m4 new file mode 100644 index 000000000..b9533847c --- /dev/null +++ b/src/m4/zzgnulib.m4 @@ -0,0 +1,23 @@ +# zzgnulib.m4 serial 1 +dnl Copyright (C) 2020-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, +dnl with or without modifications, as long as this notice is preserved. + +dnl This file must be named something that sorts after all other +dnl package- or gnulib-provided .m4 files - at least for those packages +dnl that redefine AC_PROG_CC. + +dnl Redefine AC_PROG_CC so that it ends with invocations of gl_COMPILER_CLANG +dnl and gl_COMPILER_PREPARE_CHECK_DECL. +m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[ +gl_COMPILER_CLANG +gl_COMPILER_PREPARE_CHECK_DECL +]) + +# gl_ZZGNULIB +# ----------- +# Witness macro that this file has been included. Needed to force +# Automake to include this file after all other gnulib .m4 files. +AC_DEFUN([gl_ZZGNULIB]) diff --git a/src/main.c b/src/main.c index 83e60d8e0..a437b6b4c 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ #include "config.h" #endif #include "openocd.h" +#include "helper/system.h" /* This is the main entry for developer PC hosted OpenOCD. * diff --git a/src/pld/pld.c b/src/pld/pld.c index ef7993c5d..6f4da1294 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -22,6 +22,7 @@ #include "pld.h" #include +#include #include diff --git a/src/pld/xilinx_bit.c b/src/pld/xilinx_bit.c index f83d8942d..a530ee776 100644 --- a/src/pld/xilinx_bit.c +++ b/src/pld/xilinx_bit.c @@ -25,7 +25,7 @@ #include #include - +#include static int read_section(FILE *input_file, int length_size, char section, uint32_t *buffer_length, uint8_t **buffer) diff --git a/src/pld/xilinx_bit.h b/src/pld/xilinx_bit.h index 1a35c3be2..625a9d35e 100644 --- a/src/pld/xilinx_bit.h +++ b/src/pld/xilinx_bit.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_PLD_XILINX_BIT_H #define OPENOCD_PLD_XILINX_BIT_H +#include "helper/types.h" + struct xilinx_bit_file { uint8_t unknown_header[13]; uint8_t *source_file; diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index ee9b48bb9..697f18946 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -27,12 +27,11 @@ #include "rtos.h" #include "helper/log.h" #include "helper/types.h" +#include "gnulib/gl_linkedhash_map.h" #include "rtos_standard_stackings.h" #include "target/armv7m.h" #include "target/cortex_m.h" - - #define FREERTOS_MAX_PRIORITIES 63 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset) @@ -52,11 +51,85 @@ struct FreeRTOS_params { const unsigned char list_elem_content_offset; const unsigned char thread_stack_offset; const unsigned char thread_name_offset; - const struct rtos_register_stacking *stacking_info_cm3; - const struct rtos_register_stacking *stacking_info_cm4f; - const struct rtos_register_stacking *stacking_info_cm4f_fpu; + int (*stacking)(struct rtos *rtos, const struct rtos_register_stacking **stacking, + target_addr_t stack_ptr); }; +struct FreeRTOS_thread_entry { + threadid_t threadid; + target_addr_t tcb; +}; + +struct FreeRTOS { + const struct FreeRTOS_params *param; + threadid_t last_threadid; + /* Map from threadid to FreeRTOS_thread_entry. This map owns the value and + * is responsible for free()ing it. */ + gl_map_t entry_by_threadid; + /* Map from tcb to FreeRTOS_thread_entry. */ + gl_map_t entry_by_tcb; +}; + +static int cortex_m_stacking(struct rtos *rtos, const struct rtos_register_stacking **stacking, + target_addr_t stack_ptr) +{ + /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */ + int cm4_fpu_enabled = 0; + struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); + if (is_armv7m(armv7m_target)) { + if (armv7m_target->fp_feature == FPv4_SP) { + /* Found ARM v7m target which includes a FPU */ + uint32_t cpacr; + + int retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read CPACR register to check FPU state"); + return retval; + } + + /* Check if CP10 and CP11 are set to full access. */ + if (cpacr & 0x00F00000) { + /* Found target with enabled FPU */ + cm4_fpu_enabled = 1; + } + } + } + + if (cm4_fpu_enabled == 1) { + /* Read the LR to decide between stacking with or without FPU */ + uint32_t LR_svc = 0; + int retval = target_read_u32(rtos->target, + stack_ptr + 0x20, + &LR_svc); + if (retval != ERROR_OK) { + LOG_OUTPUT("Error reading stack frame from FreeRTOS thread"); + return retval; + } + if ((LR_svc & 0x10) == 0) + *stacking = &rtos_standard_Cortex_M4F_FPU_stacking; + else + *stacking = &rtos_standard_Cortex_M4F_stacking; + } else { + *stacking = &rtos_standard_Cortex_M3_stacking; + } + + return ERROR_OK; +} + +static int nds32_stacking(struct rtos *rtos, const struct rtos_register_stacking **stacking, + target_addr_t stack_ptr) +{ + *stacking = &rtos_standard_NDS32_N1068_stacking; + return ERROR_OK; +} + +static int riscv_stacking(struct rtos *rtos, const struct rtos_register_stacking **stacking, + target_addr_t stack_ptr) +{ + *stacking = &rtos_standard_RV32_stacking; + return ERROR_OK; +} + static const struct FreeRTOS_params FreeRTOS_params_list[] = { { "cortex_m", /* target_name */ @@ -68,9 +141,7 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = { 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ - &rtos_standard_Cortex_M3_stacking, /* stacking_info */ - &rtos_standard_Cortex_M4F_stacking, - &rtos_standard_Cortex_M4F_FPU_stacking, + cortex_m_stacking, }, { "hla_target", /* target_name */ @@ -82,9 +153,7 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = { 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ - &rtos_standard_Cortex_M3_stacking, /* stacking_info */ - &rtos_standard_Cortex_M4F_stacking, - &rtos_standard_Cortex_M4F_FPU_stacking, + cortex_m_stacking, }, { "nds32_v3", /* target_name */ @@ -96,9 +165,19 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = { 12, /* list_elem_content_offset */ 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ - &rtos_standard_NDS32_N1068_stacking, /* stacking_info */ - &rtos_standard_Cortex_M4F_stacking, - &rtos_standard_Cortex_M4F_FPU_stacking, + nds32_stacking, + }, + { + "riscv", /* target_name */ + 4, /* thread_count_width; */ + 4, /* pointer_width; */ + 16, /* list_next_offset; */ + 20, /* list_width; */ + 8, /* list_elem_next_offset; */ + 12, /* list_elem_content_offset */ + 0, /* thread_stack_offset; */ + 52, /* thread_name_offset; */ + riscv_stacking, }, }; @@ -107,8 +186,10 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = { static bool FreeRTOS_detect_rtos(struct target *target); static int FreeRTOS_create(struct target *target); static int FreeRTOS_update_threads(struct rtos *rtos); -static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, +static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, threadid_t thread_id, struct rtos_reg **reg_list, int *num_regs); +static int FreeRTOS_get_thread_reg(struct rtos *rtos, threadid_t thread_id, + uint32_t reg_num, struct rtos_reg *reg); static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); struct rtos_type FreeRTOS_rtos = { @@ -118,6 +199,7 @@ struct rtos_type FreeRTOS_rtos = { .create = FreeRTOS_create, .update_threads = FreeRTOS_update_threads, .get_thread_reg_list = FreeRTOS_get_thread_reg_list, + .get_thread_reg = FreeRTOS_get_thread_reg, .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup, }; @@ -164,21 +246,21 @@ static int FreeRTOS_update_threads(struct rtos *rtos) { int retval; unsigned int tasks_found = 0; - const struct FreeRTOS_params *param; if (rtos->rtos_specific_params == NULL) - return -1; + return ERROR_FAIL; - param = (const struct FreeRTOS_params *) rtos->rtos_specific_params; + struct FreeRTOS *freertos = (struct FreeRTOS *) rtos->rtos_specific_params; + const struct FreeRTOS_params *param = freertos->param; if (rtos->symbols == NULL) { LOG_ERROR("No symbols for FreeRTOS"); - return -3; + return ERROR_FAIL; } if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) { LOG_ERROR("Don't have the number of threads in FreeRTOS"); - return -2; + return ERROR_FAIL; } uint32_t thread_list_size = 0; @@ -206,12 +288,12 @@ static int FreeRTOS_update_threads(struct rtos *rtos) LOG_ERROR("Error reading current thread in FreeRTOS thread list"); return retval; } - rtos->current_thread = pointer_casts_are_bad; + target_addr_t pxCurrentTCB = pointer_casts_are_bad; LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64 ", value 0x%" PRIx64, rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address, - rtos->current_thread); + pxCurrentTCB); - if ((thread_list_size == 0) || (rtos->current_thread == 0)) { + if ((thread_list_size == 0) || (pxCurrentTCB == 0)) { /* Either : No RTOS threads - there is always at least the current execution though */ /* OR : No current thread - all threads suspended - show the current execution * of idling */ @@ -245,19 +327,23 @@ static int FreeRTOS_update_threads(struct rtos *rtos) } /* Find out how many lists are needed to be read from pxReadyTasksLists, */ - if (rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address == 0) { - LOG_ERROR("FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around"); - return ERROR_FAIL; - } uint32_t top_used_priority = 0; - retval = target_read_u32(rtos->target, - rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address, - &top_used_priority); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64 ", value %" PRIu32, - rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address, - top_used_priority); + if (rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address == 0) { + LOG_WARNING("FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around"); + /* This is a hack specific to the binary I'm debugging. + * Ideally we get https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/33 + * into our FreeRTOS source. */ + top_used_priority = 6; + } else { + retval = target_read_u32(rtos->target, + rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address, + &top_used_priority); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64 ", value %" PRIu32, + rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address, + top_used_priority); + } if (top_used_priority > FREERTOS_MAX_PRIORITIES) { LOG_ERROR("FreeRTOS top used priority is unreasonably big, not proceeding: %" PRIu32, top_used_priority); @@ -289,6 +375,7 @@ static int FreeRTOS_update_threads(struct rtos *rtos) list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address; list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address; + rtos->current_thread = 0; for (unsigned int i = 0; i < num_lists; i++) { if (list_of_lists[i] == 0) continue; @@ -336,10 +423,34 @@ static int FreeRTOS_update_threads(struct rtos *rtos) free(list_of_lists); return retval; } - rtos->thread_details[tasks_found].threadid = pointer_casts_are_bad; - LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx32 ", value 0x%" PRIx64, - list_elem_ptr + param->list_elem_content_offset, - rtos->thread_details[tasks_found].threadid); + + target_addr_t tcb = pointer_casts_are_bad; + const struct FreeRTOS_thread_entry *value = + gl_map_get(freertos->entry_by_tcb, &tcb); + + if (value == NULL) { + struct FreeRTOS_thread_entry *new_value = calloc(1, sizeof(struct FreeRTOS_thread_entry)); + new_value->tcb = tcb; + /* threadid can't be 0. */ + new_value->threadid = ++freertos->last_threadid; + + if (gl_map_nx_put(freertos->entry_by_tcb, &new_value->tcb, new_value) == -1) { + LOG_ERROR("gl_map_nx_put failed"); + return ERROR_FAIL; + } + if (gl_map_nx_put(freertos->entry_by_threadid, &new_value->threadid, new_value) == -1) { + LOG_ERROR("gl_map_nx_put failed"); + return ERROR_FAIL; + } + value = new_value; + } + + rtos->thread_details[tasks_found].threadid = value->threadid; + + LOG_DEBUG("FreeRTOS: Thread %" PRId64 " has TCB 0x%" TARGET_PRIxADDR + "; read from 0x%" PRIx32, + value->threadid, value->tcb, + list_elem_ptr + param->list_elem_content_offset); /* get thread name */ @@ -348,7 +459,7 @@ static int FreeRTOS_update_threads(struct rtos *rtos) /* Read the thread name */ retval = target_read_buffer(rtos->target, - rtos->thread_details[tasks_found].threadid + param->thread_name_offset, + value->tcb + param->thread_name_offset, FREERTOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str); if (retval != ERROR_OK) { @@ -358,7 +469,7 @@ static int FreeRTOS_update_threads(struct rtos *rtos) } tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00'; LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64 ", value '%s'", - rtos->thread_details[tasks_found].threadid + param->thread_name_offset, + value->tcb + param->thread_name_offset, tmp_str); if (tmp_str[0] == '\x00') @@ -369,8 +480,9 @@ static int FreeRTOS_update_threads(struct rtos *rtos) strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str); rtos->thread_details[tasks_found].exists = true; - if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) { + if (value->tcb == pxCurrentTCB) { char running_str[] = "State: Running"; + rtos->current_thread = value->threadid; rtos->thread_details[tasks_found].extra_info_str = malloc( sizeof(running_str)); strcpy(rtos->thread_details[tasks_found].extra_info_str, @@ -402,76 +514,75 @@ static int FreeRTOS_update_threads(struct rtos *rtos) return 0; } -static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, - struct rtos_reg **reg_list, int *num_regs) +static int FreeRTOS_get_stacking_info(struct rtos *rtos, threadid_t thread_id, + const struct rtos_register_stacking **stacking_info, + target_addr_t *stack_ptr) { - int retval; - const struct FreeRTOS_params *param; - int64_t stack_ptr = 0; + if (rtos->rtos_specific_params == NULL) { + LOG_ERROR("rtos_specific_params is NULL!"); + return ERROR_FAIL; + } - if (rtos == NULL) - return -1; + struct FreeRTOS *freertos = (struct FreeRTOS *) rtos->rtos_specific_params; + const struct FreeRTOS_params *param = freertos->param; - if (thread_id == 0) - return -2; - - if (rtos->rtos_specific_params == NULL) - return -1; - - param = (const struct FreeRTOS_params *) rtos->rtos_specific_params; + const struct FreeRTOS_thread_entry *entry = + gl_map_get(freertos->entry_by_threadid, &thread_id); + if (entry == NULL) { + LOG_ERROR("Unknown thread id: %" PRId64, thread_id); + return ERROR_FAIL; + } /* Read the stack pointer */ uint32_t pointer_casts_are_bad; - retval = target_read_u32(rtos->target, - thread_id + param->thread_stack_offset, + int retval = target_read_u32(rtos->target, + entry->tcb + param->thread_stack_offset, &pointer_casts_are_bad); if (retval != ERROR_OK) { - LOG_ERROR("Error reading stack frame from FreeRTOS thread"); + LOG_ERROR("Error reading stack frame from FreeRTOS thread %" PRIx64, thread_id); return retval; } - stack_ptr = pointer_casts_are_bad; - LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64, - thread_id + param->thread_stack_offset, - stack_ptr); + *stack_ptr = pointer_casts_are_bad; + LOG_DEBUG("[%" PRId64 "] FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64, + thread_id, entry->tcb + param->thread_stack_offset, *stack_ptr); - /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */ - int cm4_fpu_enabled = 0; - struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); - if (is_armv7m(armv7m_target)) { - if (armv7m_target->fp_feature == FPv4_SP) { - /* Found ARM v7m target which includes a FPU */ - uint32_t cpacr; - - retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr); - if (retval != ERROR_OK) { - LOG_ERROR("Could not read CPACR register to check FPU state"); - return -1; - } - - /* Check if CP10 and CP11 are set to full access. */ - if (cpacr & 0x00F00000) { - /* Found target with enabled FPU */ - cm4_fpu_enabled = 1; - } - } + if (param->stacking(rtos, stacking_info, *stack_ptr) != ERROR_OK) { + LOG_ERROR("No stacking info found for %s!", param->target_name); + return ERROR_FAIL; } - if (cm4_fpu_enabled == 1) { - /* Read the LR to decide between stacking with or without FPU */ - uint32_t LR_svc = 0; - retval = target_read_u32(rtos->target, - stack_ptr + 0x20, - &LR_svc); - if (retval != ERROR_OK) { - LOG_OUTPUT("Error reading stack frame from FreeRTOS thread"); - return retval; - } - if ((LR_svc & 0x10) == 0) - return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f_fpu, stack_ptr, reg_list, num_regs); - else - return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f, stack_ptr, reg_list, num_regs); - } else - return rtos_generic_stack_read(rtos->target, param->stacking_info_cm3, stack_ptr, reg_list, num_regs); + return ERROR_OK; +} + +static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, threadid_t thread_id, + struct rtos_reg **reg_list, int *num_regs) +{ + /* Let the caller read registers directly for the current thread. */ + if (thread_id == 0) + return ERROR_FAIL; + + const struct rtos_register_stacking *stacking_info; + target_addr_t stack_ptr; + if (FreeRTOS_get_stacking_info(rtos, thread_id, &stacking_info, &stack_ptr) != ERROR_OK) + return ERROR_FAIL; + + return rtos_generic_stack_read(rtos->target, stacking_info, stack_ptr, reg_list, num_regs); +} + +static int FreeRTOS_get_thread_reg(struct rtos *rtos, threadid_t thread_id, + uint32_t reg_num, struct rtos_reg *reg) +{ + LOG_DEBUG("reg_num=%d", reg_num); + /* Let the caller read registers directly for the current thread. */ + if (thread_id == 0) + return ERROR_FAIL; + + const struct rtos_register_stacking *stacking_info; + target_addr_t stack_ptr; + if (FreeRTOS_get_stacking_info(rtos, thread_id, &stacking_info, &stack_ptr) != ERROR_OK) + return ERROR_FAIL; + + return rtos_generic_stack_read_reg(rtos->target, stacking_info, stack_ptr, reg_num, reg); } static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) @@ -545,6 +656,25 @@ static bool FreeRTOS_detect_rtos(struct target *target) return false; } +static bool target_addr_equals(const void *x1, const void *x2) +{ + const target_addr_t *a1 = x1; + const target_addr_t *a2 = x2; + return *a1 == *a2; +} + +static size_t target_addr_hash(const void *x) +{ + const target_addr_t *a = x; + return *a; +} + +static void free_const(const void *x) +{ + /* Cast away const. */ + free((void *) x); +} + static int FreeRTOS_create(struct target *target) { int i = 0; @@ -554,9 +684,29 @@ static int FreeRTOS_create(struct target *target) } if (i >= FREERTOS_NUM_PARAMS) { LOG_ERROR("Could not find target in FreeRTOS compatibility list"); - return -1; + return ERROR_FAIL; } - target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i]; + target->rtos->rtos_specific_params = calloc(1, sizeof(struct FreeRTOS)); + if (target->rtos->rtos_specific_params == NULL) { + LOG_ERROR("calloc failed"); + return ERROR_FAIL; + } + + struct FreeRTOS *freertos = (struct FreeRTOS *) target->rtos->rtos_specific_params; + freertos->entry_by_threadid = gl_map_nx_create_empty( + GL_LINKEDHASH_MAP, target_addr_equals, target_addr_hash, NULL, free_const); + if (freertos->entry_by_threadid == NULL) { + LOG_ERROR("gl_map_nx_create_empty failed"); + return ERROR_FAIL; + } + freertos->entry_by_tcb = gl_map_nx_create_empty( + GL_LINKEDHASH_MAP, target_addr_equals, target_addr_hash, NULL, NULL); + if (freertos->entry_by_tcb == NULL) { + LOG_ERROR("gl_map_nx_create_empty failed"); + return ERROR_FAIL; + } + freertos->param = &FreeRTOS_params_list[i]; + return 0; } diff --git a/src/rtos/ThreadX.c b/src/rtos/ThreadX.c index 7d58725c4..53788c794 100644 --- a/src/rtos/ThreadX.c +++ b/src/rtos/ThreadX.c @@ -112,18 +112,16 @@ static const struct stack_register_offset rtos_threadx_arm926ejs_stack_offsets_i static const struct rtos_register_stacking rtos_threadx_arm926ejs_stacking[] = { { - ARM926EJS_REGISTERS_SIZE_SOLICITED, /* stack_registers_size */ - -1, /* stack_growth_direction */ - 17, /* num_output_registers */ - NULL, /* stack_alignment */ - rtos_threadx_arm926ejs_stack_offsets_solicited /* register_offsets */ + .stack_registers_size = ARM926EJS_REGISTERS_SIZE_SOLICITED, + .stack_growth_direction = -1, + .num_output_registers = 17, + .register_offsets = rtos_threadx_arm926ejs_stack_offsets_solicited }, { - ARM926EJS_REGISTERS_SIZE_INTERRUPT, /* stack_registers_size */ - -1, /* stack_growth_direction */ - 17, /* num_output_registers */ - NULL, /* stack_alignment */ - rtos_threadx_arm926ejs_stack_offsets_interrupt /* register_offsets */ + .stack_registers_size = ARM926EJS_REGISTERS_SIZE_INTERRUPT, + .stack_growth_direction = -1, + .num_output_registers = 17, + .register_offsets = rtos_threadx_arm926ejs_stack_offsets_interrupt }, }; diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c index 19b93bad1..df5dbe1c6 100644 --- a/src/rtos/nuttx.c +++ b/src/rtos/nuttx.c @@ -119,11 +119,10 @@ static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = { static const struct rtos_register_stacking nuttx_stacking_cortex_m = { - 0x48, /* stack_registers_size */ - -1, /* stack_growth_direction */ - 17, /* num_output_registers */ - 0, /* stack_alignment */ - nuttx_stack_offsets_cortex_m /* register_offsets */ + .stack_registers_size = 0x48, + .stack_growth_direction = -1, + .num_output_registers = 17, + .register_offsets = nuttx_stack_offsets_cortex_m }; static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = { @@ -147,11 +146,10 @@ static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = { }; static const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = { - 0x8c, /* stack_registers_size */ - -1, /* stack_growth_direction */ - 17, /* num_output_registers */ - 0, /* stack_alignment */ - nuttx_stack_offsets_cortex_m_fpu /* register_offsets */ + .stack_registers_size = 0x8c, + .stack_growth_direction = -1, + .num_output_registers = 17, + .register_offsets = nuttx_stack_offsets_cortex_m_fpu }; static int pid_offset = PID; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index f88925a65..86ea088ee 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -68,7 +68,9 @@ int rtos_smp_init(struct target *target) return ERROR_TARGET_INIT_FAILED; } -static int rtos_target_for_threadid(struct connection *connection, int64_t threadid, struct target **t) +static int rtos_target_for_threadid(struct connection *connection, + threadid_t threadid, + struct target **t) { struct target *curr = get_target_from_connection(connection); if (t) @@ -475,7 +477,7 @@ static int rtos_put_gdb_reg_list(struct connection *connection, int rtos_get_gdb_reg(struct connection *connection, int reg_num) { struct target *target = get_target_from_connection(connection); - int64_t current_threadid = target->rtos->current_threadid; + threadid_t current_threadid = target->rtos->current_threadid; if ((target->rtos != NULL) && (current_threadid != -1) && (current_threadid != 0) && ((current_threadid != target->rtos->current_thread) || @@ -492,6 +494,7 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num) int retval; if (target->rtos->type->get_thread_reg) { reg_list = calloc(1, sizeof(*reg_list)); + reg_list[0].number = reg_num; num_regs = 1; retval = target->rtos->type->get_thread_reg(target->rtos, current_threadid, reg_num, ®_list[0]); @@ -573,7 +576,7 @@ int rtos_set_reg(struct connection *connection, int reg_num, int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, - int64_t stack_ptr, + target_addr_t stack_ptr, struct rtos_reg **reg_list, int *num_regs) { @@ -585,7 +588,7 @@ int rtos_generic_stack_read(struct target *target, } /* Read the stack */ uint8_t *stack_data = malloc(stacking->stack_registers_size); - uint32_t address = stack_ptr; + target_addr_t address = stack_ptr; if (stacking->stack_growth_direction == 1) address -= stacking->stack_registers_size; @@ -595,7 +598,7 @@ int rtos_generic_stack_read(struct target *target, LOG_ERROR("Error reading stack frame from thread"); return retval; } - LOG_DEBUG("RTOS: Read stack frame at 0x%" PRIx32, address); + LOG_DEBUG("RTOS: Read stack frame at " TARGET_ADDR_FMT, address); #if 0 LOG_OUTPUT("Stack Data :"); @@ -625,6 +628,9 @@ int rtos_generic_stack_read(struct target *target, buf_cpy(&new_stack_ptr, (*reg_list)[i].value, (*reg_list)[i].size); else if (offset != -1) buf_cpy(stack_data + offset, (*reg_list)[i].value, (*reg_list)[i].size); + + LOG_DEBUG("register %d has value 0x%" PRIx64, (*reg_list)[i].number, + buf_get_u64((*reg_list)[i].value, 0, 64)); } free(stack_data); @@ -632,6 +638,48 @@ int rtos_generic_stack_read(struct target *target, return ERROR_OK; } +/* Read an individual register from the RTOS stack. */ +int rtos_generic_stack_read_reg(struct target *target, + const struct rtos_register_stacking *stacking, + target_addr_t stack_ptr, + uint32_t reg_num, struct rtos_reg *reg) +{ + LOG_DEBUG("stack_ptr=" TARGET_ADDR_FMT ", reg_num=%d", stack_ptr, reg_num); + unsigned total_count = MAX(stacking->total_register_count, stacking->num_output_registers); + unsigned i; + for (i = 0; i < total_count; i++) { + if (stacking->register_offsets[i].number == reg_num) + break; + } + if (i >= total_count) { + /* This register is not on the stack. Return error so a caller somewhere + * will just read the register directly fromt he target. */ + return ERROR_FAIL; + } + + const struct stack_register_offset *offsets = &stacking->register_offsets[i]; + reg->size = offsets->width_bits; + + unsigned width_bytes = DIV_ROUND_UP(offsets->width_bits, 8); + if (offsets->offset >= 0) { + target_addr_t address = stack_ptr; + + if (stacking->stack_growth_direction == 1) + address -= stacking->stack_registers_size; + + if (target_read_buffer( + target, address + offsets->offset, + width_bytes, reg->value) != ERROR_OK) + return ERROR_FAIL; + LOG_DEBUG("register %d has value 0x%" PRIx64, reg->number, + buf_get_u64(reg->value, 0, 64)); + } else { + memset(reg->value, 0, width_bytes); + } + + return ERROR_OK; +} + static int rtos_try_next(struct target *target) { struct rtos *os = target->rtos; diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 1bda7301d..9f91e19a1 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -58,7 +58,7 @@ struct rtos { int thread_count; int (*gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size); int (*gdb_v_packet)(struct connection *connection, char const *packet, int packet_size); - int (*gdb_target_for_threadid)(struct connection *connection, int64_t thread_id, struct target **p_target); + int (*gdb_target_for_threadid)(struct connection *connection, threadid_t thread_id, struct target **p_target); void *rtos_specific_params; }; @@ -75,9 +75,9 @@ struct rtos_type { int (*smp_init)(struct target *target); int (*update_threads)(struct rtos *rtos); /** Return a list of general registers, with their values filled out. */ - int (*get_thread_reg_list)(struct rtos *rtos, int64_t thread_id, + int (*get_thread_reg_list)(struct rtos *rtos, threadid_t thread_id, struct rtos_reg **reg_list, int *num_regs); - int (*get_thread_reg)(struct rtos *rtos, int64_t thread_id, + int (*get_thread_reg)(struct rtos *rtos, threadid_t thread_id, uint32_t reg_num, struct rtos_reg *reg); int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]); int (*clean)(struct target *target); @@ -89,7 +89,7 @@ struct rtos_type { * the thread current. This is an assumption that cannot hold for a real * target running a multi-threading OS. If an RTOS can do this, override * needs_fake_step(). */ - bool (*needs_fake_step)(struct target *target, int64_t thread_id); + bool (*needs_fake_step)(struct target *target, threadid_t thread_id); /* Implement these if different threads in the RTOS can see memory * differently (for instance because address translation might be different * for each thread). */ @@ -110,6 +110,7 @@ struct stack_register_offset { struct rtos_register_stacking { unsigned char stack_registers_size; signed char stack_growth_direction; + /* The number of gdb general registers, in order. */ unsigned char num_output_registers; /* Some targets require evaluating the stack to determine the * actual stack pointer for a process. If this field is NULL, @@ -121,6 +122,10 @@ struct rtos_register_stacking { const struct rtos_register_stacking *stacking, int64_t stack_ptr); const struct stack_register_offset *register_offsets; + /* Total number of registers on the stack, including the general ones. This + * may be 0 if there are no additional registers on the stack beyond the + * general ones. */ + unsigned total_register_count; }; #define GDB_THREAD_PACKET_NOT_CONSUMED (-40) @@ -131,9 +136,13 @@ int rtos_set_reg(struct connection *connection, int reg_num, uint8_t *reg_value); int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, - int64_t stack_ptr, + target_addr_t stack_ptr, struct rtos_reg **reg_list, int *num_regs); +int rtos_generic_stack_read_reg(struct target *target, + const struct rtos_register_stacking *stacking, + target_addr_t stack_ptr, + uint32_t reg_num, struct rtos_reg *reg); int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size); int rtos_get_gdb_reg(struct connection *connection, int reg_num); int rtos_get_gdb_reg_list(struct connection *connection); @@ -142,7 +151,7 @@ void rtos_free_threadlist(struct rtos *rtos); int rtos_smp_init(struct target *target); /* function for handling symbol access */ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size); -bool rtos_needs_fake_step(struct target *target, int64_t thread_id); +bool rtos_needs_fake_step(struct target *target, threadid_t thread_id); int rtos_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); int rtos_write_buffer(struct target *target, target_addr_t address, diff --git a/src/rtos/rtos_chibios_stackings.c b/src/rtos/rtos_chibios_stackings.c index 2887930bd..77bcb86cb 100644 --- a/src/rtos/rtos_chibios_stackings.c +++ b/src/rtos/rtos_chibios_stackings.c @@ -47,11 +47,10 @@ static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets[ARM }; const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking = { - 0x24, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - NULL, /* stack_alignment */ - rtos_chibios_arm_v7m_stack_offsets /* register_offsets */ + .stack_registers_size = 0x24, + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .register_offsets = rtos_chibios_arm_v7m_stack_offsets }; static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets_w_fpu[ARMV7M_NUM_CORE_REGS] = { @@ -75,9 +74,8 @@ static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets_w_f }; const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking_w_fpu = { - 0x64, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - NULL, /* stack_alignment */ - rtos_chibios_arm_v7m_stack_offsets_w_fpu /* register_offsets */ + .stack_registers_size = 0x64, + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .register_offsets = rtos_chibios_arm_v7m_stack_offsets_w_fpu }; diff --git a/src/rtos/rtos_ecos_stackings.c b/src/rtos/rtos_ecos_stackings.c index ca98d9417..c6b0712c6 100644 --- a/src/rtos/rtos_ecos_stackings.c +++ b/src/rtos/rtos_ecos_stackings.c @@ -43,9 +43,9 @@ static const struct stack_register_offset rtos_eCos_Cortex_M3_stack_offsets[ARMV }; const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking = { - 0x44, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_generic_stack_align8, /* stack_alignment */ - rtos_eCos_Cortex_M3_stack_offsets /* register_offsets */ + .stack_registers_size = 0x44, + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .calculate_process_stack = rtos_generic_stack_align8, + .register_offsets = rtos_eCos_Cortex_M3_stack_offsets }; diff --git a/src/rtos/rtos_embkernel_stackings.c b/src/rtos/rtos_embkernel_stackings.c index 543a8cd2a..8c0fd2a99 100644 --- a/src/rtos/rtos_embkernel_stackings.c +++ b/src/rtos/rtos_embkernel_stackings.c @@ -45,9 +45,9 @@ static const struct stack_register_offset rtos_embkernel_Cortex_M_stack_offsets[ }; const struct rtos_register_stacking rtos_embkernel_Cortex_M_stacking = { - 0x40, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_generic_stack_align8, /* stack_alignment */ - rtos_embkernel_Cortex_M_stack_offsets /* register_offsets */ + .stack_registers_size = 0x40, + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .calculate_process_stack = rtos_generic_stack_align8, + .register_offsets = rtos_embkernel_Cortex_M_stack_offsets }; diff --git a/src/rtos/rtos_mqx_stackings.c b/src/rtos/rtos_mqx_stackings.c index f2d3b2227..f99190ea5 100644 --- a/src/rtos/rtos_mqx_stackings.c +++ b/src/rtos/rtos_mqx_stackings.c @@ -71,9 +71,8 @@ static const struct stack_register_offset rtos_mqx_arm_v7m_stack_offsets[ARMV7M_ }; const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking = { - 0x4C, /* stack_registers_size, calculate offset base address */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - NULL, /* stack_alignment */ - rtos_mqx_arm_v7m_stack_offsets /* register_offsets */ + .stack_registers_size = 0x4C, /* calculate offset base address */ + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .register_offsets = rtos_mqx_arm_v7m_stack_offsets }; diff --git a/src/rtos/rtos_riot_stackings.c b/src/rtos/rtos_riot_stackings.c index 23f4d1786..6489426e5 100644 --- a/src/rtos/rtos_riot_stackings.c +++ b/src/rtos/rtos_riot_stackings.c @@ -58,11 +58,11 @@ static const struct stack_register_offset rtos_riot_cortex_m0_stack_offsets[ARMV }; const struct rtos_register_stacking rtos_riot_cortex_m0_stacking = { - 0x44, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_riot_cortex_m_stack_align, /* stack_alignment */ - rtos_riot_cortex_m0_stack_offsets /* register_offsets */ + .stack_registers_size = 0x44, + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .calculate_process_stack = rtos_riot_cortex_m_stack_align, + .register_offsets = rtos_riot_cortex_m0_stack_offsets }; /* see thread_arch.c */ @@ -87,9 +87,9 @@ static const struct stack_register_offset rtos_riot_cortex_m34_stack_offsets[ARM }; const struct rtos_register_stacking rtos_riot_cortex_m34_stacking = { - 0x44, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_riot_cortex_m_stack_align, /* stack_alignment */ - rtos_riot_cortex_m34_stack_offsets /* register_offsets */ + .stack_registers_size = 0x44, + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .calculate_process_stack = rtos_riot_cortex_m_stack_align, + .register_offsets = rtos_riot_cortex_m34_stack_offsets }; diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index 7b054cbbc..7ff5b89c0 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -22,6 +22,7 @@ #include "rtos.h" #include "target/armv7m.h" +#include "target/riscv/riscv.h" static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets[ARMV7M_NUM_CORE_REGS] = { { ARMV7M_R0, 0x20, 32 }, /* r0 */ @@ -152,6 +153,47 @@ static const struct stack_register_offset rtos_standard_NDS32_N1068_stack_offset { 35, 0x10, 32 }, /* IFC_LP */ }; +static const struct stack_register_offset rtos_standard_RV32_stack_offsets[] = { + /* zero isn't on the stack. By making its offset -1 we leave the value at 0 + * inside rtos_generic_stack_read(). */ + { GDB_REGNO_ZERO, -1, 32 }, + { GDB_REGNO_RA, 0x04, 32 }, + { GDB_REGNO_SP, 0x08, 32 }, + { GDB_REGNO_GP, 0x0c, 32 }, + { GDB_REGNO_TP, 0x10, 32 }, + { GDB_REGNO_T0, 0x14, 32 }, + { GDB_REGNO_T1, 0x18, 32 }, + { GDB_REGNO_T2, 0x1c, 32 }, + { GDB_REGNO_FP, 0x20, 32 }, + { GDB_REGNO_S1, 0x24, 32 }, + { GDB_REGNO_A0, 0x28, 32 }, + { GDB_REGNO_A1, 0x2c, 32 }, + { GDB_REGNO_A2, 0x30, 32 }, + { GDB_REGNO_A3, 0x34, 32 }, + { GDB_REGNO_A4, 0x38, 32 }, + { GDB_REGNO_A5, 0x3c, 32 }, + { GDB_REGNO_A6, 0x40, 32 }, + { GDB_REGNO_A7, 0x44, 32 }, + { GDB_REGNO_S2, 0x48, 32 }, + { GDB_REGNO_S3, 0x4c, 32 }, + { GDB_REGNO_S4, 0x50, 32 }, + { GDB_REGNO_S5, 0x54, 32 }, + { GDB_REGNO_S6, 0x58, 32 }, + { GDB_REGNO_S7, 0x5c, 32 }, + { GDB_REGNO_S8, 0x60, 32 }, + { GDB_REGNO_S9, 0x64, 32 }, + { GDB_REGNO_S10, 0x68, 32 }, + { GDB_REGNO_S11, 0x6c, 32 }, + { GDB_REGNO_T3, 0x70, 32 }, + { GDB_REGNO_T4, 0x74, 32 }, + { GDB_REGNO_T5, 0x78, 32 }, + { GDB_REGNO_T6, 0x7c, 32 }, + { GDB_REGNO_PC, 0x80, 32 }, + /* Registers below are on the stack, but not what gdb expects to return from + * a 'g' packet so are only accessible through get_reg. */ + { GDB_REGNO_MSTATUS, 0x84, 32 }, +}; + static int64_t rtos_generic_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, int64_t stack_ptr, int align) @@ -249,41 +291,50 @@ static int64_t rtos_standard_Cortex_M4F_FPU_stack_align(struct target *target, const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking = { - 0x40, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_standard_Cortex_M3_stack_align, /* stack_alignment */ - rtos_standard_Cortex_M3_stack_offsets /* register_offsets */ + .stack_registers_size = 0x40, + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .calculate_process_stack = rtos_standard_Cortex_M3_stack_align, + .register_offsets = rtos_standard_Cortex_M3_stack_offsets }; const struct rtos_register_stacking rtos_standard_Cortex_M4F_stacking = { - 0x44, /* stack_registers_size 4 more for LR*/ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_standard_Cortex_M4F_stack_align, /* stack_alignment */ - rtos_standard_Cortex_M4F_stack_offsets /* register_offsets */ + .stack_registers_size = 0x44, /* 4 more for LR*/ + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .calculate_process_stack = rtos_standard_Cortex_M4F_stack_align, + .register_offsets = rtos_standard_Cortex_M4F_stack_offsets }; const struct rtos_register_stacking rtos_standard_Cortex_M4F_FPU_stacking = { - 0xcc, /* stack_registers_size 4 more for LR + 48 more for FPU S0-S15 register*/ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_standard_Cortex_M4F_FPU_stack_align, /* stack_alignment */ - rtos_standard_Cortex_M4F_FPU_stack_offsets /* register_offsets */ + .stack_registers_size = 0xcc, /* 4 more for LR + 48 more for FPU S0-S15 register*/ + .stack_growth_direction = -1, + .num_output_registers = ARMV7M_NUM_CORE_REGS, + .calculate_process_stack = rtos_standard_Cortex_M4F_FPU_stack_align, + .register_offsets = rtos_standard_Cortex_M4F_FPU_stack_offsets }; const struct rtos_register_stacking rtos_standard_Cortex_R4_stacking = { - 0x48, /* stack_registers_size */ - -1, /* stack_growth_direction */ - 26, /* num_output_registers */ - rtos_generic_stack_align8, /* stack_alignment */ - rtos_standard_Cortex_R4_stack_offsets /* register_offsets */ + .stack_registers_size = 0x48, + .stack_growth_direction = -1, + .num_output_registers = 26, + .calculate_process_stack = rtos_generic_stack_align8, + .register_offsets = rtos_standard_Cortex_R4_stack_offsets }; const struct rtos_register_stacking rtos_standard_NDS32_N1068_stacking = { - 0x90, /* stack_registers_size */ - -1, /* stack_growth_direction */ - 32, /* num_output_registers */ - rtos_generic_stack_align8, /* stack_alignment */ - rtos_standard_NDS32_N1068_stack_offsets /* register_offsets */ + .stack_registers_size = 0x90, + .stack_growth_direction = -1, + .num_output_registers = 32, + .calculate_process_stack = rtos_generic_stack_align8, + .register_offsets = rtos_standard_NDS32_N1068_stack_offsets +}; + +const struct rtos_register_stacking rtos_standard_RV32_stacking = { + .stack_registers_size = (32 + 2) * 4, + .stack_growth_direction = -1, + .num_output_registers = 33, + .calculate_process_stack = rtos_generic_stack_align8, + .register_offsets = rtos_standard_RV32_stack_offsets, + .total_register_count = ARRAY_SIZE(rtos_standard_RV32_stack_offsets) }; diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h index 6971efd1e..302ebed84 100644 --- a/src/rtos/rtos_standard_stackings.h +++ b/src/rtos/rtos_standard_stackings.h @@ -37,4 +37,6 @@ int64_t rtos_Cortex_M_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, int64_t stack_ptr, size_t xpsr_offset); +extern const struct rtos_register_stacking rtos_standard_RV32_stacking; + #endif /* OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H */ diff --git a/src/rtos/rtos_ucos_iii_stackings.c b/src/rtos/rtos_ucos_iii_stackings.c index d093563ba..1081d3716 100644 --- a/src/rtos/rtos_ucos_iii_stackings.c +++ b/src/rtos/rtos_ucos_iii_stackings.c @@ -68,17 +68,16 @@ static const struct stack_register_offset rtos_uCOS_III_eSi_RISC_stack_offsets[] }; const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking = { - 0x40, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARRAY_SIZE(rtos_uCOS_III_Cortex_M_stack_offsets), /* num_output_registers */ - rtos_generic_stack_align8, /* stack_alignment */ - rtos_uCOS_III_Cortex_M_stack_offsets /* register_offsets */ + .stack_registers_size = 0x40, + .stack_growth_direction = -1, + .num_output_registers = ARRAY_SIZE(rtos_uCOS_III_Cortex_M_stack_offsets), + .calculate_process_stack = rtos_generic_stack_align8, + .register_offsets = rtos_uCOS_III_Cortex_M_stack_offsets }; const struct rtos_register_stacking rtos_uCOS_III_eSi_RISC_stacking = { - 0x4c, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARRAY_SIZE(rtos_uCOS_III_eSi_RISC_stack_offsets), /* num_output_registers */ - NULL, /* stack_alignment */ - rtos_uCOS_III_eSi_RISC_stack_offsets /* register_offsets */ + .stack_registers_size = 0x4c, + .stack_growth_direction = -1, + .num_output_registers = ARRAY_SIZE(rtos_uCOS_III_eSi_RISC_stack_offsets), + .register_offsets = rtos_uCOS_III_eSi_RISC_stack_offsets }; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index a5f4acbfd..c1d46fb04 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1318,7 +1318,7 @@ static int gdb_get_register_packet(struct connection *connection, if (reg_list_size <= reg_num) { LOG_ERROR("gdb requested a non-existing register"); - return ERROR_SERVER_REMOTE_CLOSED; + return gdb_error(connection, retval); } if (!reg_list[reg_num]->valid) { @@ -2635,6 +2635,7 @@ static int gdb_query_packet(struct connection *connection, cmd = malloc((packet_size - 6) / 2 + 1); size_t len = unhexify((uint8_t *)cmd, packet + 6, (packet_size - 6) / 2); cmd[len] = 0; + LOG_DEBUG("qRcmd: %s", cmd); /* We want to print all debug output to GDB connection */ log_add_callback(gdb_log_callback, connection); diff --git a/src/server/server.h b/src/server/server.h index 99f5fe2ed..4ae6e95d4 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -30,6 +30,7 @@ #endif #include +#include #ifdef HAVE_NETINET_IN_H #include diff --git a/src/svf/svf.c b/src/svf/svf.c index 608703434..f35c61314 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -31,6 +31,7 @@ #include #include "svf.h" +#include "helper/system.h" #include /* SVF command */ diff --git a/src/target/algorithm.h b/src/target/algorithm.h index 8894241c0..0fc49d069 100644 --- a/src/target/algorithm.h +++ b/src/target/algorithm.h @@ -19,6 +19,9 @@ #ifndef OPENOCD_TARGET_ALGORITHM_H #define OPENOCD_TARGET_ALGORITHM_H +#include "helper/types.h" +#include "helper/replacements.h" + enum param_direction { PARAM_IN, PARAM_OUT, diff --git a/src/target/armv4_5_cache.h b/src/target/armv4_5_cache.h index 768938fd1..985a3a770 100644 --- a/src/target/armv4_5_cache.h +++ b/src/target/armv4_5_cache.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_ARMV4_5_CACHE_H #define OPENOCD_TARGET_ARMV4_5_CACHE_H +#include "helper/types.h" + struct command_invocation; struct armv4_5_cachesize { diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index 20faf4e6c..8c247f7a9 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -21,6 +21,8 @@ #include +#include "helper/types.h" + struct target; enum breakpoint_type { diff --git a/src/target/image.h b/src/target/image.h index 53c27d812..59b650855 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -26,6 +26,7 @@ #define OPENOCD_TARGET_IMAGE_H #include +#include #ifdef HAVE_ELF_H #include diff --git a/src/target/nds32_edm.h b/src/target/nds32_edm.h index 1dec190f1..2b5067a34 100644 --- a/src/target/nds32_edm.h +++ b/src/target/nds32_edm.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_NDS32_EDM_H #define OPENOCD_TARGET_NDS32_EDM_H +#include "helper/types.h" + /** * @file * This is the interface to the Embedded Debug Module for Andes cores. diff --git a/src/target/register.h b/src/target/register.h index 5f1c25fb4..a7705f76e 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -22,6 +22,9 @@ #ifndef OPENOCD_TARGET_REGISTER_H #define OPENOCD_TARGET_REGISTER_H +#include "helper/replacements.h" +#include "helper/types.h" + struct target; enum reg_type { diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h index 8fb5e0c3a..b83464ed5 100644 --- a/src/target/semihosting_common.h +++ b/src/target/semihosting_common.h @@ -25,6 +25,7 @@ #include #include #include +#include "helper/replacements.h" /* * According to: diff --git a/src/target/target.h b/src/target/target.h index f6044c5b9..93896906a 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -32,6 +32,8 @@ #define OPENOCD_TARGET_TARGET_H #include +#include "helper/replacements.h" +#include "helper/system.h" #include struct reg; diff --git a/src/target/trace.h b/src/target/trace.h index 2966bbd94..45308c0d8 100644 --- a/src/target/trace.h +++ b/src/target/trace.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_TRACE_H #define OPENOCD_TARGET_TRACE_H +#include "helper/types.h" + struct target; struct command_context; diff --git a/src/transport/transport.c b/src/transport/transport.c index cb000ab11..ba1f9e9f7 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -42,6 +42,7 @@ */ #include +#include #include extern struct command_context *global_cmd_ctx; diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index eaa5a3aae..2a7b56dbf 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -39,6 +39,7 @@ #endif #include "xsvf.h" +#include "helper/system.h" #include #include