]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Inherit improvements from bison's fork of m4sugar.
authorEric Blake <ebb9@byu.net>
Fri, 11 Jul 2008 17:14:46 +0000 (11:14 -0600)
committerEric Blake <ebb9@byu.net>
Fri, 11 Jul 2008 17:14:46 +0000 (11:14 -0600)
* lib/m4sugar/m4sugar.m4 (m4_PACKAGE_VERSION): Ignore failure to
find version.texi, since bison does not provide it.
(m4_prepend): Add new macro, from bison.
(m4_prepend_uniq, m4_prepend_uniq_w): Add new macros, for
completeness.
(_m4_append_uniq): Rename...
(_m4_grow_uniq_1): ...to this to share implementation, and
optimize initial assignment.
(m4_append_uniq_w): Adjust caller.
* NEWS: Document new macros.
* doc/autoconf.texi (Text processing Macros) <m4_append>: Mention
speed consideration.
<m4_prepend>: Document the new prepend variants.
* tests/m4sugar.at (m4@&t@_prepend): New test.

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

index 4df6dc32b4e006543cc054c60cc2f1fb5f9f36f2..9218ddcc7a5bec5aea5df23a7782b608b11a2397 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2008-07-11  Eric Blake  <ebb9@byu.net>
 
+       Inherit improvements from bison's fork of m4sugar.
+       * lib/m4sugar/m4sugar.m4 (m4_PACKAGE_VERSION): Ignore failure to
+       find version.texi, since bison does not provide it.
+       (m4_prepend): Add new macro, from bison.
+       (m4_prepend_uniq, m4_prepend_uniq_w): Add new macros, for
+       completeness.
+       (_m4_append_uniq): Rename...
+       (_m4_grow_uniq_1): ...to this to share implementation, and
+       optimize initial assignment.
+       (m4_append_uniq_w): Adjust caller.
+       * NEWS: Document new macros.
+       * doc/autoconf.texi (Text processing Macros) <m4_append>: Mention
+       speed consideration.
+       <m4_prepend>: Document the new prepend variants.
+       * tests/m4sugar.at (m4@&t@_prepend): New test.
+
        Work around M4 1.6 warning on undefined macros.
        * lib/m4sugar/m4sugar.m4 (changeword, symbols): Don't rename if
        not already available as builtins.
diff --git a/NEWS b/NEWS
index 06b705f7d81c8a3c9b148c18a4e39378aef42403..86203db985e9504977a6741d1a885b9a22679141 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,9 @@ GNU Autoconf NEWS - User visible changes.
 ** Config header templates `#undef UNDEFINED /* comment */' do not lead to
    nested comments any more; regression introduced in 2.62.
 
+** The following m4sugar macros are new:
+   m4_prepend  m4_prepend_uniq  m4_prepend_uniq_w
+
 \f
 * Major changes in Autoconf 2.62 (2008-04-05) [stable]
   Released by Eric Blake, based on git versions 2.61a.*.
index f3123785df8e32bbde53f27b87e6b493f4210ebd..672e76b6a2c1eea3c1a4e78825f79fc40121494d 100644 (file)
@@ -11055,6 +11055,12 @@ to grow strings without duplicating substrings.  Additionally,
 Also, @code{m4_append_uniq} warns if @var{separator} is not empty, but
 occurs within @var{string}, since that can lead to duplicates.
 
+Note that @code{m4_append} can scale @dfn{linearithmically} (ie., O(n
+log n) in complexity notation), depending on the quality of the
+underlying M4 implementation, while @code{m4_append_uniq} has an
+inherent quadratic scaling factor.  If an algorithm can tolerate
+duplicates in the final string, use the former for speed.
+
 @example
 m4_define([active], [ACTIVE])dnl
 m4_append([sentence], [This is an])dnl
@@ -11165,6 +11171,23 @@ with a single space.  This is a combination of @code{m4_flatten} and
 @code{m4_strip}.
 @end defmac
 
+@defmac m4_prepend (@var{macro-name}, @var{string}, @ovar{separator})
+@defmacx m4_prepend_uniq (@var{macro-name}, @var{string}, @ovar{separator} @
+  @ovar{if-uniq}, @ovar{if-duplicate})
+@defmacx m4_append_uniq_w (@var{macro-name}, @var{strings})
+@msindex{prepend}
+@msindex{prepend_uniq}
+@msindex{prepend_uniq_w}
+These macros were introduced in Autoconf 2.63; they are like
+@code{m4_append}, @code{m4_append_uniq}, and @code{m4_append_uniq_w}
+respectively, except that the @var{string} argument is added at the
+beginning instead of the end of the definition of @code{macro-name}.
+
+Also note that unlike @code{m4_append}, @code{m4_prepend} has quadratic
+rather than linearithmic scaling behavior.  Thus, if the order of list
+elements does not matter, it is better to append.
+@end defmac
+
 @defmac m4_re_escape (@var{string})
 @msindex{re_escape}
 Backslash-escape all characters in @var{string} that are active in
index faa86ee99e93037dba42aee48d4535c45eb439e8..0a708f6f400b8b8a201504592473ccdff7faca73 100644 (file)
@@ -1876,9 +1876,11 @@ m4_define([m4_combine],
 
 
 # m4_append(MACRO-NAME, STRING, [SEPARATOR])
-# ------------------------------------------
+# m4_prepend(MACRO-NAME, STRING, [SEPARATOR])
+# -------------------------------------------
 # Redefine MACRO-NAME to hold its former content plus `SEPARATOR`'STRING'
-# at the end.  It is valid to use this macro with MACRO-NAME undefined,
+# at the end for m4_append, or `STRING`'SEPARATOR' at the beginning for
+# m4_prepend.  It is valid to use this macro with MACRO-NAME undefined,
 # in which case no SEPARATOR is added.  Be aware that the criterion is
 # `not being defined', and not `not being empty'.
 #
@@ -1921,37 +1923,67 @@ m4_define([m4_combine],
 #    => one, two, three
 #    => [one],[two],[three]
 #
+# Note that m4_append can benefit from amortized O(n log n) m4 behavior, if
+# the underlying m4 implementation is smart enough to avoid copying existing
+# contents when enlarging a macro's definition into any pre-allocated storage
+# (m4 1.4.x unfortunately does not implement this optimization).  m4_prepend
+# is inherently O(n^2), since pre-allocated storage only occurs at the end
+# of a macro, so the existing contents must always be moved.
+#
 # Use m4_builtin to avoid overhead of m4_defn.
 m4_define([m4_append],
 [m4_define([$1],
           m4_ifdef([$1], [m4_builtin([defn], [$1])[$3]])[$2])])
+m4_define([m4_prepend],
+[m4_define([$1],
+          [$2]m4_ifdef([$1], [[$3]m4_builtin([defn], [$1])]))])
 
 
 # m4_append_uniq(MACRO-NAME, STRING, [SEPARATOR], [IF-UNIQ], [IF-DUP])
-# --------------------------------------------------------------------
-# Like `m4_append', but append only if not yet present.  Additionally,
-# expand IF-UNIQ if STRING was appended, or IF-DUP if STRING was already
-# present.  Also, warn if SEPARATOR is not empty and occurs within STRING,
-# as the algorithm no longer guarantees uniqueness.
+# m4_prepend_uniq(MACRO-NAME, STRING, [SEPARATOR], [IF-UNIQ], [IF-DUP])
+# ---------------------------------------------------------------------
+# Like `m4_append'/`m4_prepend', but add STRING only if not yet present.
+# Additionally, expand IF-UNIQ if STRING was appended, or IF-DUP if STRING
+# was already present.  Also, warn if SEPARATOR is not empty and occurs
+# within STRING, as the algorithm no longer guarantees uniqueness.
+#
+# Note that while m4_append can be O(n log n) (depending on whether the
+# underlying M4 implementation), m4_append_uniq is inherently O(n^2)
+# because each append operation searches the entire string.
 m4_define([m4_append_uniq],
-[m4_ifval([$3], [m4_if(m4_index([$2], [$3]), [-1], [],
+[_m4_grow_uniq([m4_append], $@)])
+m4_define([m4_prepend_uniq],
+[_m4_grow_uniq([m4_prepend], $@)])
+
+# _m4_grow_uniq(HOW, MACRO-NAME, STRING, [SEP], [IF-UNIQ], [IF-DUP])
+# ------------------------------------------------------------------
+# Shared implementation of m4_append_uniq and m4_prepend_uniq.  HOW is
+# used to distinguish where the STRING will be added.
+m4_define([_m4_grow_uniq],
+[m4_ifval([$4], [m4_if(m4_index([$3], [$4]), [-1], [],
                       [m4_warn([syntax],
-                               [$0: `$2' contains `$3'])])])_$0($@)])
-m4_define([_m4_append_uniq],
-[m4_ifdef([$1],
-         [m4_if(m4_index([$3]m4_builtin([defn], [$1])[$3], [$3$2$3]), [-1],
-                [m4_append([$1], [$2], [$3])$4], [$5])],
-         [m4_append([$1], [$2], [$3])$4])])
+                               [$1_uniq: `$3' contains `$4'])])])]$0_1($@))
+m4_define([_m4_grow_uniq_1],
+[m4_ifdef([$2],
+         [m4_if(m4_index([$4]m4_builtin([defn], [$2])[$4], [$4$3$4]), [-1],
+                [$1([$2], [$3], [$4])$5], [$6])],
+         [m4_define([$2], [$3])$5])])
 
 # m4_append_uniq_w(MACRO-NAME, STRINGS)
-# -------------------------------------
+# m4_prepend_uniq_w(MACRO-NAME, STRINGS)
+# --------------------------------------
 # For each of the words in the whitespace separated list STRINGS, append
 # only the unique strings to the definition of MACRO-NAME.
 #
 # Avoid overhead of m4_defn by using m4_builtin.
 m4_define([m4_append_uniq_w],
 [m4_foreach_w([m4_Word], [$2],
-             [_m4_append_uniq([$1], m4_builtin([defn], [m4_Word]), [ ])])])
+             [_m4_grow_uniq_1([m4_append], [$1],
+                              m4_builtin([defn], [m4_Word]), [ ])])])
+m4_define([m4_prepend_uniq_w],
+[m4_foreach_w([m4_Word], [$2],
+             [_m4_grow_uniq_1([m4_prepend], [$1],
+                              m4_builtin([defn], [m4_Word]), [ ])])])
 
 
 # m4_text_wrap(STRING, [PREFIX], [FIRST-PREFIX], [WIDTH])
@@ -2202,7 +2234,9 @@ m4_define([m4_version_compare],
 # m4_PACKAGE_STRING
 # m4_PACKAGE_BUGREPORT
 # --------------------
-m4_include([m4sugar/version.m4])
+# If m4sugar/version.m4 is present, then define version strings.  This
+# file is optional, provided by Autoconf but absent in Bison.
+m4_sinclude([m4sugar/version.m4])
 
 
 # m4_version_prereq(VERSION, [IF-OK], [IF-NOT = FAIL])
index 69cb74b59706102411a7afe9cc7ac49e86902953..6cbf4f65db1da41568502a29dd9b92a476353c71 100644 (file)
@@ -278,6 +278,88 @@ AT_CHECK_M4SUGAR([-o-], 0, [[a a b
 AT_CLEANUP
 
 
+## ------------ ##
+## m4_prepend.  ##
+## ------------ ##
+
+AT_SETUP([m4@&t@_prepend])
+
+AT_CHECK_M4SUGAR_TEXT(
+[[m4_define([active], [ACTIVE])dnl
+m4_prepend([sentence], [This is an])dnl
+m4_prepend([sentence], [ active ])dnl
+m4_prepend([sentence], [symbol.])dnl
+sentence
+m4_undefine([active])dnl
+sentence
+m4_define([active], [ACTIVE])dnl
+m4_prepend([hooks], [m4_define([act1], [act2])])dnl
+m4_prepend([hooks], [m4_define([act2], [active])])dnl
+m4_undefine([active])dnl
+act1
+hooks
+act1
+dnl Test for bug fixed in 2.62 when separator is active.
+m4_define([a], [A])dnl
+m4_prepend_uniq([foo], [-], [a])dnl
+m4_prepend_uniq([foo], [-], [a])dnl
+m4_prepend_uniq([bar], [-], [a])dnl
+m4_prepend_uniq([bar], [~], [a])dnl
+m4_prepend_uniq([bar], [-], [a])dnl
+m4_defn([foo])
+m4_defn([bar])
+foo
+bar
+m4_prepend_uniq([blah], [one], [, ], [new], [existing])
+m4_prepend_uniq([blah], [two], [, ], [new], [existing])
+m4_prepend_uniq([blah], [two], [, ], [new], [existing])
+m4_prepend_uniq([blah], [three], [, ], [new], [existing])
+m4_prepend([blah], [two], [, ])dnl
+blah
+m4_dquote(blah)
+m4_prepend([list], [one], [[, ]])dnl
+m4_prepend([list], [two], [[, ]])dnl
+m4_prepend([list], [three], [[, ]])dnl
+list
+m4_dquote(list)
+m4_prepend_uniq_w([numbers], [1 1 2])dnl
+m4_prepend_uniq_w([numbers], [ 2 3 ])dnl
+numbers
+]],
+[[symbol. ACTIVE This is an
+symbol. active This is an
+act1
+
+active
+-
+~a-
+-
+~A-
+new
+new
+existing
+new
+two, three, two, one
+[two],[three],[two],[one]
+three, two, one
+[three, two, one]
+3 2 1
+]])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_prepend_uniq([str], [a], [ ])
+m4_prepend_uniq([str], [a b], [ ])
+m4_divert([0])dnl
+str
+]])
+
+AT_CHECK_M4SUGAR([-o-], 0, [[a b a
+]], [[script.4s:2: warning: m4@&t@_prepend_uniq: `a b' contains ` '
+]])
+
+AT_CLEANUP
+
+
 ## --------- ##
 ## m4_join.  ##
 ## --------- ##