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


Reply via email to