* lib/m4sugar/m4sugar.m4 (m4_wrap): Override M4 implementation.
(m4_wrap_lifo, _m4_wrap): New macros.
* lib/m4sugar/m4sh.m4 (AS_INIT): Combine all cleanup into known
order, prior to m4sugar's.
(_AS_DETECT_BETTER_SHELL): Use cleanup parameter, rather than
m4_wrap.
* lib/autotest/general.m4 (AT_INIT): Combine all cleanup into
known order, prior to m4sh's.
* doc/autoconf.texi (Diagnostic Macros) <m4_fatal>: Document
argument.
(Redefined M4 Macros) <m4_wrap>: Rewrite documentation to match
new behavior.
* tests/m4sh.at (AS_INIT cleanup): New test.
* NEWS: Document the change.
Signed-off-by: Eric Blake <ebb9@byu.net>
+2008-03-11 Eric Blake <ebb9@byu.net>
+
+ Tweak m4_wrap to force FIFO or LIFO semantics.
+ * lib/m4sugar/m4sugar.m4 (m4_wrap): Override M4 implementation.
+ (m4_wrap_lifo, _m4_wrap): New macros.
+ * lib/m4sugar/m4sh.m4 (AS_INIT): Combine all cleanup into known
+ order, prior to m4sugar's.
+ (_AS_DETECT_BETTER_SHELL): Use cleanup parameter, rather than
+ m4_wrap.
+ * lib/autotest/general.m4 (AT_INIT): Combine all cleanup into
+ known order, prior to m4sh's.
+ * doc/autoconf.texi (Diagnostic Macros) <m4_fatal>: Document
+ argument.
+ (Redefined M4 Macros) <m4_wrap>: Rewrite documentation to match
+ new behavior.
+ * tests/m4sh.at (AS_INIT cleanup): New test.
+ * NEWS: Document the change.
+
2008-03-10 Eric Blake <ebb9@byu.net>
Encode nested autotest data.
m4_cmp m4_list_cmp m4_join m4_map m4_map_sep m4_sign
m4_text_box m4_text_wrap m4_version_compare
+ - The m4_wrap macro used to have unspecified order, but now
+ guarantees FIFO order. m4_wrap_lifo was added to guarantee LIFO
+ order.
+
- Packages using the undocumented m4sugar macro m4_PACKAGE_VERSION
should consider using the new AC_AUTOCONF_VERSION instead.
** The following m4sugar macros are new:
m4_append_uniq_w m4_apply m4_combine m4_cond m4_count
m4_dquote_elt m4_echo m4_expand m4_ignore m4_make_list m4_max
- m4_min m4_newline m4_shift2 m4_shift3 m4_unquote
+ m4_min m4_newline m4_shift2 m4_shift3 m4_unquote m4_wrap_lifo
** Warnings are now generated by default when an installer invokes
'configure' with an unknown --enable-* or --with-* option.
@end defmac
@defmac m4_wrap (@var{text})
+@defmacx m4_wrap_lifo (@var{text})
@msindex{wrap}
-This macro corresponds to @code{m4wrap}.
+@msindex{wrap_lifo}
+These macros correspond to @code{m4wrap}. Posix requires arguments of
+multiple wrap calls to be reprocessed at @acronym{EOF} in the same order
+as the original calls (first-in, first-out). @acronym{GNU} M4 versions
+through 1.4.10, however, reprocess them in reverse order (last-in,
+first-out). Both orders are useful, therefore, you can rely on
+@code{m4_wrap} to provide FIFO semantics and @code{m4_wrap_lifo} for
+LIFO semantics, regardless of the underlying @acronym{GNU} M4 version.
-Posix requires arguments of multiple @code{m4wrap} calls to be
-reprocessed at @acronym{EOF} in the same order as the original calls.
-@acronym{GNU} M4 versions through 1.4.x, however, reprocess them in
-reverse order. Your code should not depend on the order.
-
-Also, Posix requires @code{m4wrap} to ignore its second and succeeding
-arguments, but @acronym{GNU} M4 versions through 1.4.x concatenate the
-arguments with intervening spaces. Your code should not pass more than
-one argument.
-
-You are encouraged to end @var{text} with @samp{[]}, to avoid unexpected
-token pasting between consecutive invocations of @code{m4_wrap}, as in:
-
-@example
-m4_define([foo], [bar])
-m4_define([foofoo], [OUCH])
-m4_wrap([foo])
-m4_wrap([foo])
-@result{}OUCH
-@end example
+Unlike the @acronym{GNU} M4 builtin, these macros only recognize one
+argument, and avoid token pasting between consecutive invocations. On
+the other hand, nested calls to @code{m4_wrap} from within wrapped text
+work just as in the builtin.
@end defmac
@end defmac
@anchor{m4_fatal}
-@defmac m4_fatal
+@defmac m4_fatal (@var{message})
@msindex{fatal}
Report a severe error @var{message} prefixed with the current location,
and have @command{autom4te} die.
m4_define([AT_banner_ordinal], 0)
m4_define([AT_groups_all], [])
m4_define([AT_help_all], [])
+m4_wrap([_AT_FINISH])
AS_INIT[]dnl
m4_divert_push([DEFAULTS])dnl
AT_COPYRIGHT(
# Whether -C is in effect.
at_change_dir=false
m4_divert_pop([DEFAULTS])dnl
-m4_wrap([m4_divert_text([DEFAULTS],
+m4_define([_AT_FINISH], [m4_divert_text([DEFAULTS],
[
# List of the tested programs.
at_tested='m4_ifdef([AT_tested],
# M4 sugar for common shell constructs.
# Requires GNU M4 and M4sugar.
#
-# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free
-# Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# <http://lists.gnu.org/archive/html/autoconf-patches/2006-03/msg00081.html>.
#
m4_defun_once([_AS_DETECT_BETTER_SHELL],
-[m4_wrap([m4_divert_text([M4SH-SANITIZE], [
+[m4_append([_AS_CLEANUP], [m4_divert_text([M4SH-SANITIZE], [
AS_REQUIRE([_AS_UNSET_PREPARE])dnl
if test "x$CONFIG_SHELL" = x; then
AS_IF([_AS_RUN([_AS_DETECT_REQUIRED_BODY]) 2>/dev/null],
# -------
# Initialize m4sh.
m4_define([AS_INIT],
-[m4_init
+[# Wrap our cleanup prior to m4sugar's cleanup.
+m4_wrap([_AS_CLEANUP])
+m4_init
# Forbidden tokens and exceptions.
m4_pattern_forbid([^_?AS_])
m4_rename_m4([indir])
m4_rename_m4([len])
m4_rename([m4exit], [m4_exit])
-m4_rename([m4wrap], [m4_wrap])
+m4_undefine([m4wrap])
m4_ifdef([mkstemp],dnl added in M4 1.4.8
[m4_rename_m4([mkstemp])
m4_copy([m4_mkstemp], [m4_maketemp])
[m4_fatal([$0: undefined macro: $1])])]dnl
[m4_builtin([undefine], [$1])])
+# _m4_wrap(PRE, POST)
+# -------------------
+# Helper macro for m4_wrap and m4_wrap_lifo. Allows nested calls to
+# m4_wrap within wrapped text.
+m4_define([_m4_wrap],
+[m4_ifdef([$0_text],
+ [m4_define([$0_text], [$1]m4_builtin([defn], [$0_text])[$2])],
+ [m4_builtin([m4wrap], [$0_text(m4_builtin([popdef],
+ [$0_text]))])m4_define([$0_text], [$1$2])])])
+
+# m4_wrap(TEXT)
+# -------------
+# Append TEXT to the list of hooks to be executed at the end of input.
+# Whereas the order of the original may be LIFO in the underlying m4,
+# this version is always FIFO.
+m4_define([m4_wrap],
+[_m4_wrap([], [$1[]])])
+
+# m4_wrap_lifo(TEXT)
+# ------------------
+# Prepend TEXT to the list of hooks to be executed at the end of input.
+# Whereas the order of m4_wrap may be FIFO in the underlying m4, this
+# version is always LIFO.
+m4_define([m4_wrap_lifo],
+[_m4_wrap([$1[]])])
## ------------------------- ##
## 7. Quoting manipulation. ##
# m4_init
# -------
+# Initialize the m4sugar language.
m4_define([m4_init],
[# All the M4sugar macros start with `m4_', except `dnl' kept as is
# for sake of simplicity.
AT_BANNER([M4sh.])
-# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-# Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
]])
AT_CLEANUP
+
+
+## ----------------- ##
+## AS_INIT cleanup. ##
+## ----------------- ##
+
+AT_SETUP([AS@&t@_INIT cleanup])
+
+AT_KEYWORDS([m4@&t@_wrap m4@&t@_wrap_lifo])
+
+AT_DATA_M4SH([script.as], [[dnl
+dnl Registered before AS_INIT's cleanups
+m4_wrap([echo cleanup 1
+])
+AS_INIT
+dnl Registered after AS_INIT's cleanups, thus goes to KILL diversion
+m4_wrap([echo cleanup 2
+dnl However, nested wraps and diversions can still be used
+m4_wrap([echo cleanup 3
+m4_divert_text([M4SH-INIT], [echo prep 4
+])])])
+dnl Registered before AS_INIT's cleanups
+m4_wrap_lifo([echo cleanup 5
+])
+echo body
+]])
+
+AT_CHECK_M4SH
+AT_CHECK([./script], [], [[prep 4
+body
+cleanup 5
+cleanup 1
+]])
+
+AT_CLEANUP