In order to fix the bug in AC_REQUIRE, I had to track what was happening in low- level diversion handling. Tracing m4_builtin was too heavy-handed (we also use m4_builtin to implement m4_split, which has unbalanced ] and thus crashes the autom4te tracing engine), but tracing m4_divert was too high-level (m4_expand makes some of the diversion magic happen on a deferred basis). So I am installing this instead, so that I can trace _m4_divert_raw/_m4_undivert to see what is actually happening. By the way, using _m4_divert_raw is slightly faster than m4_builtin([divert]), as it results in fewer hashtable lookups in m4. While I was at it, I found a way to speed up _m4_require_call, which in turn exposed a recently added typo in autotest.
From: Eric Blake <[email protected]> Date: Tue, 30 Dec 2008 08:32:08 -0700 Subject: [PATCH] Make it easier to track diversion bugs. * lib/m4sugar/m4sugar.m4 (_m4_divert_raw, _m4_undivert): New internal macros, which are easier to trace than m4_builtin. (m4_cleardivert, m4_divert, m4_divert_push, m4_divert_pop) (m4_undivert): Use them. (_m4_require_call): Likewise. Use fewer macros. * lib/autotest/general.m4 (_AT_DECIDE_TRACEABLE): Fix typo. Signed-off-by: Eric Blake <[email protected]> --- ChangeLog | 10 ++++++++++ lib/autotest/general.m4 | 2 +- lib/m4sugar/m4sugar.m4 | 46 +++++++++++++++++++++++++++------------------- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index fe0fb5c..d1a5382 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2008-12-30 Eric Blake <[email protected]> + + Make it easier to track diversion bugs. + * lib/m4sugar/m4sugar.m4 (_m4_divert_raw, _m4_undivert): New + internal macros, which are easier to trace than m4_builtin. + (m4_cleardivert, m4_divert, m4_divert_push, m4_divert_pop) + (m4_undivert): Use them. + (_m4_require_call): Likewise. Use fewer macros. + * lib/autotest/general.m4 (_AT_DECIDE_TRACEABLE): Fix typo. + 2008-12-26 Bruno Haible <[email protected]> Improve multiarch detection. diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4 index a1079c8..5f2db79 100644 --- a/lib/autotest/general.m4 +++ b/lib/autotest/general.m4 @@ -1988,7 +1988,7 @@ at_fn_check_prepare_notrace], dnl We know at build time that tracing COMMANDS is always safe. [[at_fn_check_prepare_trace],]dnl dnl COMMANDS may contain parameter expansions; expand them at runtime. -[[at_fn_check_prepare_dynamic "AS_ESCAPE([$1], [`\"])"])])]dnl +[[at_fn_check_prepare_dynamic "AS_ESCAPE([$1], [`\"])"])[]]dnl [_m4_popdef([at_reason])]) diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index f64ef16..556969f 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -134,7 +134,6 @@ m4_ifdef([changeword],dnl conditionally available in 1.4.x m4_rename_m4([debugfile]) m4_rename_m4([debugmode]) m4_rename_m4([decr]) -m4_undefine([divert]) m4_rename_m4([divnum]) m4_rename_m4([dumpdef]) m4_rename_m4([errprint]) @@ -168,16 +167,21 @@ m4_rename_m4([sysval]) m4_rename_m4([traceoff]) m4_rename_m4([traceon]) m4_rename_m4([translit]) -m4_undefine([undivert]) # _m4_defn(ARG) -# ---------------- +# ------------- # _m4_defn is for internal use only - it bypasses the wrapper, so it # must only be used on one argument at a time, and only on macros # known to be defined. Make sure this still works if the user renames # m4_defn but not _m4_defn. m4_copy([m4_defn], [_m4_defn]) +# _m4_divert_raw(NUM) +# ------------------- +# _m4_divert_raw is for internal use only. Use this instead of +# m4_builtin([divert], NUM), so that tracing diversion flow is easier. +m4_rename([divert], [_m4_divert_raw]) + # _m4_popdef(ARG...) # ------------------ # _m4_popdef is for internal use only - it bypasses the wrapper, so it @@ -192,6 +196,13 @@ m4_copy([m4_popdef], [_m4_popdef]) # still works if the user renames m4_undefine but not _m4_undefine. m4_copy([m4_undefine], [_m4_undefine]) +# _m4_undivert(NUM...) +# -------------------- +# _m4_undivert is for internal use only, and should always be given +# arguments. Use this instead of m4_builtin([undivert], NUM...), so +# that tracing diversion flow is easier. +m4_rename([undivert], [_m4_undivert]) + ## ------------------- ## ## 2. Error messages. ## @@ -1320,7 +1331,7 @@ m4_define([_m4_stack_reverse], # This works even inside m4_expand. m4_define([m4_cleardivert], [m4_if([$#], [0], [m4_fatal([$0: missing argument])], - [m4_builtin([divert], [-1])m4_undivert($@)m4_builtin([divert], + [_m4_divert_raw([-1])m4_undivert($@)_m4_divert_raw( _m4_divert(_m4_defn([_m4_divert_diversion])))])]) @@ -1364,7 +1375,7 @@ m4_define([m4_divert], [m4_popdef([_m4_divert_stack])]dnl [m4_define([_m4_divert_diversion], [$1])]dnl [m4_divert_stack_push([$0], [$1])]dnl -[m4_builtin([divert], _m4_divert([$1]))]) +[_m4_divert_raw(_m4_divert([$1]))]) # m4_divert_push(DIVERSION-NAME) @@ -1373,7 +1384,7 @@ m4_define([m4_divert], m4_define([m4_divert_push], [m4_divert_stack_push([$0], [$1])]dnl [m4_pushdef([_m4_divert_diversion], [$1])]dnl -[m4_builtin([divert], _m4_divert([$1]))]) +[_m4_divert_raw(_m4_divert([$1]))]) # m4_divert_pop([DIVERSION-NAME]) @@ -1389,7 +1400,7 @@ m4_define([m4_divert_pop], [_m4_popdef([_m4_divert_stack], [_m4_divert_diversion])]dnl [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_raw(_m4_divert(_m4_defn([_m4_divert_diversion])))]) # m4_divert_text(DIVERSION-NAME, CONTENT) @@ -1425,7 +1436,7 @@ m4_define([_m4_divert_unsafe], # this should not be used to undivert files. m4_define([m4_undivert], [m4_if([$#], [0], [m4_fatal([$0: missing argument])], - [$#], [1], [m4_builtin([undivert], _m4_divert([$1]))], + [$#], [1], [_m4_undivert(_m4_divert([$1]))], [m4_map_args([$0], $@)])]) @@ -1930,17 +1941,14 @@ m4_bmatch([$0], [^AC_], [[AC_DEFUN]], [[m4_defun]])['d macro])])]], # This is called frequently, so minimize the number of macro invocations # by avoiding dnl and other overhead on the common path. m4_define([_m4_require_call], -m4_do([[m4_define([_m4_divert_grow], m4_decr(_m4_divert_grow))]], - [[m4_divert_push(_m4_divert_grow)]], - [[m4_default([$2], [$1]) -m4_provide_if([$1], - [], - [m4_warn([syntax], - [$1 is m4_require'd but not m4_defun'd])])]], - [[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))]])) +[m4_pushdef([_m4_divert_grow], m4_decr(_m4_divert_grow))]dnl +[m4_divert_push(_m4_divert_grow)]dnl +[m4_if([$2], [], [$1], [$2]) +m4_provide_if([$1], [], [m4_warn([syntax], + [$1 is m4_require'd but not m4_defun'd])])]dnl +[_m4_divert_raw(_m4_divert($3))]dnl +[_m4_undivert(_m4_divert_grow)]dnl +[m4_divert_pop(_m4_divert_grow)_m4_popdef([_m4_divert_grow])]) # _m4_divert_grow -- 1.6.0.4
