From: Paolo Bonzini Date: Tue, 28 Oct 2008 11:18:55 +0000 (+0100) Subject: Rewrite handling of diversion and expansion stack. X-Git-Tag: v2.63b~172 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=250422b094f3a4f3a49ecb78715de5adaa2eae6c;p=thirdparty%2Fautoconf.git Rewrite handling of diversion and expansion stack. * NEWS: Document stricter requirement on m4_init. * lib/m4sugar/m4sugar.m4 (m4_divert_stack): New, replacing _m4_divert_n_stack. (_m4_divert_stack_push): New. (m4_divert): Use _m4_divert_stack_push and replace m4_define with m4_popdef. (m4_divert_push): Use _m4_divert_stack_push. (m4_divert_pop): Use m4_divert_stack instead of _m4_divert_n_stack, pop _m4_divert_stack instead of m4_divert_stack. (m4_expansion_stack): New. Update comment above it. (m4_expansion_stack_push, m4_expansion_stack_pop): Work on _m4_expansion_stack instead of m4_expansion_stack. (m4_expansion_stack_dump): Check presence of _m4_expansion_stack instead of m4_expansion_stack. Use m4_expansion_stack's expansion instead of the definition, and compensate for the trailing newline in the expansion. (m4_warn, _m4_defun_pro, _m4_defun_epi): Check presence of _m4_expansion_stack instead of m4_expansion_stack. (m4_newline): Expand first argument after the newline. (m4_init): Use m4_divert_stack instead of _m4_divert_n_stack, * tests/m4sugar.at (m4_append, m4_text_wrap): Invoke m4_init. * tests/tools.at (whitespace in file names, the empty token): Likewise. --- diff --git a/ChangeLog b/ChangeLog index c1272a3ba..46f6e8153 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2008-10-29 Paolo Bonzini + + Rewrite handling of diversion and expansion stack. + * NEWS: Document stricter requirement on m4_init. + * lib/m4sugar/m4sugar.m4 (m4_divert_stack): New, replacing + _m4_divert_n_stack. + (_m4_divert_stack_push): New. + (m4_divert): Use _m4_divert_stack_push and replace m4_define with + m4_popdef. + (m4_divert_push): Use _m4_divert_stack_push. + (m4_divert_pop): Use m4_divert_stack instead of _m4_divert_n_stack, + pop _m4_divert_stack instead of m4_divert_stack. + (m4_expansion_stack): New. Update comment above it. + (m4_expansion_stack_push, m4_expansion_stack_pop): Work on + _m4_expansion_stack instead of m4_expansion_stack. + (m4_expansion_stack_dump): Check presence of _m4_expansion_stack + instead of m4_expansion_stack. Use m4_expansion_stack's expansion + instead of the definition, and compensate for the trailing newline + in the expansion. + (m4_warn, _m4_defun_pro, _m4_defun_epi): Check presence of + _m4_expansion_stack instead of m4_expansion_stack. + (m4_newline): Expand first argument after the newline. + (m4_init): Use m4_divert_stack instead of _m4_divert_n_stack, + * tests/m4sugar.at (m4_append, m4_text_wrap): Invoke m4_init. + * tests/tools.at (whitespace in file names, the empty token): Likewise. + 2008-10-28 Eric Blake Reduce forks while searching for better shell. diff --git a/NEWS b/NEWS index e22559ff2..d07c14364 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ 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/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index 9c24dacd4..6bd843e79 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -259,10 +259,8 @@ m4_define([_m4_warn], []) # Report a MESSAGE to the user if the CATEGORY of warnings is enabled. m4_define([m4_warn], [_m4_warn([$1], [$2], -m4_ifdef([m4_expansion_stack], - [_m4_defn([m4_expansion_stack]) -m4_location[: the top level]]))dnl -]) +m4_ifdef([_m4_expansion_stack], + [m4_expansion_stack[]m4_location[: the top level]]))]) @@ -1231,19 +1229,26 @@ m4_define([_m4_divert(KILL)], -1) m4_define([_m4_divert()], 0) -# _m4_divert_n_stack +# m4_divert_stack # ------------------ # Print m4_divert_stack with newline prepended, if it's nonempty. -m4_define([_m4_divert_n_stack], -[m4_ifdef([m4_divert_stack], [ -_m4_defn([m4_divert_stack])])]) +m4_define([m4_divert_stack], +[m4_stack_foreach_lifo([_m4_divert_stack], [m4_newline])]) + + +# m4_divert_stack_push(LOCATION, MACRO-NAME, DIVERSION-NAME) +# ----------------------------------------------------------- +# Form an entry of the diversion stack and push it. +m4_define([m4_divert_stack_push], +[m4_pushdef([_m4_divert_stack], [[$1: $2: $3]])]) # m4_divert(DIVERSION-NAME) # ------------------------- # Change the diversion stream to DIVERSION-NAME. m4_define([m4_divert], -[m4_define([m4_divert_stack], m4_location[: $0: $1]_m4_divert_n_stack)]dnl +[m4_popdef([_m4_divert_stack])]dnl +[m4_divert_stack_push(m4_location, [$0], [$1])]dnl [m4_builtin([divert], _m4_divert([$1]))]) @@ -1251,7 +1256,7 @@ m4_define([m4_divert], # ------------------------------ # Change the diversion stream to DIVERSION-NAME, while stacking old values. m4_define([m4_divert_push], -[m4_pushdef([m4_divert_stack], m4_location[: $0: $1]_m4_divert_n_stack)]dnl +[m4_divert_stack_push(m4_location, [$0], [$1])]dnl [m4_pushdef([_m4_divert_diversion], [$1])]dnl [m4_builtin([divert], _m4_divert([$1]))]) @@ -1266,8 +1271,8 @@ m4_define([m4_divert_pop], [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_n_stack)])]dnl -[_m4_popdef([m4_divert_stack], [_m4_divert_diversion])]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]))], @@ -1568,35 +1573,44 @@ m4_define([m4_undivert], # performance penalty this is implemented only for m4_defun'd macros, # not for define'd macros. # -# The scheme is simplistic: each time we enter an m4_defun'd macros, -# we prepend its name in m4_expansion_stack, and when we exit the -# macro, we remove it (thanks to pushdef/popdef). +# Each time we enter an m4_defun'd macros, we add a definition in +# _m4_expansion_stack, and when we exit the macro, we remove it (thanks +# to pushdef/popdef). m4_stack_foreach is used to print the expansion +# stack in the rare cases when it's needed. # # In addition, we want to detect circular m4_require dependencies. # Each time we expand a macro FOO we define _m4_expanding(FOO); and # m4_require(BAR) simply checks whether _m4_expanding(BAR) is defined. +# m4_expansion_stack +# ------------------ +# Expands to the entire contents of the expansion stack, if not empty, +# with a newline at its end. +m4_define([m4_expansion_stack], +[m4_ifdef([_m4_expansion_stack], + [m4_stack_foreach_lifo([_m4_expansion_stack], [m4_n])])]) + # m4_expansion_stack_push(TEXT) # ----------------------------- +# Form an entry of the expansion stack and push it. m4_define([m4_expansion_stack_push], -[m4_pushdef([m4_expansion_stack], - [$1]m4_ifdef([m4_expansion_stack], [ -_m4_defn([m4_expansion_stack])]))]) +[m4_pushdef([_m4_expansion_stack], [[$1]])]) # m4_expansion_stack_pop # ---------------------- +# Pop the topmost entry of the expansion stack. m4_define([m4_expansion_stack_pop], -[m4_popdef([m4_expansion_stack])]) +[m4_popdef([_m4_expansion_stack])]) # m4_expansion_stack_dump # ----------------------- # Dump the expansion stack. m4_define([m4_expansion_stack_dump], -[m4_ifdef([m4_expansion_stack], - [m4_errprintn(_m4_defn([m4_expansion_stack]))])dnl +[m4_ifdef([_m4_expansion_stack], + [m4_errprint(m4_expansion_stack)])dnl m4_errprintn(m4_location[: the top level])]) @@ -1626,7 +1640,7 @@ m4_define([_m4_divert(GROW)], 10000) # This is called frequently, so minimize the number of macro invocations # by avoiding dnl and m4_defn overhead. m4_define([_m4_defun_pro], -m4_do([[m4_ifdef([m4_expansion_stack], [], [_m4_defun_pro_outer[]])]], +m4_do([[m4_ifdef([_m4_expansion_stack], [], [_m4_defun_pro_outer[]])]], [[m4_expansion_stack_push(_m4_defn( [m4_location($1)])[: $1 is expanded from...])]], [[m4_pushdef([_m4_expanding($1)])]])) @@ -1645,7 +1659,7 @@ m4_define([_m4_defun_pro_outer], m4_define([_m4_defun_epi], m4_do([[_m4_popdef([_m4_expanding($1)])]], [[m4_expansion_stack_pop()]], - [[m4_ifdef([m4_expansion_stack], [], [_m4_defun_epi_outer[]])]], + [[m4_ifdef([_m4_expansion_stack], [], [_m4_defun_epi_outer[]])]], [[m4_provide([$1])]])) m4_define([_m4_defun_epi_outer], @@ -1753,7 +1767,7 @@ m4_define([m4_before], # If NAME-TO-CHECK has never been expanded (actually, if it is not # m4_provide'd), expand BODY-TO-EXPAND *before* the current macro # expansion. Once expanded, emit it in _m4_divert_dump. Keep track -# of the m4_require chain in m4_expansion_stack. +# of the m4_require chain in _m4_expansion_stack. # # The normal cases are: # @@ -1937,11 +1951,12 @@ _m4_define_cr_not([symbols1]) _m4_define_cr_not([symbols2]) -# m4_newline -# ---------- -# Expands to a newline. Exists for formatting reasons. +# m4_newline([STRING]) +# -------------------- +# Expands to a newline, possibly followed by STRING. Exists mostly for +# formatting reasons. m4_define([m4_newline], [ -]) +$1]) # m4_re_escape(STRING) @@ -2937,5 +2952,5 @@ m4_divert_push([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_n_stack)])[]]) + [m4_fatal([$0: unbalanced m4_divert_push:]m4_divert_stack)])[]]) ]) diff --git a/tests/m4sugar.at b/tests/m4sugar.at index af4c4d5a8..1dff27058 100644 --- a/tests/m4sugar.at +++ b/tests/m4sugar.at @@ -513,14 +513,15 @@ one, two, three ]]) AT_DATA_M4SUGAR([script.4s], -[[m4_append_uniq([str], [a], [ ]) +[[m4_init[]dnl +m4_append_uniq([str], [a], [ ]) m4_append_uniq([str], [a b], [ ]) m4_divert([0])dnl str ]]) AT_CHECK_M4SUGAR([-o-], 0, [[a a b -]], [[script.4s:2: warning: m4@&t@_append_uniq: `a b' contains ` ' +]], [[script.4s:3: warning: m4@&t@_append_uniq: `a b' contains ` ' ]]) AT_CLEANUP @@ -588,7 +589,7 @@ AT_SETUP([m4@&t@_text_wrap]) # m4-listification. AT_DATA_M4SUGAR([script.4s], -[[m4_divert([0])dnl +[[m4_init[]m4_divert([0])dnl m4_text_wrap([Short string */], [ ], [/* ], 20) m4_text_wrap([Much longer string */], [ ], [/* ], 20) diff --git a/tests/tools.at b/tests/tools.at index 06fcf6a9e..5cd64cf4f 100644 --- a/tests/tools.at +++ b/tests/tools.at @@ -165,7 +165,7 @@ do AT_CHECK([mkdir "$dir" "$cachedir" "$TMPDIR" && touch "$file" || exit 77]) cat >"$file" <<'END' -[m4@&t@_include(foo.m4) +[m4@&t@_init[]m4@&t@_include(foo.m4) m4@&t@_divert(0)d@&t@nl FOO] END @@ -186,7 +186,7 @@ END # This exercises a slightly different code path and will catch an open with # trailing whitespace: cat >"$file" <<'END' -[m4@&t@_include(foo.m4) +[m4@&t@_init[]m4@&t@_include(foo.m4) m4@&t@_pattern_forbid([^bar$]) m4@&t@_divert(0)d@&t@nl FOO] @@ -197,7 +197,7 @@ END AT_CHECK([grep 'possibly undefined macro' stderr], [], [ignore]) cat >"$file" <<'END' -[m4@&t@_include(foo.m4) +[m4@&t@_init[]m4@&t@_include(foo.m4) m4@&t@_divert(0)d@&t@nl] END rm -rf "$file.m4f" @@ -434,7 +434,7 @@ AT_CLEANUP AT_SETUP([autoconf: the empty token]) AT_DATA_M4SH([configure.ac], -[[m4_pattern_allow([^foo$]) +[[m4_init[]m4_pattern_allow([^foo$]) m4_divert([0])dnl line that begins with a space ]])