[PATCH] AC_CONFIG_COMMANDS_PRE/POST: fix nested command registrations.

Nick Bowler <[email protected]>
Newsgroups gmane.comp.sysutils.autoconf.patches,gmane.comp.sysutils.autoconf.general
Message-ID <[email protected]>
Currently, if a command registered with AC_CONFIG_COMMANDS_PRE itself
calls AC_CONFIG_COMMANDS_PRE, such commands will never be executed.
This occurs because each invocation of AC_CONFIG_COMMANDS_PRE appends
the argument to one big macro (AC_OUTPUT_COMMANDS_PRE) which is then
expanded once near the end of the configure output.

To solve this, we can keep track of the command registrations that occur
during expansion of AC_OUTPUT_COMMANDS_PRE, then after the original
registrations have been handled, output *those* commands, and so on
until there are no more commands.  This is similar to how atexit
works in the C library (although atexit uses a last-in first-out
ordering, whereas this implementation is first-in first-out).

* lib/m4sugar/m4sugar.m4 (m4_output_rec): New macro to help perform
this command expansion loop.
* lib/autoconf/status.m4 (AC_OUTPUT): Use m4_output_rec to expand
AC_OUTPUT_COMMANDS_PRE and AC_OUTPUT_COMMANDS_POST
* tests/base.at (AC_CONFIG_COMMANDS_PRE/POST: nested invocation): New
test.
---
 lib/autoconf/status.m4 |    4 ++--
 lib/m4sugar/m4sugar.m4 |   21 +++++++++++++++++++++
 tests/base.at          |   21 +++++++++++++++++++++
 3 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/lib/autoconf/status.m4 b/lib/autoconf/status.m4
index d125843..9b6e13c 100644
--- a/lib/autoconf/status.m4
+++ b/lib/autoconf/status.m4
@@ -1268,7 +1268,7 @@ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
 m4_ifdef([_AC_SEEN_CONFIG(HEADERS)], [DEFS=-DHAVE_CONFIG_H], [AC_OUTPUT_MAKE_DEFS()])
 
 dnl Commands to run before creating config.status.
-AC_OUTPUT_COMMANDS_PRE()dnl
+m4_output_rec([AC_OUTPUT_COMMANDS_PRE])dnl
 
 : "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
@@ -1281,7 +1281,7 @@ test $ac_write_fail = 0 ||
   AC_MSG_ERROR([write failure creating $CONFIG_STATUS])
 
 dnl Commands to run after config.status was created
-AC_OUTPUT_COMMANDS_POST()dnl
+m4_output_rec([AC_OUTPUT_COMMANDS_POST])dnl
 
 # configure is writing to config.log, and then calls config.status.
 # config.status does its own redirection, appending to config.log.
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index b732abc..f2e04c3 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -1305,6 +1305,27 @@ m4_define([_m4_map_args_w],
 [m4_substr([$1], [$2], m4_eval(m4_len([$1]) - [$2] - [$3]))])
 
 
+# _m4_output_rec(MACRO)
+# ---------------------
+# Internal recursive part of m4_output_rec.  This clobbers the definition of
+# MACRO so it should not be called directly.
+m4_define([_m4_output_rec], [m4_ifnblank(m4_defn([$1]),
+[m4_define([$1], [m4_define([$1])]m4_defn([$1]))dnl
+m4_indir([$1])dnl
+_m4_output_rec([$1])])])
+
+
+# m4_output_rec(MACRO)
+# --------------------
+# Until the definition of MACRO is empty, repeatedly expand MACRO in a
+# context where it has been redefined to the empty string.  The original
+# definition of MACRO is restored after all expansion is complete.
+m4_define([m4_output_rec],
+[m4_pushdef([$1], m4_defn([$1]))dnl
+_m4_output_rec([$1])dnl
+m4_popdef([$1])])
+
+
 # m4_stack_foreach(MACRO, FUNC)
 # m4_stack_foreach_lifo(MACRO, FUNC)
 # ----------------------------------
diff --git a/tests/base.at b/tests/base.at
index 87a0417..35bfd48 100644
--- a/tests/base.at
+++ b/tests/base.at
@@ -767,3 +767,24 @@ FOO
 ]])
 
 AT_CLEANUP
+
+
+# -------------------------------------- #
+# Nested AC_CONFIG_COMMANDS_{PRE,POST}.  #
+# -------------------------------------- #
+
+AT_SETUP([AC_CONFIG_COMMANDS_PRE/POST: nested invocation])
+AT_KEYWORDS([AC@&t@_CONFIG_COMMANDS_PRE AC@&t@_CONFIG_COMMANDS_POST
+AC@&t@_OUTPUT m4@&t@_output_rec])
+
+AT_DATA([configure.ac],
+[[AC_INIT([test], [1])
+AC_CONFIG_COMMANDS_PRE([AC_CONFIG_COMMANDS_PRE([m4_define([okpre])])])
+AC_CONFIG_COMMANDS_POST([AC_CONFIG_COMMANDS_POST([m4_define([okpost])])])
+AC_OUTPUT
+m4@&t@_ifndef([okpre], [m4][_fatal([dropped nested AC_CONFIG_COMMANDS_PRE])])
+m4@&t@_ifndef([okpost], [m4][_fatal([dropped nested AC_CONFIG_COMMANDS_POST])])
+]])
+AT_CHECK_AUTOCONF([], [], [], [stderr])
+
+AT_CLEANUP
-- 
1.7.8.6
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.