Eric Blake <ebb9 <at> byu.net> writes:
>
> With 1.9b, I would like to implement the resolution of XCU ERN 111. That
> is, I plan on adding support for ${11}, so that the GNU extension of more
> than 9 parameters is still alive (and in fact, I hope to borrow from shell
> syntax for other extensions such as ${1-default}). I also plan on making
> $11 obey POSIX semantics if POSIXLY_CORRECT, else obey 1.4.x semantics but
> issue a warning that obsolete syntax was encountered. Then, after a
> deprecation period, M4 2.1 could remove the POSIXLY_CORRECT check and
> always treat $11 the way POSIX requires.
Here (finally) is a patch for head, that both implements ${1}, as well as
forward ports --warn-macro-sequence from the branch. The features are
intertwined enough that I didn't see any good reason to separate this into
multiple patches (other than the earlier patches I already committed today).
However, I would like a review; so it is not applied yet. In particular, in
macro.c, this patch does not do a deprecation period for $10, as I originally
thought above, but flat out went with POSIX syntax. I did this on the
principle that relatively few uses of $10 in the wild have been discovered, and
that --warn-macro-sequence can be used to detect even those uses. Bonus points
if you can spot the corner case logic problem that I am already aware of in
macro.c.
The patch looks big, but part of it is moving implementation of regex functions
out of modules/gnu.c into m4/resyntax.c for better code sharing; part of it is
test code; and a lot of it is documentation.
Still to be written:
1) I want to implement a new builtin m4macroseq([regex],[resyntax]), which
behaves like the command-line --warn-macro-sequence (and that also means adding
a command line --m4macroseq for symmetry). With no arguments, it enables the
default warning sequence, with one empty argument, it disables warnings, and
since it uses regular expressions, it takes an optional resyntax argument to
override the current changeresyntax.
2) I have promised to implement changeextarg(start,[stop]), which allows multi-
character extended arguments, so that autoconf can reserve ${1} for shell
output and ${{1}} for the day that autoconf 3.0 depends on m4 2.0. I will
model it on changequote, including how it interacts with single-character quote
syntax in changesyntax, except that an argument always must be supplied (to go
with the policy that macros not beginning with "__" or "m4" must be blind, to
avoid risk of inadvertant expansion).
3) I would like to implement ideas from sh, such as ${1-default} expanding to
the first argument if supplied, or `default' if omitted.
I think that 2) is the only thing that should be completed before I feel
comfortable baselining m4-1.9b for wider test exposure on alpha.gnu.org.
2007-02-28 Eric Blake <[EMAIL PROTECTED]>
Implement first cut of extended arguments. Use ${10} instead of
$10 to mean the tenth argument.
* doc/m4.texinfo (Extended Arguments): New section.
(Operation modes): Document --warn-macro-sequence.
(Preprocessor features): Document current limitation of
--warn-macro-sequence combined with --import-environment.
(Arguments): Document POSIX behavior.
(Shift): Document argn macro for portably accessing tenth
argument.
(Changesyntax): Document way to override extended arguments.
(Extensions): Update wording to match implementation.
* m4/m4module.h (M4_DEFAULT_MACRO_SEQUENCE): New define.
(m4_set_macro_sequence, m4_free_macro_sequence, m4_macro_define)
(m4_check_macro_sequence): New prototypes.
(m4_pattern_buffer): Move here from gnu.c.
(m4_regexp_compile, m4_regexp_free): New prototypes.
* m4/macro.c (process_extended_argument): New helper.
(process_macro): Disable multi-digit arguments. Implement
extended arguments.
(macro_sequence, macro_sequence_inuse): New variables.
(m4_set_macro_sequence, m4_free_macro_sequence, m4_macro_define)
(m4_check_macro_sequence): New functions.
* m4/module.c (install_macro_table): Use new function.
* m4/resyntax.c (m4_regexp_compile, m4_regexp_free): New
functions, moved from gnu.c.
* modules/gnu.c (regexp_compile): Rename from m4_regexp_compile,
move implementation to libm4, and change all callers.
(M4_FINISH_HANDLER): Use new function.
* modules/m4.c (define, pushdef): Use new function.
* src/freeze.c (reload_frozen_state): Likewise.
* src/main.c (usage): Document --warn-macro-sequence.
(main): Use new functions.
* tests/macros.at (Extended arguments): New test.
* tests/options.at (--warn-macro-sequence): Likewise.
* tests/others.at (sysv-args): Fix typos.
* NEWS: Document this change.
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.40
diff -u -r1.40 NEWS
--- NEWS 28 Feb 2007 21:31:12 -0000 1.40
+++ NEWS 1 Mar 2007 04:13:58 -0000
@@ -79,6 +79,10 @@
dynamic modules from the command line. Also, `-m'/`--load-module' now
acts between input files.
+*** The `--warn-macro-sequence' command-line option can now be interspersed
+ with other options and files, and is affected by the new
+ `--regexp-syntax' option.
+
*** New `--warnings' command-line option re-enables warnings, overriding
`-Q'/`--quiet'/`--silent', allowing warnings even when POSIXLY_CORRECT.
@@ -87,8 +91,29 @@
*** The `defn' builtin now allows any number of arguments, as POSIX requires.
- FIXME: This still doesn't work with concatenating builtins with text.
- - FIXME: POSIX recommends using ${10} instead of $10 for the tenth
- positional argument. We should deprecate $10.
+*** The GNU 1.4.x extension of recognizing the sequence `$10' in macro
+ definitions as the tenth positional parameter is withdrawn, as it is
+ incompatible with POSIX. The sequence `$10' now correctly refers to
+ the first positional parameter concatenated with 0. To directly access
+ the tenth parameter, you must now use extended arguments (you can also
+ portably access the tenth argument indirectly using the `shift'
+ builtin). To detect places in existing scripts that might be affected
+ by this change in behavior, you can use the `--warn-macro-sequence'
+ command-line option.
+
+*** POSIX allows implementations to assign arbitrary behavior to the sequence
+ `${' in macro definitions. All earlier versions of GNU M4 just treated
+ it as literal output, but this version introduces extended arguments.
+ By default, the sequence `${<digits>}' now represents the extended
+ argument referring to a positional parameter, so that it is still
+ possible to directly refer to more than nine arguments. If the older
+ 1.4.x behavior of literal output is desired, the new `changesyntax' or
+ `changeextarg' builtins can be used to cripple extended arguments. To
+ detect places in existing scripts that might be affected by this change
+ in behavior, you can use the `--warn-macro-sequence' command-line
+ option.
+ - FIXME: Extended arguments are not working completely, and changeextarg
+ needs to be added. Also, defaults (ie. ${1-default}) would be nice.
- FIXME: `m4wrap' semantics need an update to FIFO.
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.98
diff -u -r1.98 m4.texinfo
--- doc/m4.texinfo 28 Feb 2007 21:31:12 -0000 1.98
+++ doc/m4.texinfo 1 Mar 2007 04:13:58 -0000
@@ -184,6 +184,7 @@
* Define:: Defining a new macro
* Arguments:: Arguments to macros
* Pseudo Arguments:: Special arguments to macros
+* Extended Arguments:: Extended arguments
* Undefine:: Deleting a macro
* Defn:: Renaming macros
* Pushdef:: Temporarily redefining macros
@@ -671,6 +672,25 @@
option is intended to make it safer to preprocess an input file of
unknown origin.
[EMAIL PROTECTED] [EMAIL PROTECTED]@[EMAIL PROTECTED]
[EMAIL PROTECTED] TODO: add m4macroseq builtin, and alias --m4macroseq
+Issue a warning if the regular expression @var{REGEXP} has a non-empty
+match in any macro definition (either by @code{define} or
[EMAIL PROTECTED]). Empty matches are ignored; therefore, supplying the
+empty string as @var{REGEXP} disables any warning. Otherwise,
[EMAIL PROTECTED] is compiled according to the current regular expression
+syntax. If the optional @var{REGEXP} is not supplied, then a default
+regular expression is used, equivalent to
[EMAIL PROTECTED](@[EMAIL PROTECTED]@}\|[0-9][0-9]+\)} in the @code{GNU_M4}
regular
+expression flavor (a literal @samp{$} followed by multiple digits or by
+an open brace). The default expression is chosen to detect the
+sequences that changed semantics in the default operation of
[EMAIL PROTECTED] M4 2.0 compared to earlier versions of GNU M4
+(@pxref{Extended 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, or accomodate uses of
[EMAIL PROTECTED] that intentionally alter extended argument syntax.
+
@item -W
@itemx --warnings
Enable warnings. Warnings are on by default unless
@@ -746,7 +766,9 @@
@item --import-environment
Imports every variable in the environment as a macro. This is done
before @option{-D} and @option{-U}, so they can override the
-environment.
+environment. However, this means that @option{--warn-macro-sequence} is
+unable to detect any environment variable definitions that have a
+questionable sequence.
@item -I @var{DIRECTORY}
@itemx [EMAIL PROTECTED]
@@ -1725,6 +1747,7 @@
* Define:: Defining a new macro
* Arguments:: Arguments to macros
* Pseudo Arguments:: Special arguments to macros
+* Extended Arguments:: Extended arguments
* Undefine:: Deleting a macro
* Defn:: Renaming macros
* Pushdef:: Temporarily redefining macros
@@ -1854,20 +1877,6 @@
(You should try and improve this example so that clients of @code{exch}
do not have to double quote; or @pxref{Improved exch, , Answers}).
[EMAIL PROTECTED] @acronym{GNU} extensions
[EMAIL PROTECTED] @code{m4} allows the number following the @samp{$} to
-consist of one
-or more digits, allowing macros to have any number of arguments. This
-is not so in UNIX implementations of @code{m4}, which only recognize
-one digit.
[EMAIL PROTECTED] FIXME - See Austin group XCU ERN 111. POSIX says that $11
must
[EMAIL PROTECTED] be the first argument concatenated with 1, and instead
reserves
[EMAIL PROTECTED] ${11} for implementation use. Once this is implemented, the
[EMAIL PROTECTED] documentation needs to reflect how these extended arguments
[EMAIL PROTECTED] are handled, as well as backwards compatibility issues with
[EMAIL PROTECTED] 1.4.x. Also, consider adding further extensions such as
[EMAIL PROTECTED] ${1-default}, which expands to `default' if $1 is empty.
-
As a special case, the zeroth argument, @code{$0}, is always the name
of the macro being expanded.
@@ -1892,6 +1901,22 @@
The @samp{foo} in the expansion text is @emph{not} expanded, since it is
a quoted string, and not a name.
[EMAIL PROTECTED] requires that if multiple digits appear after @samp{$},
+the first digit is used to select the parameter, and the remaining
+digits are concatenated as literal text. Earlier versions of
[EMAIL PROTECTED] M4 had an incompatible extension that would use all of
+the digits to reference beyond the ninth argument, but this was changed
+in M4 2.0. @xref{Extended Arguments}, for more details on this change.
+
[EMAIL PROTECTED]
+define(`foo', `$11')
[EMAIL PROTECTED]
+define(`a1', `hello')
[EMAIL PROTECTED]
+foo(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k', `l')
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
@node Pseudo Arguments
@section Special arguments to macros
@@ -2040,6 +2065,96 @@
@result{}nested quote around both: arg
@end example
[EMAIL PROTECTED] Extended Arguments
[EMAIL PROTECTED] Extended arguments
+
[EMAIL PROTECTED] @acronym{GNU} extensions
[EMAIL PROTECTED] nine arguments, more than
[EMAIL PROTECTED] more than nine arguments
[EMAIL PROTECTED] arguments, more than nine
[EMAIL PROTECTED] arguments, extended
[EMAIL PROTECTED] positional parameters, more than nine
[EMAIL PROTECTED] extended arguments
[EMAIL PROTECTED] FIXME - Need to implement the changeextarg builtin. Also,
[EMAIL PROTECTED] consider adding further extensions such as ${1-default}, which
[EMAIL PROTECTED] expands to `default' if $1 is empty.
[EMAIL PROTECTED] states that @samp{$} followed immediately by @[EMAIL
PROTECTED]
+in a macro definition is implementation-defined. Since @acronym{GNU} M4
+2.0, @code{m4} takes advantage of this to offer @dfn{extended
+arguments}. By default, an extended argument consists of the text
+between @[EMAIL PROTECTED] and @[EMAIL PROTECTED] in a macro definition. When
the text
+after @[EMAIL PROTECTED] cannot be parsed as a recognized extended argument,
+including the case where where no @[EMAIL PROTECTED] could be found, a warning
is
+issued, and the text is output literally.
+
+The currently supported extended arguments are:
+
[EMAIL PROTECTED] @code
[EMAIL PROTECTED] @var{digits}
+Refers to the @var{n}th argument, supporting arguments beyond nine.
+
[EMAIL PROTECTED] #
[EMAIL PROTECTED] *
[EMAIL PROTECTED] @@
+Has the same pseudo-argument behavior as in non-extended arguments.
[EMAIL PROTECTED] table
+
+More extended arguments may be introduced in future versions.
+
[EMAIL PROTECTED]
+define(`foo', [EMAIL PROTECTED]@}')
[EMAIL PROTECTED]
+define(`a1', `hello')
[EMAIL PROTECTED]
+foo(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k', `l')
[EMAIL PROTECTED]
+define(`m', [EMAIL PROTECTED]@} [EMAIL PROTECTED]')
[EMAIL PROTECTED]
+m
[EMAIL PROTECTED]:stdin:5: Warning: m: unrecognized extended argument: [EMAIL
PROTECTED]@}'
[EMAIL PROTECTED]:stdin:5: Warning: m: unterminated extended argument: [EMAIL
PROTECTED]'
[EMAIL PROTECTED]@[EMAIL PROTECTED] [EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
+If you need to portably access beyond the ninth argument, such as with
+earlier versions of M4 that do not recognize extended arguments, you can
+use the @code{argn} macro documented later (@pxref{Shift}).
+
+Meanwhile, if you want to guarantee that you will get a literal
[EMAIL PROTECTED]@{} in output when expanding a macro, rather than triggering
+extended argument parsing, you can use nested quoting to your advantage:
+
[EMAIL PROTECTED]
+define(`foo', `single quoted $`'@[EMAIL PROTECTED] output')
[EMAIL PROTECTED]
+define(`bar', ``double quoted $'[EMAIL PROTECTED]@} output'')
[EMAIL PROTECTED]
+foo(`a', `b')
[EMAIL PROTECTED] quoted [EMAIL PROTECTED]@} output
+bar(`a', `b')
[EMAIL PROTECTED] quoted [EMAIL PROTECTED]@} output
[EMAIL PROTECTED] example
+
+To help you detect places in your M4 input files that might have changed
+in behavior when upgrading from earlier versions of @acronym{GNU} M4,
+you can use the @option{--warn-macro-sequence} 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 @[EMAIL PROTECTED] The
+warning is not enabled by default, because it conflicts with using
+extended arguments.
+
[EMAIL PROTECTED] options: --warn-macro-sequence
[EMAIL PROTECTED]
+$ @kbd{m4 --warn-macro-sequence}
+define(`foo', `$001 [EMAIL PROTECTED]@} $1')
[EMAIL PROTECTED]:stdin:1: Warning: define: `foo' contains sequence `$001'
[EMAIL PROTECTED]:stdin:1: Warning: define: `foo' contains sequence [EMAIL
PROTECTED]@}'
[EMAIL PROTECTED]
+foo(`bar')
[EMAIL PROTECTED] bar bar
[EMAIL PROTECTED] example
+
@node Undefine
@section Deleting a macro
@@ -2920,6 +3035,33 @@
@result{}divert`'dnl
@end example
[EMAIL PROTECTED] nine arguments, more than
[EMAIL PROTECTED] more than nine arguments
[EMAIL PROTECTED] arguments, more than nine
+One more useful macro based on @code{shift} allows portably selecting an
+arbitrary argument (usually greater than the ninth argument), without
+relying on extended arguments (@pxref{Extended Arguments}).
+
[EMAIL PROTECTED] Composite argn (@var{n}, @dots{})
+Expands to argument @var{n} out of the remaining arguments. @var{n}
+must be a positive number. Usually invoked as
[EMAIL PROTECTED]([EMAIL PROTECTED]',$@@)}.
[EMAIL PROTECTED] deffn
+
+It is implemented as:
+
[EMAIL PROTECTED]
+define(`argn', `ifelse(`$1', 1, ``$2'',
+ `argn(decr(`$1'), shift(shift($@@)))')')
[EMAIL PROTECTED]
+argn(`1', `a')
[EMAIL PROTECTED]
+define(`foo', `argn(`11', $@@)')
[EMAIL PROTECTED]
+foo(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k', `l')
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
@node Forloop
@section Iteration by counting
@@ -4669,6 +4811,23 @@
Note how it is possible to have both long and short quotes, if
@code{changequote} is used before @code{changesyntax}.
[EMAIL PROTECTED] arguments, extended
[EMAIL PROTECTED] extended arguments
[EMAIL PROTECTED] disabling extended arguments
+For backwards compatibility with earlier versions of @acronym{GNU} M4,
+it is sometimes desirable to disable extended arguments
+(@pxref{Extended Arguments}). This can easily be done by ensuring that
+no characters belong to the left brace and right brace categories. The
+following example is portable to @acronym{GNU} M4 1.4.x.
+
[EMAIL PROTECTED]
+ifdef(`changesyntax', `changesyntax([EMAIL PROTECTED]', [EMAIL
PROTECTED]')')dnl
+define(`foo', [EMAIL PROTECTED]@}')
[EMAIL PROTECTED]
+foo(`a')
[EMAIL PROTECTED]@[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
The syntax table is initialized to be backwards compatible, so if you
never call @code{changesyntax}, nothing will have changed.
@@ -7173,12 +7332,11 @@
@itemize @bullet
@item
-In the @[EMAIL PROTECTED] notation for macro arguments, @var{n} can contain
-several digits, while the System V @code{m4} only accepts one digit.
-This allows macros in GNU @code{m4} to take any number of arguments, and
-not only nine (@pxref{Arguments}).
[EMAIL PROTECTED] does not allow this extension, so it is disabled if
[EMAIL PROTECTED] is set.
[EMAIL PROTECTED] allows implementations to treat @[EMAIL PROTECTED] in macro
+definitions however they would like. While most implementations merely
+output both characters literally, @acronym{GNU} M4 provides the
+extension of extended arguments (@pxref{Extended Arguments}). This
+allows macros to directly refer to more than nine positional parameters.
@item
Files included with @code{include} and @code{sinclude} are sought in a
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.106
diff -u -r1.106 m4module.h
--- m4/m4module.h 5 Feb 2007 17:31:10 -0000 1.106
+++ m4/m4module.h 1 Mar 2007 04:13:58 -0000
@@ -188,7 +188,7 @@
m4_obstack*);
extern const char * m4_get_module_name (lt_dlhandle);
-extern void m4__module_exit (m4 *context);
+extern void m4__module_exit (m4 *);
@@ -211,7 +211,6 @@
extern void m4_symbol_popdef (m4_symbol_table*, const char *);
extern m4_symbol *m4_symbol_rename (m4_symbol_table*, const char *,
const char *);
-
extern void m4_symbol_delete (m4_symbol_table*, const char *);
#define m4_symbol_delete(symtab, name) M4_STMT_START { \
@@ -280,11 +279,22 @@
/* --- MACRO MANAGEMENT --- */
-extern void m4_macro_expand_input (m4 *);
-extern void m4_macro_call (m4 *, m4_symbol_value *,
- m4_obstack *, int,
- m4_symbol_value **);
-
+/* The default sequence detects multi-digit parameters (obsolete after
+ 1.4.x), and any use of extended arguments with the default ${}
+ syntax (new in 2.0). */
+#define M4_DEFAULT_MACRO_SEQUENCE "\\$\\({[^}]*}\\|[0-9][0-9]+\\)"
+
+extern void m4_macro_expand_input (m4 *);
+extern void m4_macro_call (m4 *, m4_symbol_value *,
+ m4_obstack *, int,
+ m4_symbol_value **);
+extern void m4_set_macro_sequence (m4 *, const char *, int,
+ const char *);
+extern void m4_free_macro_sequence (m4 *);
+extern m4_symbol_value *m4_macro_define (m4 *, const char *, const char
*,
+ bool);
+extern void m4_check_macro_sequence (m4 *, const char *, const char *,
+ const char *);
/* --- RUNTIME DEBUGGING --- */
@@ -336,8 +346,21 @@
/* --- REGEXP SYNTAX --- */
+/* The regs_allocated field in an re_pattern_buffer refers to the
+ state of the re_registers struct used in successive matches with
+ the same compiled pattern. */
+
+typedef struct {
+ struct re_pattern_buffer pat; /* compiled regular expression */
+ struct re_registers regs; /* match registers */
+} m4_pattern_buffer;
+
extern const char * m4_regexp_syntax_decode (int);
extern int m4_regexp_syntax_encode (const char *);
+extern m4_pattern_buffer *m4_regexp_compile (m4 *, const char *,
+ const char *, int,
+ bool, m4_pattern_buffer *);
+extern void m4_regexp_free (m4_pattern_buffer *);
Index: m4/macro.c
===================================================================
RCS file: /sources/m4/m4/m4/macro.c,v
retrieving revision 1.64
diff -u -r1.64 macro.c
--- m4/macro.c 11 Nov 2006 16:21:25 -0000 1.64
+++ m4/macro.c 1 Mar 2007 04:13:58 -0000
@@ -1,5 +1,5 @@
/* GNU m4 -- A simple macro processor
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2001, 2006
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2001, 2006, 2007
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -406,6 +406,51 @@
}
}
+/* This function handles recognition and expansion of extended
+ arguments. The range [START,END) contains text that might be an
+ extended argument; if so, expand it based on ARGC and ARGV into
+ OBS. Return true if the argument was recognized. */
+static bool
+process_extended_argument (m4 *context, m4_obstack *obs, int argc,
+ m4_symbol_value **argv, const char *start,
+ const char *end)
+{
+ switch (*start)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ char *endp;
+ int i = (int) strtol (start, &endp, 10);
+ if (endp == end)
+ {
+ if (i < argc)
+ m4_shipout_string (context, obs, M4ARG (i), 0, false);
+ return true;
+ }
+ break;
+ }
+
+ case '#': /* number of arguments */
+ if (end - start == 1)
+ {
+ m4_shipout_int (obs, argc - 1);
+ return true;
+ }
+ break;
+
+ case '*': /* all arguments */
+ case '@': /* ... same, but quoted */
+ if (end - start == 1)
+ {
+ m4_dump_args (context, obs, argc, argv, ",", *start == '@');
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
/* This function handles all expansion of user defined and predefined
macros. It is called with an obstack OBS, where the macros expansion
will be placed, as an unfinished object. SYMBOL points to the macro
@@ -415,38 +460,31 @@
process_macro (m4 *context, m4_symbol_value *value, m4_obstack *obs,
int argc, m4_symbol_value **argv)
{
- const unsigned char *text;
+ const char *text;
int i;
for (text = m4_get_symbol_value_text (value); *text != '\0';)
{
- char ch;
+ const char *dollar;
- if (!m4_has_syntax (M4SYNTAX, *text, M4_SYNTAX_DOLLAR))
+ if (!m4_has_syntax (M4SYNTAX, to_uchar (*text), M4_SYNTAX_DOLLAR))
{
obstack_1grow (obs, *text);
text++;
continue;
}
- ch = *text++;
+ dollar = text++;
switch (*text)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- /* FIXME - multidigit arguments should convert over to ${10}
- syntax instead of $10; see
- http://lists.gnu.org/archive/html/m4-discuss/2006-08/msg00028.html
- for more discussion. */
- if (m4_get_posixly_correct_opt (context) || !isdigit(text[1]))
- {
- i = *text++ - '0';
- }
- else
- {
- char *endp;
- i = (int) strtol (text, &endp, 10);
- text = endp;
- }
+ i = *text++ - '0';
+ /* TODO - warn in this case?
+ if (! m4_get_posixly_correct_opt (context) && isdigit(text[1]))
+ m4_warn (context, 0,
+ _("%s: multi-digit parameters changed behavior from 1.4"),
+ M4ARG (0));
+ */
if (i < argc)
m4_shipout_string (context, obs, M4ARG (i), 0, false);
break;
@@ -463,19 +501,18 @@
break;
default:
- if (m4_get_posixly_correct_opt (context)
- || !VALUE_ARG_SIGNATURE (value))
- {
- obstack_1grow (obs, ch);
- }
- else
+ if (VALUE_ARG_SIGNATURE (value))
{
+ /* TODO - VALUE_ARG_SIGNATURE is not fully implemented.
+ Is it worth killing this as dead code, and figuring
+ out how to use extended arguments to do what was
+ originally envisioned by VALUE_ARG_SIGNATURE? */
size_t len = 0;
- const unsigned char *endp;
+ const char *endp;
const char *key;
for (endp = ++text;
- *endp && m4_has_syntax (M4SYNTAX, *endp,
+ *endp && m4_has_syntax (M4SYNTAX, to_uchar (*endp),
(M4_SYNTAX_OTHER | M4_SYNTAX_ALPHA
| M4_SYNTAX_NUM));
++endp)
@@ -515,9 +552,45 @@
free ((char *) key);
break;
}
+ if (m4_has_syntax (M4SYNTAX, to_uchar (*text), M4_SYNTAX_LBRACE))
+ {
+ const char *start = text + 1;
+ const char *end;
+ /* Check for extended argument candidate. */
+ while (*++text && ! m4_has_syntax (M4SYNTAX, to_uchar (*text),
+ M4_SYNTAX_RBRACE))
+ ;
+ if (! *text)
+ {
+ m4_warn (context, 0,
+ _("%s: unterminated extended argument: `%s'"),
+ M4ARG (0), dollar);
+ text = dollar + 1;
+ obstack_1grow (obs, *dollar);
+ break;
+ }
+ end = text++;
+ if (! process_extended_argument (context, obs, argc, argv,
+ start, end))
+ {
+ m4_warn (context, 0,
+ _("%s: unrecognized extended argument: `%.*s'"),
+ M4ARG (0), text - dollar, dollar);
+ text = dollar + 1;
+ obstack_1grow (obs, *dollar);
+ break;
+ }
+ }
+ else
+ {
+ /* Unrecognized character after dollar; just output the
+ dollar, and let next time around loop pick up the
+ character. */
+ obstack_1grow (obs, *dollar);
+ }
break;
- }
- }
+ } /* default case */
+ } /* for loop */
}
@@ -691,3 +764,104 @@
trace_flush (context);
}
+
+
+/* Storage for the compiled regular expression of
+ --warn-macro-sequence. */
+static m4_pattern_buffer macro_sequence;
+
+/* True if --warn-macro-sequence is in effect. */
+static bool macro_sequence_inuse;
+
+/* Set the regular expression that will be checked during define and
+ pushdef. Warn on failure. If REGEXP is NULL, use the default
+ sequence; if REGEXP is empty, disable checking; otherwise, compile
+ REGEXP written in RESYNTAX. Report errors on behalf of CALLER. */
+void
+m4_set_macro_sequence (m4 *context, const char *regexp, int resyntax,
+ const char *caller)
+{
+ if (! regexp)
+ {
+ /* The default sequence, in emacs flavor, warns for multi-digit
+ parameters, and for any use of extended arguments using
+ default ${} syntax. */
+ regexp = M4_DEFAULT_MACRO_SEQUENCE;
+ resyntax = 0;
+ caller = NULL;
+ }
+ else if (regexp[0] == '\0')
+ {
+ macro_sequence_inuse = false;
+ return;
+ }
+
+ if (m4_regexp_compile (context, caller, regexp, resyntax, false,
+ ¯o_sequence) == NULL)
+ macro_sequence_inuse = false;
+ else
+ macro_sequence_inuse = true;
+}
+
+/* Free storage used by macro_sequence. */
+void
+m4_free_macro_sequence (m4 *context)
+{
+ m4_regexp_free (¯o_sequence);
+ macro_sequence_inuse = false;
+}
+
+/* Define a text macro NAME to have VALUE. If PUSH, use pushdef
+ instead of define semantics. */
+m4_symbol_value *
+m4_macro_define (m4 *context, const char *name, const char *value,
+ bool push)
+{
+ m4_symbol_value *symbol_value = m4_symbol_value_create ();
+ char *defn = xstrdup (value ? value : "");
+
+ m4_check_macro_sequence (context, name, defn, NULL);
+ m4_set_symbol_value_text (symbol_value, defn);
+ VALUE_MAX_ARGS (symbol_value) = -1;
+ if (push)
+ m4_symbol_pushdef (M4SYMTAB, name, symbol_value);
+ else
+ m4_symbol_define (M4SYMTAB, name, symbol_value);
+ return symbol_value;
+}
+
+/* Check the macro NAME just defined to VALUE for any sequences
+ matched in macro_sequence. Report warnings on behalf of CALLER,
+ which may be NULL. */
+void
+m4_check_macro_sequence (m4 *context, const char *name, const char *value,
+ const char *caller)
+{
+ /* Implement --warn-macro-sequence. */
+ if (macro_sequence_inuse && value && value[0])
+ {
+ regoff_t offset = 0;
+ size_t len = strlen (value);
+
+ while ((offset = re_search (¯o_sequence.pat, value, len, offset,
+ len - offset, ¯o_sequence.regs)) >= 0)
+ {
+ /* Skip empty matches. */
+ if (macro_sequence.regs.start[0] == macro_sequence.regs.end[0])
+ offset++;
+ else
+ {
+ offset = macro_sequence.regs.end[0];
+ m4_warn (context, 0,
+ _("%s%s`%s' contains sequence `%.*s'"),
+ caller ? caller : "", caller ? ": " : "",
+ name, offset - macro_sequence.regs.start[0],
+ value + macro_sequence.regs.start[0]);
+ }
+ }
+ if (offset == -2)
+ m4_error (context, 0, 0,
+ _("%s: error checking for macro sequence in `%s'"),
+ caller, name);
+ }
+}
Index: m4/module.c
===================================================================
RCS file: /sources/m4/m4/m4/module.c,v
retrieving revision 1.48
diff -u -r1.48 module.c
--- m4/module.c 27 Oct 2006 17:03:51 -0000 1.48
+++ m4/module.c 1 Mar 2007 04:13:58 -0000
@@ -1,6 +1,6 @@
/* GNU m4 -- A simple macro processor
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1998, 1999, 2002, 2003,
- 2004, 2005, 2006 Free Software Foundation, Inc.
+ 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
@@ -192,12 +192,9 @@
{
for (; mp->name != NULL; mp++)
{
- m4_symbol_value *value = m4_symbol_value_create ();
-
- m4_set_symbol_value_text (value, xstrdup (mp->value));
+ m4_symbol_value *value = m4_macro_define (context, mp->name,
+ mp->value, true);
VALUE_HANDLE (value) = handle;
-
- m4_symbol_pushdef (M4SYMTAB, mp->name, value);
}
m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
Index: m4/resyntax.c
===================================================================
RCS file: /sources/m4/m4/m4/resyntax.c,v
retrieving revision 1.4
diff -u -r1.4 resyntax.c
--- m4/resyntax.c 1 Feb 2007 05:43:09 -0000 1.4
+++ m4/resyntax.c 1 Mar 2007 04:13:58 -0000
@@ -124,3 +124,51 @@
return resyntax->spec;
}
+
+/* Compile a REGEXP using the RESYNTAX bits, into the buffer BUF.
+ Report errors on behalf of CALLER. If NO_SUB, optimize the
+ compilation to skip filling out the regs member of the buffer.
+ Return BUF on success, NULL on error. BUF should start life
+ zero-initialized, or be previously initialized by this method. */
+m4_pattern_buffer *
+m4_regexp_compile (m4 *context, const char *caller,
+ const char *regexp, int resyntax, bool no_sub,
+ m4_pattern_buffer *buf)
+{
+ /* FIXME - this method is not reentrant, since re_compile_pattern
+ mallocs memory and depends on the global variable
+ re_syntax_options for its syntax (but at least the compiled regex
+ remembers its syntax even if the global variable changes later).
+ To be reentrant, we would need a mutex in this method. */
+
+ const char *msg; /* error message from re_compile_pattern */
+
+ re_set_syntax (resyntax);
+ regfree (&buf->pat);
+ buf->pat.no_sub = no_sub;
+ msg = re_compile_pattern (regexp, strlen (regexp), &buf->pat);
+
+ if (msg != NULL)
+ {
+ assert (caller);
+ m4_error (context, 0, 0, _("%s: bad regular expression `%s': %s"),
+ caller, regexp, msg);
+ return NULL;
+ }
+
+ re_set_registers (&buf->pat, &buf->regs, buf->regs.num_regs,
+ buf->regs.start, buf->regs.end);
+ return buf;
+}
+
+/* Reclaim any dynamic storage used by BUF, as obtained by
+ m4_regexp_compile. */
+void
+m4_regexp_free (m4_pattern_buffer *buf)
+{
+ regfree (&buf->pat);
+ free (buf->regs.start);
+ free (buf->regs.end);
+ /* Explicitly reset the memory, in case buf gets reused. */
+ memset (buf, 0, sizeof *buf);
+}
Index: modules/gnu.c
===================================================================
RCS file: /sources/m4/m4/modules/gnu.c,v
retrieving revision 1.71
diff -u -r1.71 gnu.c
--- modules/gnu.c 15 Jan 2007 14:04:27 -0000 1.71
+++ modules/gnu.c 1 Mar 2007 04:13:58 -0000
@@ -106,15 +106,6 @@
-/* The regs_allocated field in an re_pattern_buffer refers to the
- state of the re_registers struct used in successive matches with
- the same compiled pattern: */
-
-typedef struct {
- struct re_pattern_buffer pat; /* compiled regular expression */
- struct re_registers regs; /* match registers */
-} m4_pattern_buffer;
-
static m4_pattern_buffer gnu_buf; /* compiled regular expression */
/* Compile a REGEXP using the RESYNTAX bits, and return the buffer.
@@ -122,36 +113,13 @@
compilation to skip filling out the regs member of the buffer. */
static m4_pattern_buffer *
-m4_regexp_compile (m4 *context, const char *caller,
- const char *regexp, int resyntax, bool no_sub)
+regexp_compile (m4 *context, const char *caller,
+ const char *regexp, int resyntax, bool no_sub)
{
- /* gnu_buf is guaranteed to start life 0-initialized, which works in the
- below algorithm.
-
- FIXME - this method is not reentrant, since re_compile_pattern
- mallocs memory, depends on the global variable re_syntax_options
- for its syntax (but at least the compiled regex remembers its
- syntax even if the global variable changes later), and since we
- use a static variable. To be reentrant, we would need a mutex in
- this method, and move the storage for gnu_buf into context. */
-
- const char *msg; /* error message from re_compile_pattern */
-
- re_set_syntax (resyntax);
- regfree (&gnu_buf.pat);
- gnu_buf.pat.no_sub = no_sub;
- msg = re_compile_pattern (regexp, strlen (regexp), &gnu_buf.pat);
-
- if (msg != NULL)
- {
- m4_error (context, 0, 0, _("%s: bad regular expression `%s': %s"),
- caller, regexp, msg);
- return NULL;
- }
-
- re_set_registers (&gnu_buf.pat, &gnu_buf.regs, gnu_buf.regs.num_regs,
- gnu_buf.regs.start, gnu_buf.regs.end);
- return &gnu_buf;
+ /* FIXME - this method is not reentrant, since we reference a static
+ variable. */
+ return m4_regexp_compile (context, caller, regexp, resyntax, no_sub,
+ &gnu_buf);
}
@@ -218,7 +186,7 @@
/* For each match against compiled REGEXP (held in BUF -- as returned
- by m4_regexp_compile) in VICTIM, substitute REPLACE. Non-matching
+ by regexp_compile) in VICTIM, substitute REPLACE. Non-matching
characters are copied verbatim, and the result copied to the
obstack. Errors are reported on behalf of CALLER. Return true if
a substitution was made. If IGNORE_DUPLICATES is set, don't worry
@@ -288,12 +256,7 @@
/* Reclaim memory used by this module. */
M4FINISH_HANDLER(gnu)
{
- regfree (&gnu_buf.pat);
- free (gnu_buf.regs.start);
- free (gnu_buf.regs.end);
- /* If this module was preloaded, then we need to explicitly reset
- the memory in case it gets reloaded. */
- memset (&gnu_buf, 0, sizeof gnu_buf);
+ m4_regexp_free (&gnu_buf);
}
@@ -663,7 +626,7 @@
return;
}
- buf = m4_regexp_compile (context, me, M4ARG (2), resyntax, false);
+ buf = regexp_compile (context, me, M4ARG (2), resyntax, false);
if (!buf)
return;
@@ -720,7 +683,7 @@
/* regexp(VICTIM, REGEXP) */
replace = NULL;
- buf = m4_regexp_compile (context, me, M4ARG (2), resyntax, replace == NULL);
+ buf = regexp_compile (context, me, M4ARG (2), resyntax, replace == NULL);
if (!buf)
return;
@@ -778,7 +741,7 @@
return;
}
- buf = m4_regexp_compile (context, me, regexp, resyntax, false);
+ buf = regexp_compile (context, me, regexp, resyntax, false);
if (!buf)
return;
Index: modules/m4.c
===================================================================
RCS file: /sources/m4/m4/modules/m4.c,v
retrieving revision 1.104
diff -u -r1.104 m4.c
--- modules/m4.c 28 Feb 2007 21:31:12 -0000 1.104
+++ modules/m4.c 1 Mar 2007 04:13:58 -0000
@@ -179,7 +179,11 @@
if (argc == 2)
m4_set_symbol_value_text (value, xstrdup (""));
else
- m4_symbol_value_copy (value, argv[2]);
+ {
+ m4_symbol_value_copy (value, argv[2]);
+ if (m4_is_symbol_value_text (value))
+ m4_check_macro_sequence (context, M4ARG (1), M4ARG (2), M4ARG (0));
+ }
m4_symbol_define (M4SYMTAB, M4ARG (1), value);
}
@@ -210,7 +214,11 @@
if (argc == 2)
m4_set_symbol_value_text (value, xstrdup (""));
else
- m4_symbol_value_copy (value, argv[2]);
+ {
+ m4_symbol_value_copy (value, argv[2]);
+ if (m4_is_symbol_value_text (value))
+ m4_check_macro_sequence (context, M4ARG (1), M4ARG (2), M4ARG (0));
+ }
m4_symbol_pushdef (M4SYMTAB, M4ARG (1), value);
}
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.62
diff -u -r1.62 freeze.c
--- src/freeze.c 28 Feb 2007 21:31:12 -0000 1.62
+++ src/freeze.c 1 Mar 2007 04:13:58 -0000
@@ -244,7 +244,7 @@
produce_mem_dump (file, M4SYNTAX->lquote.string,
M4SYNTAX->lquote.length);
produce_mem_dump (file, M4SYNTAX->rquote.string,
- M4SYNTAX->rquote.length);
+ M4SYNTAX->rquote.length);
fputc ('\n', file);
}
@@ -492,7 +492,7 @@
else
m4__module_open (context, "gnu", NULL);
/* Disable { and } categories, since ${11} was not supported in
- 1.4.x. */
+ 1.4.x. */
m4_set_syntax (M4SYNTAX, 'O', '+', "{}");
break;
default:
@@ -758,17 +758,10 @@
/* Enter a macro having an expansion text as a definition. */
{
- m4_symbol_value *token = xzalloc (sizeof *token);
- lt_dlhandle handle = 0;
-
+ m4_symbol_value *token = m4_macro_define (context, string[0],
+ string[1], true);
if (number[2] > 0)
- handle = m4__module_find (string[2]);
-
- m4_set_symbol_value_text (token, xstrdup (string[1]));
- VALUE_HANDLE (token) = handle;
- VALUE_MAX_ARGS (token) = -1;
-
- m4_symbol_pushdef (M4SYMTAB, string[0], token);
+ VALUE_HANDLE (token) = m4__module_find (string[2]);
}
break;
Index: src/main.c
===================================================================
RCS file: /sources/m4/m4/src/main.c,v
retrieving revision 1.109
diff -u -r1.109 main.c
--- src/main.c 28 Feb 2007 21:31:13 -0000 1.109
+++ src/main.c 1 Mar 2007 04:13:58 -0000
@@ -84,7 +84,7 @@
--help display this help and exit\n\
--version output version information and exit\n\
"), stdout);
- fputs (_("\
+ printf (_("\
-b, --batch buffer output, process interrupts\n\
-c, --discard-comments do not copy comments to the output\n\
-E, --fatal-warnings once: warnings become errors, twice: stop\n\
@@ -94,8 +94,11 @@
-Q, --quiet, --silent suppress some warnings for builtins\n\
-r, --regexp-syntax[=SPEC] set default regexp syntax to SPEC [GNU_M4]\n\
--safer disable potentially unsafe builtins\n\
+ --warn-macro-sequence[=REGEXP]\n\
+ warn if macro definition matches REGEXP,\n\
+ default %s\n\
-W, --warnings enable all warnings\n\
-"), stdout);
+"), M4_DEFAULT_MACRO_SEQUENCE);
puts ("");
fputs (_("\
SPEC is any one of:\n\
@@ -207,6 +210,7 @@
SYNCOUTPUT_OPTION, /* not quite -s, because of opt arg */
TRACEOFF_OPTION, /* no short opt */
UNLOAD_MODULE_OPTION, /* no short opt */
+ WARN_MACRO_SEQUENCE_OPTION, /* no short opt */
WORD_REGEXP_OPTION, /* deprecated, used to be -W */
HELP_OPTION, /* no short opt */
@@ -256,6 +260,7 @@
{"syncoutput", optional_argument, NULL, SYNCOUTPUT_OPTION},
{"traceoff", required_argument, NULL, TRACEOFF_OPTION},
{"unload-module", required_argument, NULL, UNLOAD_MODULE_OPTION},
+ {"warn-macro-sequence", optional_argument, NULL, WARN_MACRO_SEQUENCE_OPTION},
{"word-regexp", required_argument, NULL, WORD_REGEXP_OPTION},
{"help", no_argument, NULL, HELP_OPTION},
@@ -423,6 +428,7 @@
case SYNCOUTPUT_OPTION:
case TRACEOFF_OPTION:
case UNLOAD_MODULE_OPTION:
+ case WARN_MACRO_SEQUENCE_OPTION:
/* Arguments that cannot be handled until later are accumulated. */
defn = xmalloc (sizeof *defn);
@@ -659,21 +665,14 @@
case 'D':
case 'p':
{
- m4_symbol_value *value = m4_symbol_value_create ();
-
/* defn->value is read-only, so we need a copy. */
char *macro_name = xstrdup (arg);
char *macro_value = strchr (macro_name, '=');
if (macro_value != NULL)
*macro_value++ = '\0';
- m4_set_symbol_value_text (value, xstrdup (macro_value
- ? macro_value : ""));
-
- if (defn->code == 'D')
- m4_symbol_define (M4SYMTAB, macro_name, value);
- else
- m4_symbol_pushdef (M4SYMTAB, macro_name, value);
+ m4_macro_define (context, macro_name, macro_value,
+ defn->code == 'p');
free (macro_name);
}
break;
@@ -726,6 +725,12 @@
m4_module_unload (context, arg, NULL);
break;
+ case WARN_MACRO_SEQUENCE_OPTION:
+ m4_set_macro_sequence (context, arg,
+ m4_get_regexp_syntax_opt (context),
+ "--warn-macro-sequence");
+ break;
+
default:
assert (!"INTERNAL ERROR: bad code in deferred arguments");
abort ();
@@ -775,6 +780,7 @@
if (read_stdin && close_stream (stdin) == EOF)
m4_error (context, 0, errno, _("error closing stdin"));
+ m4_free_macro_sequence (context);
exit_status = m4_get_exit_status (context);
m4_delete (context);
Index: tests/macros.at
===================================================================
RCS file: /sources/m4/m4/tests/macros.at,v
retrieving revision 1.12
diff -u -r1.12 macros.at
--- tests/macros.at 14 Nov 2006 05:58:01 -0000 1.12
+++ tests/macros.at 1 Mar 2007 04:13:58 -0000
@@ -1,5 +1,5 @@
# Hand crafted tests for GNU M4. -*- Autotest -*-
-# Copyright (C) 2001, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2001, 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
@@ -191,6 +191,42 @@
+## ------------------ ##
+## Extended arguments ##
+## ------------------ ##
+
+AT_SETUP([Extended arguments])
+
+dnl check that changesyntax can enable/disable extended arguments
+AT_DATA([in], [[define(`foo', `${1}')dnl
+foo(`a')
+changesyntax(`{=', `}=')dnl
+foo(`a')
+changesyntax()dnl
+foo(`a')
+]])
+AT_CHECK_M4([in], [0],
+[[a
+${1}
+a
+]])
+
+dnl check that all pseudo args are supported
+AT_DATA([in], [[define(`foo', ``${0}'[EMAIL PROTECTED]')dnl
+foo
+foo(`a')
+foo(`a', `b')
+]])
+AT_CHECK_M4([in], [0],
+[[foo-0---
+foo-1-a-a-
+foo-2-a,b-a,b-
+]])
+
+AT_CLEANUP
+
+
+
## ---------------- ##
## pushdef/popdef. ##
## ---------------- ##
Index: tests/options.at
===================================================================
RCS file: /sources/m4/m4/tests/options.at,v
retrieving revision 1.25
diff -u -r1.25 options.at
--- tests/options.at 5 Feb 2007 17:31:10 -0000 1.25
+++ tests/options.at 1 Mar 2007 04:13:58 -0000
@@ -782,3 +782,61 @@
AT_CHECK_M4([--traceoff=unknown], [0])
AT_CLEANUP
+
+
+## ------------------- ##
+## warn-macro-sequence ##
+## ------------------- ##
+
+AT_SETUP([--warn-macro-sequence])
+
+AT_DATA([[in]], [[define(`foo', `$01 ${1} ab')dnl
+pushdef(`foo', `$`'{1} $01')dnl
+foo
+]])
+
+dnl no sequence warnings by default
+AT_CHECK_M4([in], [0], [[${1} foo1
+]])
+
+dnl default regex
+AT_CHECK_M4([--warn-macro-sequence in], [0], [[${1} foo1
+]], [[m4:in:1: Warning: define: `foo' contains sequence `$01'
+m4:in:1: Warning: define: `foo' contains sequence `${1}'
+m4:in:2: Warning: pushdef: `foo' contains sequence `$01'
+]])
+
+dnl empty regex disables prior usage
+AT_CHECK_M4([--warn-macro-sequence --warn-macro-sequence= in], [0],
+[[${1} foo1
+]])
+
+dnl check interleaving between files, and alternate regex
+AT_CHECK_M4([--warn-macro-sequence=01 in --warn-macro-sequence='[[ba]*]' in],
+[0], [[${1} foo1
+${1} foo1
+]], [[m4:in:1: Warning: define: `foo' contains sequence `01'
+m4:in:2: Warning: pushdef: `foo' contains sequence `01'
+m4:in:1: Warning: define: `foo' contains sequence `ab'
+]])
+
+dnl check interaction with resyntax
+AT_CHECK_M4([--regexp-syntax=EXTENDED --warn-macro-sequence='(a|b)+' in], [0],
+[[${1} foo1
+]], [[m4:in:1: Warning: define: `foo' contains sequence `ab'
+]])
+
+dnl check interaction with resyntax
+AT_CHECK_M4([--warn-macro-sequence='(a|b)+' --regexp-syntax=EXTENDED in], [0],
+[[${1} foo1
+]])
+
+dnl default regex sequence must work with non-default resyntax
+AT_CHECK_M4([--regexp-syntax=EXTENDED --warn-macro-sequence in], [0],
+[[${1} foo1
+]], [[m4:in:1: Warning: define: `foo' contains sequence `$01'
+m4:in:1: Warning: define: `foo' contains sequence `${1}'
+m4:in:2: Warning: pushdef: `foo' contains sequence `$01'
+]])
+
+AT_CLEANUP
Index: tests/others.at
===================================================================
RCS file: /sources/m4/m4/tests/others.at,v
retrieving revision 1.31
diff -u -r1.31 others.at
--- tests/others.at 5 Feb 2007 17:31:10 -0000 1.31
+++ tests/others.at 1 Mar 2007 04:13:58 -0000
@@ -683,7 +683,8 @@
concat()
concat(`hej', `med', `dig')
concat(`hej', `med', `dig', `en gang igen')
-concat(an, awful, lot, of, argument, at, least, more, that, ten, silly,
arguments)
+concat(an, awful, lot, of, arguments,
+ at, least, more, than, ten, silly, arguments)
]])
AT_DATA([[expout]],
@@ -696,7 +697,7 @@
hej med dig
hej med dig en gang igen
-an awful lot of argument at least more that ten silly arguments
+an awful lot of arguments at least more than ten silly arguments
]])
AT_DATA([[experr]],
@@ -711,15 +712,15 @@
m4trace: -1- concat(`med', `dig', `en gang igen') -> `ifelse(1, 3, `med',
`med` 'concat(shift(`med',`dig',`en gang igen'))')'
m4trace: -1- concat(`dig', `en gang igen') -> `ifelse(1, 2, `dig',
`dig` 'concat(shift(`dig',`en gang igen'))')'
m4trace: -1- concat(`en gang igen') -> `ifelse(1, 1, `en gang igen', `en gang
igen` 'concat(shift(`en gang igen'))')'
-m4trace: -1- concat(`an', `awful', `lot', `of', `argument', `at', `least',
`more', `that', `ten', `silly', `arguments') -> `ifelse(1, 12, `an',
`an` 'concat(shift
(`an',`awful',`lot',`of',`argument',`at',`least',`more',`that',`ten',`silly',`ar
guments'))')'
-m4trace: -1- concat(`awful', `lot', `of', `argument', `at', `least', `more',
`that', `ten', `silly', `arguments') -> `ifelse(1, 11, `awful', `awful` 'concat
(shift
(`awful',`lot',`of',`argument',`at',`least',`more',`that',`ten',`silly',`argumen
ts'))')'
-m4trace: -1- concat(`lot', `of', `argument', `at', `least', `more', `that',
`ten', `silly', `arguments') -> `ifelse(1, 10, `lot', `lot` 'concat(shift
(`lot',`of',`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')'
-m4trace: -1- concat(`of', `argument', `at', `least', `more', `that', `ten',
`silly', `arguments') -> `ifelse(1, 9, `of', `of` 'concat(shift
(`of',`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')'
-m4trace: -1- concat(`argument', `at', `least', `more', `that', `ten', `silly',
`arguments') -> `ifelse(1, 8, `argument', `argument` 'concat(shift
(`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')'
-m4trace: -1- concat(`at', `least', `more', `that', `ten', `silly',
`arguments') -> `ifelse(1, 7, `at', `at` 'concat(shift
(`at',`least',`more',`that',`ten',`silly',`arguments'))')'
-m4trace: -1- concat(`least', `more', `that', `ten', `silly', `arguments') ->
`ifelse(1, 6, `least', `least` 'concat(shift
(`least',`more',`that',`ten',`silly',`arguments'))')'
-m4trace: -1- concat(`more', `that', `ten', `silly', `arguments') -> `ifelse(1,
5, `more', `more` 'concat(shift(`more',`that',`ten',`silly',`arguments'))')'
-m4trace: -1- concat(`that', `ten', `silly', `arguments') -> `ifelse(1, 4,
`that', `that` 'concat(shift(`that',`ten',`silly',`arguments'))')'
+m4trace: -1- concat(`an', `awful', `lot', `of', `arguments', `at', `least',
`more', `than', `ten', `silly', `arguments') -> `ifelse(1, 12, `an',
`an` 'concat(shift
(`an',`awful',`lot',`of',`arguments',`at',`least',`more',`than',`ten',`silly',`a
rguments'))')'
+m4trace: -1- concat(`awful', `lot', `of', `arguments', `at', `least', `more',
`than', `ten', `silly', `arguments') -> `ifelse(1, 11, `awful', `awful` 'concat
(shift
(`awful',`lot',`of',`arguments',`at',`least',`more',`than',`ten',`silly',`argume
nts'))')'
+m4trace: -1- concat(`lot', `of', `arguments', `at', `least', `more', `than',
`ten', `silly', `arguments') -> `ifelse(1, 10, `lot', `lot` 'concat(shift
(`lot',`of',`arguments',`at',`least',`more',`than',`ten',`silly',`arguments'))')
'
+m4trace: -1- concat(`of', `arguments', `at', `least', `more', `than', `ten',
`silly', `arguments') -> `ifelse(1, 9, `of', `of` 'concat(shift
(`of',`arguments',`at',`least',`more',`than',`ten',`silly',`arguments'))')'
+m4trace: -1- concat(`arguments', `at', `least', `more', `than', `ten',
`silly', `arguments') -> `ifelse(1, 8, `arguments', `arguments` 'concat(shift
(`arguments',`at',`least',`more',`than',`ten',`silly',`arguments'))')'
+m4trace: -1- concat(`at', `least', `more', `than', `ten', `silly',
`arguments') -> `ifelse(1, 7, `at', `at` 'concat(shift
(`at',`least',`more',`than',`ten',`silly',`arguments'))')'
+m4trace: -1- concat(`least', `more', `than', `ten', `silly', `arguments') ->
`ifelse(1, 6, `least', `least` 'concat(shift
(`least',`more',`than',`ten',`silly',`arguments'))')'
+m4trace: -1- concat(`more', `than', `ten', `silly', `arguments') -> `ifelse(1,
5, `more', `more` 'concat(shift(`more',`than',`ten',`silly',`arguments'))')'
+m4trace: -1- concat(`than', `ten', `silly', `arguments') -> `ifelse(1, 4,
`than', `than` 'concat(shift(`than',`ten',`silly',`arguments'))')'
m4trace: -1- concat(`ten', `silly', `arguments') -> `ifelse(1, 3, `ten',
`ten` 'concat(shift(`ten',`silly',`arguments'))')'
m4trace: -1- concat(`silly', `arguments') -> `ifelse(1, 2, `silly',
`silly` 'concat(shift(`silly',`arguments'))')'
m4trace: -1- concat(`arguments') -> `ifelse(1, 1, `arguments',
`arguments` 'concat(shift(`arguments'))')'
_______________________________________________
M4-patches mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/m4-patches