+2008-04-23 Eric Blake <ebb9@byu.net>
+
+ Allow unbalanced () in m4_expand.
+ * lib/m4sugar/m4sugar.m4 (m4_expand, _m4_expand): Use more complex
+ quotes.
+ (m4_noquote, _m4_split): Use consistent complex quote.
+ * tests/autotest.at (Left paren, Right paren): Test this.
+ (Parentheses): Ensure new quadrigraphs still work.
+ (AT_CHECK_AT_TITLE_CHAR): All title char tests exercise m4_expand.
+ * NEWS: Mention the fix.
+ * doc/autoconf.texi (Quadrigraphs): Revert mention of macros that
+ require quadrigraphs for ().
+ (Evaluation Macros) <m4_expand>: Relax the restriction against
+ unbalanced ().
+ (Pretty Help Strings) <AS_HELP_STRING>: Likewise.
+ (Writing Testsuites) <AT_SETUP>: Likewise.
+ Reported by Joel E. Denny, fix suggested by Noah Misch.
+
2008-04-22 Eric Blake <ebb9@byu.net>
Support unbalanced () in AT_SETUP by adding two new quadrigraphs.
* Major changes in Autoconf 2.62a (2008-??-??)
+** Clients of m4_expand, such as AS_HELP_STRING and AT_SETUP, can now
+ handle properly quoted but otherwise unbalanced parentheses (for
+ some macros, this fixes a regression in 2.62).
+
** Two new quadrigraphs have been introduced: @{:@ for (, and @:}@ for ),
- allowing the output of unbalanced parantheses in contexts such as
- AS_HELP_STRING or AT_SETUP that must determine the length of
- expanded text.
+ allowing the output of unbalanced parantheses in more contexts.
\f
* Major changes in Autoconf 2.62 (2008-04-05) [stable]
Autoconf quoting rules. For example, you may need to output the regular
expression @samp{[^[]}, which matches any character other than @samp{[}.
This expression contains unbalanced brackets so it cannot be put easily
-into an M4 macro. There are also a few macros, such as
-@code{m4_text_box}, @code{AS_HELP_STRING}, or @code{AT_SETUP}, which
-require balanced parentheses, regardless of the quoting, because the
-macro needs to compute the length of the expansion of its arguments.
+into an M4 macro.
You can work around this problem by using one of the following
@dfn{quadrigraphs}:
@result{}ACT, IVE, ACT, IVE
@end example
-Note that @code{m4_expand} cannot parse everything. The expansion of
-@var{arg} must not contain literal unbalanced quotes or parentheses;
-however, quadrigraphs can be used to generate unbalanced output.
+Note that @code{m4_expand} cannot handle an @var{arg} that expands to
+literal unbalanced quotes, but that quadrigraphs can be used when
+unbalanced output is necessary. Likewise, unbalanced parentheses must
+be supplied with double quoting or a quadrigraph.
@example
m4_define([pattern], [[!@@<:@@]])dnl
m4_define([bar], [BAR])dnl
m4_expand([case $foo in
m4_defn([pattern])@@:@}@@ bar ;;
+ *[)] blah ;;
esac])
@result{}case $foo in
@result{} [![]) BAR ;;
+@result{} *) blah ;;
@result{}esac
@end example
@end defmac
The @code{AS_HELP_STRING} macro is particularly helpful when the
@var{left-hand-side} and/or @var{right-hand-side} are composed of macro
arguments, as shown in the following example. Be aware that
-@var{left-hand-side} may not contain unbalanced quotes or parentheses,
+@var{left-hand-side} may not expand to unbalanced quotes,
although quadrigraphs can be used.
@example
This macro starts a group of related tests, all to be executed in the
same subshell. It accepts a single argument, which holds a few words
(no more than about 30 or 40 characters) quickly describing the purpose
-of the test group being started. @var{test-group-name} must not contain
-unbalanced quotes or parentheses, although quadrigraphs can be used.
+of the test group being started. @var{test-group-name} must not expand
+to unbalanced quotes, although quadrigraphs can be used.
@end defmac
@defmac AT_KEYWORDS (@var{keywords})
# m4_expand([active, active2])
# => ACT, IVE, ACT, IVE
#
-# Unfortunately, due to limitations in m4, ARG must contain balanced quotes
-# (use quadrigraphs) and balanced parentheses (use creative shell comments
-# when writing shell case statements).
+# Unfortunately, due to limitations in m4, ARG must expand to something
+# with balanced quotes (use quadrigraphs to get around this). The input
+# is not likely to have unbalanced -=<{(/)}>=- quotes, and it is possible
+# to have unbalanced (), provided it was specified with proper [] quotes.
#
# Exploit that extra () will group unquoted commas and the following
# whitespace, then convert () to []. m4_bpatsubst can't handle newlines
# inside $1, and m4_substr strips quoting. So we (ab)use m4_changequote.
-m4_define([m4_expand], [_$0(($1))])
+m4_define([m4_expand], [_$0(-=<{($1)}>=-)])
m4_define([_m4_expand],
-[m4_changequote([(], [)])$1m4_changequote`'m4_changequote(`[', `]')])
+[m4_changequote([-=<{(], [)}>=-])$1m4_changequote([, ])])
# m4_ignore(ARGS)
# and help-strings). On the other hand, since all quotes are disabled,
# any macro expanded during this time that relies on nested [] quoting
# will likely crash and burn. This macro is seldom useful; consider
-# m4_unquote instead.
+# m4_unquote or m4_expand instead.
m4_define([m4_noquote],
-[m4_changequote(-=<{,}>=-)$1-=<{}>=-m4_changequote([,])])
+[m4_changequote([-=<{(],[)}>=-])$1-=<{()}>=-m4_changequote([,])])
# m4_quote(ARGS)
#
# Also, notice that $1 is quoted twice, since we want the result to
# be quoted. Then you should understand that the argument of
-# patsubst is -=<{STRING}>=- (i.e., with additional -=<{ and }>=-).
+# patsubst is -=<{(STRING)}>=- (i.e., with additional -=<{( and )}>=-).
#
# This macro is safe on active symbols, i.e.:
# m4_define(active, ACTIVE)
[_$0($@)])])
m4_define([_m4_split],
-[m4_changequote(-=<{,}>=-)]dnl
-[[m4_bpatsubst(-=<{-=<{$1}>=-}>=-, -=<{$2}>=-,
- -=<{], [}>=-)]m4_changequote([, ])])
+[m4_changequote([-=<{(],[)}>=-])]dnl
+[[m4_bpatsubst(-=<{(-=<{($1)}>=-)}>=-, -=<{($2)}>=-,
+ -=<{(], [)}>=-)]m4_changequote([, ])])
]], [$4], [], [], [],
dnl This sed script checks for two things - that the output is properly
dnl expanded, and that the 'ok' starts on the right column.
-[AT_CHECK([[$CONFIG_SHELL ./micro-suite |
+[AT_KEYWORDS([m4@&t@_expand])
+AT_CHECK([[$CONFIG_SHELL ./micro-suite |
sed -n '/^ 1:/{
h
s/[^:]*: \(.*[^ ]\)[ ]*ok.*/\1/p
AT_CHECK_AT_TITLE_CHAR([Pound], [[#]], [#])
AT_CHECK_AT_TITLE_CHAR([Quoted comma],[[,]], [,])
AT_CHECK_AT_TITLE_CHAR([Comma], [,], [,])
-AT_CHECK_AT_TITLE_CHAR([Parentheses], [()])
-AT_CHECK_AT_TITLE_CHAR([Left paren], [@{@&t@:@], [(])
-AT_CHECK_AT_TITLE_CHAR([Right paren], [@:@&t@}@], [)])
+dnl this test also hits quadrigraphs for ()
+AT_CHECK_AT_TITLE_CHAR([Parentheses], [(@{:@)@:}@], [(())])
+AT_CHECK_AT_TITLE_CHAR([Left paren], [[(]], [(])
+AT_CHECK_AT_TITLE_CHAR([Right paren], [[)]], [)])
AT_CHECK_AT_TITLE_CHAR([Quoted Macro], [[macro_name]], [macro_name])
AT_CHECK_AT_TITLE_CHAR([Macro], [macro_name], [macro_expanded])