Improve AC_DEFUN_ONCE semantics.

* lib/m4sugar/m4sugar.m4 (m4_defun_once): Rewrite to be no-op,
rather than warning, on second use, and make sure first use never
occurs out of order.
* tests/m4sugar.at (m4@&t@_require: one-shot initialization):
Enhance test.
* tests/base.at (AC_REQUIRE & AC_DEFUN_ONCE: [Require, expand],
(AC_REQUIRE & AC_DEFUN_ONCE: [Expand, require]): Adjust tests.
* NEWS: Document this.
* doc/autoconf.texi (Macro Definitions) <AC_DEFUN>: Mention
AC_DEFUN_ONCE.
(Prerequisite Macros) <AC_REQUIRE>: Likewise.
(Expanded Before Required): Likewise.
(One-Shot Macros) <AC_DEFUN_ONCE>: Document new semantics.
Reported by Bruno Haible, with suggestion by Paolo Bonzini.

Signed-off-by: Eric Blake <ebb9@byu.net>
This commit is contained in:
Eric Blake 2009-01-26 09:55:57 -07:00
parent 2cc17c497c
commit 9f32bcf860
6 changed files with 93 additions and 27 deletions

View File

@ -1,3 +1,21 @@
2009-01-26 Eric Blake <ebb9@byu.net>
Improve AC_DEFUN_ONCE semantics.
* lib/m4sugar/m4sugar.m4 (m4_defun_once): Rewrite to be no-op,
rather than warning, on second use, and make sure first use never
occurs out of order.
* tests/m4sugar.at (m4@&t@_require: one-shot initialization):
Enhance test.
* tests/base.at (AC_REQUIRE & AC_DEFUN_ONCE: [Require, expand],
(AC_REQUIRE & AC_DEFUN_ONCE: [Expand, require]): Adjust tests.
* NEWS: Document this.
* doc/autoconf.texi (Macro Definitions) <AC_DEFUN>: Mention
AC_DEFUN_ONCE.
(Prerequisite Macros) <AC_REQUIRE>: Likewise.
(Expanded Before Required): Likewise.
(One-Shot Macros) <AC_DEFUN_ONCE>: Document new semantics.
Reported by Bruno Haible, with suggestion by Paolo Bonzini.
2009-01-24 Eric Blake <ebb9@byu.net>
Fix typos in recent patches.

6
NEWS
View File

@ -14,6 +14,12 @@ GNU Autoconf NEWS - User visible changes.
the bug in earlier autoconf versions and avoid increased script
size in the current version.
** AC_DEFUN_ONCE has improved semantics. Previously, a macro declared
with AC_DEFUN_ONCE warned on a second invocation; and out-of-order
expansion was still possible. Now, dependencies are guaranteed,
and subsequent invocations are a silent no-op. This makes
AC_DEFUN_ONCE an ideal macro for silencing AC_REQUIRE warnings.
** AC_LANG_ERLANG works once again (regression introduced in 2.61a).
** AC_HEADER_ASSERT is fixed so that './configure --enable-assert' no

View File

@ -12830,7 +12830,8 @@ the argument to @code{AC_REQUIRE}. The other category includes macros
which are shorthand for a fixed block of text, and therefore do not take
arguments. For this category of macros, directly expanding the macro
multiple times results in redundant output, so it is more common to use
the macro as the argument to @code{AC_REQUIRE}.
the macro as the argument to @code{AC_REQUIRE}, or to declare the macro
with @code{AC_DEFUN_ONCE} (@pxref{One-Shot Macros}).
Be sure to properly quote both the @var{macro-body} @emph{and} the
@var{macro-name} to avoid any problems if the macro happens to have
@ -13171,7 +13172,9 @@ in C
The bug is not in Autoconf, but in the macro definitions. If you ever
pass a particular macro name to @code{AC_REQUIRE}, then you are implying
that the macro only needs to be expanded once. But to enforce this, all
that the macro only needs to be expanded once. But to enforce this,
either the macro must be declared with @code{AC_DEFUN_ONCE} (although
this only helps in Autoconf 2.64 or newer), or all
uses of that macro should be through @code{AC_REQUIRE}; directly
expanding the macro defeats the point of using @code{AC_REQUIRE} to
eliminate redundant expansion. In the example, this rule of thumb was
@ -13271,16 +13274,21 @@ macros can be defined using @code{AC_DEFUN_ONCE}.
@defmac AC_DEFUN_ONCE (@var{macro-name}, @var{macro-body})
@acindex{DEFUN_ONCE}
Declare macro @var{macro-name} like @code{AC_DEFUN} would (@pxref{Macro
Definitions}), and emit a warning any time the macro is called more than
once.
Definitions}), but add additional logic that guarantees that only the
first use of the macro (whether by direct expansion or
@code{AC_REQUIRE}) causes an expansion of @var{macro-body}; the
expansion will occur before the start of any enclosing macro defined by
@code{AC_DEFUN}. Subsequent expansions are silently ignored.
Generally, it does not make sense for @var{macro-body} to use parameters
such as @code{$1}.
@end defmac
Obviously it is not sensible to evaluate a macro defined by
@code{AC_DEFUN_ONCE} in a macro defined by @code{AC_DEFUN}.
Most of the time you want to use @code{AC_REQUIRE} (@pxref{Prerequisite
Macros}).
Prior to Autoconf 2.64, a macro defined by @code{AC_DEFUN_ONCE} would
emit a warning if it was directly expanded a second time, so for
portability, it is better to use @code{AC_REQUIRE} than direct
invocation of @var{macro-name} inside a macro defined by @code{AC_DEFUN}
(@pxref{Prerequisite Macros}).
@node Obsoleting Macros
@section Obsoleting Macros
@ -22867,7 +22875,10 @@ $ @kbd{autoconf}
@noindent
To avoid this warning, decide what purpose the macro in question serves.
If it only needs to be expanded once (for example, if it provides
initialization text used by later macros), then the fix is to change all
initialization text used by later macros), then the simplest fix is to
change the macro to be declared with @code{AC_DEFUN_ONCE}
(@pxref{One-Shot Macros}), although this only works in Autoconf 2.64 and
newer. A more portable fix is to change all
instances of direct calls to instead go through @code{AC_REQUIRE}
(@pxref{Prerequisite Macros}). If, instead, the macro is parameterized
by arguments or by the current definition of other macros in the m4

View File

@ -1914,14 +1914,17 @@ m4_define([m4_defun_init],
# m4_defun_once(NAME, EXPANSION)
# ------------------------------
# Like m4_defun, but issues the EXPANSION only once, and warns if used
# several times.
# Like m4_defun, but guarantee that EXPANSION only happens once
# (thereafter, using NAME is a no-op).
#
# If _m4_divert_dump is empty, we are called at the top level;
# otherwise, we must ensure that we are required in front of the
# current defun'd macro.
m4_define([m4_defun_once],
[m4_define([m4_location($1)], m4_location)dnl
m4_define([$1],
[m4_provide_if([$1],
[m4_warn([syntax], [$1 invoked multiple times])],
[_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])])])
[m4_define([m4_location($1)], m4_location)]dnl
[m4_define([$1], [m4_pushdef([$1])m4_if(_m4_divert_dump, [],
[_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])],
[_m4_require_call([$1], [$2[]m4_provide([$1])], _m4_divert_dump)])])])
# m4_pattern_forbid(ERE, [WHY])

View File

@ -2,8 +2,8 @@
AT_BANNER([Autoconf base layer.])
# Copyright (C) 2000, 2001, 2003, 2005, 2006, 2007, 2008 Free Software
# Foundation, Inc.
# Copyright (C) 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009 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
@ -28,6 +28,7 @@ AT_BANNER([Autoconf base layer.])
# Check that dependencies are always properly honored.
AT_SETUP([AC_REQUIRE: topological sort])
AT_KEYWORDS([m4@&t@_require])
AT_DATA([configure.ac],
[[define([REQUIRE_AND_CHECK],
@ -71,6 +72,7 @@ AT_CLEANUP
# Check that the message mentions AC_DEFUN, not m4_defun.
AT_SETUP([AC_REQUIRE: error message])
AT_KEYWORDS([m4@&t@_require])
AT_DATA([configure.ac],
[[AC_REQUIRE([AC_PROG_CC])
]])
@ -88,6 +90,7 @@ AT_CLEANUP
## ----------------------------------------------- ##
AT_SETUP([AC_REQUIRE & AC_DEFUN_ONCE: [Require, expand]])
AT_KEYWORDS([m4@&t@_require m4@&t@_require_once])
AT_DATA([configure.ac],
[[AC_DEFUN([TEST],
@ -116,10 +119,7 @@ case $multi_test:$single_test in
esac
]])
AT_CHECK_AUTOCONF([], 0, [],
[configure.ac:17: warning: SINGLE_TEST invoked multiple times
configure.ac:18: warning: SINGLE_TEST invoked multiple times
])
AT_CHECK_AUTOCONF([], 0, [])
AT_CHECK_CONFIGURE
@ -132,6 +132,7 @@ AT_CLEANUP
## ----------------------------------------------- ##
AT_SETUP([AC_REQUIRE & AC_DEFUN_ONCE: [Expand, require]])
AT_KEYWORDS([m4@&t@_require m4@&t@_require_once])
AT_DATA([configure.ac],
[[AC_DEFUN([TEST],
@ -161,9 +162,7 @@ case $multi_test:$single_test in
esac
]])
AT_CHECK_AUTOCONF([], 0, [],
[configure.ac:16: warning: SINGLE_TEST invoked multiple times
])
AT_CHECK_AUTOCONF([], 0, [])
AT_CHECK_CONFIGURE
AT_CLEANUP
@ -175,6 +174,7 @@ AT_CLEANUP
## ------------------------- ##
AT_SETUP([AC_REQUIRE & AC_PROVIDE])
AT_KEYWORDS([m4@&t@_require])
AT_DATA([configure.ac],
[[AC_DEFUN([TEST],

View File

@ -430,8 +430,9 @@ AT_CLEANUP
AT_SETUP([m4@&t@_require: one-shot initialization])
AT_KEYWORDS([m4@&t@_require])
AT_KEYWORDS([m4@&t@_defun_init m4@&t@_copy])
AT_KEYWORDS([m4@&t@_defun_init m4@&t@_copy m4@&t@_defun_once])
dnl check out m4_defun_init, m4_copy, and odd macro names
AT_CHECK_M4SUGAR_TEXT([[
m4_defun_init([a], [[init a
]], [[common a]])dnl
@ -455,6 +456,33 @@ hello, world
goodbye
hello, again
]])
dnl Check m4_defun_once behavior
AT_CHECK_M4SUGAR_TEXT([[
m4_defun_once([a], [[a]])dnl
m4_defun([b], [[b]m4_require([a])])dnl
m4_defun([c], [[c]
a[]m4_require([b])])dnl
c
a
m4_defun_once([d], [[d]m4_require([a])])dnl
d
m4_defun_once([e], [[e]])dnl
m4_defun([f], [[f]m4_require([e])e])dnl
f
]], [[
a
b
c
d
e
f
]])
AT_CLEANUP