+2008-10-28 Eric Blake <ebb9@byu.net>
+
+ Override m4 1.4.x dumpdef, as it breaks autom4te.
+ * lib/m4sugar/m4sugar.m4 (m4_dumpdef): New implementation.
+ (m4_copy): Formatting touchup.
+ * doc/autoconf.texi (Redefined M4 Macros) <m4_dumpdef>: Mention
+ semantic differences as well as m4_dumpdefs.
+ * NEWS: Likewise.
+ * tests/m4sugar.at (m4@&t@_dumpdef): New test.
+
2008-10-28 Eric Blake <ebb9@byu.net>
Allow m4sugar to be used without autom4te, such as in bison.
@msindex{decr}
@msindex{define}
@msindex{divnum}
-@msindex{dumpdef}
@msindex{errprint}
@msindex{esyscmd}
@msindex{eval}
@item m4_decr
@item m4_define
@item m4_divnum
-@item m4_dumpdef
@item m4_errprint
@item m4_esyscmd
@item m4_eval
diversion stack.
@end defmac
+@defmac m4_dumpdef (@var{name}@dots{})
+@defmacx m4_dumpdefs (@var{name})
+@msindex{dumpdef}
+@msindex{dumpdefs}
+@code{m4_dumpdef} is like the M4 builtin, except that this version
+requires at least one argument, output always goes to standard error
+rather than the current debug file, and an error is issued if any
+@var{name} is undefined. @code{m4_dumpdefs} is a convenience macro that
+takes exactly one @var{name}, and calls @code{m4_dumpdef} for all of the
+@code{m4_pushdef} stack of definitions, starting with the current, and
+silently does nothing if @var{name} is undefined.
+@end defmac
+
@defmac m4_exit (@var{exit-status})
@msindex{exit}
This macro corresponds to @code{m4exit}.
# involved in the implementation of m4_stack_foreach and m4_curry.
m4_define([m4_copy],
[m4_ifdef([$2], [m4_fatal([$0: won't overwrite defined macro: $2])],
- [m4_stack_foreach([$1], [m4_curry([m4_pushdef], [$2])])m4_ifdef([m4_location($1)],
-[m4_define([m4_location($2)], m4_location)])])])
+ [m4_stack_foreach([$1], [m4_curry([m4_pushdef], [$2])])])]dnl
+[m4_ifdef([m4_location($1)], [m4_define([m4_location($2)], m4_location)])])
# m4_define_default(MACRO, VALUE)
[m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])
+# m4_dumpdef(NAME...)
+# -------------------
+# In m4 1.4.x, dumpdef writes to the current debugfile, rather than
+# stderr. This in turn royally confuses autom4te; so we follow the
+# lead of newer m4 and always dump to stderr. Unlike the original,
+# this version requires an argument, since there is no convenient way
+# in m4 1.4.x to grab the names of all defined macros. Newer m4
+# always dumps to stderr, regardless of the current debugfile; it also
+# provides m4symbols as a way to grab all current macro names. But
+# dumpdefs is not frequently called, so we don't need to worry about
+# conditionally using these newer features.
+m4_define([m4_dumpdef],
+[m4_if([$#], [0], [m4_fatal([$0: missing argument])],
+ [$#], [1], [m4_ifdef([$1], [m4_errprintn(
+ [$1: ]m4_dquote(_m4_defn([$1])))], [m4_fatal([$0: undefined macro: $1])])],
+ [m4_foreach([_m4_macro], [$@], [$0(_m4_defn([_m4_macro]))])])])
+
+
# m4_dumpdefs(NAME)
# -----------------
# Similar to `m4_dumpdef(NAME)', but if NAME was m4_pushdef'ed, display its
#
# This macro cheats, because it relies on the current definition of NAME
# while the second argument of m4_stack_foreach_lifo is evaluated (which
-# would be undefined according to the API). If m4_dumpdef is ever rewritten
-# not to use the builtin, revisit this.
+# would be undefined according to the API).
m4_define([m4_dumpdefs],
[m4_stack_foreach_lifo([$1], [m4_dumpdef([$1])m4_ignore])])
AT_CLEANUP
+## ------------ ##
+## m4_dumpdef. ##
+## ------------ ##
+
+AT_SETUP([m4@&t@_dumpdef])
+
+AT_KEYWORDS([m4@&t@_dumpdefs])
+
+# Ensure that m4sugar dies when dereferencing undefined macros.
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_define([good], [yep])
+m4_dumpdef([good], [oops])
+]])
+
+AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
+AT_CHECK([grep '^good: \[[yep\]]$' stderr], [0], [ignore])
+AT_CHECK([grep 'm4@&t@_dumpdef: undefined.*oops' stderr], [0], [ignore])
+
+# Check that pushdef stacks can be dumped.
+AT_CHECK_M4SUGAR_TEXT([[m4_divert_push([KILL])
+m4_pushdef([a], [1])
+m4_pushdef([a], [2])
+m4_dumpdef([a])
+m4_dumpdefs([a])
+m4_dumpdefs([oops])
+m4_divert_pop([KILL])dnl
+]], [],
+[[a: [2]
+a: [2]
+a: [1]
+]])
+
+AT_CLEANUP
+
+
## --------- ##
## m4_warn. ##
## --------- ##