The shell variables $as_echo and $as_echo_n and the substitution variables @ECHO_C@, @ECHO_N@, and @ECHO_T@ are implementation details of the old implementation of AS_ECHO and AS_ECHO_N (2.69-era; before the switch to use ‘printf’). We continue to provide them for compatibility with various third-party macros and Makefiles that used them, even though, as far as I can tell, they were never documented. (Someone made ECHO_C etc. substitution variables on purpose, though.)
For $as_echo and $as_echo_n, we can tell precisely when they are needed, because all uses are exposed to M4 macro expansion. Therefore, emit the necessary support code on first use and not from AS_INIT. As a side effect this means the -Wobsolete warning only appears on the first use of each, which IMHO is polite. For @ECHO_C@, @ECHO_N@, and @ECHO_T@, we have no way of knowing whether a substitution variable is used, but we *do* know that substitution variables are exclusively a configure.ac thing, so their support code can be moved to general.m4 and emitted from AC_INIT rather than from AS_INIT. (It’s faintly possible that someone decided to use $ECHO_C in an Autotest script but considering how rare it is for people to use Autotest at all, or any other non-Autoconf application of M4sh, I think we can worry about that when we hear about it.) * lib/m4sugar/m4sh.m4 (_AS_ECHO_N_PREPARE): Removed. (AS_PREPARE, _AS_PREPARE): Don’t use _AS_ECHO_N_PREPARE. (_as_echo_var_prepare, _as_echo_n_var_prepare): New macros which emit the -Wobsolete warning and the support code for $as_echo and $as_echo_n respectively. (as_echo, as_echo_n): Move to bottom of the block that sets up the current implementation of AS_ECHO. Invoke _as_echo_var_prepare and _as_echo_n_var_prepare, respectively, on first use. * lib/autoconf/general.m4 (_AC_INIT_ECHO_N): New internal macro, contains the probe code that used to be in _AS_ECHO_N_PREPARE. AC_SUBSTs ECHO_C, ECHO_N, and ECHO_T. (AC_INIT): Don’t AC_SUBST ECHO_C, ECHO_N, and ECHO_T here. Invoke _AC_INIT_ECHO_N. --- lib/autoconf/general.m4 | 44 +++++++++++++++-- lib/m4sugar/m4sh.m4 | 106 ++++++++++++++++++++-------------------- tests/m4sh.at | 73 ++++++++++++++------------- 3 files changed, 133 insertions(+), 90 deletions(-) diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4 index 4f64186e..f5ad64ba 100644 --- a/lib/autoconf/general.m4 +++ b/lib/autoconf/general.m4 @@ -1401,6 +1401,44 @@ m4_divert_pop([INIT_PREPARE])dnl ])# _AC_INIT_PREPARE +# _AC_INIT_ECHO_N +# --------------- +# Emit code for backward compatibility with Makefiles that use the +# ECHO_C, ECHO_N, and ECHO_T substitution variables. From Autoconf's +# perspective, these were undocumented internals of the old definition +# of AS_ECHO_N, before that was changed to use 'printf' instead of +# 'echo', but they were AC_SUBSTed and Makefiles were written to use +# them. We don't have any way to know whether substitution variables +# are actually used in the project being configured, and the cost of +# this test is minimal. +# +# Test logic borrowed from dist 3.0. Use '*c*,', not '*c,' because if '\c' +# failed there is also a newline to match. Use 'xy' because '\c' echoed +# in a command substitution prints only the first character of the output +# with ksh version M-11/16/88f on AIX 6.1; it needs to be reset by another +# backquoted echo. +m4_define([_AC_INIT_ECHO_N], [ +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in @%:@((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac +AC_SUBST([ECHO_C])dnl +AC_SUBST([ECHO_N])dnl +AC_SUBST([ECHO_T])dnl +]) + + # AU::AC_INIT([UNIQUE-FILE-IN-SOURCE-DIR]) # ---------------------------------------- # This macro is used only for Autoupdate. @@ -1457,14 +1495,14 @@ m4_ifval([$2], , [m4_ifval([$1], [AC_CONFIG_SRCDIR([$1])])])dnl dnl dnl Substitute for predefined variables. AC_SUBST([DEFS])dnl -AC_SUBST([ECHO_C])dnl -AC_SUBST([ECHO_N])dnl -AC_SUBST([ECHO_T])dnl AC_SUBST([LIBS])dnl _AC_ARG_VAR_PRECIOUS([build_alias])AC_SUBST([build_alias])dnl _AC_ARG_VAR_PRECIOUS([host_alias])AC_SUBST([host_alias])dnl _AC_ARG_VAR_PRECIOUS([target_alias])AC_SUBST([target_alias])dnl dnl +dnl Backward compatibility with old Makefiles and old macros. +_AC_INIT_ECHO_N +dnl AC_LANG_PUSH(C) dnl dnl Record that AC_INIT has been called. It doesn't make sense to diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4 index f6580d07..ba6d5409 100644 --- a/lib/m4sugar/m4sh.m4 +++ b/lib/m4sugar/m4sh.m4 @@ -365,7 +365,6 @@ _AS_BASENAME_PREPARE _AS_DIRNAME_PREPARE _AS_ME_PREPARE _AS_CR_PREPARE -_AS_ECHO_N_PREPARE _AS_LN_S_PREPARE _AS_MKDIR_P_PREPARE _AS_TEST_PREPARE @@ -389,7 +388,6 @@ AS_REQUIRE([_AS_DIRNAME_PREPARE]) AS_REQUIRE([_AS_ME_PREPARE]) AS_REQUIRE([_AS_CR_PREPARE]) AS_REQUIRE([_AS_LINENO_PREPARE]) -AS_REQUIRE([_AS_ECHO_N_PREPARE]) AS_REQUIRE([_AS_EXIT_PREPARE]) AS_REQUIRE([_AS_LN_S_PREPARE]) AS_REQUIRE([_AS_MKDIR_P_PREPARE]) @@ -852,47 +850,6 @@ m4_defun_init([_AS_ECHO_LOG], [_AS_ECHO([$as_me:${as_lineno-$LINENO}: $1], AS_MESSAGE_LOG_FD)]) -# _AS_ECHO_N_PREPARE -# ------------------ -# Check whether to use -n, \c, or newline-tab to separate -# checking messages from result messages. -# Don't try to cache, since the results of this macro are needed to -# display the checking message. In addition, caching something used once -# has little interest. -# Idea borrowed from dist 3.0. Use '*c*,', not '*c,' because if '\c' -# failed there is also a newline to match. Use 'xy' because '\c' echoed -# in a command substitution prints only the first character of the output -# with ksh version M-11/16/88f on AIX 6.1; it needs to be reset by another -# backquoted echo. -m4_defun([_AS_ECHO_N_PREPARE], [ -# Determine whether it's possible to make 'echo' print without a newline. -# These variables are no longer used directly by Autoconf, but are AC_SUBSTed -# for compatibility with existing Makefiles. -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in @%:@((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -# For backward compatibility with old third-party macros, we provide -# the shell variables $as_echo and $as_echo_n. New code should use -# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. -dnl The @&t@ prevents a spurious deprecation diagnostic. -dnl Extra quoting in case 's' or 'n' are user-defined macros when this -dnl is expanded; they almost certainly aren't meant to be used here. -dnl See bug 110377. -as_@&t@echo='printf [%s\n]' -as_@&t@echo_n='printf [%s]' -])# _AS_ECHO_N_PREPARE - - # _AS_ECHO_N(STRING, [FD = AS_MESSAGE_FD]) # ---------------------------------------- # Same as _AS_ECHO, but echo doesn't return to a new line. @@ -978,6 +935,59 @@ m4_defun([AS_LINENO_POP], [eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno]) +# as_echo +# ------- +# Define the obsolete internal shell variable as_echo if necessary. +# It is known to be used by some third party macros. New code should +# use AS_ECHO(["message"]). +# +# This macro will typically be used like +# $as_echo "message" +# and that line of the script must not be changed by the expansion; +# especially, we cannot introduce whitespace between '$' and 'a'. +# This means we cannot use m4_require and we need to invoke +# _as_echo_var_prepare with call parentheses. +m4_defun([as_echo], +[m4_provide_if([_as_echo_var_prepare], [], [_as_echo_var_prepare()])]dnl +[as@&t@_echo]) + +# _as_echo_var_prepare +# -------------------- +# The @&t@ prevents recursive expansion. +# Extra quoting in case 's' or 'n' are user-defined macros when this +# is expanded; they almost certainly aren't meant to be used here. +# See bug 110377. +m4_defun([_as_echo_var_prepare], +[m4_warn([obsolete], + [$as_echo is obsolete; use AS_ECHO(["message"]) instead])]dnl +[m4_divert_once([M4SH-INIT], [ +# Provided for backward compatibility. Change uses to AS_ECHO(["message"]). +as@&t@_echo='printf [%s\n]'])]) + +# as_echo_n +# --------- +# Define the obsolete internal shell variable as_echo_n if necessary. +# It is known to be used by some third party macros. New code should +# use AS_ECHO_N(["message"]). +# See as_echo for implementation notes. +m4_defun([as_echo_n], +[m4_provide_if([_as_echo_n_var_prepare], [], [_as_echo_n_var_prepare()])]dnl +[as@&t@_echo_n]) + +# _as_echo_n_var_prepare +# ---------------------- +# The @&t@ prevents recursive expansion. +# Extra quoting in case 's' or 'n' are user-defined macros when this +# is expanded; they almost certainly aren't meant to be used here. +# See bug 110377. +m4_defun([_as_echo_n_var_prepare], +[m4_warn([obsolete], + [$as_echo_n is obsolete; use AS_ECHO_N(["message"]) instead])]dnl +[m4_divert_once([M4SH-INIT], [ +# Provided for backward compatibility. Change uses to AS_ECHO_N(["message"]). +as@&t@_echo_n='printf [%s]'])]) + + ## -------------------------------------- ## ## 4. Portable versions of common tools. ## @@ -1102,11 +1112,6 @@ dnl is expanded; they almost certainly aren't meant to be used here. dnl See bug 110377. [printf "[%s\n]" $1]) -# Deprecation warning for the former internal shell variable $as_echo. -m4_define([as_echo], -[m4_warn([obsolete], - [$as_echo is obsolete; use AS_ECHO(["message"]) instead])as_@&t@echo]) - # AS_ECHO_N(WORD) # --------------- @@ -1117,11 +1122,6 @@ dnl is expanded; it almost certainly isn't meant to be used here. dnl See bug 110377. [printf [%s] $1]) -# Deprecation warning for the former internal shell variable $as_echo_n. -m4_define([as_echo_n], -[m4_warn([obsolete], - [$as_echo_n is obsolete; use AS_ECHO_N(["message"]) instead])as_@&t@echo_n]) - # AS_TEST_X # --------- diff --git a/tests/m4sh.at b/tests/m4sh.at index 8bf0c896..ae85f97c 100644 --- a/tests/m4sh.at +++ b/tests/m4sh.at @@ -564,7 +564,6 @@ AT_KEYWORDS([m4sh]) AT_DATA_M4SH([script.as], [[AS_INIT -AS_REQUIRE([_AS_ECHO_N_PREPARE]) m4_define([ECHO_TEST], [echo=`$as_echo '$1'` @@ -598,36 +597,14 @@ AS_EXIT(0) ]]) AT_CHECK_M4SH([], 0, [], -[[script.as:13: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:13: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:14: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:14: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:15: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:15: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:16: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:16: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:17: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:17: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:18: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:18: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:19: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:19: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:20: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:20: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:21: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:21: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:22: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:22: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:23: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:23: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:24: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:24: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:25: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:25: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:28: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:28: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead -script.as:30: warning: $as@&t@_echo is obsolete; use AS@&t@_ECHO(["message"]) instead -script.as:30: warning: $as@&t@_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead +[[script.as:12: warning: $as_echo is obsolete; use AS@&t@_ECHO(["message"]) instead +m4sh.m4: _as_echo_var_prepare is expanded from... +m4sh.m4: as_echo is expanded from... +script.as:12: the top level +script.as:12: warning: $as_echo_n is obsolete; use AS@&t@_ECHO_N(["message"]) instead +m4sh.m4: _as_echo_n_var_prepare is expanded from... +m4sh.m4: as_echo_n is expanded from... +script.as:12: the top level ]]) AT_CHECK([$CONFIG_SHELL ./script]) @@ -645,17 +622,19 @@ AT_SETUP([Redefining AS@&t@_ECHO internals]) # this file to exist anyway. AT_DATA([config.hin]) -# Defining a macro named 's' or 'n' should not affect AS_ECHO or +# Defining a macro named 's', 'n', or 'c' should not affect AS_ECHO or # macros that use it. AT_CONFIGURE_AC( [[m4@&t@_pushdef([s], [z]) m4@&t@_pushdef([n], [u]) +m4@&t@_pushdef([c], [d]) AC_MSG_NOTICE([checking whether m4sugar echo works... yes]) AC_MSG_CHECKING([whether m4sugar echo_n works]) AC_MSG_RESULT([yes]) m4@&t@_popdef([s]) m4@&t@_popdef([n]) +m4@&t@_popdef([c]) ]]) AT_CHECK_AUTOCONF @@ -668,8 +647,32 @@ config.status: creating config.h AT_CHECK_ENV rm config.h -# More elaborate version of the above; derived from actual code in -# ruby 2.7.2's configure script. +# Defining 's', 'n', or 'c' also should not affect use of the +# obsolete $as_echo and $as_echo_n macros. +AT_CONFIGURE_AC( +[[m4@&t@_pushdef([s], [z]) +m4@&t@_pushdef([n], [u]) +m4@&t@_pushdef([c], [d]) +$as_echo "checking whether obsolete \$as_echo works... yes" +$as_echo_n "checking whether obsolete \$as_echo_n works... " +$as_echo yes +m4@&t@_popdef([s]) +m4@&t@_popdef([n]) +m4@&t@_popdef([c]) +]]) + +AT_CHECK_AUTOCONF([-Wno-obsolete]) +AT_CHECK_CONFIGURE([], [], +[[checking whether obsolete $as@&t@_echo works... yes +checking whether obsolete $as@&t@_echo_n works... yes +configure: creating ./config.status +config.status: creating config.h +]], []) +AT_CHECK_ENV +rm config.h + +# A more realistic scenario, derived from actual code in ruby 2.7.2's +# configure script. AT_CONFIGURE_AC( [[AC@&t@_DEFUN([RUBY_CHECK_SIZEOF],[ @@ -689,6 +692,8 @@ RUBY_CHECK_SIZEOF(int) echo "ac_cv_sizeof_int=${ac_cv_sizeof_int}" ]]) + + AT_CHECK_AUTOCONF AT_CHECK_CONFIGURE([], [], [[checking size of int... 1 -- 2.44.2