From: Eric Blake Date: Thu, 30 Oct 2008 21:32:56 +0000 (-0600) Subject: Simplify diversion stack handling. X-Git-Tag: v2.63b~152 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f4363abb6ea4803dd85e9fa55f569b6e641b8c8;p=thirdparty%2Fautoconf.git Simplify diversion stack handling. * lib/m4sugar/m4sugar.m4 (m4_divert_stack): Use fewer macros, and avoid extra newlines. (m4_divert_stack_push): Compute location here, rather than caller. (m4_divert_push): Update caller. (m4_divert): Likewise, and also adjust current diversion name. (m4_divert_pop): Simplify rule that diversion stack must never go empty. (_m4_require_call): Bypass diversion stack when collecting required macro text. (m4_init): Set current diversion without requiring m4_init. * lib/m4sugar/m4sh.m4 (AS_INIT): Avoid too many pops. * lib/autotest/general.m4 (AT_INIT): Likewise. * lib/autoconf/general.m4 (_AC_INIT_DEFAULTS): Schedule wrapped text to run prior to m4sugar cleanup. * doc/autoconf.texi (Text processing Macros) : Mention optional argument. (Conditional constructs) : Mention use of dnl. * NEWS: Undo blurb about m4_divert. * tests/m4sugar.at (m4@&t@_divert_stack): New test. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 18c291952..ef29a6e44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,26 @@ 2008-10-31 Eric Blake + Simplify diversion stack handling. + * lib/m4sugar/m4sugar.m4 (m4_divert_stack): Use fewer macros, and + avoid extra newlines. + (m4_divert_stack_push): Compute location here, rather than caller. + (m4_divert_push): Update caller. + (m4_divert): Likewise, and also adjust current diversion name. + (m4_divert_pop): Simplify rule that diversion stack must never go + empty. + (_m4_require_call): Bypass diversion stack when collecting + required macro text. + (m4_init): Set current diversion without requiring m4_init. + * lib/m4sugar/m4sh.m4 (AS_INIT): Avoid too many pops. + * lib/autotest/general.m4 (AT_INIT): Likewise. + * lib/autoconf/general.m4 (_AC_INIT_DEFAULTS): Schedule wrapped + text to run prior to m4sugar cleanup. + * doc/autoconf.texi (Text processing Macros) : Mention + optional argument. + (Conditional constructs) : Mention use of dnl. + * NEWS: Undo blurb about m4_divert. + * tests/m4sugar.at (m4@&t@_divert_stack): New test. + Simplify expansion stack handling. * lib/m4sugar/m4sugar.m4 (m4_expansion_stack): Use fewer macros; always output 'top level'. diff --git a/NEWS b/NEWS index d07c14364..e22559ff2 100644 --- a/NEWS +++ b/NEWS @@ -12,8 +12,6 @@ GNU Autoconf NEWS - User visible changes. ** Configure scripts now use shell functions. -** m4sugar requires m4_init in order to use m4_divert. - ** The following documented m4sugar macros are new: m4_curry m4_default_quoted m4_map_args m4_map_args_pair m4_set_map diff --git a/doc/autoconf.texi b/doc/autoconf.texi index 35c9bfa9c..c50cee47d 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -10824,12 +10824,13 @@ m4_if([@var{cond}], [], [@var{if-true}], [@var{if-false}]) @defmac m4_ifvaln (@var{cond}, @ovar{if-true}, @ovar{if-false}) @msindex{ifvaln} Similar to @code{m4_ifval}, except guarantee that a newline is present -after any non-empty expansion. +after any non-empty expansion. Often followed by @code{dnl}. @end defmac @defmac m4_n (@var{text}) @msindex{n} Expand to @var{text}, and add a newline if @var{text} is not empty. +Often followed by @code{dnl}. @end defmac @@ -11432,9 +11433,10 @@ them, to form a quoted list suitable for @code{m4_foreach}, it is more efficient to use @code{m4_dquote}. @end defmac -@defmac m4_newline +@defmac m4_newline (@ovar{text}) @msindex{newline} -This macro was introduced in Autoconf 2.62, and expands to a newline. +This macro was introduced in Autoconf 2.62, and expands to a newline, +followed by any @var{text}. It is primarily useful for maintaining macro formatting, and ensuring that M4 does not discard leading whitespace during argument collection. @end defmac diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4 index ccaf3400e..c990c0558 100644 --- a/lib/autoconf/general.m4 +++ b/lib/autoconf/general.m4 @@ -433,7 +433,7 @@ AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])])dnl m4_divert_pop([DEFAULTS])dnl -m4_wrap([m4_divert_text([DEFAULTS], +m4_wrap_lifo([m4_divert_text([DEFAULTS], [ac_subst_vars='m4_set_dump([_AC_SUBST_VARS], m4_newline)' ac_subst_files='m4_ifdef([_AC_SUBST_FILES], [m4_defn([_AC_SUBST_FILES])])' ac_user_opts=' diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4 index 03d39024e..68f75d879 100644 --- a/lib/autotest/general.m4 +++ b/lib/autotest/general.m4 @@ -1423,8 +1423,7 @@ m4_divert_pop([TESTS])dnl dnl End of AT_INIT: divert to KILL, only test groups are to be dnl output, the rest is ignored. Current diversion is BODY, inherited dnl from M4sh. -m4_divert_pop([BODY]) -m4_divert_push([KILL]) +m4_divert([KILL]) ])# AT_INIT diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4 index 1a6172989..a506ef06d 100644 --- a/lib/m4sugar/m4sh.m4 +++ b/lib/m4sugar/m4sh.m4 @@ -235,8 +235,8 @@ dnl Remove any tests from suggested that are also required as_shell=$as_dir/$as_base AS_IF([{ test -f "$as_shell" || test -f "$as_shell.exe"; } && _AS_RUN(["$as_required"], ["$as_shell"])], - [CONFIG_SHELL=$as_shell as_have_required=yes - m4_set_empty([_AS_DETECT_SUGGESTED_BODY], [break 2], + [CONFIG_SHELL=$as_shell as_have_required=yes + m4_set_empty([_AS_DETECT_SUGGESTED_BODY], [break 2], [AS_IF([_AS_RUN(["$as_suggested"], ["$as_shell"])], [break 2])])]) done;; @@ -1906,8 +1906,7 @@ m4_divert_text([M4SH-SANITIZE], [_AS_SHELL_SANITIZE]) m4_divert_text([M4SH-INIT-FN], [m4_text_box([M4sh Shell Functions.])]) # Let's go! -m4_divert_pop([KILL])[]dnl -m4_divert_push([BODY]) +m4_divert([BODY])dnl m4_text_box([Main body of script.]) _AS_DETECT_REQUIRED([_AS_SHELL_FN_WORK])dnl AS_REQUIRE([_AS_UNSET_PREPARE], [], [M4SH-INIT-FN])dnl diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index 9a0d184b3..fc912e24a 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -1258,16 +1258,19 @@ m4_define([_m4_divert()], 0) # m4_divert_stack # ------------------ -# Print m4_divert_stack with newline prepended, if it's nonempty. +# Print the diversion stack, if it's nonempty. The caller is +# responsible for any leading or trailing newline. m4_define([m4_divert_stack], -[m4_stack_foreach_lifo([_m4_divert_stack], [m4_newline])]) +[m4_stack_foreach_sep_lifo([_m4_divert_stack], [], [], [ +])]) -# m4_divert_stack_push(LOCATION, MACRO-NAME, DIVERSION-NAME) -# ----------------------------------------------------------- -# Form an entry of the diversion stack and push it. +# m4_divert_stack_push(MACRO-NAME, DIVERSION-NAME) +# ------------------------------------------------ +# Form an entry of the diversion stack from caller MACRO-NAME and +# entering DIVERSION-NAME and push it. m4_define([m4_divert_stack_push], -[m4_pushdef([_m4_divert_stack], [[$1: $2: $3]])]) +[m4_pushdef([_m4_divert_stack], m4_location[: $1: $2])]) # m4_divert(DIVERSION-NAME) @@ -1275,7 +1278,8 @@ m4_define([m4_divert_stack_push], # Change the diversion stream to DIVERSION-NAME. m4_define([m4_divert], [m4_popdef([_m4_divert_stack])]dnl -[m4_divert_stack_push(m4_location, [$0], [$1])]dnl +[m4_define([_m4_divert_diversion], [$1])]dnl +[m4_divert_stack_push([$0], [$1])]dnl [m4_builtin([divert], _m4_divert([$1]))]) @@ -1283,7 +1287,7 @@ m4_define([m4_divert], # ------------------------------ # Change the diversion stream to DIVERSION-NAME, while stacking old values. m4_define([m4_divert_push], -[m4_divert_stack_push(m4_location, [$0], [$1])]dnl +[m4_divert_stack_push([$0], [$1])]dnl [m4_pushdef([_m4_divert_diversion], [$1])]dnl [m4_builtin([divert], _m4_divert([$1]))]) @@ -1294,16 +1298,14 @@ m4_define([m4_divert_push], # If specified, verify we left DIVERSION-NAME. # When we pop the last value from the stack, we divert to -1. m4_define([m4_divert_pop], -[m4_ifndef([_m4_divert_diversion], - [m4_fatal([too many m4_divert_pop])])]dnl [m4_if([$1], [], [], [$1], _m4_defn([_m4_divert_diversion]), [], - [m4_fatal([$0($1): diversion mismatch: ]m4_divert_stack)])]dnl + [m4_fatal([$0($1): diversion mismatch: +]m4_divert_stack)])]dnl [_m4_popdef([_m4_divert_stack], [_m4_divert_diversion])]dnl -[m4_builtin([divert], - m4_ifdef([_m4_divert_diversion], - [_m4_divert(_m4_defn([_m4_divert_diversion]))], - -1))]) +[m4_ifdef([_m4_divert_diversion], [], + [m4_fatal([too many m4_divert_pop])])]dnl +[m4_builtin([divert], _m4_divert(_m4_defn([_m4_divert_diversion])))]) # m4_divert_text(DIVERSION-NAME, CONTENT) @@ -1839,8 +1841,8 @@ m4_provide_if([$1], [], [m4_warn([syntax], [$1 is m4_require'd but not m4_defun'd])])]], - [[m4_divert($3)]], - [[m4_undivert(_m4_divert_grow)]], + [[m4_builtin([divert], _m4_divert($3))]], + [[m4_builtin([undivert], _m4_divert_grow)]], [[m4_divert_pop(_m4_divert_grow)]], [[m4_define([_m4_divert_grow], m4_incr(_m4_divert_grow))]])) @@ -2933,6 +2935,8 @@ m4_if(m4_sysval, [0], [], ## 17. Setting M4sugar up. ## ## ------------------------ ## +# _m4_divert_diversion should be defined. +m4_divert_push([KILL]) # m4_init # ------- @@ -2958,11 +2962,14 @@ m4_define([m4_popdef], _m4_defn([m4_popdef])) m4_define([m4_undefine], _m4_defn([m4_undefine]))], [m4_builtin([include], [m4sugar/foreach.m4])]) -# _m4_divert_diversion should be defined: -m4_divert_push([KILL]) +# Rewrite the first entry of the diversion stack. +m4_divert([KILL]) # Check the divert push/pop perfect balance. -m4_wrap([m4_divert_pop([]) - m4_ifdef([_m4_divert_diversion], - [m4_fatal([$0: unbalanced m4_divert_push:]m4_divert_stack)])[]]) +# Some users are prone to also use m4_wrap to register last-minute +# m4_divert_text; so after our diversion cleanups, we restore +# KILL as the bottom of the diversion stack. +m4_wrap([m4_popdef([_m4_divert_diversion])m4_ifdef( + [_m4_divert_diversion], [m4_fatal([$0: unbalanced m4_divert_push: +]m4_divert_stack)])_m4_popdef([_m4_divert_stack])m4_divert_push([KILL])]) ]) diff --git a/tests/m4sugar.at b/tests/m4sugar.at index d8554b562..8034ced43 100644 --- a/tests/m4sugar.at +++ b/tests/m4sugar.at @@ -243,6 +243,74 @@ script.4s:6: the top level AT_CLEANUP +## ----------------- ## +## m4_divert_stack. ## +## ----------------- ## + +AT_SETUP([m4@&t@_divert_stack]) + +AT_CHECK_M4SUGAR_TEXT([[1.m4_divert_stack +m4_divert_push([10])2.m4_divert_stack +m4_divert_text([20], [3.m4_divert_stack])dnl +m4_divert([30])4.m4_divert_stack +m4_divert_pop([30])dnl +5.m4_undivert([20]) +6.m4_undivert([30]) +m4_pattern_allow([^m4_divert])dnl +]], [[1.script.4s:2: m4@&t@_divert_push: 0 +script.4s:1: m4@&t@_divert: KILL +5.3.script.4s:5: m4@&t@_divert_push: 20 +script.4s:4: m4@&t@_divert_push: 10 +script.4s:2: m4@&t@_divert_push: 0 +script.4s:1: m4@&t@_divert: KILL + +6.4.script.4s:6: m4@&t@_divert: 30 +script.4s:2: m4@&t@_divert_push: 0 +script.4s:1: m4@&t@_divert: KILL + +2.script.4s:4: m4@&t@_divert_push: 10 +script.4s:2: m4@&t@_divert_push: 0 +script.4s:1: m4@&t@_divert: KILL +]]) + +AT_DATA_M4SUGAR([script.4s], +[[m4_divert_pop +]]) +AT_CHECK_M4SUGAR([-o-], [1], [], +[[script.4s:1: error: too many m4@&t@_divert_pop +script.4s:1: the top level +autom4te: m4 failed with exit status: 1 +]]) + +AT_DATA_M4SUGAR([script.4s], +[[m4_init +m4_divert_push([1]) +m4_divert_pop([2]) +]]) +AT_CHECK_M4SUGAR([-o-], [1], [], +[[script.4s:3: error: m4@&t@_divert_pop(2): diversion mismatch: +script.4s:2: m4@&t@_divert_push: 1 +script.4s:1: m4@&t@_divert: KILL +script.4s:3: the top level +autom4te: m4 failed with exit status: 1 +]]) + +AT_DATA_M4SUGAR([script.4s], +[[m4_divert([1]) +m4_init +m4_divert_push([2]) +]]) +AT_CHECK_M4SUGAR([-o-], [1], [], +[[script.4s:2: error: m4@&t@_init: unbalanced m4@&t@_divert_push: +script.4s:3: m4@&t@_divert_push: 2 +script.4s:2: m4@&t@_divert: KILL +script.4s:2: the top level +autom4te: m4 failed with exit status: 1 +]]) + +AT_CLEANUP + + ## -------------------- ## ## m4_expansion_stack. ## ## -------------------- ##