2008-07-19 Eric Blake <ebb9@byu.net>
+ Support multiple arguments to m4_defn, m4_popdef, and m4_undefine.
+ * lib/m4sugar/m4sugar.m4 (m4_defn, m4_popdef, m4_undefine): Loop
+ through all variables, per POSIX and newer m4.
+ (_m4_text_wrap): Exploit the looping capabilities.
+ * tests/m4sugar.at (m4@&t@_defn): Test this.
+ * NEWS: Document it.
+ * doc/autoconf.texi (Redefined M4 Macros) <m4_defn, m4_popdef>
+ <m4_undefine>: Likewise.
+
Reduce overhead of m4_builtin([defn]).
* lib/m4sugar/m4sugar.m4 (_m4_defn, _m4_popdef, _m4_undefine): New
internal macros, which are slightly more efficient than
** The following m4sugar macros are new:
m4_joinall
+** The following m4sugar macros now accept multiple arguments, as is the
+ case with underlying m4:
+ m4_defn m4_popdef m4_undefine
+
** AT_KEYWORDS once again performs expansion on its argument, such that
AT_KEYWORDS([m4_if([$1], [], [default])]) no longer complains about
the possibly unexpanded m4_if [regression introduced in 2.62].
released and supports extended regular expression syntax.
@end defmac
-@defmac m4_defn (@var{macro})
+@defmac m4_defn (@var{macro}@dots{})
@msindex{defn}
-Unlike the M4 builtin, this macro fails if @var{macro} is not
-defined. Also, while newer M4 can concatenate multiple definitions,
-this version currently only supports a single @var{macro}. See
-@code{m4_undefine}.
+This macro fails if @var{macro} is not defined, even when using older
+versions of M4 that did not warn. See @code{m4_undefine}.
+Unfortunately, in order to support these older versions of M4, there are
+some situations involving unbalanced quotes where concatenating multiple
+macros together will work in newer M4 but not in m4sugar; use
+quadrigraphs to work around this.
@end defmac
@defmac m4_divert (@var{diversion})
underlying M4 provides.
@end defmac
-@defmac m4_popdef (@var{macro})
+@defmac m4_popdef (@var{macro}@dots{})
@msindex{popdef}
-Unlike the M4 builtin, this macro fails if @var{macro} is not
-defined. Also, while newer M4 can pop multiple definitions at once,
-this version currently only supports a single @var{macro}. See
-@code{m4_undefine}.
+This macro fails if @var{macro} is not defined, even when using older
+versions of M4 that did not warn. See @code{m4_undefine}.
@end defmac
-@defmac m4_undefine (@var{macro})
+@defmac m4_undefine (@var{macro}@dots{})
@msindex{undefine}
-Unlike the M4 builtin, this macro fails if @var{macro} is not
-defined. Also, while newer M4 can undefine multiple definitions at
-once, this version currently only supports a single @var{macro}. Use
+This macro fails if @var{macro} is not defined, even when using older
+versions of M4 that did not warn. Use
@example
m4_ifdef([@var{macro}], [m4_undefine([@var{macro}])])
@end example
@noindent
-to recover the behavior of the builtin.
+if you are not sure whether @var{macro} is defined.
@end defmac
@defmac m4_undivert (@var{diversion})
# m4_defn(NAME)
# -------------
# Like the original, except guarantee a warning when using something which is
-# undefined (unlike M4 1.4.x), and only support one argument.
+# undefined (unlike M4 1.4.x). This replacement is not a full-featured
+# replacement: if any of the defined macros contain unbalanced quoting, but
+# when pasted together result in a well-quoted string, then only native m4
+# support is able to get it correct. But that's where quadrigraphs come in
+# handy, if you really need unbalanced quotes inside your macros.
#
# This macro is called frequently, so minimize the amount of additional
# expansions by skipping m4_ifndef. Better yet, if __m4_version__ exists,
[m4_define([m4_defn],
[m4_ifdef([$1], [],
[m4_fatal([$0: undefined macro: $1])])]dnl
-[_m4_defn([$1])])])
+[_m4_defn([$1])m4_if([$#], [1], [], [$0(m4_shift($@))])])])
# _m4_dumpdefs_up(NAME)
# m4_popdef(NAME)
# ---------------
# Like the original, except guarantee a warning when using something which is
-# undefined (unlike M4 1.4.x), and only support one argument.
+# undefined (unlike M4 1.4.x).
#
# This macro is called frequently, so minimize the amount of additional
# expansions by skipping m4_ifndef. Better yet, if __m4_version__ exists,
[m4_define([m4_popdef],
[m4_ifdef([$1], [],
[m4_fatal([$0: undefined macro: $1])])]dnl
-[_m4_popdef([$1])])])
+[_m4_popdef([$1])m4_if([$#], [1], [], [$0(m4_shift($@))])])])
# m4_shiftn(N, ...)
# m4_undefine(NAME)
# -----------------
# Like the original, except guarantee a warning when using something which is
-# undefined (unlike M4 1.4.x), and only support one argument.
+# undefined (unlike M4 1.4.x).
#
# This macro is called frequently, so minimize the amount of additional
# expansions by skipping m4_ifndef. Better yet, if __m4_version__ exists,
[m4_define([m4_undefine],
[m4_ifdef([$1], [],
[m4_fatal([$0: undefined macro: $1])])]dnl
-[_m4_undefine([$1])])])
+[_m4_undefine([$1])m4_if([$#], [1], [], [$0(m4_shift($@))])])])
# _m4_wrap(PRE, POST)
# -------------------
[$2]],
[m4_Separator[]])_m4_defn([m4_Word])])]],
dnl finally, clean up the local variabls
-[[_m4_popdef([m4_Separator])]],
-[[_m4_popdef([m4_Cursor])]],
-[[_m4_popdef([m4_Indent])]]))
+[[_m4_popdef([m4_Separator], [m4_Cursor], [m4_Indent])]]))
# m4_text_box(MESSAGE, [FRAME-CHARACTER = `-'])
# this is provided by m4 natively or faked by wrappers in m4sugar.
AT_DATA_M4SUGAR([script.4s],
-[[m4_defn([oops])
+[[m4_define([good])
+m4_defn([good], [oops])
]])
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
+AT_CHECK([grep good stderr], [1])
AT_CHECK([grep 'm4@&t@_defn: undefined.*oops' stderr], [0], [ignore])
AT_DATA_M4SUGAR([script.4s],
-[[m4_popdef([oops])
+[[m4_define([good])
+m4_popdef([good], [oops])
]])
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
+AT_CHECK([grep good stderr], [1])
AT_CHECK([grep 'm4@&t@_popdef: undefined.*oops' stderr], [0], [ignore])
AT_DATA_M4SUGAR([script.4s],
-[[m4_undefine([oops])
+[[m4_define([good])
+m4_undefine([good], [oops])
]])
AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
+AT_CHECK([grep good stderr], [1])
AT_CHECK([grep 'm4@&t@_undefine: undefined.*oops' stderr], [0], [ignore])
AT_CLEANUP