diff options
author | Zack Weinberg <zackw@panix.com> | 2020-12-14 18:13:44 -0500 |
---|---|---|
committer | Zack Weinberg <zackw@panix.com> | 2020-12-31 17:01:35 -0500 |
commit | 3436c6a94b8d565bf236bb916ebd3ade28834496 (patch) | |
tree | fa51a2c9e57f45aee0b42fa5368cca48e9c823be /build-aux | |
parent | 941a32bb879d5228246bdb162c9fb44788c8387a (diff) | |
download | libxcrypt-3436c6a94b8d565bf236bb916ebd3ade28834496.tar.gz libxcrypt-3436c6a94b8d565bf236bb916ebd3ade28834496.tar.bz2 libxcrypt-3436c6a94b8d565bf236bb916ebd3ade28834496.zip |
Move most scripts to top-level build-aux directory.
Since we might not want to keep the build scripts as a combination of
sh + awk forever, move most of them to a new top-level directory and
rename them without any .sh or .awk suffixes. This directory is named
build-aux, consistent with the recommendations in the autoconf manual,
and all of the .m4 files extending autoconf move there as well.
The shell scripts in test/ remain there, so that all of the tests stay
together, and they keep their .sh suffix, because this is how Automake
knows that they are not C programs.
Diffstat (limited to 'build-aux')
24 files changed, 2433 insertions, 0 deletions
diff --git a/build-aux/ax_append_compile_flags.m4 b/build-aux/ax_append_compile_flags.m4 new file mode 100644 index 0000000..9c85635 --- /dev/null +++ b/build-aux/ax_append_compile_flags.m4 @@ -0,0 +1,46 @@ +# ============================================================================ +# https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# For every FLAG1, FLAG2 it is checked whether the compiler works with the +# flag. If it does, the flag is added FLAGS-VARIABLE +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. During the check the flag is always added to the +# current language's flags. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: This macro depends on the AX_APPEND_FLAG and +# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with +# AX_APPEND_LINK_FLAGS. +# +# LICENSE +# +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +AC_DEFUN([AX_APPEND_COMPILE_FLAGS], +[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) +for flag in $1; do + AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) +done +])dnl AX_APPEND_COMPILE_FLAGS diff --git a/build-aux/ax_append_flag.m4 b/build-aux/ax_append_flag.m4 new file mode 100644 index 0000000..dd6d8b6 --- /dev/null +++ b/build-aux/ax_append_flag.m4 @@ -0,0 +1,50 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) +# +# DESCRIPTION +# +# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space +# added in between. +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains +# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly +# FLAG. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AC_DEFUN([AX_APPEND_FLAG], +[dnl +AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) +AS_VAR_SET_IF(FLAGS,[ + AS_CASE([" AS_VAR_GET(FLAGS) "], + [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], + [ + AS_VAR_APPEND(FLAGS,[" $1"]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) + ], + [ + AS_VAR_SET(FLAGS,[$1]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) +AS_VAR_POPDEF([FLAGS])dnl +])dnl AX_APPEND_FLAG diff --git a/build-aux/ax_check_compile_flag.m4 b/build-aux/ax_check_compile_flag.m4 new file mode 100644 index 0000000..bd753b3 --- /dev/null +++ b/build-aux/ax_check_compile_flag.m4 @@ -0,0 +1,53 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> +# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/build-aux/ax_check_vscript.m4 b/build-aux/ax_check_vscript.m4 new file mode 100644 index 0000000..9851f32 --- /dev/null +++ b/build-aux/ax_check_vscript.m4 @@ -0,0 +1,142 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_vscript.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_VSCRIPT +# +# DESCRIPTION +# +# Check whether the linker supports version scripts. Version scripts are +# used when building shared libraries to bind symbols to version nodes +# (helping to detect incompatibilities) or to limit the visibility of +# non-public symbols. +# +# Output: +# +# If version scripts are supported, VSCRIPT_LDFLAGS will contain the +# appropriate flag to pass to the linker. On GNU systems this would +# typically be "-Wl,--version-script", and on Solaris it would typically +# be "-Wl,-M". +# +# Two Automake conditionals are also set: +# +# HAVE_VSCRIPT is true if the linker supports version scripts with +# entries that use simple wildcards, like "local: *". +# +# HAVE_VSCRIPT_COMPLEX is true if the linker supports version scripts with +# pattern matching wildcards, like "global: Java_*". +# +# On systems that do not support symbol versioning, such as Mac OS X, both +# conditionals will be false. They will also be false if the user passes +# "--disable-symvers" on the configure command line. +# +# Example: +# +# configure.ac: +# +# AX_CHECK_VSCRIPT +# +# Makefile.am: +# +# if HAVE_VSCRIPT +# libfoo_la_LDFLAGS += $(VSCRIPT_LDFLAGS),@srcdir@/libfoo.map +# endif +# +# if HAVE_VSCRIPT_COMPLEX +# libbar_la_LDFLAGS += $(VSCRIPT_LDFLAGS),@srcdir@/libbar.map +# endif +# +# LICENSE +# +# Copyright (c) 2014 Kevin Cernekee <cernekee@gmail.com> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +# _AX_CHECK_VSCRIPT(flag, global-sym, action-if-link-succeeds, [junk-file=no]) +AC_DEFUN([_AX_CHECK_VSCRIPT], [ + AC_LANG_PUSH([C]) + ax_check_vscript_save_flags="$LDFLAGS" + echo "V1 { global: $2; local: *; };" > conftest.map + AS_IF([test x$4 = xyes], [ + echo "{" >> conftest.map + ]) + LDFLAGS="$LDFLAGS -Wl,$1,conftest.map" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[int show, hide;]], [])], [$3]) + LDFLAGS="$ax_check_vscript_save_flags" + rm -f conftest.map + AC_LANG_POP([C]) +]) dnl _AX_CHECK_VSCRIPT + +AC_DEFUN([AX_CHECK_VSCRIPT], [ + + AC_ARG_ENABLE([symvers], + AS_HELP_STRING([--disable-symvers], + [disable library symbol versioning [default=auto]]), + [want_symvers=$enableval], + [want_symvers=yes] + ) + + AS_IF([test x$want_symvers = xyes], [ + + dnl First test --version-script and -M with a simple wildcard. + + AC_CACHE_CHECK([linker version script flag], ax_cv_check_vscript_flag, [ + ax_cv_check_vscript_flag=unsupported + _AX_CHECK_VSCRIPT([--version-script], [show], [ + ax_cv_check_vscript_flag=--version-script + ]) + AS_IF([test x$ax_cv_check_vscript_flag = xunsupported], [ + _AX_CHECK_VSCRIPT([-M], [show], [ax_cv_check_vscript_flag=-M]) + ]) + + dnl The linker may interpret -M (no argument) as "produce a load map." + dnl If "-M conftest.map" doesn't fail when conftest.map contains + dnl obvious syntax errors, assume this is the case. + + AS_IF([test x$ax_cv_check_vscript_flag != xunsupported], [ + _AX_CHECK_VSCRIPT([$ax_cv_check_vscript_flag], [show], + [ax_cv_check_vscript_flag=unsupported], [yes]) + ]) + ]) + + dnl If the simple wildcard worked, retest with a complex wildcard. + + AS_IF([test x$ax_cv_check_vscript_flag != xunsupported], [ + ax_check_vscript_flag=$ax_cv_check_vscript_flag + AC_CACHE_CHECK([if version scripts can use complex wildcards], + ax_cv_check_vscript_complex_wildcards, [ + ax_cv_check_vscript_complex_wildcards=no + _AX_CHECK_VSCRIPT([$ax_cv_check_vscript_flag], [sh*], [ + ax_cv_check_vscript_complex_wildcards=yes]) + ]) + ax_check_vscript_complex_wildcards="$ax_cv_check_vscript_complex_wildcards" + ], [ + ax_check_vscript_flag= + ax_check_vscript_complex_wildcards=no + ]) + ], [ + AC_MSG_CHECKING([linker version script flag]) + AC_MSG_RESULT([disabled]) + + ax_check_vscript_flag= + ax_check_vscript_complex_wildcards=no + ]) + + AS_IF([test x$ax_check_vscript_flag != x], [ + VSCRIPT_LDFLAGS="-Wl,$ax_check_vscript_flag" + AC_SUBST([VSCRIPT_LDFLAGS]) + ]) + + AM_CONDITIONAL([HAVE_VSCRIPT], + [test x$ax_check_vscript_flag != x]) + AM_CONDITIONAL([HAVE_VSCRIPT_COMPLEX], + [test x$ax_check_vscript_complex_wildcards = xyes]) + +]) dnl AX_CHECK_VSCRIPT diff --git a/build-aux/ax_require_defined.m4 b/build-aux/ax_require_defined.m4 new file mode 100644 index 0000000..17c3eab --- /dev/null +++ b/build-aux/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/build-aux/ax_valgrind_check.m4 b/build-aux/ax_valgrind_check.m4 new file mode 100644 index 0000000..b2297e1 --- /dev/null +++ b/build-aux/ax_valgrind_check.m4 @@ -0,0 +1,239 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_VALGRIND_DFLT(memcheck|helgrind|drd|sgcheck, on|off) +# AX_VALGRIND_CHECK() +# +# DESCRIPTION +# +# AX_VALGRIND_CHECK checks whether Valgrind is present and, if so, allows +# running `make check` under a variety of Valgrind tools to check for +# memory and threading errors. +# +# Defines VALGRIND_CHECK_RULES which should be substituted in your +# Makefile; and $enable_valgrind which can be used in subsequent configure +# output. VALGRIND_ENABLED is defined and substituted, and corresponds to +# the value of the --enable-valgrind option, which defaults to being +# enabled if Valgrind is installed and disabled otherwise. Individual +# Valgrind tools can be disabled via --disable-valgrind-<tool>, the +# default is configurable via the AX_VALGRIND_DFLT command or is to use +# all commands not disabled via AX_VALGRIND_DFLT. All AX_VALGRIND_DFLT +# calls must be made before the call to AX_VALGRIND_CHECK. +# +# If unit tests are written using a shell script and automake's +# LOG_COMPILER system, the $(VALGRIND) variable can be used within the +# shell scripts to enable Valgrind, as described here: +# +# https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html +# +# Usage example: +# +# configure.ac: +# +# AX_VALGRIND_DFLT([sgcheck], [off]) +# AX_VALGRIND_CHECK +# +# in each Makefile.am with tests: +# +# @VALGRIND_CHECK_RULES@ +# VALGRIND_SUPPRESSIONS_FILES = my-project.supp +# EXTRA_DIST = my-project.supp +# +# This results in a "check-valgrind" rule being added. Running `make +# check-valgrind` in that directory will recursively run the module's test +# suite (`make check`) once for each of the available Valgrind tools (out +# of memcheck, helgrind and drd) while the sgcheck will be skipped unless +# enabled again on the commandline with --enable-valgrind-sgcheck. The +# results for each check will be output to test-suite-$toolname.log. The +# target will succeed if there are zero errors and fail otherwise. +# +# Alternatively, a "check-valgrind-$TOOL" rule will be added, for $TOOL in +# memcheck, helgrind, drd and sgcheck. These are useful because often only +# some of those tools can be ran cleanly on a codebase. +# +# The macro supports running with and without libtool. +# +# LICENSE +# +# Copyright (c) 2014, 2015, 2016 Philip Withnall <philip.withnall@collabora.co.uk> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 17 + +dnl Configured tools +m4_define([valgrind_tool_list], [[memcheck], [helgrind], [drd], [sgcheck]]) +m4_set_add_all([valgrind_exp_tool_set], [sgcheck]) +m4_foreach([vgtool], [valgrind_tool_list], + [m4_define([en_dflt_valgrind_]vgtool, [on])]) + +AC_DEFUN([AX_VALGRIND_DFLT],[ + m4_define([en_dflt_valgrind_$1], [$2]) +])dnl + +AM_EXTRA_RECURSIVE_TARGETS([check-valgrind]) +m4_foreach([vgtool], [valgrind_tool_list], + [AM_EXTRA_RECURSIVE_TARGETS([check-valgrind-]vgtool)]) + +AC_DEFUN([AX_VALGRIND_CHECK],[ + dnl Check for --enable-valgrind + AC_ARG_ENABLE([valgrind], + [AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])], + [enable_valgrind=$enableval],[enable_valgrind=]) + + AS_IF([test "$enable_valgrind" != "no"],[ + # Check for Valgrind. + AC_PATH_PROG([VALGRIND],[valgrind]) + AS_IF([test "$VALGRIND" = ""],[ + AS_IF([test "$enable_valgrind" = "yes"],[ + AC_MSG_ERROR([Could not find valgrind; either install it or reconfigure with --disable-valgrind]) + ],[ + enable_valgrind=no + ]) + ],[ + enable_valgrind=yes + ]) + ]) + + AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"]) + AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind]) + + # Check for Valgrind tools we care about. + [valgrind_enabled_tools=] + m4_foreach([vgtool],[valgrind_tool_list],[ + AC_ARG_ENABLE([valgrind-]vgtool, + m4_if(m4_defn([en_dflt_valgrind_]vgtool),[off],dnl +[AS_HELP_STRING([--enable-valgrind-]vgtool, [Whether to use ]vgtool[ during the Valgrind tests])],dnl +[AS_HELP_STRING([--disable-valgrind-]vgtool, [Whether to skip ]vgtool[ during the Valgrind tests])]), + [enable_valgrind_]vgtool[=$enableval], + [enable_valgrind_]vgtool[=]) + AS_IF([test "$enable_valgrind" = "no"],[ + enable_valgrind_]vgtool[=no], + [test "$enable_valgrind_]vgtool[" ]dnl +m4_if(m4_defn([en_dflt_valgrind_]vgtool), [off], [= "yes"], [!= "no"]),[ + AC_CACHE_CHECK([for Valgrind tool ]vgtool, + [ax_cv_valgrind_tool_]vgtool,[ + ax_cv_valgrind_tool_]vgtool[=no + m4_set_contains([valgrind_exp_tool_set],vgtool, + [m4_define([vgtoolx],[exp-]vgtool)], + [m4_define([vgtoolx],vgtool)]) + AS_IF([`$VALGRIND --tool=]vgtoolx[ --help >/dev/null 2>&1`],[ + ax_cv_valgrind_tool_]vgtool[=yes + ]) + ]) + AS_IF([test "$ax_cv_valgrind_tool_]vgtool[" = "no"],[ + AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ + AC_MSG_ERROR([Valgrind does not support ]vgtool[; reconfigure with --disable-valgrind-]vgtool) + ],[ + enable_valgrind_]vgtool[=no + ]) + ],[ + enable_valgrind_]vgtool[=yes + ]) + ]) + AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ + valgrind_enabled_tools="$valgrind_enabled_tools ]m4_bpatsubst(vgtool,[^exp-])[" + ]) + AC_SUBST([ENABLE_VALGRIND_]vgtool,[$enable_valgrind_]vgtool) + ]) + AC_SUBST([valgrind_tools],["]m4_join([ ], valgrind_tool_list)["]) + AC_SUBST([valgrind_enabled_tools],[$valgrind_enabled_tools]) + +[VALGRIND_CHECK_RULES=' +# Valgrind check +# +# Optional: +# - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions +# files to load. (Default: empty) +# - VALGRIND_FLAGS: General flags to pass to all Valgrind tools. +# (Default: --num-callers=30) +# - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of: +# memcheck, helgrind, drd, sgcheck). (Default: various) + +# Optional variables +VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES)) +VALGRIND_FLAGS ?= --num-callers=30 +VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no +VALGRIND_helgrind_FLAGS ?= --history-level=approx +VALGRIND_drd_FLAGS ?= +VALGRIND_sgcheck_FLAGS ?= + +# Internal use +valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools))) + +valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS) +valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS) +valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS) +valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS) + +valgrind_quiet = $(valgrind_quiet_$(V)) +valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY)) +valgrind_quiet_0 = --quiet +valgrind_v_use = $(valgrind_v_use_$(V)) +valgrind_v_use_ = $(valgrind_v_use_$(AM_DEFAULT_VERBOSITY)) +valgrind_v_use_0 = @echo " USE " $(patsubst check-valgrind-%-am,%,$''@):; + +# Support running with and without libtool. +ifneq ($(LIBTOOL),) +valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute +else +valgrind_lt = +endif + +# Use recursive makes in order to ignore errors during check +check-valgrind-am: +ifeq ($(VALGRIND_ENABLED),yes) + $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k \ + $(foreach tool, $(valgrind_enabled_tools), check-valgrind-$(tool)) +else + @echo "Need to reconfigure with --enable-valgrind" +endif + +# Valgrind running +VALGRIND_TESTS_ENVIRONMENT = \ + $(TESTS_ENVIRONMENT) \ + env VALGRIND=$(VALGRIND) \ + G_SLICE=always-malloc,debug-blocks \ + G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly + +VALGRIND_LOG_COMPILER = \ + $(valgrind_lt) \ + $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) + +define valgrind_tool_rule +check-valgrind-$(1)-am: +ifeq ($$(VALGRIND_ENABLED)-$$(ENABLE_VALGRIND_$(1)),yes-yes) +ifneq ($$(TESTS),) + $$(valgrind_v_use)$$(MAKE) check-TESTS \ + TESTS_ENVIRONMENT="$$(VALGRIND_TESTS_ENVIRONMENT)" \ + LOG_COMPILER="$$(VALGRIND_LOG_COMPILER)" \ + LOG_FLAGS="$$(valgrind_$(1)_flags)" \ + TEST_SUITE_LOG=test-suite-$(1).log +endif +else ifeq ($$(VALGRIND_ENABLED),yes) + @echo "Need to reconfigure with --enable-valgrind-$(1)" +else + @echo "Need to reconfigure with --enable-valgrind" +endif +endef + +$(foreach tool,$(valgrind_tools),$(eval $(call valgrind_tool_rule,$(tool)))) + +A''M_DISTCHECK_CONFIGURE_FLAGS ?= +A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind + +MOSTLYCLEANFILES ?= +MOSTLYCLEANFILES += $(valgrind_log_files) + +.PHONY: check-valgrind $(add-prefix check-valgrind-,$(valgrind_tools)) +'] + + AC_SUBST([VALGRIND_CHECK_RULES]) + m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([VALGRIND_CHECK_RULES])]) +]) diff --git a/build-aux/clang-gcov-wrapper b/build-aux/clang-gcov-wrapper new file mode 100755 index 0000000..4e320d8 --- /dev/null +++ b/build-aux/clang-gcov-wrapper @@ -0,0 +1,2 @@ +#!/bin/bash +exec llvm-cov gcov "$@" diff --git a/build-aux/expand-selected-hashes b/build-aux/expand-selected-hashes new file mode 100644 index 0000000..da6cfd7 --- /dev/null +++ b/build-aux/expand-selected-hashes @@ -0,0 +1,136 @@ +# Expand a list of selected hashes to a list of enabled hashes, using +# the information in hashes.conf. +# +# Copyright 2018 Zack Weinberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see +# <https://www.gnu.org/licenses/>. + +BEGIN { + enable_all = 0 + enable_strong = 0 + enable_glibc = 0 + enable_alt = 0 + enable_fedora = 0 + enable_freebsd = 0 + enable_netbsd = 0 + enable_openbsd = 0 + enable_osx = 0 + enable_owl = 0 + enable_solaris = 0 + enable_suse = 0 + error = 0 + split(SELECTED_HASHES, selected_hashes_list, ",") + for (i in selected_hashes_list) { + h = selected_hashes_list[i] + if (h == "all") { + enable_all = 1 + } else if (h == "strong") { + enable_strong = 1 + } else if (h == "glibc") { + enable_glibc = 1 + } else if (h == "alt") { + enable_alt = 1 + } else if (h == "fedora") { + enable_fedora = 1 + } else if (h == "freebsd") { + enable_freebsd = 1 + } else if (h == "netbsd") { + enable_netbsd = 1 + } else if (h == "openbsd") { + enable_openbsd = 1 + } else if (h == "osx") { + enable_osx = 1 + } else if (h == "owl") { + enable_owl = 1 + } else if (h == "solaris") { + enable_solaris = 1 + } else if (h == "suse") { + enable_suse = 1 + } else { + enable_some = 1 + selected_hashes[h] = 1 + } + } + if (enable_all && (enable_strong || enable_glibc || enable_some || \ + enable_alt || enable_fedora || enable_freebsd || \ + enable_netbsd || enable_openbsd || enable_osx || \ + enable_owl || enable_solaris || enable_suse)) { + error = 1 + exit 1 + } +} + +/^#/ { + next +} + +{ + if (enable_all || $1 in selected_hashes) { + enabled_hashes[$1] = 1 + } else { + enabled_hashes[$1] = 0 + + split($4, flags, ",") + for (i in flags) { + flag = flags[i] + if (flag == "STRONG" && enable_strong) { + enabled_hashes[$1] = 1 + } else if (flag == "GLIBC" && enable_glibc) { + enabled_hashes[$1] = 1 + } else if (flag == "ALT" && enable_alt) { + enabled_hashes[$1] = 1 + } else if (flag == "FEDORA" && enable_fedora) { + enabled_hashes[$1] = 1 + } else if (flag == "FREEBSD" && enable_freebsd) { + enabled_hashes[$1] = 1 + } else if (flag == "NETBSD" && enable_netbsd) { + enabled_hashes[$1] = 1 + } else if (flag == "OPENBSD" && enable_openbsd) { + enabled_hashes[$1] = 1 + } else if (flag == "OSX" && enable_osx) { + enabled_hashes[$1] = 1 + } else if (flag == "OWL" && enable_owl) { + enabled_hashes[$1] = 1 + } else if (flag == "SOLARIS" && enable_solaris) { + enabled_hashes[$1] = 1 + } else if (flag == "SUSE" && enable_suse) { + enabled_hashes[$1] = 1 + } + } + } +} + + +END { + if (error) { + exit 1 + } + + # Check for individual selected hashes that didn't appear in + # hashes.conf. + for (h in selected_hashes) { + if (!(h in enabled_hashes)) { + exit 1 + } + } + + enabled_hash_list = "," + for (i in enabled_hashes) { + if (enabled_hashes[i]) { + enabled_hash_list = enabled_hash_list i "," + } + } + print enabled_hash_list +} diff --git a/build-aux/gen-crypt-h b/build-aux/gen-crypt-h new file mode 100644 index 0000000..d7ca1a2 --- /dev/null +++ b/build-aux/gen-crypt-h @@ -0,0 +1,62 @@ +# Generation of crypt.h from crypt.h.in and config.h. +# +# Written by Zack Weinberg <zackw at panix.com> in 2017. +# To the extent possible under law, Zack Weinberg has waived all +# copyright and related or neighboring rights to this work. +# +# See https://creativecommons.org/publicdomain/zero/1.0/ for further +# details. + +BEGIN { + HAVE_SYS_CDEFS_H = 0 + HAVE_SYS_CDEFS_BEGIN_END_DECLS = 0 + HAVE_SYS_CDEFS_THROW = 0 +} +END { + if (!HAVE_SYS_CDEFS_H && + (HAVE_SYS_CDEFS_BEGIN_END_DECLS || + HAVE_SYS_CDEFS_THROW)) { + print "config.h is inconsistent" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } +} +FILENAME ~ /config\.h$/ { + if ($0 ~ /^#define HAVE_SYS_CDEFS_H 1$/) { + HAVE_SYS_CDEFS_H = 1 + } else if ($0 ~ /^#define HAVE_SYS_CDEFS_BEGIN_END_DECLS 1$/) { + HAVE_SYS_CDEFS_BEGIN_END_DECLS = 1 + } else if ($0 ~ /^#define HAVE_SYS_CDEFS_THROW 1$/) { + HAVE_SYS_CDEFS_THROW = 1 + } +} +FILENAME !~ /config\.h$/ { + if ($0 ~ /^\/\*HEADER\*\/$/) { + if (HAVE_SYS_CDEFS_H) { + print "#include <sys/cdefs.h>" + } + if (!HAVE_SYS_CDEFS_THROW) { + print "#define __THROW /* nothing */" + } + print "" + if (HAVE_SYS_CDEFS_BEGIN_END_DECLS) { + print "__BEGIN_DECLS" + } else { + print "#ifdef __cplusplus" + print "extern \"C\" {" + print "#endif" + } + + } else if ($0 ~ /^\/\*TRAILER\*\/$/) { + if (HAVE_SYS_CDEFS_BEGIN_END_DECLS) { + print "__END_DECLS" + } else { + print "#ifdef __cplusplus" + print "} /* extern \"C\" */" + print "#endif" + } + + } else { + print; + } +} diff --git a/build-aux/gen-crypt-hashes-h b/build-aux/gen-crypt-hashes-h new file mode 100644 index 0000000..d042456 --- /dev/null +++ b/build-aux/gen-crypt-hashes-h @@ -0,0 +1,172 @@ +# Generate crypt-hashes.h from hashes.conf and configure settings. +# +# Copyright 2018 Zack Weinberg +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see +# <https://www.gnu.org/licenses/>. + +BEGIN { + next_output = 0 + error = 0 + default_prefix = "" + + # ENABLED_HASHES is set on the command line. + split(ENABLED_HASHES, enabled_hashes_list, ",") + for (i in enabled_hashes_list) { + h = enabled_hashes_list[i] + if (h != "") { + hash_enabled[h] = 1 + } + } +} + +/^#/ { + next +} + +{ + if ($1 == ":") { + printf("%s:%d: error: method name cannot be blank\n", FILENAME, NR) \ + > "/dev/stderr" + error = 1 + } + # No two hashing method names can be the same. + if ($1 in line_index) { + printf("%s:%d: error: method name '%s' reused\n", FILENAME, NR, $1); + printf("%s: note: previous use was here\n", line_index[$1]); + error = 1 + } else { + line_index[$1] = sprintf("%s:%d", FILENAME, NR); + if (!($1 in hash_enabled)) { + hash_enabled[$1] = 0 + } + default_cand[$1] = "" + output_order[next_output++] = $1 + } + if ($2 == ":") $2 = "" + prefixes[$1] = $2 + if ($3 !~ /^[0-9]+$/ || $3 == 0) { + printf("%s:%d: nrbytes must be a positive integer\n", FILENAME, NR) \ + > "/dev/stderr" + error = 1 + } + + crypt_fn = "crypt_" $1 "_rn" + gensalt_fn = "gensalt_" $1 "_rn" + + renames[$1] = \ + "#define " crypt_fn " _crypt_" crypt_fn "\n" \ + "#define " gensalt_fn " _crypt_" gensalt_fn "\n" + prototypes[$1] = \ + "extern void " crypt_fn " (const char *, size_t, const char *,\n" \ + " size_t, uint8_t *, size_t, void *, size_t);\n" \ + "extern void " gensalt_fn " (unsigned long,\n" \ + " const uint8_t *, size_t, uint8_t *, size_t);\n" + + table_entry[$1] = sprintf(" { \"%s\", %d, %s, %s, %d }, \\", + $2, length($2), crypt_fn, gensalt_fn, $3) + + if ($4 == ":") $4 = "" + split($4, flags, ",") + for (i in flags) { + flag = flags[i] + if (flag == "DEFAULT") { + default_cand[$1] = $2 + } else if (flag == "STRONG" || flag == "GLIBC" || \ + flag == "ALT" || flag == "FEDORA" || \ + flag == "FREEBSD" || flag == "NETBSD" || \ + flag == "OPENBSD" || flag == "OSX" || \ + flag == "OWL" || flag == "SOLARIS" || \ + flag == "SUSE") { + # handled in expand-selected-hashes + } else { + printf("%s:%d: unrecognized flag %s\n", FILENAME, NR, flag) \ + > "/dev/stderr" + error = 1 + } + } +} + + +END { + # No hash prefix can be a prefix of any other hash prefix, except + # for the empty prefix. + for (i in prefixes) { + a = prefixes[i] + if (a == "") { continue } + for (j in prefixes) { + if (i == j) { continue } + b = prefixes[j] + if (b == "") { continue } + if (substr(b, 1, length(a)) == a) { + printf("%s: error: prefix collision: '%s' begins with '%s'\n", + line_index[j], b, a) > "/dev/stderr" + printf("%s: note: '%s' is used here\n", line_index[i], a) \ + > "/dev/stderr" + error = 1 + } + } + } + + if (error) { + exit 1 + } + + print "/* Generated by gen-crypt-hashes-h from hashes.conf. DO NOT EDIT. */" + print "" + print "#ifndef _CRYPT_HASHES_H" + print "#define _CRYPT_HASHES_H 1" + + print "" + for (i = 0; i < next_output; ++i) { + hash = output_order[i] + printf("#define INCLUDE_%-13s %d\n", hash, hash_enabled[hash]) + if (hash_enabled[hash] && default_cand[hash] != "" && default_prefix == "") { + default_prefix = default_cand[hash] + } + } + + print "" + print "/* Internal symbol renames for static linkage, see crypt-port.h. */" + for (i = 0; i < next_output; ++i) { + hash = output_order[i] + if (hash_enabled[hash]) { + print renames[hash] + } + } + + print "/* Prototypes for hash algorithm entry points. */" + for (i = 0; i < next_output; ++i) { + hash = output_order[i] + if (hash_enabled[hash]) { + print prototypes[hash] + } + } + + print "#define HASH_ALGORITHM_TABLE_ENTRIES \\" + for (i = 0; i < next_output; ++i) { + hash = output_order[i] + if (hash_enabled[hash]) { + print table_entry[hash] + } + } + print " { 0, 0, 0, 0, 0 }" + + print "" + if (default_prefix != "") { + print "#define HASH_ALGORITHM_DEFAULT \"" default_prefix "\"" + print "" + } + print "#endif /* crypt-hashes.h */" +} diff --git a/build-aux/gen-crypt-symbol-vers-h b/build-aux/gen-crypt-symbol-vers-h new file mode 100644 index 0000000..5cc046d --- /dev/null +++ b/build-aux/gen-crypt-symbol-vers-h @@ -0,0 +1,211 @@ +# Generate macros that control the symbol versions of the public +# library API, from a .map.in file. +# +# Written by Zack Weinberg <zackw at panix.com> in 2017. +# To the extent possible under law, Zack Weinberg has waived all +# copyright and related or neighboring rights to this work. +# +# See https://creativecommons.org/publicdomain/zero/1.0/ for further +# details. + +# The .map.in file is the first input file, and we expect the Makefile +# to have set the variables SYMVER_MIN, SYMVER_FLOOR, and COMPAT_ABI. +# See libcrypt.map.in and gen-libcrypt-map for explanations of the format +# of .map.in files. See crypt-port.h for an explanation of how to use +# the macros generated by this program. +# +# Note: if you change the format of .map.in files you probably need to +# update gen-libcrypt-map too. +# +# Note: we currently don't support compatibility symbols that need +# a different definition from the default version. + +BEGIN { + split("", SYMBOLS) # ensure SYMBOLS is an array + split("", VCHAIN) # ditto VCHAIN + NVCHAIN = 0 + + # This arranges for sorted output if gawk is in use, and is + # harmless otherwise. + PROCINFO["sorted_in"] = "@ind_str_asc" +} + +NF == 0 { next } # blank line, discard +$1 == "#" { next } # comment, discard +$1 == "%chain" { + for (i = 2; i <= NF; i++) { + VCHAIN[++NVCHAIN] = $i + } + next +} + +{ + if ($2 == "-") { + compat_only[$1] = 1 + } else { + compat_only[$1] = 0 + if ($2 in SYMBOLS) { + SYMBOLS[$2] = SYMBOLS[$2] SUBSEP $1 + } else { + SYMBOLS[$2] = $1 + } + } + for (i = 3; i <= NF; i++) { + sym=$i + n=split(sym, a, ":") + if (n > 1) { + sym="" + for (j = 2; j <= n; j++) { + if (COMPAT_ABI == "yes" || COMPAT_ABI == a[j]) { + sym=a[1] + } + } + } + if (sym != "") { + if (sym in SYMBOLS) { + SYMBOLS[sym] = SYMBOLS[sym] SUBSEP $1 + } else { + SYMBOLS[sym] = $1 + } + } + } +} + +END { + if (NVCHAIN == 0) { + print ARGV[1] ": error: missing %chain directive" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + symver_min_idx = 0 + symver_floor_idx = 0 + for (i = 1; i <= NVCHAIN; i++) { + if (VCHAIN[i] == SYMVER_MIN) { + symver_min_idx = i + } + if (VCHAIN[i] == SYMVER_FLOOR) { + symver_floor_idx = i + } + } + if (symver_min_idx == 0) { + print ARGV[1] ": error: SYMVER_MIN (" SYMVER_MIN ") " \ + "not found in %chain directives" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + if (symver_floor_idx == 0) { + print ARGV[1] ": error: SYMVER_FLOOR (" SYMVER_FLOOR ") " \ + "not found in %chain directives" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + if (symver_floor_idx < symver_min_idx) { + print ARGV[1] ": error: SYMVER_FLOOR (" SYMVER_FLOOR ") " \ + "is lower than SYMVER_MIN (" SYMVER_MIN ")" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + + # Construct a pruned set of symbols and versions, including only + # versions with symbols, discarding all symbols associated with + # versions below SYMVER_MIN, raising symbols below SYMVER_FLOOR to + # SYMVER_FLOOR, and removing duplicates. + # Note: unlike in gen-libcrypt-map, symbols all of whose versions are + # below SYMVER_MIN must still be counted in 'allsyms' so their + # INCLUDE macros are generated. + for (i = 1; i <= NVCHAIN; i++) { + v = VCHAIN[i] + if (v in SYMBOLS) { + nsyms = split(SYMBOLS[v], syms, SUBSEP) + j = i; + if (j < symver_floor_idx) + j = symver_floor_idx; + vr = VCHAIN[j] + for (s = 1; s <= nsyms; s++) { + if (syms[s]) { + allsyms[syms[s]] = 1 + if (i >= symver_min_idx) { + symset[vr, syms[s]] = 1 + } + } + } + } + } + + print "/* Generated from " ARGV[1] " by gen-crypt-symbol-vers-h. DO NOT EDIT. */" + print "" + print "#ifndef _CRYPT_SYMBOL_VERS_H" + print "#define _CRYPT_SYMBOL_VERS_H 1" + + print "" + print "/* For each public symbol <sym>, INCLUDE_<sym> is true if it" + print " has any versions above the backward compatibility minimum." + print " Compatibility-only symbols are not included in the static" + print " library, or in the shared library when configured with" + print " --disable-obsolete-api. */" + print "#if defined PIC && ENABLE_OBSOLETE_API" + print "" + for (sym in allsyms) { + include = 0 + for (i = symver_floor_idx; i <= NVCHAIN; i++) { + if ((VCHAIN[i], sym) in symset) { + include++ + } + } + includesym[sym] = include + printf("#define INCLUDE_%s %d\n", sym, include) + } + print "" + print "#else" + print "" + for (sym in allsyms) { + printf("#define INCLUDE_%s %d\n", sym, + (includesym[sym] && !compat_only[sym])) + } + print "" + print "#endif" + + print "" + print "/* For each public symbol <sym> that is included, define its" + print " highest version as the default, and aliases at each" + print " compatibility version. */" + + for (sym in allsyms) { + if (includesym[sym]) { + seq = 0 + for (i = NVCHAIN; i >= symver_floor_idx; i--) { + v = VCHAIN[i] + if ((v, sym) in symset) { + if (seq == 0) { + if (compat_only[sym] || includesym[sym] > 0) { + printf("#ifdef PIC\n#define %s _crypt_%s\n#endif\n", + sym, sym); + } + printf("#define SYMVER_%s \\\n", sym) + if (compat_only[sym]) { + printf(" symver_compat0 (\"%s\", %s, %s)", sym, sym, v) + } else if (includesym[sym] > 0) { + printf(" symver_default (\"%s\", %s, %s)", sym, sym, v) + } else { + # Due to what appears to be a bug in GNU ld, + # we must not issue symver_default() if there + # aren't going to be any other versions. + printf(" symver_nop ()") + } + } else { + printf("; \\\n symver_compat (%d, \"%s\", %s, %s, %s)", + seq, sym, sym, sym, v) + } + seq++ + } + } + print "" + } else { + printf("#define SYMVER_%s symver_nop()\n", sym) + } + } + + + print "" + print "#endif /* crypt-symbol-vers.h */" +} diff --git a/build-aux/gen-libcrypt-map b/build-aux/gen-libcrypt-map new file mode 100644 index 0000000..e4383b6 --- /dev/null +++ b/build-aux/gen-libcrypt-map @@ -0,0 +1,147 @@ +# Generate a version map file from a .map.in file. +# +# Written by Zack Weinberg <zackw at panix.com> in 2017. +# To the extent possible under law, Zack Weinberg has waived all +# copyright and related or neighboring rights to this work. +# +# See https://creativecommons.org/publicdomain/zero/1.0/ for further +# details. + +# The .map.in file is the first input file, and we expect the Makefile +# to have set the variables SYMVER_MIN, SYMVER_FLOOR, and COMPAT_ABI. +# All compat symbol versions that do not match COMPAT_ABI are ignored. +# All symbol versions lower than SYMVER_MIN are discarded from the output. +# All symbol versions lower than SYMVER_FLOOR are replaced with SYMVER_FLOOR. +# SYMVER_FLOOR must be greater than or equal to SYMVER_MIN. +# +# The ordering of symbol versions is entirely controlled by the %chain +# directive, which must therefore list both all of the versions +# actually used for symbols, and all of the versions that might be +# used as SYMVER_MIN or SYMVER_FLOOR. +# +# Note: if you change the format of .map.in files you probably need to +# update gen-crypt-symbol-vers-h too. + +BEGIN { + split("", SYMBOLS) # ensure SYMBOLS is an array + split("", VCHAIN) # ditto VCHAIN + NVCHAIN = 0 + + # This arranges for sorted output if gawk is in use, and is + # harmless otherwise. + PROCINFO["sorted_in"] = "@ind_str_asc" +} + +NF == 0 { next } # blank line, discard +$1 == "#" { next } # comment, discard +$1 == "%chain" { + for (i = 2; i <= NF; i++) { + VCHAIN[++NVCHAIN] = $i + } + next +} + +{ + for (i = 2; i <= NF; i++) { + sym=$i + if (sym != "-") { + n=split(sym, a, ":") + if (n > 1) { + sym="-" + for (j = 2; j <= n; j++) { + if (COMPAT_ABI == "yes" || COMPAT_ABI == a[j]) { + sym=a[1] + } + } + } + } + if (sym != "-") { + if (sym in SYMBOLS) { + SYMBOLS[sym] = SYMBOLS[sym] SUBSEP $1 + } else { + SYMBOLS[sym] = $1 + } + } + } +} + +END { + if (NVCHAIN == 0) { + print ARGV[1] ": error: missing %chain directive" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + symver_min_idx = 0 + symver_floor_idx = 0 + for (i = 1; i <= NVCHAIN; i++) { + if (VCHAIN[i] == SYMVER_MIN) { + symver_min_idx = i + } + if (VCHAIN[i] == SYMVER_FLOOR) { + symver_floor_idx = i + } + } + if (symver_min_idx == 0) { + print ARGV[1] ": error: SYMVER_MIN (" SYMVER_MIN ") " \ + "not found in %chain directives" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + if (symver_floor_idx == 0) { + print ARGV[1] ": error: SYMVER_FLOOR (" SYMVER_FLOOR ") " \ + "not found in %chain directives" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + if (symver_floor_idx < symver_min_idx) { + print ARGV[1] ": error: SYMVER_FLOOR (" SYMVER_FLOOR ") " \ + "is lower than SYMVER_MIN (" SYMVER_MIN ")" > "/dev/stderr" + close("/dev/stderr") + exit 1 + } + + # Construct a pruned set of symbols and versions, including only + # versions with symbols, discarding all symbols associated with + # versions below SYMVER_MIN, raising symbols below SYMVER_FLOOR to + # SYMVER_FLOOR, and removing duplicates. + for (i = symver_min_idx; i <= NVCHAIN; i++) { + v = VCHAIN[i] + if (v in SYMBOLS) { + nsyms = split(SYMBOLS[v], syms, SUBSEP) + j = i; + if (j < symver_floor_idx) + j = symver_floor_idx; + vr = VCHAIN[j] + for (s = 1; s <= nsyms; s++) { + if (syms[s]) { + symset[vr, syms[s]] = 1 + allsyms[syms[s]] = 1 + } + } + } + } + + vp = "" + for (i = symver_floor_idx; i <= NVCHAIN; i++) { + v = VCHAIN[i] + split("", osyms) + j = 0 + for (sym in allsyms) { + if ((v, sym) in symset) { + osyms[++j] = sym + } + } + if (j > 0) { + printf("%s {\n global:\n", v); + for (s = 1; s <= j; s++) { + printf(" %s;\n", osyms[s]); + } + if (vp == "") { + vp = v + printf(" local:\n *;\n};\n"); + } else { + printf("} %s;\n", vp); + } + } + } +} diff --git a/build-aux/pkg_installdir_compat.m4 b/build-aux/pkg_installdir_compat.m4 new file mode 100644 index 0000000..2bbe156 --- /dev/null +++ b/build-aux/pkg_installdir_compat.m4 @@ -0,0 +1,47 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 11 (pkg-config-0.29.1) + +# Copyright © 2004 Scott James Remnant <scott@netsplit.com>. +# Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. + +# PKG_INSTALLDIR_COMPAT([DIRECTORY]) +# ------------------------- +# Backported from pkg-config 0.27. +# +# Substitutes the variable pkgconfigdir as the location where a module +# should install pkg-config .pc files. By default the directory is +# $libdir/pkgconfig, but the default can be changed by passing +# DIRECTORY. The user can override through the --with-pkgconfigdir +# parameter. +AC_DEFUN([PKG_INSTALLDIR_COMPAT], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +]) diff --git a/build-aux/skip-if-exec-format-error b/build-aux/skip-if-exec-format-error new file mode 100755 index 0000000..901e6bb --- /dev/null +++ b/build-aux/skip-if-exec-format-error @@ -0,0 +1,28 @@ +#! /bin/sh +# Run a test given as "$@" and then munge its exit code to 77 if it +# failed because of an "exec format error." +# +# Written by Zack Weinberg <zackw at panix.com> in 2017. +# To the extent possible under law, Zack Weinberg has waived all +# copyright and related or neighboring rights to this work. +# +# See https://creativecommons.org/publicdomain/zero/1.0/ for further +# details. + +set -u + +tmplog=`mktemp -p "${TMPDIR:-/tmp}" tmplog.XXXXXXXXXX` || exit 99 +trap "rm -f '$tmplog'" 0 + +"$@" > "$tmplog" 2>&1 +status="$?" +cat "$tmplog" || exit 99 + +case "$status" in + 0|77|99) exit "$status";; +esac + +if grep -q '[eE]xec format error' "$tmplog" +then exit 77 +else exit "$status" +fi diff --git a/build-aux/travis-after-success b/build-aux/travis-after-success new file mode 100755 index 0000000..fee3d5d --- /dev/null +++ b/build-aux/travis-after-success @@ -0,0 +1,49 @@ +#! /bin/sh +set -e + +if [ "$PERFORM_COVERITY_SCAN" = 1 ] || [ "$DISTCHECK" = 1 ]; then + exit 0 +fi + +GCOV=gcov + +if [ "$TRAVIS_OS_NAME" = osx ]; then + case "$CC" in + gcc*) + GCC_VER="$( (brew list --versions gcc || echo gcc 0) | + sed 's/^gcc \([0-9]*\)\..*$/\1/' )" + if command -V "gcov-$GCC_VER"; then + GCOV="gcov-$GCC_VER" + fi + ;; + esac + +elif [ "$TRAVIS_OS_NAME" = linux ]; then + if [ "$CC" = clang ]; then + GCOV="$PWD/build-aux/clang-gcov-wrapper" + fi + +fi +export GCOV + +# Log the identities and versions of the coverage tools. +for tool in "$GCOV" lcov codecov +do + # $tool might include mandatory command-line arguments. + # Interpret it the same way Make would. + set fnord $tool + shift + if command -V $1; then + echo + "$@" --version + "$@" --version + fi + echo +done +set fnord; shift # clear $@ + +set -x +lcov --gcov-tool $GCOV --directory . --capture --output-file all_coverage.info +lcov --gcov-tool $GCOV --remove all_coverage.info \ + '/usr/*' '*test*' > coverage.info +rm all_coverage.info +codecov -X gcov diff --git a/build-aux/travis-before b/build-aux/travis-before new file mode 100755 index 0000000..abe48e5 --- /dev/null +++ b/build-aux/travis-before @@ -0,0 +1,28 @@ +#! /bin/sh +set -e + +# Log the identities and versions of the build tools. +for tool in \ + "${CC-cc}" \ + "${AUTOCONF-autoconf}" \ + "${AUTOMAKE-automake}" \ + "${LIBTOOLIZE-libtoolize}" \ + "${PKG_CONFIG-pkg-config}" \ + "${PERL-perl}" \ + "${PYTHON-python3}" +do + # $tool might include mandatory command-line arguments. + # Interpret it the same way Make would. + set fnord $tool + shift + if command -V $1; then + echo + "$@" --version + "$@" --version + fi + echo +done +set fnord; shift # clear $@ + +# Prepare the configure scripts. +set -x +. ./autogen.sh diff --git a/build-aux/travis-build b/build-aux/travis-build new file mode 100755 index 0000000..36a84b1 --- /dev/null +++ b/build-aux/travis-build @@ -0,0 +1,163 @@ +#!/bin/bash +set -e + +log_time () { + local duration="$SECONDS" + local secs=$((duration % 60)); duration=$((duration / 60)) + local mins=$((duration % 60)); duration=$((duration / 60)) + local hours=$duration + if [ $hours -gt 0 ]; then + txt="${hours}h ${mins}m ${secs}s" + elif [[ $mins -gt 0 ]]; then + txt="${mins}m ${secs}s" + else + txt="${secs}s" + fi + printf 'time for %s: %s\n' "$1" "$txt" + SECONDS=0 +} + +# travis_wait is not a proper command, it's a bash function, so it is +# not available to this script. This is a simplification of code from +# https://github.com/travis-ci/travis-build/lib/travis/build/bash/ +travis_jigger () { + local cmd_pid="$1" + local timeout="$2" + local count=0 + + while [[ "$count" -lt "$timeout" ]]; do + sleep 60 + count="$((count + 1))" + echo "Long job still running (${count}m / ${timeout}m)" + done + printf '\033[33;1m%s\033[0m\n' "Timeout, terminating long job." + # Use a negative process ID to target the entire process group of + # the background job. + kill -15 "-$cmd_pid" + sleep 60 + printf '\033[31;1m%s\033[0m\n' "Timeout, killing long job." + kill -9 "-$cmd_pid" + # Ensure, as best we can, that this PID sticks around to be killed + # by travis_wait. + sleep 3600 +} +travis_wait () { + local timeout="${1}" + if [[ "${timeout}" =~ ^[0-9]+$ ]]; then + shift + else + timeout=20 + fi + + # The background jobs we're about to start must be run in separate + # process groups, so we can kill them off all at once later. + set -m + + "$@" & + local cmd_pid="$!" + + travis_jigger "$cmd_pid" "$timeout" & + local jigger_pid="$!" + + # ... but don't print reports when they finish. + set +m + + wait "$cmd_pid" 2>/dev/null + local result="$?" + if [[ "$result" -eq 0 ]]; then + : # successful completion + elif [[ "$result" -eq -15 || $result -eq -9 ]]; then + : # terminated, error already printed + elif [[ "$result" -lt 0 ]]; then + printf '\033[31;1m%s\033[0m\n' "Long job killed by signal ${result#-}" + else + printf '\033[33;1m%s\033[0m\n' "Long job exited with status ${result}" + fi + kill -15 "-$jigger_pid" + wait "$jigger_pid" + return "$result" +} + + +export NPROCS="$((`nproc --all 2>/dev/null || sysctl -n hw.ncpu` * 2))" +echo paralleism is $NPROCS + +if [[ "$PERFORM_COVERITY_SCAN" == "1" ]]; then + TAG_VERSION="`echo ${TRAVIS_BRANCH} | sed -e 's/^v//g'`" + curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" \ + --output /tmp/travisci_build_coverity_scan.sh + sed -i -e "s/--form version=\$SHA/--form version=\"${TAG_VERSION}\"/g" \ + -e "s/--form description=\"Travis CI build\"/--form description=\"${SHA}\"/g" \ + -e "s/201/200/g" /tmp/travisci_build_coverity_scan.sh + bash /tmp/travisci_build_coverity_scan.sh + exit 0 +fi + +if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then + export CFLAGS="-O2 -g -arch i386 -arch x86_64 --coverage" + export CXXFLAGS="$CFLAGS" + export LDFLAGS="-arch i386 -arch x86_64 --coverage" + if [[ "$CC" == "gcc" ]]; then + GCC_VER="$(brew list --versions gcc | sed 's/^gcc \([0-9]*\)\..*$/\1/')" + export CC="gcc-$GCC_VER" + export CPP="cpp-$GCC_VER" + export CXX="g++-$GCC_VER" + export AR="gcc-ar-$GCC_VER" + export NM="gcc-nm-$GCC_VER" + export RANLIB="gcc-ranlib-$GCC_VER" + $CC --version + fi +elif [[ "$CODECOV" == "1" ]]; then + export CFLAGS="-O0 -g --coverage" + export CXXFLAGS="$CFLAGS" +else + export DEB_BUILD_MAINT_OPTIONS="hardening=+all" + export CPPFLAGS="$(dpkg-buildflags --get CPPFLAGS)" + export CFLAGS="$(dpkg-buildflags --get CFLAGS) --coverage" + export CXXFLAGS="$(dpkg-buildflags --get CXXFLAGS) --coverage" + export LDFLAGS="$(dpkg-buildflags --get LDFLAGS) --coverage" +fi + +if [[ "$CC" == "clang" ]]; then + export CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" + export CXXFLAGS="$CXXFLAGS -fprofile-arcs -ftest-coverage" +fi + +MAKE_ARGS= +if [[ "$SANITIZER" == "1" ]]; then + # ASan is incompatible with -z defs. + MAKE_ARGS="UNDEF_FLAG=" + export CFLAGS="$CFLAGS -fsanitize=undefined,address" + export CXXFLAGS="$CXXFLAGS -fsanitize=undefined,address" +fi + +mkdir build +pushd build +log_time preparation + +$(cd .. && pwd)/configure --disable-silent-rules $CONF || \ + (cat config.log && exit 1) +log_time configure + +if [[ "$DISTCHECK" == "1" ]]; then + make -j$NPROCS $MAKE_ARGS distcheck + log_time distcheck +else + make -j$NPROCS $MAKE_ARGS all + log_time build + travis_wait 60 \ + make -j$NPROCS $MAKE_ARGS check || (cat test-suite.log && exit 1) + log_time test +fi + +if [[ "$VALGRIND" == "1" ]]; then + # This step can take considerably longer than the default + # Travis no-output timeout on individual tests, just because + # that's how slow memcheck is. + travis_wait 60 \ + make -j$NPROCS $MAKE_ARGS check-valgrind-memcheck || \ + (cat test-suite-memcheck.log && exit 1) + log_time test-memcheck +fi + +popd diff --git a/build-aux/travis-install b/build-aux/travis-install new file mode 100755 index 0000000..3fc154b --- /dev/null +++ b/build-aux/travis-install @@ -0,0 +1,7 @@ +#! /bin/sh + +if [ "$PERFORM_COVERITY_SCAN" = 1 ] || [ "$DISTCHECK" = 1 ]; then + exit 0 +fi +set -x +pip install --user codecov diff --git a/build-aux/zw_alignment.m4 b/build-aux/zw_alignment.m4 new file mode 100644 index 0000000..a714196 --- /dev/null +++ b/build-aux/zw_alignment.m4 @@ -0,0 +1,90 @@ +dnl Written by Zack Weinberg <zackw at panix.com> in 2017. +dnl To the extent possible under law, Zack Weinberg has waived all +dnl copyright and related or neighboring rights to this work. +dnl +dnl See https://creativecommons.org/publicdomain/zero/1.0/ for further +dnl details. +dnl +dnl Find out how to query and set data alignment. +dnl Currently knows about C11's _Alignas and _Alignof, +dnl and GCC's __attribute__ ((aligned)) and __alignof. +dnl +dnl Note: AC_PROG_CC_C11 includes a test for _Alignas and _Alignof, +dnl but not for <stdalign.h>, which we don't bother using anyway. +dnl +dnl Compatibility note: alignas (TYPE) does not work when alignas() is +dnl defined using __attribute__ ((aligned)). Use alignas (alignof (TYPE)) +dnl instead. +AC_DEFUN([zw_C_ALIGNAS], + [AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([how to control data alignment], [zw_cv_c_alignas], + [AS_IF([test x$ac_prog_cc_stdc = xc11], + [zw_cv_c_alignas=_Alignas], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + int __attribute__((__aligned__(8))) global; + struct __attribute__((__aligned__(8))) aggregate { int x, y; }; + ]], [[ + int __attribute__((__aligned__(8))) local; + ]])], + [zw_cv_c_alignas=__attribute__], + [zw_cv_c_alignas=unknown]) + ]) + ]) + AS_IF([test x$zw_cv_c_alignas = x_Alignas], + [zw_c_alignas_expr="_Alignas(n)"], + [test x$zw_cv_c_alignas = x__attribute__], + [zw_c_alignas_expr="__attribute__((__aligned__(n)))"], + [AC_MSG_FAILURE([could not find a way to control data alignment])]) + AC_DEFINE_UNQUOTED([alignas(n)], [$zw_c_alignas_expr], + [Define as a type specifier which sets the alignment of a variable or type + to N bytes. C11 alignas(TYPE) does not need to be supported.]) +]) + +AC_DEFUN([zw_C_ALIGNOF], + [AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([how to query data alignment], [zw_cv_c_alignof], + [AS_IF([test x$ac_prog_cc_stdc = xc11], + [zw_cv_c_alignof=_Alignof], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + struct agg { int x, y; }; + extern const char align_int[__alignof__(int)]; + extern const char align_agg[__alignof__(struct agg)]; + ]], [[ + double d; + char align_var[__alignof__(d)]; + ]])], + [zw_cv_c_alignof=__alignof__], + [zw_cv_c_alignof=unknown]) + ]) + ]) + AS_IF([test x$zw_cv_c_alignof = x_Alignof], + [zw_c_alignof_expr="_Alignof(thing)"], + [test x$zw_cv_c_alignof = x__alignof__], + [zw_c_alignof_expr="__alignof__(thing)"], + [AC_MSG_FAILURE([could not find a way to query data alignment])]) + AC_DEFINE_UNQUOTED([alignof(thing)], [$zw_c_alignof_expr], + [Define as an expression which evaluates to the alignment of THING. + Must be computed at compile time (an "integer constant expression").]) +]) + +AC_DEFUN([zw_C_MAX_ALIGN_T], + [AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([zw_C_ALIGNOF]) + AC_CACHE_CHECK([for max_align_t in stddef.h], [zw_cv_c_max_align_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #include <stddef.h> + ]], [[ + max_align_t var; + return alignof(var); + ]])], + [zw_cv_c_max_align_t=yes], + [zw_cv_c_max_align_t=no]) + ]) + AS_IF([test x$zw_cv_c_max_align_t = xyes], + [AC_DEFINE([HAVE_MAX_ALIGN_T], 1, + [Define if stddef.h provides max_align_t.]) + ]) +]) diff --git a/build-aux/zw_automodern.m4 b/build-aux/zw_automodern.m4 new file mode 100644 index 0000000..8451b20 --- /dev/null +++ b/build-aux/zw_automodern.m4 @@ -0,0 +1,307 @@ +dnl Copyright 2017 Zack Weinberg <zackw at panix.com>. +dnl Partially based on Autoconf, copyright 1992-2017 Free Software Foundation. +dnl +dnl This program is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU General Public License as +dnl published by the Free Software Foundation, either version 3 of the +dnl License, or (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl Under Section 7 of GPL version 3, you are granted additional +dnl permissions described in the Autoconf Configure Script Exception, +dnl version 3.0, as published by the Free Software Foundation. +dnl +dnl Because only two files in this source tree are released +dnl under GPLv3 with exceptions, neither the GPLv3 nor the exception are +dnl distributed with this source tree. Copies can be retrieved from +dnl https://www.gnu.org/licenses/ +dnl +dnl As of this writing (September 2017), Autoconf 2.70 is not yet released. +dnl Backport some improvements: +dnl - switch AC_CHECK_HEADER to compile-only +dnl - eliminate unnecessary tests in AC_INCLUDES_DEFAULT +dnl - Darwin (OSX) support in AC_USE_SYSTEM_EXTENSIONS +dnl - C11 mode by default in AC_PROG_CC, falling back to C99 +AC_PREREQ([2.62])dnl earliest version with working m4_version_prereq +m4_version_prereq([2.70], [], [ + + m4_define([AC_CHECK_HEADER], [_AC_CHECK_HEADER_COMPILE($@)]) + + AC_DEFUN_ONCE([_AC_INCLUDES_DEFAULT_REQUIREMENTS], +[m4_divert_text([DEFAULTS], +[# Factoring default headers for most tests. +ac_includes_default="\ +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" +])]dnl +[AC_CHECK_HEADERS( + [sys/types.h sys/stat.h strings.h inttypes.h stdint.h unistd.h],,,[/**/])]dnl +dnl For backward compatibility, provide unconditional AC_DEFINEs of +dnl HAVE_STDLIB_H, HAVE_STRING_H, and STDC_HEADERS. +[AC_DEFINE([HAVE_STDLIB_H], [1], + [Always define to 1, for backward compatibility. + You can assume <stdlib.h> exists.])]dnl +[AC_DEFINE([HAVE_STRING_H], [1], + [Always define to 1, for backward compatibility. + You can assume <string.h> exists.])]dnl +[AC_DEFINE([STDC_HEADERS], [1], + [Always define to 1, for backward compatibility. + You can assume the C90 standard headers exist.])]) + + m4_define([AC_USE_SYSTEM_EXTENSIONS], + m4_defn([AC_USE_SYSTEM_EXTENSIONS])[ + AH_VERBATIM([USE_SYSTEM_EXTENSIONS_270], +[/* Enable general extensions on OSX. */ +#ifndef _DARWIN_C_SOURCE +# undef _DARWIN_C_SOURCE +#endif +]) + AC_DEFINE([_DARWIN_C_SOURCE]) + ]) + +dnl Prior to 2.70, AC_PROG_CC ends with an unconditional call to +dnl _AC_PROG_CC_C89. Use this as an extension hook, replacing it with +dnl the logic that will be used in 2.70. +m4_define([_AC_PROG_CC_C89_original], m4_defn([_AC_PROG_CC_C89])) +m4_define([_AC_PROG_CC_C89], [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_original([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 Must also supply the definition of _AC_PROG_CC_C11. +dnl This is also taken verbatim from Autoconf trunk. +dnl I regret the bulk. +AC_DEFUN([_AC_PROG_CC_C11], +[_AC_C_STD_TRY([c11], +[[#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> + +// 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; +} + +// 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; +]], +[[ + // 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); + + 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 + + +])dnl m4_version_prereq([2.70], ...) diff --git a/build-aux/zw_endianness.m4 b/build-aux/zw_endianness.m4 new file mode 100644 index 0000000..9513216 --- /dev/null +++ b/build-aux/zw_endianness.m4 @@ -0,0 +1,152 @@ +dnl Written by Zack Weinberg <zackw at panix.com> in 2018. +dnl To the extent possible under law, Zack Weinberg has waived all +dnl copyright and related or neighboring rights to this work. +dnl +dnl See https://creativecommons.org/publicdomain/zero/1.0/ for further +dnl details. +dnl +dnl This macro is like AC_C_BIGENDIAN, but it doesn't try to determine +dnl a final value at configure time. Instead, it probes for a set of +dnl headers and compile-time macros that may or may not be available, +dnl and uses them to guide preprocessor logic that makes the final +dnl determination. This works better with MacOS "universal binaries", +dnl which may involve compiling the program twice under opposite +dnl endiannesses; no fixed byte-order macro is correct in that case, +dnl but the compiler's built-ins will be. This approach is also +dnl friendlier to cross-compilation. +dnl +dnl This is the preprocessor logic that should be put in an appropriate +dnl location, after including config.h: +dnl +dnl #include <limits.h> +dnl #ifdef HAVE_ENDIAN_H +dnl #include <endian.h> +dnl #endif +dnl #ifdef HAVE_SYS_ENDIAN_H +dnl #include <sys/endian.h> +dnl #endif +dnl #ifdef HAVE_SYS_PARAM_H +dnl #include <sys/param.h> +dnl #endif +dnl +dnl #if ENDIANNESS_IS_BIG +dnl # define ENDIAN_BIG +dnl #elif ENDIANNESS_IS_LITTLE +dnl # define ENDIAN_LITTLE +dnl #elif ENDIANNESS_IS_PDP +dnl # define ENDIAN_PDP +dnl #else +dnl # error "Unable to determine byte order" +dnl #endif +dnl ------------------------------------------------ + +dnl There's no good way to implement this macro as a _shell_ loop, but we +dnl can reasonably implement it as an _m4_ loop that expands to a sequence +dnl of conditionals. Actually two sequences of conditionals, one inside +dnl AC_CACHE_CHECK and one outside. + +m4_define([zw_C_ENDIANNESS_options], [ +[ [BYTE_ORDER and xxx_ENDIAN], + [defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN && BIG_ENDIAN != LITTLE_ENDIAN], + [BYTE_ORDER == BIG_ENDIAN], + [BYTE_ORDER == LITTLE_ENDIAN], + [BYTE_ORDER == PDP_ENDIAN], +], +[ [__BYTE_ORDER and __xxx_ENDIAN], + [defined __BYTE_ORDER && defined __BIG_ENDIAN && defined __LITTLE_ENDIAN && __BIG_ENDIAN != __LITTLE_ENDIAN], + [__BYTE_ORDER == __BIG_ENDIAN], + [__BYTE_ORDER == __LITTLE_ENDIAN], + [__BYTE_ORDER == __PDP_ENDIAN], +], +[ [__BYTE_ORDER__ and __xxx_ENDIAN__], + [defined __BYTE_ORDER__ && defined __BIG_ENDIAN__ && defined __LITTLE_ENDIAN__ && __BIG_ENDIAN__ != __LITTLE_ENDIAN__], + [__BYTE_ORDER__ == __BIG_ENDIAN__], + [__BYTE_ORDER__ == __LITTLE_ENDIAN__], + [__BYTE_ORDER__ == __PDP_ENDIAN__], +], +[ [__BYTE_ORDER__ and __ORDER_xxx_ENDIAN__], + [defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ && defined __ORDER_LITTLE_ENDIAN__ && __ORDER_BIG_ENDIAN__ != __ORDER_LITTLE_ENDIAN__], + [__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__], + [__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__], + [__BYTE_ORDER__ == __ORDER_PDP_ENDIAN__], +], +[ [_BIG_ENDIAN and _LITTLE_ENDIAN], + [(defined _BIG_ENDIAN) != (defined _LITTLE_ENDIAN)], + [defined _BIG_ENDIAN], [defined _LITTLE_ENDIAN], [0], +], +[ [__BIG_ENDIAN__ and __LITTLE_ENDIAN__], + [(defined __BIG_ENDIAN__) != (defined __LITTLE_ENDIAN__)], + [defined __BIG_ENDIAN__], [defined __LITTLE_ENDIAN__], [0], +], +[ [__ARMEB__ and __ARMEL__], + [(defined __ARMEB__) != (defined __ARMEL__)], + [defined __ARMEB__], [defined __ARMEL__], [0], +], +[ [__THUMBEB__ and __THUMBEL__], + [(defined __THUMBEB__) != (defined __THUMBEL__)], + [defined __THUMBEB__], [defined __THUMBEL__], [0], +], +[ [__AARCH64EB__ and __AARCH64EL__], + [(defined __AARCH64EB__) != (defined __AARCH64EL__)], + [defined __AARCH64EB__], [defined __AARCH64EL__], [0], +], +[ [__MIPSEB__ and __MIPSEL__], + [(defined __MIPSEB__) != (defined __MIPSEL__)], + [defined __MIPSEB__], [defined __MIPSEL__], [0], +], +[ [__MIPSEB and __MIPSEL], + [(defined __MIPSEB) != (defined __MIPSEL)], + [defined __MIPSEB], [defined __MIPSEL], [0], +], +[ [_MIPSEB and _MIPSEL], + [(defined _MIPSEB) != (defined _MIPSEL)], + [defined _MIPSEB], [defined _MIPSEL], [0], +] +]) + +m4_define([zw_C_ENDIANNESS_test_one], [ +if test "$[]ac_cv_c_byte_order_macros" = unknown; then + AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[ +#include <limits.h> +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#endif +#ifdef HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#if !($2) +#error fail +#endif +]])], + [ac_cv_c_byte_order_macros="$1"]) +fi]) + +m4_define([zw_C_ENDIANNESS_case_one], + [["$1"], [ + zw_C_ENDIANNESS_IS_BIG="($3)" + zw_C_ENDIANNESS_IS_LIT="($4)" + zw_C_ENDIANNESS_IS_PDP="($5)"]]) + +AC_DEFUN([zw_C_ENDIANNESS], [ +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) +AC_CHECK_HEADERS_ONCE([endian.h sys/endian.h sys/param.h]) +AC_CACHE_CHECK([for byte order macros], + [ac_cv_c_byte_order_macros], [ + ac_cv_c_byte_order_macros=unknown + m4_map([zw_C_ENDIANNESS_test_one], [zw_C_ENDIANNESS_options])]) + +AS_CASE([$ac_cv_c_byte_order_macros], + m4_map_sep([zw_C_ENDIANNESS_case_one], [,], [zw_C_ENDIANNESS_options]), + [AC_MSG_ERROR([unable to determine byte order at compile time])]) + +AC_DEFINE_UNQUOTED([ENDIANNESS_IS_BIG], [$zw_C_ENDIANNESS_IS_BIG], + [Define as an @%:@if expression that is true when compiling for a big-endian CPU.]) +AC_DEFINE_UNQUOTED([ENDIANNESS_IS_LITTLE], [$zw_C_ENDIANNESS_IS_LIT], + [Define as an @%:@if expression that is true when compiling for a little-endian CPU.]) +AC_DEFINE_UNQUOTED([ENDIANNESS_IS_PDP], [$zw_C_ENDIANNESS_IS_PDP], + [Define as an @%:@if expression that is true when compiling for a PDP-endian CPU.]) +]) diff --git a/build-aux/zw_ld_wrap.m4 b/build-aux/zw_ld_wrap.m4 new file mode 100644 index 0000000..87b22e7 --- /dev/null +++ b/build-aux/zw_ld_wrap.m4 @@ -0,0 +1,47 @@ +dnl Written by Zack Weinberg <zackw at panix.com> in 2018. +dnl To the extent possible under law, Zack Weinberg has waived all +dnl copyright and related or neighboring rights to this work. +dnl +dnl See https://creativecommons.org/publicdomain/zero/1.0/ for further +dnl details. +dnl +dnl Find out whether ld --wrap is supported. +AC_DEFUN([zw_PROG_LD_WRAP], + [AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([for ld --wrap], [zw_cv_prog_ld_wrap], + [save_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" + LDFLAGS="" + LIBS="" + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[ + extern void bar(void); + void foo(void) { bar(); } + ]])], + [mv conftest.$OBJEXT conftest2.$OBJEXT + LDFLAGS="-Wl,--wrap,bar" + LIBS="conftest2.$OBJEXT" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + extern void foo(void); + void __wrap_bar(void) {} + ]], [[ + foo(); + ]])], + [zw_cv_prog_ld_wrap=yes], + [zw_cv_prog_ld_wrap=no]) + rm -f conftest2.$OBJEXT + ], + [zw_cv_prog_ld_wrap=no]) + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS"]) + if test x$zw_cv_prog_ld_wrap = xyes; then + have_ld_wrap=yes + AC_DEFINE([HAVE_LD_WRAP], 1, + [Define to 1 if -Wl,--wrap,SYMBOL can be used to intercept + calls to SYMBOL at link time.]) + else + have_ld_wrap=no + fi + AM_CONDITIONAL([HAVE_LD_WRAP], [test $have_ld_wrap = yes]) +]) diff --git a/build-aux/zw_simple_warnings.m4 b/build-aux/zw_simple_warnings.m4 new file mode 100644 index 0000000..fef1312 --- /dev/null +++ b/build-aux/zw_simple_warnings.m4 @@ -0,0 +1,150 @@ +# serial 1 +dnl Copyright 2017 Zack Weinberg <zackw at panix.com>. +dnl Partially based on Autoconf, copyright 1992-2017 Free Software Foundation. +dnl +dnl This program is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU General Public License as +dnl published by the Free Software Foundation, either version 3 of the +dnl License, or (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl Under Section 7 of GPL version 3, you are granted additional +dnl permissions described in the Autoconf Configure Script Exception, +dnl version 3.0, as published by the Free Software Foundation. +dnl +dnl Because only two files in this source tree are released +dnl under GPLv3 with exceptions, neither the GPLv3 nor the exception are +dnl distributed with this source tree. Copies can be retrieved from +dnl https://www.gnu.org/licenses/ +dnl +dnl Autoconf core has no good way of enabling compiler warnings. +dnl This is a cut-down version of the elaborate thing in the extras +dnl archive, which we do not need nearly all of. +dnl +dnl Partly based on: +dnl https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_cflags.html + +AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF + +AC_DEFUN([zw_SIMPLE_ENABLE_WARNINGS], +[ +AC_ARG_ENABLE( + [werror], + AS_HELP_STRING( + [--disable-werror], + [do not treat all warnings as errors] + ), + [case "${enableval}" in + yes) warnings_are_errors=true ;; + no) warnings_are_errors=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-werror]) ;; + esac], + [warnings_are_errors=true] +) + + # Always pass -Werror=unknown-warning-option to get Clang to fail + # on bad flags, otherwise they are always appended to the + # warn_cflags variable, and Clang warns on them for every + # compilation unit. If this is passed to GCC, it will explode, so + # the flag must be enabled conditionally. + AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[ + ax_compiler_flags_test="-Werror=unknown-warning-option" + ],[ + ax_compiler_flags_test="" + ]) + + # Don't enable -pedantic if we don't have C11, or we may get junk + # warnings about static_assert. + ax_candidate_warnings="dnl + -Wall dnl + -Wextra dnl + -Walloc-zero dnl + -Walloca dnl + -Wbad-function-cast dnl + -Wcast-align dnl + -Wcast-qual dnl + -Wconversion dnl + -Wformat=2 dnl + -Wformat-overflow=2 dnl + -Wformat-signedness dnl + -Wformat-truncation=1 dnl + -Wlogical-op dnl + -Wmissing-declarations dnl + -Wmissing-prototypes dnl + -Wnested-externs dnl + -Wnull-dereference dnl + -Wold-style-definition dnl + -Wpointer-arith dnl + -Wrestrict dnl + -Wshadow dnl + -Wstrict-overflow=2 dnl + -Wstrict-prototypes dnl + -Wundef dnl + -Wvla dnl + -Wwrite-strings dnl + " + if test x$ac_prog_cc_stdc = xc11; then + ax_candidate_warnings="$ax_candidate_warnings -Wpedantic" + fi + if test x$warnings_are_errors = xtrue; then + ax_candidate_warnings="$ax_candidate_warnings -Werror" + fi + + # If we are building for OSX, turn -Wdeprecated-declarations off. + # Apple is a little too trigger-happy with deprecations. + case "$host_os" in + (*darwin*) + ax_candidate_warnings="$ax_candidate_warnings -Wno-deprecated-declarations" + ;; + esac + + AX_APPEND_COMPILE_FLAGS( + [$ax_candidate_warnings], [WARN_CFLAGS], + [$ax_compiler_flags_test]) + + AC_SUBST(WARN_CFLAGS) + + if test $cross_compiling = yes; then + # Repeat the above logic for the build compiler. + + save_cross_compiling=$cross_compiling + save_ac_tool_prefix=$ac_tool_prefix + save_CC="$CC" + save_CFLAGS="$CFLAGS" + save_CPPFLAGS="$CPPFLAGS" + save_LDFLAGS="$LDFLAGS" + + cross_compiling=no + ac_tool_prefix= + CC="$CC_FOR_BUILD" + CFLAGS="$CFLAGS_FOR_BUILD" + CPPFLAGS="$CPPFLAGS_FOR_BUILD" + LDFLAGS="$LDFLAGS_FOR_BUILD" + + pushdef([_AC_LANG_ABBREV],[build_c]) + + AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[ + ax_compiler_flags_test="-Werror=unknown-warning-option" + ],[ + ax_compiler_flags_test="" + ]) + AX_APPEND_COMPILE_FLAGS( + [$ax_candidate_warnings], [WARN_CFLAGS_FOR_BUILD], + [$ax_compiler_flags_test]) + + popdef([_AC_LANG_ABBREV]) + + AC_SUBST(WARN_CFLAGS_FOR_BUILD) + + cross_compiling=$save_cross_compiling + ac_tool_prefix=$save_ac_tool_prefix + CC="$save_CC" + CFLAGS="$save_CFLAGS" + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + fi # cross_compiling +]) diff --git a/build-aux/zw_static_assert.m4 b/build-aux/zw_static_assert.m4 new file mode 100644 index 0000000..e33931a --- /dev/null +++ b/build-aux/zw_static_assert.m4 @@ -0,0 +1,68 @@ +dnl Written by Zack Weinberg <zackw at panix.com> in 2017. +dnl To the extent possible under law, Zack Weinberg has waived all +dnl copyright and related or neighboring rights to this work. +dnl +dnl See https://creativecommons.org/publicdomain/zero/1.0/ for further +dnl details. +dnl +dnl Check for static_assert in <assert.h>; failing that, check for intrinsic +dnl support for C11 _Static_assert. +dnl assert.h itself is in C89 and does not need to be probed for; +dnl moreover, AC_PROG_CC's check for C11 includes _Static_assert (but not +dnl static_assert). +dnl Some logic borrowed from gnulib's assert_h.m4. +dnl 2*2 != 7 is tested in honor of Stanisław Lem. +AC_DEFUN([zw_C_STATIC_ASSERT], + [AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([for static_assert in assert.h], + [zw_cv_c_assert_h_static_assert], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #undef NDEBUG + #include <assert.h> + static_assert(2 + 2 == 4, "arithmetic does not work"); + ]], [[ + static_assert(sizeof (char) == 1, "sizeof does not work"); + ]])], + [static_assert_true=yes], + [static_assert_true=no]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #undef NDEBUG + #include <assert.h> + static_assert(2 * 2 == 7, "this assertion should fail"); + ]])], + [static_assert_false=no], + [static_assert_false=yes]) + AS_IF([test $static_assert_false$static_assert_true = yesyes], + [zw_cv_c_assert_h_static_assert=yes], + [zw_cv_c_assert_h_static_assert=no])]) + AS_IF([test $zw_cv_c_assert_h_static_assert = yes], + [AC_DEFINE([HAVE_STATIC_ASSERT_IN_ASSERT_H], 1, + [Define if <assert.h> defines static_assert.])], + [AC_CACHE_CHECK([for _Static_assert], + [zw_cv_c__Static_assert], + [AS_IF([test x$ac_prog_cc_stdc = xc11], + [zw_cv_c__Static_assert=yes], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + _Static_assert(2 + 2 == 4, "arithmetic does not work"); + ]], [[ + _Static_assert(sizeof (char) == 1, "sizeof does not work"); + ]])], + [_Static_assert_true=yes], + [_Static_assert_true=no]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + _Static_assert(2 * 2 == 7, "this assertion should fail"); + ]])], + [_Static_assert_false=no], + [_Static_assert_false=yes]) + AS_IF([test $static_assert_false$static_assert_true = yesyes], + [zw_cv_c__Static_assert=yes], + [zw_cv_c__Static_assert=no])])]) + AS_IF([test $zw_cv_c__Static_assert = yes], + [AC_DEFINE([HAVE__STATIC_ASSERT], 1, + [Define if the compiler supports the _Static_assert intrinsic.])]) + ]) +]) |