From: Simon Marchi Date: Fri, 21 May 2021 03:23:21 +0000 (-0400) Subject: Import warning flags and tap from Babeltrace X-Git-Url: http://git.efficios.com/?p=argpar.git;a=commitdiff_plain;h=a99ee691baf201d91c8a2f7e727de22e9d4b8bb5 Import warning flags and tap from Babeltrace Since we are going to use this code in Babeltrace, lttng-tools, and perhaps other projects, I think it would be useful to use warning flags at least as strict here as we do in these other projects, so we don't have bad surprises when importing the code there. Start by importing the warning flag checking system from Babeltrace, and the list of warning flags used there. Import the tap code as well, since the current tap code would generate some errors with the new warning flags. Change-Id: I86bf5a18bcbce35b887d3ef3285d5566b3f7c69f Signed-off-by: Simon Marchi --- diff --git a/.gitignore b/.gitignore index 68a6cf7..21bb97e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,11 @@ depcomp install-sh libtool ltmain.sh -m4 +/m4/libtool.m4 +/m4/lt~obsolete.m4 +/m4/ltoptions.m4 +/m4/ltsugar.m4 +/m4/ltversion.m4 missing test-driver Makefile diff --git a/configure.ac b/configure.ac index 01f70d7..8464b8c 100644 --- a/configure.ac +++ b/configure.ac @@ -4,9 +4,48 @@ LT_INIT AC_CONFIG_MACRO_DIRS([m4]) +AC_USE_SYSTEM_EXTENSIONS + # Depend on glib just for the tests. PKG_CHECK_MODULES([GLIB], [glib-2.0]) +# When given, add -Werror to WARN_CFLAGS and WARN_CXXFLAGS. +# Disabled by default +AE_FEATURE_DEFAULT_DISABLE +AE_FEATURE([Werror],[Treat compiler warnings as errors.]) + +# Detect warning flags supported by the C compiler and append them to +# WARN_CFLAGS. +# +m4_define([WARN_FLAGS_LIST], [ dnl + -Wall dnl + -Wextra dnl + -Wmissing-prototypes dnl + -Wmissing-declarations dnl + -Wnull-dereference dnl + -Wundef dnl + -Wredundant-decls dnl + -Wshadow dnl + -Wjump-misses-init dnl + -Wsuggest-attribute=format dnl + -Wtautological-constant-out-of-range-compare dnl + -Wnested-externs dnl + -Wwrite-strings dnl + -Wformat=2 dnl + -Wstrict-aliasing dnl + -Wmissing-noreturn dnl + -Winit-self dnl + -Wduplicated-cond dnl + -Wduplicated-branches dnl + -Wlogical-op dnl +]) + +AX_APPEND_COMPILE_FLAGS([WARN_FLAGS_LIST], [WARN_CFLAGS], [-Werror]) +AE_IF_FEATURE_ENABLED([Werror], [WARN_CFLAGS="${WARN_CFLAGS} -Werror"]) +AM_CFLAGS="${AM_CFLAGS} ${WARN_CFLAGS}" + +AC_SUBST(AM_CFLAGS) + AC_CONFIG_FILES([ Makefile argpar/Makefile diff --git a/m4/ac_extensions.m4 b/m4/ac_extensions.m4 new file mode 100644 index 0000000..6d378ec --- /dev/null +++ b/m4/ac_extensions.m4 @@ -0,0 +1,143 @@ +# serial 13 -*- Autoconf -*- +# Enable extensions on systems that normally disable them. + +# Copyright (C) 2003, 2006-2016 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This definition of AC_USE_SYSTEM_EXTENSIONS is stolen from git +# Autoconf. Perhaps we can remove this once we can assume Autoconf +# 2.70 or later everywhere, but since Autoconf mutates rapidly +# enough in this area it's likely we'll need to redefine +# AC_USE_SYSTEM_EXTENSIONS for quite some time. + +# If autoconf reports a warning +# warning: AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS +# or warning: AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS +# the fix is +# 1) to ensure that AC_USE_SYSTEM_EXTENSIONS is never directly invoked +# but always AC_REQUIREd, +# 2) to ensure that for each occurrence of +# AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) +# or +# AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) +# the corresponding gnulib module description has 'extensions' among +# its dependencies. This will ensure that the gl_USE_SYSTEM_EXTENSIONS +# invocation occurs in gl_EARLY, not in gl_INIT. + +# AC_USE_SYSTEM_EXTENSIONS +# ------------------------ +# Enable extensions on systems that normally disable them, +# typically due to standards-conformance issues. +# +# Remember that #undef in AH_VERBATIM gets replaced with #define by +# AC_DEFINE. The goal here is to define all known feature-enabling +# macros, then, if reports of conflicts are made, disable macros that +# cause problems on some platforms (such as __EXTENSIONS__). +AC_DEFUN_ONCE([AC_USE_SYSTEM_EXTENSIONS], +[AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl +AC_BEFORE([$0], [AC_RUN_IFELSE])dnl + + AC_CHECK_HEADER([minix/config.h], [MINIX=yes], [MINIX=]) + if test "$MINIX" = yes; then + AC_DEFINE([_POSIX_SOURCE], [1], + [Define to 1 if you need to in order for 'stat' and other + things to work.]) + AC_DEFINE([_POSIX_1_SOURCE], [2], + [Define to 2 if the system does not provide POSIX.1 features + except with this defined.]) + AC_DEFINE([_MINIX], [1], + [Define to 1 if on MINIX.]) + AC_DEFINE([_NETBSD_SOURCE], [1], + [Define to 1 to make NetBSD features available. MINIX 3 needs this.]) + fi + +dnl Use a different key than __EXTENSIONS__, as that name broke existing +dnl configure.ac when using autoheader 2.62. + AH_VERBATIM([USE_SYSTEM_EXTENSIONS], +[/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable general extensions on OS X. */ +#ifndef _DARWIN_C_SOURCE +# undef _DARWIN_C_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Use GNU style printf and scanf. */ +#ifndef __USE_MINGW_ANSI_STDIO +# undef __USE_MINGW_ANSI_STDIO +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable X/Open extensions if necessary. HP-UX 11.11 defines + mbstate_t only if _XOPEN_SOURCE is defined to 500, regardless of + whether compiling with -Ae or -D_HPUX_SOURCE=1. */ +#ifndef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +]) + AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__], + [ac_cv_safe_to_define___extensions__], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ +# define __EXTENSIONS__ 1 + ]AC_INCLUDES_DEFAULT])], + [ac_cv_safe_to_define___extensions__=yes], + [ac_cv_safe_to_define___extensions__=no])]) + test $ac_cv_safe_to_define___extensions__ = yes && + AC_DEFINE([__EXTENSIONS__]) + AC_DEFINE([_ALL_SOURCE]) + AC_DEFINE([_DARWIN_C_SOURCE]) + AC_DEFINE([_GNU_SOURCE]) + AC_DEFINE([__USE_MINGW_ANSI_STDIO]) + AC_DEFINE([_POSIX_PTHREAD_SEMANTICS]) + AC_DEFINE([_TANDEM_SOURCE]) + AC_CACHE_CHECK([whether _XOPEN_SOURCE should be defined], + [ac_cv_should_define__xopen_source], + [ac_cv_should_define__xopen_source=no + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #include + mbstate_t x;]])], + [], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #define _XOPEN_SOURCE 500 + #include + mbstate_t x;]])], + [ac_cv_should_define__xopen_source=yes])])]) + test $ac_cv_should_define__xopen_source = yes && + AC_DEFINE([_XOPEN_SOURCE], [500]) +])# AC_USE_SYSTEM_EXTENSIONS + +# gl_USE_SYSTEM_EXTENSIONS +# ------------------------ +# Enable extensions on systems that normally disable them, +# typically due to standards-conformance issues. +AC_DEFUN_ONCE([gl_USE_SYSTEM_EXTENSIONS], +[ + dnl Require this macro before AC_USE_SYSTEM_EXTENSIONS. + dnl gnulib does not need it. But if it gets required by third-party macros + dnl after AC_USE_SYSTEM_EXTENSIONS is required, autoconf 2.62..2.63 emit a + dnl warning: "AC_COMPILE_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS". + dnl Note: We can do this only for one of the macros AC_AIX, AC_GNU_SOURCE, + dnl AC_MINIX. If people still use AC_AIX or AC_MINIX, they are out of luck. + AC_REQUIRE([AC_GNU_SOURCE]) + + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) +]) diff --git a/m4/ae_config_feature.m4 b/m4/ae_config_feature.m4 new file mode 100644 index 0000000..7582c00 --- /dev/null +++ b/m4/ae_config_feature.m4 @@ -0,0 +1,258 @@ +# +# SYNOPSIS +# +# AE_FEATURE(FEATURE-NAME, FEATURE-DESCRIPTION, +# ACTION-IF-GIVEN?, ACTION-IF-NOT-GIVEN?, +# ACTION-IF-ENABLED?, ACTION-IF-NOT-ENABLED?) +# +# DESCRIPTION +# +# AE_FEATURE is a simple wrapper for AC_ARG_ENABLE. +# +# FEATURE-NAME should consist only of alphanumeric characters, dashes, +# plus signs, and dots. +# +# FEATURE-DESCRIPTION will be formatted with AS_HELP_STRING. +# +# If the user gave configure the option --enable-FEATURE or --disable-FEATURE, +# run shell commands ACTION-IF-GIVEN. If neither option was given, run shell +# commands ACTION-IF-NOT-GIVEN. The name feature indicates an optional +# +# If the feature is enabled, run shell commands ACTION-IF-ENABLED, if it is +# disabled, run shell commands ACTION-IF-NOT-ENABLED. +# +# A FEATURE has 3 different states, enabled, disabled and undefined. The first +# two are self explanatory, the third state means it's disabled by default +# and it was not explicitly enabled or disabled by the user or by the +# AE_FEATURE_ENABLE and AE_FEATURE_DISABLE macros. +# +# A feature is disabled by default, in order to change this behaviour use the +# AE_FEATURE_DEFAULT_ENABLE and AE_FEATURE_DEFAULT_DISABLE +# macros. +# +# A simple example: +# +# AE_FEATURE_DEFAULT_ENABLE +# AE_FEATURE(feature_xxxxx, [turns on/off XXXXX support]) +# +# ... +# +# AE_FEATURE_DEFAULT_DISABLE +# AE_FEATURE(feature_yyyyy, [turns on/off YYYYY support]) +# AM_CONDITIONAL(YYYYY, AE_IS_FEATURE_ENABLED([feature_yyyyy])) +# +# AE_FEATURE_DEFAULT_ENABLE +# AE_FEATURE(...) +# +# ... +# +# Use AE_FEATURE_ENABLE or AE_FEATURE_DISABLE in order to +# enable or disable a specific feature. +# +# Another simple example: +# +# AS_IF([some_test_here],[AE_FEATURE_ENABLE(feature_xxxxx)],[]) +# +# AE_FEATURE(feature_xxxxx, [turns on/off XXXXX support], +# HAVE_XXXXX, [Define if you want XXXXX support]) +# AE_FEATURE(feature_yyyyy, [turns on/off YYYYY support], +# HAVE_YYYYY, [Define if you want YYYYY support]) +# +# ... +# +# NOTE: AE_FEATURE_ENABLE/DISABLE() must be placed first of the relative +# AE_FEATURE() macro if you want the the proper ACTION-IF-ENABLED and +# ACTION-IF-NOT-ENABLED to run. +# +# LICENSE +# +# Copyright (c) 2020 Michael Jeanson +# Copyright (c) 2008 Francesco Salvestrini +# +# 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, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 1 + + +# AE_FEATURE_DEFAULT_ENABLE: The next feature defined with AE_FEATURE will +# default to enable. +AC_DEFUN([AE_FEATURE_DEFAULT_ENABLE], [ + m4_define([ae_feature_default_arg], [yes]) + m4_define([ae_feature_default_switch], [disable]) +]) + + +# AE_FEATURE_DEFAULT_DISABLE: The next feature defined with AE_FEATURE will +# default to disable. +# +AC_DEFUN([AE_FEATURE_DEFAULT_DISABLE], [ + m4_define([ae_feature_default_arg], [no]) + m4_define([ae_feature_default_switch], [enable]) +]) + + +# AE_FEATURE_ENABLE(FEATURE-NAME): Enable the FEATURE, this will override the +# user's choice if it was made. +# +AC_DEFUN([AE_FEATURE_ENABLE],[ dnl + enable_[]patsubst([$1], -, _)[]=yes +]) + + +# AE_FEATURE_DISABLE(FEATURE-NAME): Disable the FEATURE, this will override the +# user's choice if it was made. +# +AC_DEFUN([AE_FEATURE_DISABLE],[ dnl + enable_[]patsubst([$1], -, _)[]=no +]) + + +# AE_IF_FEATURE_ENABLED(FEATURE-NAME, ACTION-IF-ENABLED, ACTION-IF-NOT-ENABLED?): +# Run shell code ACTION-IF-ENABLED if the FEATURE is enabled, otherwise run +# shell code ACTION-IF-NOT-ENABLED. +# +AC_DEFUN([AE_IF_FEATURE_ENABLED],[ dnl +m4_pushdef([FEATURE], patsubst([$1], -, _))dnl + + AS_IF([test "$enable_[]FEATURE[]" = yes],[ dnl + $2 + ],[: dnl + $3 + ]) +]) + + +# AE_IF_FEATURE_NOT_ENABLED(FEATURE-NAME, ACTION-IF-NOT-ENABLED, +# ACTION-IF-NOT-NOT-ENABLED?): +# Run shell code ACTION-IF-NOT-ENABLED if the FEATURE is not explicitly +# enabled, otherwise run shell code ACTION-IF-NOT-NOT-DISABLED. +# +# The distinction with AE_IF_FEATURE_DISABLED is that this will also +# match a feature that is undefined. +# +# A feature is undefined when it's disabled by default and was not explicitly +# enabled or disabled by the user or by AE_FEATURE_ENABLE/DISABLE. +# +AC_DEFUN([AE_IF_FEATURE_NOT_ENABLED],[ dnl +m4_pushdef([FEATURE], patsubst([$1], -, _))dnl + + AS_IF([test "$enable_[]FEATURE[]" != yes],[ dnl + $2 + ],[: dnl + $3 + ]) +]) + + +# AE_IF_FEATURE_DISABLED(FEATURE-NAME, ACTION-IF-DISABLED, ACTION-IF-NOT-DISABLED?): +# Run shell code ACTION-IF-DISABLED if the FEATURE is disabled, otherwise run +# shell code ACTION-IF-NOT-DISABLED. +# +AC_DEFUN([AE_IF_FEATURE_DISABLED],[ dnl +m4_pushdef([FEATURE], patsubst([$1], -, _))dnl + + AS_IF([test "$enable_[]FEATURE[]" = no],[ dnl + $2 + ],[: dnl + $3 + ]) +]) + + +# AE_IF_FEATURE_UNDEF(FEATURE-NAME, ACTION-IF-UNDEF, ACTION-IF-NOT-UNDEF?): +# Run shell code ACTION-IF-UNDEF if the FEATURE is undefined, otherwise run +# shell code ACTION-IF-NOT-UNDEF. +# +# A feature is undefined when it's disabled by default and was not explicitly +# enabled or disabled by the user or by AE_FEATURE_ENABLE/DISABLE. +# +AC_DEFUN([AE_IF_FEATURE_UNDEF],[ dnl +m4_pushdef([FEATURE], patsubst([$1], -, _))dnl + + AS_IF([test "x$enable_[]FEATURE[]" = x],[ dnl + $2 + ],[: dnl + $3 + ]) +]) + + +# AE_IS_FEATURE_ENABLED(FEATURE-NAME): outputs a shell condition (suitable +# for use in a shell if statement) that will return true if the FEATURE is +# enabled. +# +AC_DEFUN([AE_IS_FEATURE_ENABLED],[dnl +m4_pushdef([FEATURE], patsubst([$1], -, _))dnl + test "x$enable_[]FEATURE[]" = xyes dnl +]) + + +dnl Disabled by default, unless already overriden +m4_ifndef([ae_feature_default_arg],[AE_FEATURE_DEFAULT_DISABLE]) + + +# AE_FEATURE(FEATURE-NAME, FEATURE-DESCRIPTION, +# ACTION-IF-GIVEN?, ACTION-IF-NOT-GIVEN?, +# ACTION-IF-ENABLED?, ACTION-IF-NOT-ENABLED?): +# +# +AC_DEFUN([AE_FEATURE],[ dnl +m4_pushdef([FEATURE], patsubst([$1], -, _))dnl + +dnl If the option wasn't specified and the default is enabled, set enable_FEATURE to yes +AS_IF([test "x$enable_[]FEATURE[]" = x && test "ae_feature_default_arg" = yes],[ dnl + enable_[]FEATURE[]="ae_feature_default_arg" +]) + +AC_ARG_ENABLE([$1], + AS_HELP_STRING([--ae_feature_default_switch-$1],dnl + [$2 [default=ae_feature_default_arg]]),[ +case "${enableval}" in + yes) + enable_[]FEATURE[]=yes + ;; + no) + enable_[]FEATURE[]=no + ;; + *) + AC_MSG_ERROR([bad value ${enableval} for feature --$1]) + ;; +esac + +$3 +],[: dnl +$4 +]) + +AS_IF([test "$enable_[]FEATURE[]" = yes],[: dnl + $5 +],[: dnl + $6 +]) + +m4_popdef([FEATURE])dnl +]) diff --git a/m4/ax_append_compile_flags.m4 b/m4/ax_append_compile_flags.m4 new file mode 100644 index 0000000..9c85635 --- /dev/null +++ b/m4/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 +# +# 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/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4 new file mode 100644 index 0000000..dd6d8b6 --- /dev/null +++ b/m4/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 +# Copyright (c) 2011 Maarten Bosmans +# +# 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/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 0000000..bd753b3 --- /dev/null +++ b/m4/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 +# Copyright (c) 2011 Maarten Bosmans +# +# 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/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 new file mode 100644 index 0000000..17c3eab --- /dev/null +++ b/m4/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 +# +# 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/tests/tap/tap.c b/tests/tap/tap.c index 09ac2af..9f41408 100644 --- a/tests/tap/tap.c +++ b/tests/tap/tap.c @@ -1,34 +1,17 @@ -/*- - * Copyright (c) 2004 Nik Clayton - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. +/* + * SPDX-License-Identifier: BSD-2-Clause * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * Copyright (C) 2004 Nik Clayton + * Copyright (C) 2017 Jérémie Galarneau */ -#define _GNU_SOURCE #include #include #include #include +#include +#include +#include #include "tap.h" @@ -39,15 +22,13 @@ static unsigned int test_count = 0; /* Number of tests that have been run */ static unsigned int e_tests = 0; /* Expected number of tests to run */ static unsigned int failures = 0; /* Number of tests that failed */ static char *todo_msg = NULL; -static char *todo_msg_fixed = "libtap malloc issue"; +static const char *todo_msg_fixed = "libtap malloc issue"; static int todo = 0; static int test_died = 0; -static const int exit_die = 255; /* exit-code on die() */ - /* Encapsulate the pthread code in a conditional. In the absence of libpthread the code does nothing */ -#if defined(LIBTAP_ENABLE_BROKEN_THREAD_SAFE) && defined(HAVE_LIBPTHREAD) +#ifdef HAVE_LIBPTHREAD #include static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER; # define LOCK pthread_mutex_lock(&M); @@ -61,6 +42,18 @@ static void _expected_tests(unsigned int); static void _tap_init(void); static void _cleanup(void); +#ifdef __MINGW32__ +static inline +void flockfile (FILE * filehandle) { + return; +} + +static inline +void funlockfile(FILE * filehandle) { + return; +} +#endif + /* * Generate a test result. * @@ -85,10 +78,9 @@ _gen_result(int ok, const char *func, const char *file, unsigned int line, expansions on it */ if(test_name != NULL) { va_start(ap, test_name); - if (vasprintf(&local_test_name, test_name, ap) < 0) - { - local_test_name = NULL; - } + if (vasprintf(&local_test_name, test_name, ap) == -1) { + local_test_name = NULL; + } va_end(ap); /* Make sure the test name contains more than digits @@ -97,7 +89,7 @@ _gen_result(int ok, const char *func, const char *file, unsigned int line, if(local_test_name) { name_is_digits = 1; for(c = local_test_name; *c != '\0'; c++) { - if(!isdigit(*c) && !isspace(*c)) { + if(!isdigit((unsigned char) *c) && !isspace((unsigned char) *c)) { name_is_digits = 0; break; } @@ -150,10 +142,13 @@ _gen_result(int ok, const char *func, const char *file, unsigned int line, printf("\n"); - if(!ok) + if(!ok) { + if(getenv("HARNESS_ACTIVE") != NULL) + fputs("\n", stderr); + diag(" Failed %stest (%s:%s() at line %d)", todo ? "(TODO) " : "", file, func, line); - + } free(local_test_name); UNLOCK; @@ -172,8 +167,6 @@ _tap_init(void) { static int run_once = 0; - LOCK; - if(!run_once) { atexit(_cleanup); @@ -183,8 +176,6 @@ _tap_init(void) setbuf(stdout, 0); run_once = 1; } - - UNLOCK; } /* @@ -202,7 +193,7 @@ plan_no_plan(void) fprintf(stderr, "You tried to plan twice!\n"); test_died = 1; UNLOCK; - exit(exit_die); + exit(255); } have_plan = 1; @@ -229,7 +220,7 @@ plan_skip_all(const char *reason) printf("1..0"); if(reason != NULL) - printf(" # SKIP %s", reason); + printf(" # Skip %s", reason); printf("\n"); @@ -253,14 +244,14 @@ plan_tests(unsigned int tests) fprintf(stderr, "You tried to plan twice!\n"); test_died = 1; UNLOCK; - exit(exit_die); + exit(255); } if(tests == 0) { fprintf(stderr, "You said to run 0 tests! You've got to run something.\n"); test_died = 1; UNLOCK; - exit(exit_die); + exit(255); } have_plan = 1; @@ -269,7 +260,7 @@ plan_tests(unsigned int tests) UNLOCK; - return 1; + return e_tests; } unsigned int @@ -277,8 +268,6 @@ diag(const char *fmt, ...) { va_list ap; - LOCK; - fputs("# ", stderr); va_start(ap, fmt); @@ -287,36 +276,51 @@ diag(const char *fmt, ...) fputs("\n", stderr); - UNLOCK; - return 0; } void -_expected_tests(unsigned int tests) +diag_multiline(const char *val) { + size_t len, i, line_start_idx = 0; - LOCK; + assert(val); + len = strlen(val); + + for (i = 0; i < len; i++) { + int line_length; + + if (val[i] != '\n') { + continue; + } + + assert((i - line_start_idx + 1) <= INT_MAX); + line_length = i - line_start_idx + 1; + fprintf(stderr, "# %.*s", line_length, &val[line_start_idx]); + line_start_idx = i + 1; + } +} + +void +_expected_tests(unsigned int tests) +{ printf("1..%d\n", tests); e_tests = tests; - - UNLOCK; } int skip(unsigned int n, const char *fmt, ...) { va_list ap; - char *skip_msg; + char *skip_msg = NULL; LOCK; va_start(ap, fmt); - if (vasprintf(&skip_msg, fmt, ap) < 0) - { - skip_msg = NULL; - } + if (vasprintf(&skip_msg, fmt, ap) == -1) { + skip_msg = NULL; + } va_end(ap); while(n-- > 0) { @@ -341,10 +345,9 @@ todo_start(const char *fmt, ...) LOCK; va_start(ap, fmt); - if (vasprintf(&todo_msg, fmt, ap) < 0) - { - todo_msg = NULL; - } + if (vasprintf(&todo_msg, fmt, ap) == -1) { + todo_msg = NULL; + } va_end(ap); todo = 1; @@ -413,7 +416,7 @@ _cleanup(void) } if(test_died) { - diag("Looks like your test exited with %d just after %d.", exit_die, test_count); + diag("Looks like your test died just after %d.", test_count); UNLOCK; return; } @@ -426,22 +429,22 @@ _cleanup(void) } if((have_plan && !no_plan) && e_tests < test_count) { - diag("Looks like you planned %d test%s but ran %d extra.", - e_tests, e_tests == 1 ? "":"s", test_count - e_tests); + diag("Looks like you planned %d %s but ran %d extra.", + e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests); UNLOCK; return; } if((have_plan || !no_plan) && e_tests > test_count) { - diag("Looks like you planned %d test%s but ran %d.", - e_tests, e_tests == 1 ? "":"s", test_count); + diag("Looks like you planned %d %s but only ran %d.", + e_tests, e_tests == 1 ? "test" : "tests", test_count); UNLOCK; return; } if(failures) - diag("Looks like you failed %d test%s of %d.", - failures, failures == 1 ? "":"s", test_count); + diag("Looks like you failed %d %s of %d.", + failures, failures == 1 ? "test" : "tests", test_count); UNLOCK; } diff --git a/tests/tap/tap.h b/tests/tap/tap.h index c2dfb4b..b3e9445 100644 --- a/tests/tap/tap.h +++ b/tests/tap/tap.h @@ -1,114 +1,46 @@ -/*- - * Copyright (c) 2004 Nik Clayton - * All rights reserved. +/* + * SPDX-License-Identifier: BSD-2-Clause * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * Copyright (C) 2004 Nik Clayton + * Copyright (C) 2017 Jérémie Galarneau */ -/** - * plan_tests - announce the number of tests you plan to run - * @tests: the number of tests - * - * This should be the first call in your test program: it allows tracing - * of failures which mean that not all tests are run. - * - * If you don't know how many tests will actually be run, assume all of them - * and use skip() if you don't actually run some tests. - * - * Example: - * plan_tests(13); - */ -int plan_tests(unsigned int tests); -static inline int plan(unsigned int tests) -{ - return plan_tests(tests); -} -#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__GNUC__) -# error "Needs gcc or C99 compiler for variadic macros." -#else +/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting + and requires the caller to add the final comma if they've ommitted + the optional arguments */ +#ifdef __GNUC__ +# define ok(e, test, ...) ((e) ? \ + _gen_result(1, __func__, __FILE__, __LINE__, \ + test, ## __VA_ARGS__) : \ + _gen_result(0, __func__, __FILE__, __LINE__, \ + test, ## __VA_ARGS__)) -/** - * ok1 - Simple conditional test - * @e: the expression which we expect to be true. - * - * This is the simplest kind of test: if the expression is true, the - * test passes. The name of the test which is printed will simply be - * file name, line number, and the expression itself. - * - * Example: - * ok1(init_subsystem() == 1); - */ # define ok1(e) ((e) ? \ _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \ _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e)) -/** - * ok - Conditional test with a name - * @e: the expression which we expect to be true. - * @...: the printf-style name of the test. - * - * If the expression is true, the test passes. The name of the test will be - * the filename, line number, and the printf-style string. This can be clearer - * than simply the expression itself. - * - * Example: - * ok1(init_subsystem() == 1); - * ok(init_subsystem() == 0, "Second initialization should fail"); - */ +# define pass(test, ...) ok(1, test, ## __VA_ARGS__); +# define fail(test, ...) ok(0, test, ## __VA_ARGS__); + +# define skip_start(test, n, fmt, ...) \ + do { \ + if((test)) { \ + skip(n, fmt, ## __VA_ARGS__); \ + continue; \ + } +#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */ # define ok(e, ...) ((e) ? \ _gen_result(1, __func__, __FILE__, __LINE__, \ __VA_ARGS__) : \ _gen_result(0, __func__, __FILE__, __LINE__, \ __VA_ARGS__)) -/** - * pass - Note that a test passed - * @...: the printf-style name of the test. - * - * For complicated code paths, it can be easiest to simply call pass() in one - * branch and fail() in another. - * - * Example: - * x = do_something(); - * if (!checkable(x) || check_value(x)) - * pass("do_something() returned a valid value"); - * else - * fail("do_something() returned an invalid value"); - */ -# define pass(...) ok(1, __VA_ARGS__) - -/** - * fail - Note that a test failed - * @...: the printf-style name of the test. - * - * For complicated code paths, it can be easiest to simply call pass() in one - * branch and fail() in another. - */ -# define fail(...) ok(0, __VA_ARGS__) +# define ok1(e) ((e) ? \ + _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \ + _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e)) -/* I don't find these to be useful. */ -# define skip_if(cond, n, ...) \ - if (cond) skip((n), __VA_ARGS__); \ - else +# define pass(...) ok(1, __VA_ARGS__); +# define fail(...) ok(0, __VA_ARGS__); # define skip_start(test, n, ...) \ do { \ @@ -116,134 +48,35 @@ static inline int plan(unsigned int tests) skip(n, __VA_ARGS__); \ continue; \ } +#else /* __STDC_VERSION__ */ +# error "Needs gcc or C99 compiler for variadic macros." +#endif /* __STDC_VERSION__ */ -# define skip_end } while(0) +#define skip_end() } while(0); -#ifndef PRINTF_ATTRIBUTE -#ifdef __GNUC__ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#ifdef __MINGW_PRINTF_FORMAT +# define TAP_PRINTF_FORMAT __MINGW_PRINTF_FORMAT #else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif +# define TAP_PRINTF_FORMAT printf #endif -unsigned int _gen_result(int, const char *, const char *, unsigned int, - const char *, ...) PRINTF_ATTRIBUTE(5, 6); +__attribute__((format(TAP_PRINTF_FORMAT, 5, 6))) +unsigned int _gen_result(int, const char *, const char *, unsigned int, const char *, ...); -/** - * diag - print a diagnostic message (use instead of printf/fprintf) - * @fmt: the format of the printf-style message - * - * diag ensures that the output will not be considered to be a test - * result by the TAP test harness. It will append '\n' for you. - * - * Example: - * diag("Now running complex tests"); - */ -unsigned int diag(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2); +int plan_no_plan(void); +__attribute__((noreturn)) +int plan_skip_all(const char *); +int plan_tests(unsigned int); -/** - * skip - print a diagnostic message (use instead of printf/fprintf) - * @n: number of tests you're skipping. - * @fmt: the format of the reason you're skipping the tests. - * - * Sometimes tests cannot be run because the test system lacks some feature: - * you should explicitly document that you're skipping tests using skip(). - * - * From the Test::More documentation: - * If it's something the user might not be able to do, use SKIP. This - * includes optional modules that aren't installed, running under an OS that - * doesn't have some feature (like fork() or symlinks), or maybe you need an - * Internet connection and one isn't available. - * - * Example: - * #ifdef HAVE_SOME_FEATURE - * ok1(test_some_feature()); - * #else - * skip(1, "Don't have SOME_FEATURE"); - * #endif - */ -int skip(unsigned int n, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3); +__attribute__((format(TAP_PRINTF_FORMAT, 1, 2))) +unsigned int diag(const char *, ...); +void diag_multiline(const char *); -/** - * todo_start - mark tests that you expect to fail. - * @fmt: the reason they currently fail. - * - * It's extremely useful to write tests before you implement the matching fix - * or features: surround these tests by todo_start()/todo_end(). These tests - * will still be run, but with additional output that indicates that they are - * expected to fail. - * - * This way, should a test start to succeed unexpectedly, tools like prove(1) - * will indicate this and you can move the test out of the todo block. This - * is much more useful than simply commenting out (or '#if 0') the tests. - * - * From the Test::More documentation: - * If it's something the programmer hasn't done yet, use TODO. This is for - * any code you haven't written yet, or bugs you have yet to fix, but want to - * put tests in your testing script (always a good idea). - * - * Example: - * todo_start("dwim() not returning true yet"); - * ok(dwim(), "Did what the user wanted"); - * todo_end(); - */ -void todo_start(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2); +__attribute__((format(TAP_PRINTF_FORMAT, 2, 3))) +int skip(unsigned int, const char *, ...); -/** - * todo_end - end of tests you expect to fail. - * - * See todo_start(). - */ +__attribute__((format(TAP_PRINTF_FORMAT, 1, 2))) +void todo_start(const char *, ...); void todo_end(void); -/** - * exit_status - the value that main should return. - * - * For maximum compatability your test program should return a particular exit - * code (ie. 0 if all tests were run, and every test which was expected to - * succeed succeeded). - * - * Example: - * exit(exit_status()); - */ int exit_status(void); - -/** - * plan_no_plan - I have no idea how many tests I'm going to run. - * - * In some situations you may not know how many tests you will be running, or - * you are developing your test program, and do not want to update the - * plan_tests() call every time you make a change. For those situations use - * plan_no_plan() instead of plan_tests(). It indicates to the test harness - * that an indeterminate number of tests will be run. - * - * Remember, if you fail to plan, you plan to fail. - * - * Example: - * plan_no_plan(); - * while (random() % 2) - * ok1(some_test()); - * exit(exit_status()); - */ -int plan_no_plan(void); - -/** - * plan_skip_all - Indicate that you will skip all tests. - * @reason: the string indicating why you can't run any tests. - * - * If your test program detects at run time that some required functionality - * is missing (for example, it relies on a database connection which is not - * present, or a particular configuration option that has not been included - * in the running kernel) use plan_skip_all() instead of plan_tests(). - * - * Example: - * if (!have_some_feature) { - * plan_skip_all("Need some_feature support"); - * exit(exit_status()); - * } - * plan_tests(13); - */ -int plan_skip_all(const char *reason); - -#endif /* C99 or gcc */