]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Improve m4_copy.
authorEric Blake <ebb9@byu.net>
Fri, 24 Oct 2008 03:17:25 +0000 (21:17 -0600)
committerEric Blake <ebb9@byu.net>
Fri, 24 Oct 2008 12:41:49 +0000 (06:41 -0600)
* lib/m4sugar/m4sugar.m4 (m4_copy): Add second implementation for
public use.
(_m4_copy): New macro, which preserves pushdef stacks.
(_m4_defun_pro_outer): Bypass it, for speed.
(m4_init): Bypass new implementation, since it breaks on m4_defn.
* bin/autoupdate.in (handle_autoconf_macros): Likewise.
* lib/autoconf/general.m4 (AC_PREREQ): Undefine before redefining,
now that m4_copy checks this.
* doc/autoconf.texi (Redefined M4 Macros) <m4_copy>: Document
this, as well as m4_rename.
* lib/autoconf/autoconf.m4 (m4_copy): Temporarily redefine when
renaming builtins.
* NEWS: Likewise.
* tests/m4sugar.at (m4@&t@_defn): Enhance test.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
NEWS
bin/autoupdate.in
doc/autoconf.texi
lib/autoconf/autoconf.m4
lib/autoconf/general.m4
lib/m4sugar/m4sugar.m4
tests/m4sugar.at

index 0a835899d4e6edff7c8c68734e77a9f88ccb8074..f8361b7955a49fb4ece9a0759730d9b14f8d5267 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2008-10-24  Eric Blake  <ebb9@byu.net>
+
+       Improve m4_copy.
+       * lib/m4sugar/m4sugar.m4 (m4_copy): Add second implementation for
+       public use.
+       (_m4_copy): New macro, which preserves pushdef stacks.
+       (_m4_defun_pro_outer): Bypass it, for speed.
+       (m4_init): Bypass new implementation, since it breaks on m4_defn.
+       * bin/autoupdate.in (handle_autoconf_macros): Likewise.
+       * lib/autoconf/general.m4 (AC_PREREQ): Undefine before redefining,
+       now that m4_copy checks this.
+       * doc/autoconf.texi (Redefined M4 Macros) <m4_copy>: Document
+       this, as well as m4_rename.
+       * lib/autoconf/autoconf.m4 (m4_copy): Temporarily redefine when
+       renaming builtins, since it breaks on m4_ifdef.
+       * NEWS: Likewise.
+       * tests/m4sugar.at (m4@&t@_defn): Enhance test.
+
 2008-10-24  Eric Blake  <ebb9@byu.net>
 
        AC_FUNC_GETGROUPS: Revert regression.
diff --git a/NEWS b/NEWS
index 8b682b84031c557ec75e361154db37197747a1d5..496fac711e1a9362b0ca58ecf7a807185d38d7d0 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,10 +12,13 @@ GNU Autoconf NEWS - User visible changes.
 
 ** Configure scripts now use shell functions.
 
-** The following m4sugar macros are new:
+** The following documented m4sugar macros are new:
    m4_curry  m4_default_quoted  m4_map_args  m4_map_args_pair
    m4_set_map
 
+** The following m4sugar macros are documented now:
+   m4_copy  m4_rename
+
 ** The following documented m4sh macros are new:
    AS_LINENO_PREPARE  AS_ME_PREPARE  AS_VAR_APPEND  AS_VAR_COPY
 
index d23048a1cc73c355a39e9de3db10f1381c43ded6..c9235596b85130954daaae544550cf9205cd5dfc 100644 (file)
@@ -271,7 +271,8 @@ foreach my $file (@ARGV)
       define([_au__include], defn([include]))
       define([_au___undefine], defn([undefine]))
       define([_au__undefine], [_au__ifdef([$1], [_au___undefine([$1])])])
-      define([_au__save], [m4_ifdef([$1], [m4_copy([$1], [_au_$1])])])
+      define([_au__save], [m4_ifdef([$1],
+       [m4_define([_au_$1], _m4_defn([$1]))])])
       define([_au__restore],
        [_au_m4_ifdef([_au_$1],
          [_au_m4_define([$1], _au__defn([_au_$1]))])])
index 71f507f1e5e14ddd5e5ccdac8f9d9ed2e67a4907..85093229ac4962bbc71ed3677bf3ef25f14e43e2 100644 (file)
@@ -10363,6 +10363,25 @@ is kept for future versions of M4sugar, once @acronym{GNU} M4 2.0 is
 released and supports extended regular expression syntax.
 @end defmac
 
+@defmac m4_copy (@var{source}, @var{dest})
+@defmacx m4_rename (@var{source}, @var{dest})
+@msindex{copy}
+@msindex{rename}
+These macros aren't directly builtins, but are closely related to
+@code{m4_pushdef} and @code{m4_defn}.  They both ensures that @var{dest}
+is undefined, then proceed to copy the entire pushdef stack of
+definitions of @var{source}.  @code{m4_copy} preserves the source, while
+@code{m4_rename} undefines the original macro name.
+
+Note that attempting to invoke a renamed macro might not work, since the
+macro may have a dependence on helper macros accessed via composition of
+@samp{$0} but that were not also renamed; likewise, other macros may
+have a hard-coded dependence on @var{source} and could break if
+@var{source} has been deleted.  On the other hand, it is always safe to
+rename a macro to temporarily move it out of the way, then rename it
+back later to restore original semantics.
+@end defmac
+
 @defmac m4_defn (@var{macro}@dots{})
 @msindex{defn}
 This macro fails if @var{macro} is not defined, even when using older
index c802959569ebe30271ae5956ef85fdc047909dc7..0a838a6e2dbc1d38ee642d901206185abad2d2a1 100644 (file)
@@ -1,7 +1,7 @@
 # This file is part of Autoconf.                -*- Autoconf -*-
 # Driver that loads the Autoconf macro files.
 #
-# Copyright (C) 1994, 1999, 2000, 2001, 2002, 2006 Free Software
+# Copyright (C) 1994, 1999, 2000, 2001, 2002, 2006, 2008 Free Software
 # Foundation, Inc.
 #
 # This program is free software: you can redistribute it and/or modify
@@ -76,6 +76,14 @@ m4_include([autoconf/oldnames.m4])
 # names too.  But users may still depend upon these, so reestablish
 # them.
 
+# In order to copy pushdef stacks, m4_copy temporarily destroys the
+# current pushdef stack.  But these builtins are so primitive that:
+#   1. they should not have more than one pushdef definition
+#   2. undefining the pushdef stack to copy breaks m4_copy
+# Hence, we temporarily restore a simpler m4_copy.
+
+m4_pushdef([m4_copy], [m4_define([$2], m4_defn([$1]))])
+
 m4_copy_unm4([m4_builtin])
 m4_copy_unm4([m4_changequote])
 m4_copy_unm4([m4_decr])
@@ -104,6 +112,8 @@ m4_copy_unm4([m4_translit])
 m4_copy_unm4([m4_undefine])
 m4_copy_unm4([m4_undivert])
 
+m4_popdef([m4_copy])
+
 # Yet some people have started to use m4_patsubst and m4_regexp.
 m4_define([m4_patsubst],
 [m4_expand_once([m4_warn([syntax],
index 158391cd149fb7a1a56aa45320765be83fd5c80d..4f13b58e68dc3ed4930db0fbc92fc84d6b7ee10c 100644 (file)
@@ -317,6 +317,7 @@ AU_DEFUN([AC_PREREQ],
 # AC_PREREQ(VERSION)
 # ------------------
 # Complain and exit if the Autoconf version is less than VERSION.
+m4_undefine([AC_PREREQ])
 m4_copy([m4_version_prereq], [AC_PREREQ])
 
 
index ee8ee63e3f656eed6d022dc268048c51b8cbf3f2..d0fe9adee2c05f92a7157ef3bac95c145bb03e3e 100644 (file)
@@ -91,6 +91,10 @@ m4_undefine([undefine])
 # Nevertheless, one huge difference is the handling of `$0'.  If `from'
 # uses `$0', then with 1, `to''s `$0' is `to', while it is `from' in 2.
 # The user would certainly prefer to see `to'.
+#
+# This definition is in effect during m4sugar initialization, when
+# there are no pushdef stacks; later on, we redefine it to something
+# more powerful for all other clients to use.
 m4_define([m4_copy],
 [m4_define([$2], m4_defn([$1]))])
 
@@ -166,6 +170,28 @@ m4_rename_m4([traceon])
 m4_rename_m4([translit])
 m4_undefine([undivert])
 
+# _m4_defn(ARG)
+# ----------------
+# _m4_defn is for internal use only - it bypasses the wrapper, so it
+# must only be used on one argument at a time, and only on macros
+# known to be defined.  Make sure this still works if the user renames
+# m4_defn but not _m4_defn.
+m4_copy([m4_defn], [_m4_defn])
+
+# _m4_popdef(ARG...)
+# ------------------
+# _m4_popdef is for internal use only - it bypasses the wrapper, so it
+# must only be used on macros known to be defined.  Make sure this
+# still works if the user renames m4_popdef but not _m4_popdef.
+m4_copy([m4_popdef], [_m4_popdef])
+
+# _m4_undefine(ARG...)
+# --------------------
+# _m4_undefine is for internal use only - it bypasses the wrapper, so
+# it must only be used on macros known to be defined.  Make sure this
+# still works if the user renames m4_undefine but not _m4_undefine.
+m4_copy([m4_undefine], [_m4_undefine])
+
 
 ## ------------------- ##
 ## 2. Error messages.  ##
@@ -501,6 +527,28 @@ m4_define([_m4_bpatsubsts],
           m4_shift3($@))])])
 
 
+# m4_copy(SRC, DST)
+# -----------------
+# Define the pushdef stack DST as a copy of the pushdef stack SRC;
+# give an error if DST is already defined.  This is particularly nice
+# for copying self-modifying pushdef stacks, where the top definition
+# includes one-shot initialization that is later popped to the normal
+# definition.
+#
+# The recursive worker destructively swaps the order of a stack.  We
+# use a temporary stack, and swap directions twice, using the third
+# argument to restore the original stack.
+#
+# Some macros simply can't be renamed with this method: namely,
+# anything involved in the implementation of _m4_copy.
+m4_define([m4_copy],
+[m4_ifdef([$2], [m4_fatal([$0: won't overwrite defined macro: $2])],
+         [_$0([$1], [m4_tmp])_$0([m4_tmp], [$2],
+  [m4_pushdef([$1], _m4_defn([m4_tmp]))])])])
+m4_define([_m4_copy],
+[m4_ifdef([$1], [m4_pushdef([$2], _m4_defn([$1]))$3[]_m4_popdef([$1])$0($@)])])
+
+
 # m4_define_default(MACRO, VALUE)
 # -------------------------------
 # If MACRO is undefined, set it to VALUE.
@@ -547,12 +595,6 @@ m4_define([m4_default_quoted],
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
 # (added in M4 1.6), then let m4 do the job for us (see m4_init).
-#
-# _m4_defn is for internal use only - it bypasses the wrapper, so it
-# must only be used on one argument at a time, and only on macros
-# known to be defined.  Make sure this still works if the user renames
-# m4_defn but not _m4_defn.
-m4_copy([m4_defn], [_m4_defn])
 m4_define([m4_defn],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_defn([$1])],
@@ -596,11 +638,6 @@ _m4_dumpdefs_down([$1])])
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
 # (added in M4 1.6), then let m4 do the job for us (see m4_init).
-#
-# _m4_popdef is for internal use only - it bypasses the wrapper, so it
-# must only be used on macros known to be defined.  Make sure this
-# still works if the user renames m4_popdef but not _m4_popdef.
-m4_copy([m4_popdef], [_m4_popdef])
 m4_define([m4_popdef],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_popdef([$1])],
@@ -662,11 +699,6 @@ m4_define([_m4_shift3],
 # This macro is called frequently, so minimize the amount of additional
 # expansions by skipping m4_ifndef.  Better yet, if __m4_version__ exists,
 # (added in M4 1.6), then let m4 do the job for us (see m4_init).
-#
-# _m4_undefine is for internal use only - it bypasses the wrapper, so
-# it must only be used on macros known to be defined.  Make sure this
-# still works if the user renames m4_undefine but not _m4_undefine.
-m4_copy([m4_undefine], [_m4_undefine])
 m4_define([m4_undefine],
 [m4_if([$#], [0], [[$0]],
        [$#], [1], [m4_ifdef([$1], [_m4_undefine([$1])],
@@ -1578,7 +1610,8 @@ m4_do([[m4_ifdef([m4_expansion_stack], [], [_m4_defun_pro_outer[]])]],
       [[m4_pushdef([_m4_expanding($1)])]]))
 
 m4_define([_m4_defun_pro_outer],
-[m4_copy([_m4_divert_diversion], [_m4_divert_dump])m4_divert_push([GROW])])
+[m4_define([_m4_divert_dump],
+  m4_defn([_m4_divert_diversion]))m4_divert_push([GROW])])
 
 # _m4_defun_epi(MACRO-NAME)
 # -------------------------
@@ -2838,12 +2871,13 @@ m4_pattern_forbid([^dnl$])
 # But if it is missing, we assume we are being run by M4 1.4.x, that
 # $@ recursion is quadratic, and that we need foreach-based
 # replacement macros.  Use the raw builtin to avoid tripping up
-# include tracing.
+# include tracing.  Meanwhile, avoid m4_copy, since it temporarily
+# undefines m4_defn.
 m4_ifdef([__m4_version__],
 [m4_debugmode([+d])
-m4_copy([_m4_defn], [m4_defn])
-m4_copy([_m4_popdef], [m4_popdef])
-m4_copy([_m4_undefine], [m4_undefine])],
+m4_define([m4_defn], _m4_defn([m4_defn]))
+m4_define([m4_popdef], _m4_defn([m4_popdef]))
+m4_define([m4_undefine], _m4_defn([m4_undefine]))],
 [m4_builtin([include], [m4sugar/foreach.m4])])
 
 # _m4_divert_diversion should be defined:
index f34bca36d5e06321dd40b95652eca76362608196..deb6f8ca453aa2e6640b8ba83eb47a94bd25a613 100644 (file)
@@ -43,7 +43,7 @@ AT_CHECK_M4SUGAR([-o-],, [$2], [$3])
 
 AT_SETUP([m4@&t@_defn])
 
-AT_KEYWORDS([m4@&t@_popdef m4@&t@_undefine])
+AT_KEYWORDS([m4@&t@_popdef m4@&t@_undefine m4@&t@_copy m4@&t@_rename])
 
 # Ensure that m4sugar dies when dereferencing undefined macros, whether
 # this is provided by m4 natively or faked by wrappers in m4sugar.
@@ -75,6 +75,25 @@ AT_CHECK_M4SUGAR([-o-], 1, [], [stderr])
 AT_CHECK([grep good stderr], [1])
 AT_CHECK([grep 'm4@&t@_undefine: undefined.*oops' stderr], [0], [ignore])
 
+# Check that pushdef stacks can be renamed.
+AT_CHECK_M4SUGAR_TEXT([[m4_pushdef([a], [1])dnl
+m4_pushdef([a], [2])dnl
+a b c
+m4_rename([a], [b])dnl
+a b c
+m4_copy([b], [c])dnl
+a b c
+m4_popdef([b], [c])dnl
+a b c
+m4_popdef([b], [c])dnl
+a b c
+]], [[2 b c
+a 2 c
+a 2 2
+a 1 1
+a b c
+]])
+
 AT_CLEANUP