-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Ralf Wildenhues on 3/7/2008 11:30 AM:
| Hello Eric,
|
| This patch series is OK, but please look at the nits below.
| Thanks for your good work on this!

I'm committing the first two in the series as is, since there were no
nits.  As for the remaining two, here is the revised version for another
round of reviews.  Rather than adding a cleanup parameter to
m4_init/AS_INIT, I made m4_wrap guarantee FIFO behavior and added
m4_wrap_lifo, then used these calls in the proper order.  I tested with
both M4 1.4.10b (where m4wrap is LIFO) and the M4 argv_ref branch (will
become M4 1.4.11 or maybe 1.5, where m4wrap is FIFO).

- --
Don't work too hard, make some time for fun as well!

Eric Blake             [EMAIL PROTECTED]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkfWh60ACgkQ84KuGfSFAYD3/QCgmrvxEBVs6SpmreqK93sirkhK
bxIAmwS8ltaTOAwOhxr4UIMjJ6PnlTEQ
=QYBZ
-----END PGP SIGNATURE-----
>From aaf35d7985a94338621fe3577003a8c379162252 Mon Sep 17 00:00:00 2001
From: Eric Blake <[EMAIL PROTECTED]>
Date: Tue, 11 Mar 2008 07:11:44 -0600
Subject: [PATCH] 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.

Signed-off-by: Eric Blake <[EMAIL PROTECTED]>
---
 ChangeLog               |   18 ++++++++++++++++++
 NEWS                    |    6 +++++-
 doc/autoconf.texi       |   34 ++++++++++++----------------------
 lib/autotest/general.m4 |    3 ++-
 lib/m4sugar/m4sh.m4     |   10 ++++++----
 lib/m4sugar/m4sugar.m4  |   26 +++++++++++++++++++++++++-
 tests/m4sh.at           |   35 +++++++++++++++++++++++++++++++++--
 7 files changed, 101 insertions(+), 31 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4576d29..94168a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2008-03-11  Eric Blake  <[EMAIL PROTECTED]>
+
+       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  <[EMAIL PROTECTED]>
 
        Encode nested autotest data.
diff --git a/NEWS b/NEWS
index d6e3b3b..79d72f1 100644
--- a/NEWS
+++ b/NEWS
@@ -111,6 +111,10 @@ GNU Autoconf NEWS - User visible changes.
      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.
 
@@ -139,7 +143,7 @@ GNU Autoconf NEWS - User visible changes.
 ** 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.
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 4e24e31..3cdad19 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -10336,29 +10336,19 @@ diversion stack.
 @end defmac
 
 @defmac m4_wrap (@var{text})
[EMAIL PROTECTED] m4_wrap_lifo (@var{text})
 @msindex{wrap}
-This macro corresponds to @code{m4wrap}.
[EMAIL PROTECTED]
+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
[EMAIL PROTECTED] 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.
[EMAIL PROTECTED] 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:
-
[EMAIL PROTECTED]
-m4_define([foo], [bar])
-m4_define([foofoo], [OUCH])
-m4_wrap([foo])
-m4_wrap([foo])
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+Unlike the @acronym{GNU} M4 builtin, these macros only recognize one
+argument, and avoid token pasting between consecutive invocations.
 @end defmac
 
 
@@ -10384,7 +10374,7 @@ guaranteed after @var{message}.
 @end defmac
 
 @anchor{m4_fatal}
[EMAIL PROTECTED] m4_fatal
[EMAIL PROTECTED] m4_fatal (@var{message})
 @msindex{fatal}
 Report a severe error @var{message} prefixed with the current location,
 and have @command{autom4te} die.
diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4
index 98cceae..2f930b5 100644
--- a/lib/autotest/general.m4
+++ b/lib/autotest/general.m4
@@ -194,6 +194,7 @@ m4_define([AT_ordinal], 0)
 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(
@@ -403,7 +404,7 @@ esac]
 # 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],
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 6689e4b..8014f15 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -2,8 +2,8 @@
 # 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
@@ -237,7 +237,7 @@ m4_expand_once([m4_append([_AS_DETECT_SUGGESTED_BODY], [
 # <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],
@@ -1647,7 +1647,9 @@ _AS_RUN([_AS_SHELL_FN_WORK]) || {
 # -------
 # 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_])
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index cd4a1c6..8d5288f 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -138,7 +138,6 @@ m4_rename_m4([index])
 m4_rename_m4([indir])
 m4_rename_m4([len])
 m4_rename([m4exit], [m4_exit])
-m4_rename([m4wrap], [m4_wrap])
 m4_ifdef([mkstemp],dnl added in M4 1.4.8
 [m4_rename_m4([mkstemp])
 m4_copy([m4_mkstemp], [m4_maketemp])
@@ -607,6 +606,30 @@ m4_define([m4_undefine],
          [m4_fatal([$0: undefined macro: $1])])]dnl
 [m4_builtin([undefine], [$1])])
 
+# _m4_wrap(PRE, POST)
+# -------------------
+# 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.  ##
@@ -2215,6 +2238,7 @@ m4_if(m4_sysval, [0], [],
 
 # 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.
diff --git a/tests/m4sh.at b/tests/m4sh.at
index 2b55bc9..29392b0 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -2,8 +2,8 @@
 
 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
@@ -758,3 +758,34 @@ ok 7
 ]])
 
 AT_CLEANUP
+
+
+## ----------------- ##
+## AS_INIT cleanup.  ##
+## ----------------- ##
+
+AT_SETUP([AS@&[EMAIL PROTECTED] cleanup])
+
+AT_KEYWORDS([m4@&[EMAIL PROTECTED] m4@&[EMAIL PROTECTED])
+
+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 Registered before AS_INIT's cleanups
+m4_wrap_lifo([echo cleanup 3
+])
+echo body
+]])
+
+AT_CHECK_M4SH
+AT_CHECK([./script], [], [[body
+cleanup 3
+cleanup 1
+]])
+
+AT_CLEANUP
-- 
1.5.4


>From 3896053aa67797b68ce22c2fcfd916f75c0cb491 Mon Sep 17 00:00:00 2001
From: Eric Blake <[EMAIL PROTECTED]>
Date: Wed, 5 Mar 2008 13:39:23 -0700
Subject: [PATCH] Improve error messages for common testsuite bugs.

* lib/autotest/general.m4 (_AT_DEFINE_INIT, _AT_DEFINE_SETUP): New
macros for defining order-enforced macros.
(AT_INIT, AT_SETUP, AT_CLEANUP, AT_BANNER, AT_XFAIL_IF)
(AT_CAPTURE_FILE, AT_DATA, AT_CHECK, AT_CHECK_NOESCAPE): Add error
messages when order violations are detected.
* tests/autotest.at (AT_CHECK_AT_SYNTAX): New helper macro.
(AT_SETUP without AT_INIT, AT_BANNER without AT_INIT)
(AT_CLEANUP without AT_INIT, Missing AT_CLEANUP)
(AT_CHECK without AT_SETUP, AT_DATA without AT_SETUP)
(AT_XFAIL_IF without AT_DATA, AT_KEYWORDS without AT_SETUP,
(AT_CLEANUP without AT_SETUP, AT_BANNER inside AT_SETUP)
(AT_SETUP inside AT_SETUP, Multiple AT_INIT)
(Banner-only test suite): New tests.
Reported by Christopher Hulbert.

Signed-off-by: Eric Blake <[EMAIL PROTECTED]>
---
 ChangeLog               |   16 ++++++++
 lib/autotest/general.m4 |   55 +++++++++++++++++++++--------
 tests/autotest.at       |   89 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 144 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 94168a0..c6cc1e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2008-03-11  Eric Blake  <[EMAIL PROTECTED]>
 
+       Improve error messages for common testsuite bugs.
+       * lib/autotest/general.m4 (_AT_DEFINE_INIT, _AT_DEFINE_SETUP): New
+       macros for defining order-enforced macros.
+       (AT_INIT, AT_SETUP, AT_CLEANUP, AT_BANNER, AT_XFAIL_IF)
+       (AT_CAPTURE_FILE, AT_DATA, AT_CHECK, AT_CHECK_NOESCAPE): Add error
+       messages when order violations are detected.
+       * tests/autotest.at (AT_CHECK_AT_SYNTAX): New helper macro.
+       (AT_SETUP without AT_INIT, AT_BANNER without AT_INIT)
+       (AT_CLEANUP without AT_INIT, Missing AT_CLEANUP)
+       (AT_CHECK without AT_SETUP, AT_DATA without AT_SETUP)
+       (AT_XFAIL_IF without AT_DATA, AT_KEYWORDS without AT_SETUP,
+       (AT_CLEANUP without AT_SETUP, AT_BANNER inside AT_SETUP)
+       (AT_SETUP inside AT_SETUP, Multiple AT_INIT)
+       (Banner-only test suite): New tests.
+       Reported by Christopher Hulbert.
+
        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.
diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4
index 2f930b5..c4cff41 100644
--- a/lib/autotest/general.m4
+++ b/lib/autotest/general.m4
@@ -181,19 +181,37 @@ m4_define([_AT_NORMALIZE_TEST_GROUP_NUMBER],
   done'
 ])
 
+# _AT_DEFINE_INIT(NAME, [DEFINITION])
+# -----------------------------------
+# Define macro NAME to die if invoked prior to AT_INIT, and to DEFINITION
+# after AT_INIT.
+m4_define([_AT_DEFINE_INIT],
+[m4_define($@)m4_pushdef([$1], [m4_fatal([$1: missing AT_INIT detected])])dnl
+m4_append([_AT_DEFINE_INIT_LIST], [[$1]], [,])])
+
+# _AT_DEFINE_SETUP(NAME, [DEFINITION])
+# -----------------------------------
+# Define macro NAME to die if invoked outside AT_SETUP/AT_CLEANUP, and
+# to DEFINITION otherwise.
+m4_define([_AT_DEFINE_SETUP],
+[m4_define([$1], [m4_ifndef([AT_ingroup],
+ [m4_fatal([$1: missing AT_SETUP detected])])$2])])
+
 
 # AT_INIT([TESTSUITE-NAME])
 # -------------------------
 # Begin test suite.
 m4_define([AT_INIT],
-[m4_pattern_forbid([^_?AT_])
+[m4_pushdef([AT_INIT], [m4_fatal([$0: invoked multiple times])])
+m4_pattern_forbid([^_?AT_])
 m4_pattern_allow([^_AT_T_EOF$])
 m4_define([AT_TESTSUITE_NAME],
-         m4_defn([AT_PACKAGE_STRING])[ test suite]m4_ifval([$1], [: $1]))
+  m4_defn([AT_PACKAGE_STRING])[ test suite]m4_ifval([$1], [m4_expand([: $1])]))
 m4_define([AT_ordinal], 0)
 m4_define([AT_banner_ordinal], 0)
 m4_define([AT_groups_all], [])
 m4_define([AT_help_all], [])
+m4_foreach([AT_name], [_AT_DEFINE_INIT_LIST], [m4_popdef(m4_defn([AT_name]))])
 m4_wrap([_AT_FINISH])
 AS_INIT[]dnl
 m4_divert_push([DEFAULTS])dnl
@@ -404,7 +422,9 @@ esac]
 # Whether -C is in effect.
 at_change_dir=false
 m4_divert_pop([DEFAULTS])dnl
-m4_define([_AT_FINISH], [m4_divert_text([DEFAULTS],
+m4_define([_AT_FINISH],
+[m4_ifdef([AT_ingroup], [m4_fatal([missing AT_CLEANUP detected])])dnl
+m4_divert_text([DEFAULTS],
 [
 # List of the tested programs.
 at_tested='m4_ifdef([AT_tested],
@@ -1401,8 +1421,10 @@ $1])])# AT_COPYRIGHT
 # ---------------------
 # Start a group of related tests, all to be executed in the same subshell.
 # The group is testing what DESCRIPTION says.
-m4_define([AT_SETUP],
-[m4_ifdef([AT_keywords], [m4_undefine([AT_keywords])])
+_AT_DEFINE_INIT([AT_SETUP],
+[m4_ifdef([AT_ingroup], [m4_fatal([$0: nested AT_SETUP detected])],
+  [m4_define([AT_ingroup])])
+m4_ifdef([AT_keywords], [m4_undefine([AT_keywords])])
 m4_define([AT_capture_files], [])
 m4_define([AT_line], AT_LINE)
 m4_define([AT_xfail], [at_xfail=no])
@@ -1426,7 +1448,7 @@ m4_divert_push([TEST_SCRIPT])dnl
 # -----------------------------
 # Set up the test to be expected to fail if SHELL-EXPRESSION evaluates to
 # true (exitcode = 0).
-m4_define([AT_XFAIL_IF],
+_AT_DEFINE_SETUP([AT_XFAIL_IF],
 [dnl
 dnl Try to limit the amount of conditionals that we emit.
 m4_case([$1],
@@ -1442,7 +1464,7 @@ m4_case([$1],
 # ---------------------
 # Declare a list of keywords associated to the current test group.
 # The list is stored in lower case, since the -k option is case-insensitive.
-m4_define([AT_KEYWORDS],
+_AT_DEFINE_SETUP([AT_KEYWORDS],
 [m4_append_uniq_w([AT_keywords], m4_tolower([[$1]]))])
 
 
@@ -1450,7 +1472,7 @@ m4_define([AT_KEYWORDS],
 # ---------------------
 # If the current test group does not behave as expected, save the contents of
 # FILE in the test suite log.
-m4_define([AT_CAPTURE_FILE],
+_AT_DEFINE_SETUP([AT_CAPTURE_FILE],
 [m4_append_uniq([AT_capture_files], ["$1"], [ \
 ])])
 
@@ -1458,8 +1480,10 @@ m4_define([AT_CAPTURE_FILE],
 # AT_CLEANUP
 # ----------
 # Complete a group of related tests.
-m4_define([AT_CLEANUP],
-[m4_append([AT_help_all],
+_AT_DEFINE_INIT([AT_CLEANUP],
+[m4_ifdef([AT_ingroup], [m4_undefine([AT_ingroup])],
+  [m4_fatal([$0: missing AT_SETUP detected])])dnl
+m4_append([AT_help_all],
 m4_defn([AT_ordinal]);m4_defn([AT_line]);m4_defn([AT_description]);dnl
 m4_ifdef([AT_keywords], [m4_defn([AT_keywords])]);
 )dnl
@@ -1484,8 +1508,9 @@ m4_divert_pop([TEST_GROUPS])dnl Back to KILL.
 # Start a category of related test groups.  If multiple groups are executed,
 # output TEXT as a banner without any shell expansion, prior to any test
 # from the category.  If TEXT is empty, no banner is printed.
-m4_define([AT_BANNER],
-[m4_define([AT_banner_ordinal], m4_incr(AT_banner_ordinal))
+_AT_DEFINE_INIT([AT_BANNER],
+[m4_ifdef([AT_ingroup], [m4_fatal([$0: nested AT_SETUP detected])])dnl
+m4_define([AT_banner_ordinal], m4_incr(AT_banner_ordinal))
 m4_divert_text([BANNERS],
 [EMAIL PROTECTED]:@ Banner AT_banner_ordinal. AT_LINE
 @%:@ Category starts at test group m4_incr(AT_ordinal).
@@ -1499,7 +1524,7 @@ at_banner_text_[]AT_banner_ordinal="AS_ESCAPE([$1])"])dnl
 # an end of line.
 # This macro is not robust to active symbols in CONTENTS *on purpose*.
 # If you don't want CONTENTS to be evaluated, quote it twice.
-m4_define([AT_DATA],
+_AT_DEFINE_SETUP([AT_DATA],
 [cat >$1 <<'_ATEOF'
 $2[]_ATEOF
 ])
@@ -1545,7 +1570,7 @@ $2[]_ATEOF
 # out, since most shells when tracing include subshell traces in stderr.
 # This may cause spurious failures when the test suite is run with `-x'.
 #
-m4_define([AT_CHECK],
+_AT_DEFINE_SETUP([AT_CHECK],
 [_AT_CHECK([$1],[$2],[$3],[$4],[$5],[$6],1)])
 
 # AT_CHECK_NOESCAPE(COMMANDS, [STATUS = 0], STDOUT, STDERR,
@@ -1553,7 +1578,7 @@ m4_define([AT_CHECK],
 # ---------------------------------------------------------
 # Like AT_CHECK, but do not AS_ESCAPE shell metacharacters in the STDOUT
 # and STDERR arguments before running the comparison.
-m4_define([AT_CHECK_NOESCAPE],
+_AT_DEFINE_SETUP([AT_CHECK_NOESCAPE],
 [_AT_CHECK([$1],[$2],[$3],[$4],[$5],[$6])])
 
 
diff --git a/tests/autotest.at b/tests/autotest.at
index fea0adc..3ba3ebf 100644
--- a/tests/autotest.at
+++ b/tests/autotest.at
@@ -81,7 +81,20 @@ AT_INIT([artificial test suite])
 AT_SETUP([my only test])
 $2
 AT_CLEANUP
-]], m4_shift2($@))])
+]], m4_shift2($@))]) # AT_CHECK_AT_TEST
+
+# AT_CHECK_AT_SYNTAX(TITLE, SUITE, MESSAGE)
+# -----------------------------------------
+# Create a test named TITLE that tries compiling SUITE with syntax
+# errors with autotest.  Expect a failed compilation, and grep for
+# MESSAGE occuring within the error output.
+m4_define([AT_CHECK_AT_SYNTAX],
+[AT_SETUP([$1])
+AT_CHECK_AT_PREP([micro-suite], [$2], [1], [], [stderr])
+AT_CHECK([grep '$3' stderr], [0], [ignore])
+AT_CLEANUP
+])# AT_CHECK_AT_SYNTAX
+
 
 # AT_NO_CMDSUBST
 # --------------
@@ -109,12 +122,86 @@ AT_CHECK_AT([Empty test suite],
 [[AT_INIT([empty test suite])
 ]])
 
+AT_CHECK_AT([Banner-only test suite],
+[[AT_INIT([empty test suite])
+AT_BANNER([banner])
+]])
+
 # Next level of emptiness.
 AT_CHECK_AT_TEST([Empty test], [])
 
 # And finally, an empty check should not cause a syntax error.
 AT_CHECK_AT_TEST([Empty check], [AT_CHECK])
 
+# Check for sensible error messages for common bugs.
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_SETUP([only test])
+AT_CHECK([:])
+AT_CLEANUP
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_BANNER([just a banner])
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_CLEANUP
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([Missing AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_SETUP([only test])
+AT_CHECK([:])
+]], [missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_CHECK([:])
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_DATA([file])
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_XFAIL_IF([:])
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_KEYWORDS([keyword])
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] without AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_CLEANUP
+]], [AT@&[EMAIL PROTECTED]: missing AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] inside AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_SETUP([only test])
+AT_BANNER([banner])
+AT_CHECK([:])
+AT_CLEANUP
+]], [AT@&[EMAIL PROTECTED]: nested AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([AT@&[EMAIL PROTECTED] inside AT@&[EMAIL PROTECTED],
+[[AT_INIT([incomplete test suite])
+AT_SETUP([only test])
+ AT_SETUP([nested test])
+ AT_CHECK([:])
+ AT_CLEANUP
+AT_CHECK([:])
+AT_CLEANUP
+]], [AT@&[EMAIL PROTECTED]: nested AT@&[EMAIL PROTECTED] detected])
+
+AT_CHECK_AT_SYNTAX([Multiple AT@&[EMAIL PROTECTED],
+[[AT_INIT([[suite, take one]])
+AT_INIT([repeat])
+]], [AT@&[EMAIL PROTECTED]: invoked multiple times])
+
 # Check for tested programs.  autoconf should only appear once.
 AT_CHECK_AT([Tested programs],
 [[AT_INIT([programs test suite])
-- 
1.5.4

Reply via email to