[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/7] Add AS_LITERAL_WORD_IF.
From: |
Eric Blake |
Subject: |
[PATCH 2/7] Add AS_LITERAL_WORD_IF. |
Date: |
Fri, 2 Jul 2010 13:37:47 -0600 |
* lib/m4sugar/m4sh.m4 (_AS_LITERAL_IF): Also reject shell quoting
characters as non-literal, and provide way to reject space.
(AS_LITERAL_WORD_IF): New macro.
* doc/autoconf.texi (Polymorphic Variables) <AS_LITERAL_IF>:
Document new macro. Fix example to match reality.
* NEWS: Document change and new macro.
* tests/m4sh.at (AS@&address@hidden): Update test.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 9 +++++++++
NEWS | 5 +++++
doc/autoconf.texi | 42 +++++++++++++++++++++++++++++++++---------
lib/m4sugar/m4sh.m4 | 42 ++++++++++++++++++++++++++++++++----------
tests/m4sh.at | 36 ++++++++++++++++++++++++++++--------
5 files changed, 107 insertions(+), 27 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 601b169..354e948 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2010-07-02 Eric Blake <address@hidden>
+ Add AS_LITERAL_WORD_IF.
+ * lib/m4sugar/m4sh.m4 (_AS_LITERAL_IF): Also reject shell quoting
+ characters as non-literal, and provide way to reject space.
+ (AS_LITERAL_WORD_IF): New macro.
+ * doc/autoconf.texi (Polymorphic Variables) <AS_LITERAL_IF>:
+ Document new macro. Fix example to match reality.
+ * NEWS: Document change and new macro.
+ * tests/m4sh.at (AS@&address@hidden): Update test.
+
Optimize AC_DEFINE.
* lib/autoconf/general.m4 (_AC_DEFINE_Q): Avoid overhead of
AS_LITERAL_IF.
diff --git a/NEWS b/NEWS
index eecb9f6..c5e5ded 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,11 @@ GNU Autoconf NEWS - User visible changes.
AT_ARG_OPTION has been changed in that the negative of a long option
--OPTION is now --no-OPTION rather than --noOPTION.
+** The macro AS_LITERAL_IF is slightly more conservative; text
+ containing shell quotes are no longer treated as literals.
+ Furthermore, a new macro, AS_LITERAL_WORD_IF, adds an additional
+ level of checking that no whitespace occurs in literals.
+
* Major changes in Autoconf 2.65 (2009-11-21) [stable]
Released by Eric Blake, based on git versions 2.64.*.
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 6353f87..ab7ed93 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -13299,23 +13299,47 @@ Polymorphic Variables
literal variable name.
@defmac AS_LITERAL_IF (@var{expression}, @ovar{if-literal}, @ovar{if-not})
address@hidden AS_LITERAL_WORD_IF (@var{expression}, @ovar{if-literal})
@asindex{LITERAL_IF}
address@hidden
If the expansion of @var{expression} is definitely a shell literal,
expand @var{if-literal}. If the expansion of @var{expression} looks
like it might contain shell indirections (such as @code{$var} or
address@hidden), then @var{if-not} is expanded. In order to reduce the
-time spent deciding whether an expression is literal, the implementation
-is somewhat conservative (for example, @samp{'[$]'} is a single-quoted
-shell literal, but causes @var{if-not} to be expanded). While this
-macro is often used for recognizing shell variable names, it can also be
-used in other contexts.
address@hidden), then @var{if-not} is expanded.
address@hidden only expands
address@hidden if @var{expression} looks like a single shell word,
+containing no whitespace; while @code{AS_LITERAL_IF} allows whitespace
+in @var{expression}.
+
+In order to reduce the time spent recognizing whether an
address@hidden qualifies as a literal or a simple indirection, the
+implementation is somewhat conservative: @var{expression} must be a
+single shell word (possibly after stripping whitespace), consisting only
+of bytes that would have the same meaning whether unquoted or enclosed
+in double quotes (for example, @samp{a.b} results in @var{if-literal},
+even though it is not a valid shell variable name; while both @samp{'a'}
+and @samp{[$]} result in @var{if-not}, because they behave differently
+than @samp{"'a'"} and @samp{"[$]"}). This macro can be used in contexts
+for recognizing portable file names (such as in the implementation of
address@hidden), or coupled with some transliterations for forming
+valid variable names (such as in the implementation of @code{AS_TR_SH},
+which uses an additional @code{m4_translit} to convert @samp{.} to
address@hidden).
+
+This example shows how to read the contents of the shell variable
address@hidden, exercising both arguments to @code{AS_LITERAL_IF}. It
+results in a script that will output the line @samp{hello} three times.
@example
AC_DEFUN([MY_ACTION],
[AS_LITERAL_IF([$1],
-[echo "$1"],
-[AS_VAR_COPY([tmp], [$1])
-echo "$tmp"])])
+ [echo "$$1"],
+ [AS_VAR_COPY([tmp], [$1])
+ echo "$tmp"])])
+foo=bar bar=hello
+MY_ACTION([bar])
+MY_ACTION([`echo bar`])
+MY_ACTION([$foo])
@end example
@end defmac
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 024498d..41b92f6 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1519,15 +1519,24 @@ m4_dquote(m4_dquote(m4_defn([m4_cr_symbols1])))[[))],
[0], [-])])
# AS_LITERAL_IF(EXPRESSION, IF-LITERAL, IF-NOT-LITERAL)
# -----------------------------------------------------
-# If EXPRESSION has shell indirections ($var or `expr`), expand
+# If EXPRESSION has no shell indirections ($var or `expr`), expand
# IF-LITERAL, else IF-NOT-LITERAL.
-# This is an *approximation*: for instance EXPRESSION = `\$' is
-# definitely a literal, but will not be recognized as such.
+#
+# EXPRESSION is treated as a literal if it results in the same
+# interpretation whether it is unquoted or contained within double
+# quotes, with the exception that whitespace is ignored (on the
+# assumption that it will be flattened to _). Therefore, neither `\$'
+# nor `a''b' is a literal, since both backslash and single quotes have
+# different quoting behavior in the two contexts; and `a*' is not a
+# literal, because it has different globbing.
+# This macro is an *approximation*: it is possible that
+# there are some EXPRESSIONs which the shell would treat as literals,
+# but which this macro does not recognize.
#
# Why do we reject EXPRESSION expanding with `[' or `]' as a literal?
# Because AS_TR_SH is MUCH faster if it can use m4_translit on literals
# instead of m4_bpatsubst; but m4_translit is much tougher to do safely
-# if `[' is translated.
+# if `[' is translated. That, and file globbing matters.
#
# Note that the quadrigraph @S|@ can result in non-literals, but outright
# rejecting all @ would make AC_INIT complain on its bug report address.
@@ -1535,10 +1544,14 @@ m4_dquote(m4_dquote(m4_defn([m4_cr_symbols1])))[[))],
[0], [-])])
# We used to use m4_bmatch(m4_quote($1), [[`$]], [$3], [$2]), but
# 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, commas, or unbalanced
-# parentheses. All the problem characters are unified so that a single
-# m4_index can scan the result.
+# Because the translit is stripping quotes, it must also neutralize
+# anything that might be in a macro name, as well as comments, commas,
+# or unbalanced parentheses. Valid shell variable characters and
+# unambiguous literal characters are deleted (`a.b'), and remaining
+# characters are normalized into `$' if they are special to the
+# shell or to m4 parsing, and left alone otherwise.
+# _AS_LITERAL_IF_ only has to check for an empty string after removing
+# the normalized characters.
#
# Rather than expand m4_defn every time AS_LITERAL_IF is expanded, we
# inline its expansion up front.
@@ -1547,10 +1560,19 @@ m4_define([AS_LITERAL_IF],
m4_define([_AS_LITERAL_IF],
[m4_if(m4_cond([m4_eval(m4_index([$1], address@hidden|@]) == -1)], [0], [],
- [m4_index(m4_translit([$1], [[]`,#()]]]dnl
-m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[, [$$$]), [$])],
+ [m4_index(m4_translit([$1], [[]`'\"$4,#()]]]dnl
+m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[, [$$$$$$$5]), [$])],
[-1], [-]), [-], [$2], [$3])])
+# AS_LITERAL_WORD_IF(EXPRESSION, IF-LITERAL, IF-NOT-LITERAL)
+# ----------------------------------------------------------
+# Like AS_LITERAL_IF, except that spaces and tabs in EXPRESSION
+# are treated as non-literal.
+m4_define([AS_LITERAL_WORD_IF],
+[_AS_LITERAL_IF(m4_expand([$1]), [$2], [$3], [ ][
+], [$$$])])
+
+
# AS_TMPDIR(PREFIX, [DIRECTORY = $TMPDIR [= /tmp]])
# -------------------------------------------------
diff --git a/tests/m4sh.at b/tests/m4sh.at
index 05cea85..5b3a55d 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -1077,20 +1077,31 @@ AT_CLEANUP
## --------------- ##
AT_SETUP([AS@&address@hidden)
-AT_KEYWORDS([m4sh])
+AT_KEYWORDS([m4sh AS@&address@hidden)
AT_DATA_M4SH([script.as], [[dnl
AS_INIT
echo AS_LITERAL_IF([lit], [ok], [ERR]) 1
-echo AS_LITERAL_IF([l$it], [ERR], [ok]) 2
-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
+echo AS_LITERAL_IF([l-/.it], [ok], [ERR]) 2
+echo AS_LITERAL_IF([l''it], [ERR], [ok]) 3
+echo AS_LITERAL_IF([l$it], [ERR], [ok]) 4
+echo AS_LITERAL_IF([l$it], [ERR1], [ok], [fixme]) 5
+echo AS_LITERAL_IF([l${it}], [ERR1], [ok], [fixme]) 6
+echo AS_LITERAL_IF([l`case a in b) ;; esac`it], [ERR], [ok]) 7
+echo AS_LITERAL_IF([l`case a in b) ;; esac`it], [ERR1], [ok], [ERR2]) 8
+m4_define([mac], [l-/.it])
+echo AS_LITERAL_IF([mac], [ok], [ERR]) 9
+echo AS_LITERAL_IF([mac($, ``)], [ok], [ERR]) 10
m4_define([mac], [l$it])
-echo AS_LITERAL_IF([mac], [ERR], [ok]) 6
+echo AS_LITERAL_IF([mac], [ERR], [ok]) 11
+echo AS_LITERAL_IF([mac], [ERR1], [ok], [fixme]) 12
m4_define([mac], [l``it])
-echo AS_LITERAL_IF([mac], [ERR], [ok]) 7
+echo AS_LITERAL_IF([mac], [ERR], [ok]) 13
+echo AS_LITERAL_IF([mac], [ERR1], [ok], [ERR2]) 14
+echo AS_LITERAL_IF([ a ][
+b], [ok], [ok]) 15
+echo AS_LITERAL_WORD_IF([ a ][
+b], [ERR], [ok]) 16
]])
AT_CHECK_M4SH
@@ -1102,6 +1113,15 @@ ok 4
ok 5
ok 6
ok 7
+ok 8
+ok 9
+ok 10
+ok 11
+ok 12
+ok 13
+ok 14
+ok 15
+ok 16
]])
AT_CLEANUP
--
1.7.1
- [PATCH 0/7] AS_LITERAL_IF speedups, Eric Blake, 2010/07/02
- [PATCH 1/7] Optimize AC_DEFINE., Eric Blake, 2010/07/02
- [PATCH 5/7] Add tests for AS_BOX., Eric Blake, 2010/07/02
- [PATCH 2/7] Add AS_LITERAL_WORD_IF.,
Eric Blake <=
- [PATCH 6/7] Use new AS_LITERAL_IF argument when appropriate., Eric Blake, 2010/07/02
- [PATCH 7/7] Optimize AS_BOX., Eric Blake, 2010/07/02
- [PATCH 3/7] Use AS_LITERAL_WORD_IF as appropriate., Eric Blake, 2010/07/02
- [PATCH 4/7] Add optional argument to AS_LITERAL_IF., Eric Blake, 2010/07/02