[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: M4 syntax $11 vs. ${11}
From: |
Eric Blake |
Subject: |
Re: M4 syntax $11 vs. ${11} |
Date: |
Thu, 08 Feb 2007 07:52:11 -0700 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.9) Gecko/20061207 Thunderbird/1.5.0.9 Mnenhy/0.7.4.666 |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
According to Eric Blake on 1/30/2007 7:23 AM:
>
> Let me think on this for a couple more days (as it is, I still haven't
> completely implemented extended arguments in CVS m4; partly because I want
> to do it right, so I want this thread to come to a consensus before I
> commit to coding something), and get more feedback. But after typing and
> re-reading this email, I'm starting to lean towards the following:
> - in m4 1.4.9: make --warn-syntax (or whatever name we decide on) take an
> optional argument of a regular expression to warn about if encountered in
> macro definitions, with the default regex being \$[{0-9][0-9].
Here's what I'm checking in for 1.4.9. Anyone who has been testing the
- --warn-syntax option (available only in CVS for a couple of weeks) now
needs to test with --warn-macro-sequence. I'm hoping this is the last
change prior to 1.4.9, but will not release it for a couple of weeks to
make sure things settle first.
2007-02-08 Eric Blake <address@hidden>
Rename --warn-syntax to --warn-macro-sequence[=regex], to make it
more flexible, and so that autoconf can use it.
* src/m4.h (set_macro_sequence, free_macro_sequence): New
prototypes.
* src/builtin.c (macro_sequence_buf, macro_sequence_regs)
(macro_sequence_inuse, set_macro_sequence, free_macro_sequence):
New variables and functions.
(define_user_macro): Allow flexibility in regular expression used
to trigger warning.
* src/m4.c (warn_syntax): Delete.
(usage, WARN_MACRO_SEQUENCE_OPTION, main): Implement changed
spelling of option, along with optional argument.
* doc/m4.texinfo (Operation modes, Arguments): Document this
change.
* NEWS: Document this change.
> - in m4 2.0: have ${1} be the out-of-the-box syntax for extended
> arguments, but add a new macro changeextarg that can be used to recognize
> ${{1}} instead
Still to be implemented (and it may be a couple of weeks, because I'm
about to head out on a two-week vacation). I think once I get that
implemented, it will be time to release beta 1.9b. But I am planning on
adding changeextarg({{,}}) as the means to print ${1} literally but treat
${{1}} like $1.
> - in autoconf 2.62: if --warn-syntax is supported by the installed m4,
> then turn it on with a regular expression to reject $10 and ${{1}},
> neither of which seem to be in many current autoconf snippets; and in
> m4sugar, if changesyntax is supported, then disable extended arguments;
> that way, ${1} is reserved for the shell no matter what
Here's an updated patch that lets autoconf 2.62 exploit
- --warn-macro-sequence to warn users about $10 and ${{, as well as avoid
false positives for ${1} even if the user does M4=path/to/m4\
- --warn-macro-sequence. Plus, it completes last week's patch to require m4
1.4.5 or greater. It does not tackle whether $[1] or $[]1 should be the
preferred style for escaping literal shell variables, which was a
secondary point raised by Ralf. And I verified that I get no false
positives (and therefore don't have to change any .m4 files) in autoconf.
2007-02-08 Eric Blake <address@hidden>
* bin/autom4te.in (m4): Require GNU M4 1.4.5 or better. Use
--warn-macro-sequence if it is supported. For now, warn users
about ${{1}}, since we don't depend on M4 2.0.
* lib/m4sugar/m4sugar.m4: Tell M4 2.0 to use ${{1}}, not ${1},
for extended parameters.
* doc/autoconf.texi (Quoting and Parameters): New section.
(Quotation and Nested Macros): Touch up example.
* NEWS: Document the new limitation on user macros not exceeding
$9.
> - in autoconf 3.0: require m4 2.0, no longer use --warn-syntax, and use
> changeextarg to support ${{1}} m4 extended arguments
>
We'll just leave allowing ${{1}} for the future :)
- --
Don't work too hard, make some time for fun as well!
Eric Blake address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFFyzka84KuGfSFAYARAiGSAKCnwZkcsIad3ZlyeCl/MrhoHvWRVQCgi+CH
qJxUpzaObENgnbgZUSJxsrc=
=Ciwu
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.1.1.1.2.92
diff -u -p -r1.1.1.1.2.92 NEWS
--- NEWS 2 Feb 2007 02:55:11 -0000 1.1.1.1.2.92
+++ NEWS 8 Feb 2007 14:42:13 -0000
@@ -20,15 +20,19 @@ Version 1.4.9 - ?? ??? 2007, by ???? (C
continues, so that you can see all warnings instead of fixing them one
at a time. To acheive 1.4.8 behavior, where the first warning
immediately exits, specify -E twice on the command line.
-* A new `--warn-syntax' command-line option allows detection of
- non-portable syntax that might be broken when upgrading to M4 2.0. For
- example, POSIX requires a macro definition containing `$11' to expand to
- the first argument concatenated with 1, rather than the eleventh
- argument; and allows implementations to choose whether `${11}' is treated
- as literal text, as in M4 1.4.x, or as the eleventh argument, as in the
- eventual M4 2.0. Be aware that Autoconf 2.61 will not work with this
- option enabled.
-* Improved portability to platforms such as BSD/OS.
+* A new `--warn-macro-sequence' command-line option allows detection of
+ sequences in `define' and `pushdef' definitions that match an optional
+ regular expression. The default regular expression is
+ `\$\({[0-9][^}]*}\|[0-9][0-9]+\)', corresponding to the sequences that
+ might not behave correctly when upgrading to the eventual M4 2.0. By
+ default, M4 2.0 will follow the POSIX requirement that a macro definition
+ containing `$11' must expand to the first argument concatenated with 1,
+ rather than the eleventh argument; and will take advantage of the POSIX
+ wording that allows implementations to treat `${11}' as the eleventh
+ argument instead of literal text. Be aware that Autoconf 2.61 will not
+ work with this option enabled with the default regular expression; but
+ Autoconf 2.62 will be compatible with this option.
+* Improved portability to platforms such as BSD/OS and AIX.
Version 1.4.8 - 20 November 2006, by Eric Blake (CVS version 1.4.7a)
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.1.1.1.2.113
diff -u -p -r1.1.1.1.2.113 m4.texinfo
--- doc/m4.texinfo 5 Feb 2007 13:25:06 -0000 1.1.1.1.2.113
+++ doc/m4.texinfo 8 Feb 2007 14:42:14 -0000
@@ -584,12 +584,19 @@ is also specified.
Suppress warnings, such as missing or superfluous arguments in macro
calls, or treating the empty string as zero.
address@hidden --warn-syntax
-Issue warnings when syntax is encountered that will change semantics in
address@hidden M4 2.0. For now, the only semantics that will change have
-to do with how more than 9 arguments in a macro definition are handled
-(@pxref{Arguments}). This warning is disabled by default because it
-triggers spurious failures in @acronym{GNU} Autoconf 2.61.
address@hidden address@hidden@address@hidden
+Issue a warning if the regular expression @var{REGEXP} has a non-empty
+match in any macro definition (either by @code{define} or
address@hidden). Empty matches are ignored; therefore, supplying the
+empty string as @var{REGEXP} disables any warning. If the optional
address@hidden is not supplied, then the default regular expression is
address@hidden(@address@hidden@}\|[0-9][0-9]+\)} (a literal @samp{$} followed
+by multiple digits or by an open brace and a digit), since these
+sequences will change semantics in the default operation of
address@hidden M4 2.0 (due to a change in how more than 9 arguments in a
+macro definition will be handled, @pxref{Arguments}). Providing an
+alternate regular expression can provide a useful reverse lookup feature
+of finding where a macro is defined to have a given definition.
@item -W @var{REGEXP}
@itemx address@hidden
@@ -1635,13 +1642,24 @@ bar(`a', `b')
To help you detect places in your M4 input files that might change in
behavior due to the changed behavior of M4 2.0, you can use the
address@hidden command-line option (@pxref{Operation modes, ,
-Invoking m4}). This will add a warning any time a macro definition
-includes @samp{$} followed by multiple digits, or by @address@hidden and a
-digit. The warning is not enabled by default, because it triggers a
-number of warnings in Autoconf 2.61 (and Autoconf uses @option{-E} to
-treat warnings as errors), and because it will still be possible to
-restore traditional behavior in M4 2.0.
address@hidden command-line option (@pxref{Operation
+modes, , Invoking m4}) with the default regular expression. This will
+add a warning any time a macro definition includes @samp{$} followed by
+multiple digits, or by @address@hidden and a digit. The warning is not
+enabled by default, because it triggers a number of warnings in Autoconf
+2.61 (and Autoconf uses @option{-E} to treat warnings as errors), and
+because it will still be possible to restore older behavior in M4 2.0.
+
address@hidden ignore
address@hidden
+$ @kbd{m4 --warn-macro-sequence}
+define(`foo', `$001 address@hidden@} $1')
address@hidden:stdin:1: Warning: definition of `foo' contains sequence `$001'
address@hidden:stdin:1: Warning: definition of `foo' contains sequence
address@hidden@}'
address@hidden
+foo(`bar')
address@hidden address@hidden@} bar
address@hidden example
@node Pseudo Arguments
@section Special arguments to macros
Index: src/builtin.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/builtin.c,v
retrieving revision 1.1.1.1.2.56
diff -u -p -r1.1.1.1.2.56 builtin.c
--- src/builtin.c 28 Jan 2007 01:54:44 -0000 1.1.1.1.2.56
+++ src/builtin.c 8 Feb 2007 14:42:15 -0000
@@ -221,6 +221,68 @@ define_builtin (const char *name, const
SYMBOL_FUNC (sym) = bp->func;
}
+/* Storage for the compiled regular expression of
+ --warn-macro-sequence. */
+static struct re_pattern_buffer macro_sequence_buf;
+
+/* Storage for the matches of --warn-macro-sequence. */
+static struct re_registers macro_sequence_regs;
+
+/* True if --warn-macro-sequence is in effect. */
+static bool macro_sequence_inuse;
+
+/*----------------------------------------.
+| Clean up regular expression variables. |
+`----------------------------------------*/
+
+static void
+free_pattern_buffer (struct re_pattern_buffer *buf, struct re_registers *regs)
+{
+ regfree (buf);
+ free (regs->start);
+ free (regs->end);
+}
+
+/*-----------------------------------------------------------------.
+| Set the regular expression of --warn-macro-sequence that will be |
+| checked during define and pushdef. Exit on failure. |
+`-----------------------------------------------------------------*/
+void
+set_macro_sequence (const char *regexp)
+{
+ const char *msg;
+
+ if (! regexp)
+ regexp = "\\$\\({[0-9][^}]*}\\|[0-9][0-9]+\\)";
+ else if (regexp[0] == '\0')
+ {
+ macro_sequence_inuse = false;
+ return;
+ }
+
+ msg = re_compile_pattern (regexp, strlen (regexp), ¯o_sequence_buf);
+ if (msg != NULL)
+ {
+ M4ERROR ((EXIT_FAILURE, 0,
+ "--warn-macro-sequence: bad regular expression `%s': %s",
+ regexp, msg));
+ }
+ re_set_registers (¯o_sequence_buf, ¯o_sequence_regs,
+ macro_sequence_regs.num_regs,
+ macro_sequence_regs.start, macro_sequence_regs.end);
+ macro_sequence_inuse = true;
+}
+
+/*------------------------------------------------------------.
+| Free dynamic memory utilized by the define sequence regular |
+| expression. |
+`------------------------------------------------------------*/
+void
+free_macro_sequence (void)
+{
+ free_pattern_buffer (¯o_sequence_buf, ¯o_sequence_regs);
+}
+
/*-------------------------------------------------------------------------.
| Define a predefined or user-defined macro, with name NAME, and expansion |
| TEXT. MODE destinguishes between the "define" and the "pushdef" case. |
@@ -231,50 +293,43 @@ void
define_user_macro (const char *name, const char *text, symbol_lookup mode)
{
symbol *s;
- size_t len;
+ char *defn = xstrdup (text ? text : "");
s = lookup_symbol (name, mode);
if (SYMBOL_TYPE (s) == TOKEN_TEXT)
free (SYMBOL_TEXT (s));
SYMBOL_TYPE (s) = TOKEN_TEXT;
- SYMBOL_TEXT (s) = xstrdup (text ? text : "");
+ SYMBOL_TEXT (s) = defn;
- /* In M4 2.0, $11 will mean the first argument concatenated with 1,
- not the eleventh argument. Also, ${1} will mean the first
- argument, rather than literal text (although for compatibility
- sake, it will be possible to restore the traditional meaning of
- ${1} using changesyntax). Needing more than 9 arguments is
- somewhat rare, but using M4 to process shell code is quite
- common; either way, warn on usages that will change in
- semantics. */
- if (warn_syntax && text && (len = strlen (text)) >= 3)
+ /* Implement --warn-macro-sequence. */
+ if (macro_sequence_inuse && text)
{
- static struct re_pattern_buffer buf;
- static bool init = false;
regoff_t offset = 0;
+ size_t len = strlen (defn);
- if (! init)
+ while ((offset = re_search (¯o_sequence_buf, defn, len, offset,
+ len - offset, ¯o_sequence_regs)) >= 0)
{
- const char *msg = "\\$[{0-9][0-9]";
- init_pattern_buffer (&buf, NULL);
- msg = re_compile_pattern (msg, strlen (msg), &buf);
- if (msg != NULL)
+ /* Skip empty matches. */
+ if (macro_sequence_regs.start[0] == macro_sequence_regs.end[0])
+ offset++;
+ else
{
- M4ERROR ((EXIT_FAILURE, 0,
- "unable to check --warn-syntax: %s", msg));
+ char tmp;
+ offset = macro_sequence_regs.end[0];
+ tmp = defn[offset];
+ defn[offset] = '\0';
+ M4ERROR ((warning_status, 0,
+ "Warning: definition of `%s' contains sequence `%s'",
+ name, defn + macro_sequence_regs.start[0]));
+ defn[offset] = tmp;
}
- init = true;
- }
- while ((offset = re_search (&buf, text, len, offset, len - offset,
- NULL)) >= 0)
- {
- M4ERROR ((warning_status, 0,
- "Warning: semantics of `$%c%c%s' in `%s' will change",
- text[offset + 1], text[offset + 2],
- text[offset + 1] == '{' ? "...}" : "", name));
- offset += 3;
}
+ if (offset == -2)
+ M4ERROR ((warning_status, 0,
+ "error checking --warn-define-sequence for macro `%s'",
+ name));
}
}
@@ -1880,18 +1935,6 @@ init_pattern_buffer (struct re_pattern_b
}
}
-/*----------------------------------------.
-| Clean up regular expression variables. |
-`----------------------------------------*/
-
-static void
-free_pattern_buffer (struct re_pattern_buffer *buf, struct re_registers *regs)
-{
- regfree (buf);
- free (regs->start);
- free (regs->end);
-}
-
/*--------------------------------------------------------------------------.
| Regular expression version of index. Given two arguments, expand to the |
| index of the first match of the second argument (a regexp) in the first. |
Index: src/m4.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/m4.c,v
retrieving revision 1.1.1.1.2.43
diff -u -p -r1.1.1.1.2.43 m4.c
--- src/m4.c 2 Feb 2007 02:55:11 -0000 1.1.1.1.2.43
+++ src/m4.c 8 Feb 2007 14:42:15 -0000
@@ -58,9 +58,6 @@ static bool fatal_warnings = false;
/* If not zero, then value of exit status for warning diagnostics. */
int warning_status = 0;
-/* If true, then warn about usage of ${1} in macro definitions. */
-bool warn_syntax = false;
-
/* Artificial limit for expansion_level in macro.c. */
int nesting_limit = 1024;
@@ -163,7 +160,9 @@ Operation modes:\n\
-i, --interactive unbuffer output, ignore interrupts\n\
-P, --prefix-builtins force a `m4_' prefix to all builtins\n\
-Q, --quiet, --silent suppress some warnings for builtins\n\
- --warn-syntax warn on syntax that will change in future\n\
+ --warn-macro-sequence[=REGEXP]\n\
+ warn if macro definition matches REGEXP,\n\
+ default \\$\\({[0-9][^}]*}\\|[0-9]+\\)\n\
", stdout);
#ifdef ENABLE_CHANGEWORD
fputs ("\
@@ -239,7 +238,7 @@ enum
{
DEBUGFILE_OPTION = CHAR_MAX + 1, /* no short opt */
DIVERSIONS_OPTION, /* not quite -N, because of message */
- WARN_SYNTAX_OPTION, /* no short opt */
+ WARN_MACRO_SEQUENCE_OPTION, /* no short opt */
HELP_OPTION, /* no short opt */
VERSION_OPTION /* no short opt */
@@ -269,7 +268,7 @@ static const struct option long_options[
{"debugfile", required_argument, NULL, DEBUGFILE_OPTION},
{"diversions", required_argument, NULL, DIVERSIONS_OPTION},
- {"warn-syntax", no_argument, NULL, WARN_SYNTAX_OPTION},
+ {"warn-macro-sequence", optional_argument, NULL, WARN_MACRO_SEQUENCE_OPTION},
{"help", no_argument, NULL, HELP_OPTION},
{"version", no_argument, NULL, VERSION_OPTION},
@@ -337,6 +336,7 @@ main (int argc, char *const *argv, char
const char *debugfile = NULL;
const char *frozen_file_to_read = NULL;
const char *frozen_file_to_write = NULL;
+ const char *macro_sequence = "";
program_name = argv[0];
retcode = EXIT_SUCCESS;
@@ -474,8 +474,12 @@ main (int argc, char *const *argv, char
debugfile = optarg;
break;
- case WARN_SYNTAX_OPTION:
- warn_syntax = true;
+ case WARN_MACRO_SEQUENCE_OPTION:
+ /* Don't call set_macro_sequence here, as it can exit.
+ --warn-macro-sequence sets optarg to NULL (which uses the
+ default regexp); --warn-macro-sequence= sets optarg to ""
+ (which disables these warnings). */
+ macro_sequence = optarg;
break;
case VERSION_OPTION:
@@ -497,6 +501,7 @@ main (int argc, char *const *argv, char
input_init ();
output_init ();
symtab_init ();
+ set_macro_sequence (macro_sequence);
include_env_init ();
if (frozen_file_to_read)
@@ -595,5 +600,6 @@ main (int argc, char *const *argv, char
undivert_all ();
}
output_exit ();
+ free_macro_sequence ();
exit (retcode);
}
Index: src/m4.h
===================================================================
RCS file: /sources/m4/m4/src/m4.h,v
retrieving revision 1.1.1.1.2.38
diff -u -p -r1.1.1.1.2.38 m4.h
--- src/m4.h 5 Feb 2007 13:43:36 -0000 1.1.1.1.2.38
+++ src/m4.h 8 Feb 2007 14:42:15 -0000
@@ -119,7 +119,6 @@ extern int max_debug_argument_length; /*
extern int suppress_warnings; /* -Q */
extern int warning_status; /* -E */
extern int nesting_limit; /* -L */
-extern bool warn_syntax; /* --warn-syntax */
#ifdef ENABLE_CHANGEWORD
extern const char *user_word_regexp; /* -W */
#endif
@@ -411,6 +410,8 @@ struct re_registers;
void builtin_init (void);
void define_builtin (const char *, const builtin *, symbol_lookup);
+void set_macro_sequence (const char *);
+void free_macro_sequence (void);
void define_user_macro (const char *, const char *, symbol_lookup);
void undivert_all (void);
void expand_user_macro (struct obstack *, symbol *, int, token_data **);
Index: NEWS
===================================================================
RCS file: /sources/autoconf/autoconf/NEWS,v
retrieving revision 1.424
diff -u -p -r1.424 NEWS
--- NEWS 2 Feb 2007 14:11:43 -0000 1.424
+++ NEWS 8 Feb 2007 14:47:54 -0000
@@ -9,8 +9,9 @@
These warnings can be disabled with the new AC_DISABLE_OPTION_CHECKING
macro, or by invoking 'configure' with --disable-option-checking.
-** For portability with the eventual M4 2.0, macros should no longer use
- anything larger than $9 to refer to arguments.
+** For portability with POSIX and the eventual M4 2.0, macros should not
+ refer to arguments greater than $9. If M4 1.4.9 or later is
+ available, a warning is issued that detects usage such as $10.
* Major changes in Autoconf 2.61a (2006-12-11)
Index: bin/autom4te.in
===================================================================
RCS file: /sources/autoconf/autoconf/bin/autom4te.in,v
retrieving revision 1.105
diff -u -p -r1.105 autom4te.in
--- bin/autom4te.in 4 Jan 2007 16:43:06 -0000 1.105
+++ bin/autom4te.in 8 Feb 2007 14:47:55 -0000
@@ -89,9 +89,14 @@ my $freeze = 0;
# $M4.
my $m4 = $ENV{"M4"} || '@M4@';
-# Some non-GNU m4's don't reject the --help option, so give them /dev/null.
-fatal "need GNU m4 1.4 or later: $m4"
- if system "$m4 --help </dev/null 2>&1 | grep reload-state >/dev/null";
+fatal "need GNU m4 1.4.5 or later: $m4"
+ unless system "echo 'ifdef(mac,bug)dnl' | $m4 --trace=mac 2>&1 | grep bug
>/dev/null";
+
+# Detect if we can use feature added in M4 1.4.9 to warn user about $10.
+# Override the user's choice of --warn-macro-sequence, since the default
+# macro sequence rejects ${1} even though we guarantee it is safe.
+$m4 .= " --warn-macro-sequence='\\\$\\([0-9][0-9]+\\|{{\\)'"
+ if ! system "$m4 --help | grep warn-macro-sequence >/dev/null";
# Set some high recursion limit as the default limit, 250, has already
# been hit with AC_OUTPUT. Don't override the user's choice.
Index: doc/autoconf.texi
===================================================================
RCS file: /sources/autoconf/autoconf/doc/autoconf.texi,v
retrieving revision 1.1131
diff -u -p -r1.1131 autoconf.texi
--- doc/autoconf.texi 7 Feb 2007 17:45:37 -0000 1.1131
+++ doc/autoconf.texi 8 Feb 2007 14:48:00 -0000
@@ -434,6 +434,7 @@ M4 Quotation
* Active Characters:: Characters that change the behavior of M4
* One Macro Call:: Quotation and one macro call
+* Quoting and Parameters:: M4 vs. shell parameters
* Quotation and Nested Macros:: Macros calling macros
* Changequote is Evil:: Worse than INTERCAL: M4 + changequote
* Quadrigraphs:: Another way to escape special characters
@@ -8862,10 +8863,6 @@ and their interface might change in the
@cindex M4 quotation
@cindex quotation
address@hidden FIXME: Grmph, yet another quoting myth: quotation has *never*
address@hidden prevented `expansion' of $1. Unless it refers to the expansion
address@hidden of the value of $1? Anyway, we need a rewrite address@hidden
-
The most common problem with existing macros is an improper quotation.
This section, which users of Autoconf can skip, but which macro writers
@emph{must} read, first justifies the quotation scheme that was chosen
@@ -8875,6 +8872,7 @@ former helps one to follow the latter.
@menu
* Active Characters:: Characters that change the behavior of M4
* One Macro Call:: Quotation and one macro call
+* Quoting and Parameters:: M4 vs. shell parameters
* Quotation and Nested Macros:: Macros calling macros
* Changequote is Evil:: Worse than INTERCAL: M4 + changequote
* Quadrigraphs:: Another way to escape special characters
@@ -8888,8 +8886,8 @@ To fully understand where proper quotati
to know what the special characters are in Autoconf: @samp{#} introduces
a comment inside which no macro expansion is performed, @samp{,}
separates arguments, @samp{[} and @samp{]} are the quotes themselves,
-and finally @samp{(} and @samp{)} (which M4 tries to match by
-pairs).
address@hidden(} and @samp{)} (which M4 tries to match by pairs), and finally
address@hidden inside a macro definition.
In order to understand the delicate case of macro calls, we first have
to present some obvious failures. Below they are ``obvious-ified'',
@@ -9010,10 +9008,77 @@ car([[[a]]])
@result{}[a]
@end example
address@hidden Quoting and Parameters
address@hidden
+
+When M4 encounters @samp{$} within a macro definition, followed
+immediately by a character it recognizes, it will perform M4 parameter
+expansion. This happens regardless of how many layers of quotes the
+parameter expansion is nested within, or even if it occurs in text that
+will be rescanned as a comment.
+
address@hidden
+define([none], [$1])
address@hidden
+define([one], [[$1]])
address@hidden
+define([two], [[[$1]]])
address@hidden
+define([comment], [# $1])
address@hidden
+define([active], [ACTIVE])
address@hidden
+none([active])
address@hidden
+one([active])
address@hidden
+two([active])
address@hidden
+comment([active])
address@hidden active
address@hidden example
+
+On the other hand, since autoconf generates shell code, you often want
+to output shell variable expansion, rather than performing M4 parameter
+expansion. To do this, you must use M4 quoting to separate the @samp{$}
+from the next character in the definition of your macro. If the macro
+definition occurs in single-quoted text, then insert another level of
+quoting; if the usage is already inside a double-quoted string, then
+split it into concatenated strings.
+
address@hidden
+define([single], [one set of quotes for $[1] in definition])
address@hidden
+define([double], [[two sets of quotes for $][1 in definition]])
address@hidden
+single
address@hidden set of quotes for $1 in definition
+double
address@hidden sets of quotes for $1 in definition
address@hidden example
+
address@hidden states that M4 implementations are free to use
address@hidden@{} in macro definitions however they like. @acronym{GNU} M4
+1.4.x always outputs those two characters literally, whereas
address@hidden M4 2.0 has a new feature called extended arguments that is
+modeled after shell variable expansion semantics. This is due in part
+to the fact that M4 1.4.x violates @acronym{POSIX} by treating
address@hidden as the eleventh parameter. To comply with @acronym{POSIX},
+M4 2.0 defaults to treating @address@hidden@}} as the eleventh parameter,
+while treating @samp{$11} as the first parameter concatenated with
address@hidden Meanwhile, m4sugar uses other features of M4 2.0 to reserve
+the notation @address@hidden@address@hidden@}} (note the doubled
@address@hidden) for M4
+extended arguments instead of M4's default, so that you can safely use
address@hidden@address@hidden to get literal output meaning the shell's first
argument
+regardless of your version of M4. However, it does mean that you cannot
+portably refer to anything higher than @samp{$9} in your macro and still
+work with all supported versions of M4. In fact, if you use M4 1.4.9 or
+greater, Autoconf is able to warn you of non-portable usage of a
+multi-digit parameter.
+
With this in mind, we can explore the cases where macros invoke
address@hidden
-
@node Quotation and Nested Macros
@subsection Quotation and Nested Macros
@@ -9107,17 +9172,20 @@ qar([int tab[10];])
@noindent
Ahhh! That's much better.
-But note what you've done: now that the arguments are literal strings,
-if the user wants to use the results of expansions as arguments, she has
-to use an @emph{unquoted} macro call:
+But note what you've done: now that the result of @code{qar} is always
+a literal string, the only time a user can use the results of
+expansions is with an @emph{unquoted} macro call:
@example
qar(active)
@result{}ACT
+qar([active])
address@hidden
@end example
@noindent
-where she wanted to reproduce what she used to do with @code{car}:
+leaving no way for the user to reproduce what she used to do with
address@hidden:
@example
car([active])
Index: lib/m4sugar/m4sugar.m4
===================================================================
RCS file: /sources/autoconf/autoconf/lib/m4sugar/m4sugar.m4,v
retrieving revision 2.100
diff -u -p -r2.100 m4sugar.m4
--- lib/m4sugar/m4sugar.m4 20 Oct 2006 01:34:33 -0000 2.100
+++ lib/m4sugar/m4sugar.m4 8 Feb 2007 14:48:00 -0000
@@ -3,8 +3,8 @@ divert(-1)#
# Base M4 layer.
# Requires GNU M4.
#
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
-# Foundation, Inc.
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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
@@ -54,6 +54,13 @@ divert(-1)#
# Set the quotes, whatever the current quoting system.
changequote()
changequote([, ])
+# M4 1.9b and greater defaults to treating ${1} as an expansion of parameter
+# one, but too many existing autoconf macros expect the 1.4.x behavior of
+# literal output. We can tell the difference by whether the changeextarg
+# builtin exists; in which case we reserve ${{1}} as extended parameters for
+# the day when we can rely on M4 2.0. autom4te also warns the user that
+# $10 is non-portable.
+ifdef([changeextarg], [changeextarg({{,}})])
# Some old m4's don't support m4exit. But they provide
# equivalent functionality by core dumping because of the
- Re: M4 syntax $11 vs. ${11},
Eric Blake <=