[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: m4sugar update
From: |
Eric Blake |
Subject: |
Re: m4sugar update |
Date: |
Wed, 06 Aug 2008 22:21:43 -0600 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.16) Gecko/20080708 Thunderbird/2.0.0.16 Mnenhy/0.7.5.666 |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
According to Eric Blake on 8/6/2008 8:21 PM:
| | Now that m4_wrap is FIFO, I believe the m4_wrap invocation in bison.m4
| | should be converted to m4_wrap_lifo. Otherwise, the m4_wrap text at the
| | end of m4sugar.m4 isn't expanded last as intended.
|
| Committed with that one difference.
Next, a unification of m4_shift* macros. This implementation speeds up
several recursive algorithms. It is a subtle change in semantics of
m4_join, but bison wasn't using m4_join. OK to apply?
$ git fetch git://repo.or.cz/bison/ericb.git +m4sugar
- --
Don't work too hard, make some time for fun as well!
Eric Blake address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkiaeFcACgkQ84KuGfSFAYDEhACgiVp4rwIw/6+leJMLViC4i/6v
M9EAniJ5dEXzLJrw+sdFGW2Nn4qH9TAE
=ZBX9
-----END PGP SIGNATURE-----
>From a3764451d3188132ed22f622ba0d35edd6e386cd Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 6 Aug 2008 21:22:06 -0600
Subject: [PATCH] Partial m4sugar merge from autoconf: m4_shiftn.
* data/m4sugar/m4sugar.m4 (m4_shiftn): Faster implementation.
(m4_shift2, m4_shift3): New macros.
(m4_case, m4_bmatch, m4_bpatsubsts, m4_join): Adjust clients.
* data/c.m4 (b4_c_function_def, b4_c_ansi_function_def)
(b4_c_ansi_function_decl, b4_c_function_call): Likewise.
* data/java.m4 (b4_remove_comma): Likewise.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 8 ++++
data/c.m4 | 13 ++++---
data/java.m4 | 6 ++--
data/m4sugar/m4sugar.m4 | 86 +++++++++++++++++++++++++++++++++++++----------
4 files changed, 86 insertions(+), 27 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 114f5e2..5af268e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2008-08-06 Eric Blake <address@hidden>
+ Partial m4sugar merge from autoconf: m4_shiftn.
+ * data/m4sugar/m4sugar.m4 (m4_shiftn): Faster implementation.
+ (m4_shift2, m4_shift3): New macros.
+ (m4_case, m4_bmatch, m4_bpatsubsts, m4_join): Adjust clients.
+ * data/c.m4 (b4_c_function_def, b4_c_ansi_function_def)
+ (b4_c_ansi_function_decl, b4_c_function_call): Likewise.
+ * data/java.m4 (b4_remove_comma): Likewise.
+
Partial m4sugar merge from autoconf: m4_wrap vs. m4 1.6.
* data/m4sugar/m4sugar.m4 (m4_unquote, m4_wrap_lifo): New macros.
(m4_wrap): Guarantee FIFO order, in spite of m4 1.6.
diff --git a/data/c.m4 b/data/c.m4
index dbec53c..ced2b1e 100644
--- a/data/c.m4
+++ b/data/c.m4
@@ -1,7 +1,8 @@
-*- Autoconf -*-
# C M4 Macros for Bison.
-# Copyright (C) 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+# Copyright (C) 2002, 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
@@ -228,8 +229,8 @@ m4_define([b4_c_function_def],
b4_c_ansi_function_def($@)
#else
$2
-$1 (b4_c_knr_formal_names(m4_shiftn(2, $@)))
-b4_c_knr_formal_decls(m4_shiftn(2, $@))
+$1 (b4_c_knr_formal_names(m4_shift2($@)))
+b4_c_knr_formal_decls(m4_shift2($@))
#endif[]dnl
])
@@ -239,7 +240,7 @@ b4_c_knr_formal_decls(m4_shiftn(2, $@))
# Declare the function NAME in ANSI.
m4_define([b4_c_ansi_function_def],
[$2
-$1 (b4_c_ansi_formals(m4_shiftn(2, $@)))[]dnl
+$1 (b4_c_ansi_formals(m4_shift2($@)))[]dnl
])
@@ -301,7 +302,7 @@ $2 $1 ();
# ----------------------------------------------------------------
# Declare the function NAME.
m4_define([b4_c_ansi_function_decl],
-[$2 $1 (b4_c_ansi_formals(m4_shiftn(2, $@)));[]dnl
+[$2 $1 (b4_c_ansi_formals(m4_shift2($@)));[]dnl
])
@@ -316,7 +317,7 @@ m4_define([b4_c_ansi_function_decl],
# -----------------------------------------------------------
# Call the function NAME with arguments NAME1, NAME2 etc.
m4_define([b4_c_function_call],
-[$1 (b4_c_args(m4_shiftn(2, $@)))[]dnl
+[$1 (b4_c_args(m4_shift2($@)))[]dnl
])
diff --git a/data/java.m4 b/data/java.m4
index 3f259fd..1387694 100644
--- a/data/java.m4
+++ b/data/java.m4
@@ -2,7 +2,7 @@
# Java language support for Bison
-# Copyright (C) 2007 Free Software Foundation, Inc.
+# Copyright (C) 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
@@ -75,7 +75,7 @@ m4_define([b4_identification],
m4_define([b4_int_type],
[m4_if(b4_ints_in($@, [-128], [127]), [1], [byte],
b4_ints_in($@, [-32768], [32767]), [1], [short],
- [int])])
+ [int])])
# b4_int_type_for(NAME)
# ---------------------
@@ -205,7 +205,7 @@ m4_define([b4_param_decls],
[m4_map([b4_param_decl], address@hidden)])
m4_define([b4_param_decl], [, $1])
-m4_define([b4_remove_comma], [m4_ifval($1, [$1, ], [])m4_shiftn(2, $@)])
+m4_define([b4_remove_comma], [m4_ifval($1, [$1, ], [])m4_shift2($@)])
diff --git a/data/m4sugar/m4sugar.m4 b/data/m4sugar/m4sugar.m4
index 4fa54b3..97b38a4 100644
--- a/data/m4sugar/m4sugar.m4
+++ b/data/m4sugar/m4sugar.m4
@@ -366,7 +366,7 @@ m4_define([m4_case],
[$#], 1, [],
[$#], 2, [$2],
[$1], [$2], [$3],
- [$0([$1], m4_shiftn(3, $@))])])
+ [$0([$1], m4_shift3($@))])])
# m4_bmatch(SWITCH, RE1, VAL1, RE2, VAL2, ..., DEFAULT)
@@ -388,7 +388,7 @@ m4_define([m4_bmatch],
[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
[$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
[$#], 2, [$2],
- [m4_if(m4_bregexp([$1], [$2]), -1, [$0([$1], m4_shiftn(3, $@))],
+ [m4_if(m4_bregexp([$1], [$2]), -1, [$0([$1], m4_shift3($@))],
[$3])])])
@@ -445,13 +445,19 @@ m4_define([m4_map_sep],
# I would have liked to name this macro `m4_bpatsubst', unfortunately,
# due to quotation problems, I need to double quote $1 below, therefore
# the anchors are broken :( I can't let users be trapped by that.
+#
+# Recall that m4_shift3 always results in an argument. Hence, we need
+# to distinguish between a final deletion vs. ending recursion.
m4_define([m4_bpatsubsts],
[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
[$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
- [$#], 2, [m4_builtin([patsubst], $@)],
+ [$#], 2, [m4_unquote(m4_builtin([patsubst], [[$1]], [$2]))],
+ [$#], 3, [m4_unquote(m4_builtin([patsubst], [[$1]], [$2], [$3]))],
+ [_$0(address@hidden(m4_eval($# & 1), 0, [,]))])])
+m4_define([_m4_bpatsubsts],
+[m4_if([$#], 2, [$1],
[$0(m4_builtin([patsubst], [[$1]], [$2], [$3]),
- m4_shiftn(3, $@))])])
-
+ m4_shift3($@))])])
# m4_do(STRING, ...)
@@ -555,14 +561,45 @@ m4_define([m4_noquote],
# m4_shiftn(N, ...)
# -----------------
# Returns ... shifted N times. Useful for recursive "varargs" constructs.
+#
+# Autoconf does not use this macro, because it is inherently slower than
+# calling the common cases of m4_shift2 or m4_shift3 directly. But it
+# might as well be fast for other clients, such as Libtool. One way to
+# do this is to expand $@ only once in _m4_shiftn (otherwise, for long
+# lists, the expansion of m4_if takes twice as much memory as what the
+# list itself occupies, only to throw away the unused branch). The end
+# result is strictly equivalent to
+# m4_if([$1], 1, [m4_shift(,m4_shift(m4_shift($@)))],
+# [_m4_shiftn(m4_decr([$1]), m4_shift(m4_shift($@)))])
+# but with the final `m4_shift(m4_shift($@)))' shared between the two
+# paths. The first leg uses a no-op m4_shift(,$@) to balance out the ().
m4_define([m4_shiftn],
-[m4_assert(($1 >= 0) && ($# > $1))dnl
-_m4_shiftn($@)])
+[m4_assert(0 < $1 && $1 < $#)_$0($@)])
m4_define([_m4_shiftn],
-[m4_if([$1], 0,
- [m4_shift($@)],
- [_m4_shiftn(m4_eval([$1]-1), m4_shift(m4_shift($@)))])])
+[m4_if([$1], 1, [m4_shift(],
+ [$0(m4_decr([$1])]), m4_shift(m4_shift($@)))])
+
+# m4_shift2(...)
+# m4_shift3(...)
+# -----------------
+# Returns ... shifted twice, and three times. Faster than m4_shiftn.
+m4_define([m4_shift2], [m4_shift(m4_shift($@))])
+m4_define([m4_shift3], [m4_shift(m4_shift(m4_shift($@)))])
+
+# _m4_shift2(...)
+# _m4_shift3(...)
+# ---------------
+# Like m4_shift2 or m4_shift3, except include a leading comma unless shifting
+# consumes all arguments. Why? Because in recursion, it is nice to
+# distinguish between 1 element left and 0 elements left, based on how many
+# arguments this shift expands to.
+m4_define([_m4_shift2],
+[m4_if([$#], [2], [],
+ [, m4_shift(m4_shift($@))])])
+m4_define([_m4_shift3],
+[m4_if([$#], [3], [],
+ [, m4_shift(m4_shift(m4_shift($@)))])])
# m4_undefine(NAME)
@@ -717,7 +754,9 @@ m4_if($1, [$2], [],
# Hence the design below.
#
# The M4 manual now includes a chapter devoted to this issue, with
-# the lessons learned from m4sugar.
+# the lessons learned from m4sugar. And still, this design is only
+# optimal for M4 1.6; see foreach.m4 for yet more comments on why
+# M4 1.4.x uses yet another implementation.
# m4_foreach(VARIABLE, LIST, EXPRESSION)
@@ -1524,13 +1563,24 @@ m4_define([m4_normalize],
# m4_join(SEP, ARG1, ARG2...)
# ---------------------------
-# Produce ARG1SEPARG2...SEPARGn.
-m4_defun([m4_join],
-[m4_case([$#],
- [1], [],
- [2], [[$2]],
- [[$2][$1]$0([$1], m4_shiftn(2, $@))])])
-
+# Produce ARG1SEPARG2...SEPARGn. Avoid back-to-back SEP when a given ARG
+# is the empty string. No expansion is performed on SEP or ARGs.
+#
+# Since the number of arguments to join can be arbitrarily long, we
+# want to avoid having more than one $@ in the macro definition;
+# otherwise, the expansion would require twice the memory of the already
+# long list. Hence, m4_join merely looks for the first non-empty element,
+# and outputs just that element; while _m4_join looks for all non-empty
+# elements, and outputs them following a separator. The final trick to
+# note is that we decide between recursing with $0 or _$0 based on the
+# nested m4_if ending with `_'.
+m4_define([m4_join],
+[m4_if([$#], [1], [],
+ [$#], [2], [[$2]],
+ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift2($@))])])
+m4_define([_m4_join],
+[m4_if([$#$2], [2], [],
+ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift2($@))])])
# m4_append(MACRO-NAME, STRING, [SEPARATOR])
--
1.5.6.4