2009-10-28 Eric Blake <ebb9@byu.net>
+ Fix corner cases in AS_LITERAL_IF and AS_TR_SH.
+ * lib/m4sugar/m4sh.m4 (AS_LITERAL_IF): Fix bug with unbalanced
+ parens. Move guts...
+ (_AS_LITERAL_IF): into new helper.
+ (AS_TR_SH, AS_TR_CPP): Fix bugs with expansion of wrong macro.
+ Move guts...
+ (_AS_TR_SH, _AS_TR_SH_LITERAL, _AS_TR_SH_INDIR, _AS_TR_CPP)
+ (_AS_TR_CPP_LITERAL, _AS_TR_CPP_INDIR): ...into new helpers.
+ (AS_VAR_PUSHDEF): Hoist m4_require, by moving guts...
+ (_AS_VAR_PUSHDEF): ...into new helper.
+ * tests/m4sh.at (AS@&t@_LITERAL_IF): Enhance test.
+
Minor optimizations to m4sh.
* lib/m4sugar/m4sh.m4 (AS_VAR_IF, AS_IDENTIFIER_IF)
(AS_LITERAL_IF): Parse fewer bytes during expansion, by visiting
# profiling shows that it is faster to use m4_translit.
#
# Because the translit is stripping quotes, it must also neutralize anything
-# that might be in a macro name, as well as comments and commas. All the
-# problem characters are unified so that a single m4_index can scan the
-# result.
+# that might be in a macro name, as well as comments, commas, or unbalanced
+# parentheses. All the problem characters are unified so that a single
+# m4_index can scan the result.
#
# Rather than expand m4_defn every time AS_LITERAL_IF is expanded, we
# inline its expansion up front.
m4_define([AS_LITERAL_IF],
-[m4_if(m4_cond([m4_eval(m4_index(m4_quote($1), [@S|@]) == -1)], [0], [],
- [m4_index(m4_translit(m4_quote($1), [[]`,#]]]dnl
+[_$0(m4_expand([$1]), [$2], [$3])])
+
+m4_define([_AS_LITERAL_IF],
+[m4_if(m4_cond([m4_eval(m4_index([$1], [@S|@]) == -1)], [0], [],
+ [m4_index(m4_translit([$1], [[]`,#()]]]dnl
m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[, [$$$]), [$])],
[-1], [-]), [-], [$2], [$3])])
# For speed, we inline the literal definitions that can be computed up front.
m4_defun_init([AS_TR_SH],
[AS_REQUIRE([_$0_PREPARE])],
-[AS_LITERAL_IF([$1],
- [m4_translit([$1], [*+[]]]]dnl
-m4_dquote(m4_dquote(m4_defn([m4_cr_not_symbols2])))[[,
- [pp[]]]]dnl
-m4_dquote(m4_dquote(m4_for(,1,255,,[[_]])))[[)],
- [`AS_ECHO(["_AS_ESCAPE(m4_dquote(m4_expand([$1])),
- [`], [\])"]) | $as_tr_sh`])])
+[_$0(m4_expand([$1]))])
+
+m4_define([_AS_TR_SH],
+[_AS_LITERAL_IF([$1], [$0_LITERAL], [$0_INDIR])([$1])])
+
+m4_define([_AS_TR_SH_LITERAL],
+[m4_translit([[$1]],
+ [*+[]]]m4_dquote(m4_defn([m4_cr_not_symbols2]))[,
+ [pp[]]]m4_dquote(m4_for(,1,255,,[[_]]))[)])
+
+m4_define([_AS_TR_SH_INDIR],
+[`AS_ECHO(["_AS_ESCAPE([[$1]], [`], [\])"]) | $as_tr_sh`])
# _AS_TR_CPP_PREPARE
# See implementation comments in AS_TR_SH.
m4_defun_init([AS_TR_CPP],
[AS_REQUIRE([_$0_PREPARE])],
-[AS_LITERAL_IF([$1],
- [m4_translit([$1], [*[]]]]dnl
-m4_dquote(m4_dquote(m4_defn([m4_cr_letters])m4_defn([m4_cr_not_symbols2])))[[,
- [P[]]]]dnl
-m4_dquote(m4_dquote(m4_defn([m4_cr_LETTERS])m4_for(,1,255,,[[_]])))[[)],
- [`AS_ECHO(["$1"]) | $as_tr_cpp`])])
+[_$0(m4_expand([$1]))])
+
+m4_define([_AS_TR_CPP],
+[_AS_LITERAL_IF([$1], [$0_LITERAL], [$0_INDIR])([$1])])
+
+m4_define([_AS_TR_CPP_LITERAL],
+[m4_translit([$1],
+ [*[]]]m4_dquote(m4_defn([m4_cr_letters])m4_defn([m4_cr_not_symbols2]))[,
+ [P[]]]m4_dquote(m4_defn([m4_cr_LETTERS])m4_for(,1,255,,[[_]]))[)])
+
+m4_define([_AS_TR_CPP_INDIR],
+[`AS_ECHO(["$1"]) | $as_tr_cpp`])
# _AS_TR_PREPARE
# don't work. Therefore, we must require the preparation ourselves.
m4_defun_init([AS_VAR_PUSHDEF],
[AS_REQUIRE([_AS_TR_SH_PREPARE])],
-[AS_LITERAL_IF([$2],
- [m4_pushdef([$1], [AS_TR_SH($2)])],
- [as_$1=AS_TR_SH($2)
+[_$0([$1], m4_expand([$2]))])
+
+m4_define([_AS_VAR_PUSHDEF],
+[_AS_LITERAL_IF([$2],
+ [m4_pushdef([$1], [_AS_TR_SH_LITERAL([$2])])],
+ [as_$1=_AS_TR_SH_INDIR([$2])
m4_pushdef([$1], [$as_[$1]])])])
AS_INIT
echo AS_LITERAL_IF([lit], [ok], [ERR]) 1
echo AS_LITERAL_IF([l$it], [ERR], [ok]) 2
-echo AS_LITERAL_IF([l``it], [ERR], [ok]) 3
+echo AS_LITERAL_IF([l`case a in b) ;; esac`it], [ERR], [ok]) 3
m4_define([mac], [lit])
echo AS_LITERAL_IF([mac], [ok], [ERR]) 4
echo AS_LITERAL_IF([mac($, ``)], [ok], [ERR]) 5
m4_define([mac], [l$it])
echo AS_LITERAL_IF([mac], [ERR], [ok]) 6
-m4_define([mac], [l`it])
+m4_define([mac], [l``it])
echo AS_LITERAL_IF([mac], [ERR], [ok]) 7
]])