[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: |
Tue, 23 Jan 2007 07:28:13 -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/18/2007 7:50 AM:
>
> 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.
>
As a first step, we need syntax categories for { and }, similar to $.
I'm not sure whether $, {, and } should be category masks (for example,
allowing $ to be in both the 'A' and '$' categories at once, to both
participate in macro names during parsing as well trigger parameter
substitution during expansion), but for now I kept the status quo and
the new categories are mutually exclusive with other categories.
Followup patches that still need to be written include: allowing
- --changesyntax from the 1.9a command line, adding --warn-syntax to 1.4.9
and 1.9a, actually coding up ${11} parsing, proposing a patch to
autoconf to call changesyntax(O+{}) alongside changequote([,]).
2007-01-23 Eric Blake <address@hidden>
* m4/m4module.h (M4_SYNTAX_ASSIGN): Delete this unused
extension to make enough room.
(M4_SYNTAX_IGNORE): Change value to zero, since the (commented)
code in input.c special cases this category.
(M4_SYNTAX_LBRACE, M4_SYNTAX_RBRACE): New values in preparation
for define(eleventh,${11}) extension.
* m4/syntax.c: Update comments accordingly.
(m4_syntax_create, m4_syntax_code): Handle { and }.
* m4/input.c (m4__next_token): Likewise.
* src/freeze.c (produce_frozen_state): Support new categories.
(reload_frozen_state): When loading version 1, disable syntax
features not present in 1.4.x.
* tests/freeze.at: Sort and rename existing tests.
(loading format 1): Ensure we don't break v1 frozen files that
used raw ${.
(loading format 2, reloading changecom, reloading changesyntax):
New tests.
* doc/m4.texinfo (Changesyntax, Frozen file format 1): Document
the new syntax categories.
(Arguments): Update the FIXME comment.
(M4wrap): Merge examples from branch, before worrying about fixing
m4wrap to obey POSIX.
(Using frozen files): Start merging from branch.
* NEWS: Update.
- --
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
iD8DBQFFtht884KuGfSFAYARAmy7AKDJ4ET0q8mJ8GHH9BJI1+5I0oimNACgtRZF
cC750gJ/9NwMzdZYsIE/+0w=
=jNzN
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.37
diff -u -p -r1.37 NEWS
--- NEWS 21 Jan 2007 04:09:06 -0000 1.37
+++ NEWS 23 Jan 2007 14:26:22 -0000
@@ -155,7 +155,9 @@ promoted to 2.0.
*** The `changesyntax' builtin has been improved, to make it easier to add
and remove characters from a syntax class without having to specify the
- entire set of characters in that class.
+ entire set of characters in that class. It also supports two new
+ syntax categories, `{' and `}', for extended argument handling in macro
+ definitions.
*** New `m' flag to `-d'/`--debug' command-line option or `debugmode'
builtin traces actions related to module loading and unloading, and
@@ -192,7 +194,7 @@ promoted to 2.0.
** Other changes
*** The syntax of frozen files format V2 has been improved to save
- additional state. This includes the 'R' directive for default regular
+ additional state. This includes the `R' directive for default regular
expression syntax. Also, a V2 file can now be represented completely
in ASCII, thanks to escape sequences. Unfortunately, files frozen by
M4 1.4q that contain \ in macros cannot be read by 1.9b, but since 1.4q
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.93
diff -u -p -r1.93 m4.texinfo
--- doc/m4.texinfo 15 Jan 2007 14:04:26 -0000 1.93
+++ doc/m4.texinfo 23 Jan 2007 14:26:24 -0000
@@ -1706,12 +1706,13 @@ 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.
address@hidden FIXME - See Austin group XCU ERN 111. This is controversial,
address@hidden and POSIX is moving to reserve ${ for implementation use. We
address@hidden should phase out $10 and replace it with ${10}, and consider
address@hidden other extensions like ${1-default}. There are existing m4
address@hidden scripts that depend on $10 being the first parameter
address@hidden concatenated with 0, not the tenth argument.
address@hidden FIXME - See Austin group XCU ERN 111. POSIX says that $11 must
address@hidden be the first argument concatenated with 1, and instead reserves
address@hidden ${11} for implementation use. Once this is implemented, the
address@hidden documentation needs to reflect how these extended arguments
address@hidden are handled, as well as backwards compatibility issues with
address@hidden 1.4.x. Also, consider adding further extensions such as
address@hidden ${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.
@@ -4154,6 +4155,15 @@ the single character @samp{,}.
Characters that can introduce an argument reference in the body of a
macro. The default is the single character @samp{$}.
address@hidden Left brace
+Characters that introduce an extended argument reference in the body of
+a macro immediately after a character in the Dollar category. The
+default is the single character @address@hidden
+
address@hidden Right brace
+Characters that conclude an extended argument reference in the body of a
+macro. The default is the single character @address@hidden
+
@item Left quote
The set of characters that can start a single-character quoted string.
The default is the single character @samp{`}. For multiple-character
@@ -4523,11 +4533,54 @@ This is the first and last normal input
The saved input is only reread when the end of normal input is seen, and
not if @code{m4exit} is used to exit @code{m4}.
address@hidden FIXME: this contradicts POSIX, which requires that "If the
address@hidden m4wrap macro is used multiple times, the arguments specified
address@hidden shall be processed in the order in which the m4wrap macros were
address@hidden processed."
It is safe to call @code{m4wrap} from saved text, but then the order in
which the saved text is reread is undefined. If @code{m4wrap} is not used
recursively, the saved pieces of text are reread in the opposite order
in which they were saved (LIFO---last in, first out).
+Here is an example of implementing a factorial function using
address@hidden:
+
address@hidden
+define(`f', `ifelse(`$1', `0', `Answer: 0!=1
+', eval(`$1>1'), `0', `Answer: $2$1=eval(`$2$1')
+', `m4wrap(`f(decr(`$1'), `$2$1*')')')')
address@hidden
+f(`10')
address@hidden
+^D
address@hidden: 10*9*8*7*6*5*4*3*2*1=3628800
address@hidden example
+
+Invocations of @code{m4wrap} at the same recursion level are
+concatenated and rescanned as usual:
+
address@hidden
+define(`aa', `AA
+')
address@hidden
+m4wrap(`a')m4wrap(`a')
address@hidden
+^D
address@hidden
address@hidden example
+
address@hidden
+however, the transition between recursion levels behaves like an end of
+file condition between two input files.
+
address@hidden status: 1
address@hidden
+m4wrap(`m4wrap(`)')len(abc')
address@hidden
+^D
address@hidden:stdin:1: end of file in argument list
address@hidden example
+
@node File Inclusion
@chapter File inclusion
@@ -6739,7 +6792,11 @@ Some bigger @code{m4} applications may b
containing hundreds of definitions and other costly initializations.
Usually, the common base is kept in one or more declarative files,
which files are listed on each @code{m4} invocation prior to the
-user's input file, or else, @code{include}'d from this input file.
+user's input file, or else each input file uses @code{include}.
+
+Reading the common base of a big application, over and over again, may
+be time consuming. @acronym{GNU} @code{m4} offers some machinery to
+speed up the start of an application using lengthy common bases.
@menu
* Using frozen files:: Using frozen files
@@ -6756,23 +6813,22 @@ user's input file, or else, @code{includ
@cindex dumping into frozen file
@cindex reloading a frozen file
@cindex @acronym{GNU} extensions
-Reading the common base of a big application, over and over again, may
-be time consuming. GNU @code{m4} offers some machinery to speed up
-the start of an application using lengthy common bases. Presume the
-user repeatedly uses:
+Suppose a user has a library of @code{m4} initializations in
address@hidden, which is then used with multiple input files:
@comment ignore
@example
-m4 base.m4 input.m4
+$ @kbd{m4 base.m4 input1.m4}
+$ @kbd{m4 base.m4 input2.m4}
+$ @kbd{m4 base.m4 input3.m4}
@end example
address@hidden
-with a varying contents of @file{input.m4}, but a rather fixed contents
-for @file{base.m4}. Then, the user might rather execute:
+Rather than spending time parsing the fixed contents of @file{base.m4}
+every time, the user might rather execute:
@comment ignore
@example
-m4 -F base.m4f base.m4
+$ @kbd{m4 -F base.m4f base.m4}
@end example
@noindent
@@ -6780,20 +6836,22 @@ once, and further execute, as often as n
@comment ignore
@example
-m4 -R base.m4f input.m4
+$ @kbd{m4 -R base.m4f input1.m4}
+$ @kbd{m4 -R base.m4f input2.m4}
+$ @kbd{m4 -R base.m4f input3.m4}
@end example
@noindent
with the varying input. The first call, containing the @code{-F}
-option, only reads and executes file @file{base.m4}, so defining
-various application macros and computing other initializations. Only
-once the input file @file{base.m4} has been completely processed, GNU
address@hidden produces on @file{base.m4f} a @dfn{frozen} file, that is, a
+option, only reads and executes file @file{base.m4}, defining
+various application macros and computing other initializations.
+Once the input file @file{base.m4} has been completely processed, @acronym{GNU}
address@hidden produces in @file{base.m4f} a @dfn{frozen} file, that is, a
file which contains a kind of snapshot of the @code{m4} internal state.
Later calls, containing the @code{-R} option, are able to reload
-the internal state of @code{m4}'s memory, from @file{base.m4f},
address@hidden to reading any other input files. By this mean,
+the internal state of @code{m4}, from @file{base.m4f},
address@hidden to reading any other input files. This means
instead of starting with a virgin copy of @code{m4}, input will be
read after having effectively recovered the effect of a prior run.
In our example, the effect is the same as if file @file{base.m4} has
@@ -6807,7 +6865,7 @@ some care is taken, the command:
@comment ignore
@example
-m4 file1.m4 file2.m4 file3.m4 file4.m4
+$ @kbd{m4 file1.m4 file2.m4 file3.m4 file4.m4}
@end example
@noindent
@@ -6816,20 +6874,13 @@ output:
@comment ignore
@example
-m4 -F file1.m4f file1.m4
-m4 -R file1.m4f -F file2.m4f file2.m4
-m4 -R file2.m4f -F file3.m4f file3.m4
-m4 -R file3.m4f file4.m4
address@hidden example
-
-This could also be done in a simple way, if everything has been prepared
-before:
-
address@hidden ignore
address@hidden
-m4 -F file1.m4f file1.m4 file2.m4 file3.m4 file4.m4
+$ @kbd{m4 -F file1.m4f file1.m4}
+$ @kbd{m4 -R file1.m4f -F file2.m4f file2.m4}
+$ @kbd{m4 -R file2.m4f -F file3.m4f file3.m4}
+$ @kbd{m4 -R file3.m4f file4.m4}
@end example
address@hidden FIXME - merge the rest of this section.
Some care is necessary because not every effort has been made for
this to work in all cases. In particular, the trace attribute of
macros is not handled.
@@ -6855,6 +6906,13 @@ Wow - thanks for really reading the manu
this text is not removed before a release.
FIXME - split out the two formats into separate nodes.
+When loading format 1, the syntax categories @address@hidden and
@address@hidden are
+disabled (reverting braces to be treated like plain characters). This
+is because frozen files created with M4 1.4.x did not understand
address@hidden@address@hidden@}} extended argument notation, and a frozen macro
that
+contained this character sequence should not behave differently just
+because a newer version of M4 reloaded the file.
+
@node Frozen file format 2
@section Frozen file format 2
Index: m4/input.c
===================================================================
RCS file: /sources/m4/m4/m4/input.c,v
retrieving revision 1.59
diff -u -p -r1.59 input.c
--- m4/input.c 23 Dec 2006 00:02:20 -0000 1.59
+++ m4/input.c 23 Jan 2007 14:26:24 -0000
@@ -1,5 +1,5 @@
/* GNU m4 -- A simple macro processor
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006 Free Software
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006, 2007 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -1170,11 +1170,13 @@ m4__next_token (m4 *context, m4_symbol_v
obstack_1grow (&token_stack, ch);
if (m4_has_syntax (M4SYNTAX, ch,
- M4_SYNTAX_OTHER | M4_SYNTAX_NUM | M4_SYNTAX_DOLLAR))
+ (M4_SYNTAX_OTHER | M4_SYNTAX_NUM | M4_SYNTAX_DOLLAR
+ | M4_SYNTAX_LBRACE | M4_SYNTAX_RBRACE)))
{
consume_syntax (context, &token_stack,
(M4_SYNTAX_OTHER | M4_SYNTAX_NUM
- | M4_SYNTAX_DOLLAR));
+ | M4_SYNTAX_DOLLAR | M4_SYNTAX_LBRACE
+ | M4_SYNTAX_RBRACE));
type = M4_TOKEN_STRING;
}
else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_SPACE))
@@ -1192,7 +1194,8 @@ m4__next_token (m4 *context, m4_symbol_v
obstack_1grow (&token_stack, ch);
if (m4_has_syntax (M4SYNTAX, ch,
- M4_SYNTAX_OTHER | M4_SYNTAX_NUM | M4_SYNTAX_DOLLAR))
+ (M4_SYNTAX_OTHER | M4_SYNTAX_NUM | M4_SYNTAX_DOLLAR
+ | M4_SYNTAX_LBRACE | M4_SYNTAX_RBRACE)))
type = M4_TOKEN_STRING;
else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_SPACE))
type = M4_TOKEN_SPACE;
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.104
diff -u -p -r1.104 m4module.h
--- m4/m4module.h 13 Jan 2007 13:55:37 -0000 1.104
+++ m4/m4module.h 23 Jan 2007 14:26:24 -0000
@@ -355,30 +355,32 @@ extern bool m4_is_syntax_single_quotes
extern bool m4_is_syntax_single_comments (m4_syntax_table *);
extern bool m4_is_syntax_macro_escaped (m4_syntax_table *);
-/* These are values to be assigned to syntax table entries, although they
- are bit masks for fast categorisation in m4__next_token(), only one
- value per syntax table entry is allowed. */
+/* These are values to be assigned to syntax table entries. Although
+ they are bit masks for fast categorization in m4__next_token(),
+ only one value per syntax table entry is allowed. The enumeration
+ is currently sorted in order of parsing precedence. */
enum {
- M4_SYNTAX_OTHER = (1 << 0),
- M4_SYNTAX_IGNORE = (1 << 1),
- M4_SYNTAX_SPACE = (1 << 2),
- M4_SYNTAX_OPEN = (1 << 3),
- M4_SYNTAX_CLOSE = (1 << 4),
- M4_SYNTAX_COMMA = (1 << 5),
- M4_SYNTAX_DOLLAR = (1 << 6),
- M4_SYNTAX_ACTIVE = (1 << 7),
- M4_SYNTAX_ESCAPE = (1 << 8),
- M4_SYNTAX_ASSIGN = (1 << 9),
- M4_SYNTAX_ALPHA = (1 << 10),
- M4_SYNTAX_NUM = (1 << 11),
- M4_SYNTAX_LQUOTE = (1 << 12),
- M4_SYNTAX_BCOMM = (1 << 13),
+ M4_SYNTAX_IGNORE = 0,
+ M4_SYNTAX_ESCAPE = 1 << 0,
+ M4_SYNTAX_ALPHA = 1 << 1,
+ M4_SYNTAX_LQUOTE = 1 << 2,
+ M4_SYNTAX_BCOMM = 1 << 3,
+ M4_SYNTAX_OTHER = 1 << 4,
+ M4_SYNTAX_NUM = 1 << 5,
+ M4_SYNTAX_DOLLAR = 1 << 6,
+ M4_SYNTAX_LBRACE = 1 << 7,
+ M4_SYNTAX_RBRACE = 1 << 8,
+ M4_SYNTAX_SPACE = 1 << 9,
+ M4_SYNTAX_ACTIVE = 1 << 10,
+ M4_SYNTAX_OPEN = 1 << 11,
+ M4_SYNTAX_CLOSE = 1 << 12,
+ M4_SYNTAX_COMMA = 1 << 13,
/* These values are bit masks to OR with categories above, a syntax entry
may have any number of these in addition to a maximum of one of the
values above. */
- M4_SYNTAX_RQUOTE = (1 << 14),
- M4_SYNTAX_ECOMM = (1 << 15),
+ M4_SYNTAX_RQUOTE = 1 << 14,
+ M4_SYNTAX_ECOMM = 1 << 15
};
#define M4_SYNTAX_MASKS (M4_SYNTAX_RQUOTE | M4_SYNTAX_ECOMM)
Index: m4/syntax.c
===================================================================
RCS file: /sources/m4/m4/m4/syntax.c,v
retrieving revision 1.20
diff -u -p -r1.20 syntax.c
--- m4/syntax.c 12 Jan 2007 23:07:27 -0000 1.20
+++ m4/syntax.c 23 Jan 2007 14:26:24 -0000
@@ -36,9 +36,10 @@
M4_SYNTAX_CLOSE Close list of macro arguments
M4_SYNTAX_COMMA Separates macro arguments
M4_SYNTAX_DOLLAR Indicates macro argument in user macros
+ M4_SYNTAX_LBRACE Indicates start of extended macro argument
+ M4_SYNTAX_RBRACE Indicates end of extended macro argument
M4_SYNTAX_ACTIVE This character is a macro name by itself
M4_SYNTAX_ESCAPE Use this character to prefix all macro names
- M4_SYNTAX_ASSIGN *Used to assign defaults in parameter lists
M4_SYNTAX_ALPHA Alphabetic characters (can start macro names)
M4_SYNTAX_NUM Numeric characters (can form macro names)
@@ -75,22 +76,29 @@
The precedence as implemented by next_token () is:
M4_SYNTAX_IGNORE *Filtered out below next_token ()
- M4_SYNTAX_ESCAPE Reads macro name iff set, else next
- M4_SYNTAX_ALPHA Reads macro name
+ M4_SYNTAX_ESCAPE Reads macro name iff set, else next character
+ M4_SYNTAX_ALPHA Reads M4_SYNTAX_ALPHA and M4_SYNTAX_NUM as macro name
M4_SYNTAX_LQUOTE Reads all until balanced M4_SYNTAX_RQUOTE
M4_SYNTAX_BCOMM Reads all until M4_SYNTAX_ECOMM
M4_SYNTAX_OTHER } Reads all M4_SYNTAX_OTHER, M4_SYNTAX_NUM
- M4_SYNTAX_NUM } and M4_SYNTAX_DOLLAR
+ M4_SYNTAX_NUM } M4_SYNTAX_DOLLAR, M4_SYNTAX_LBRACE, M4_SYNTAX_RBRACE
M4_SYNTAX_DOLLAR }
+ M4_SYNTAX_LBRACE }
+ M4_SYNTAX_RBRACE }
- M4_SYNTAX_SPACE Reads all M4_SYNTAX_SPACE
- M4_SYNTAX_ACTIVE Returns a single char as a word
- the rest Returned as a single char
-
- The $ is not really a part of m4's input syntax in the sense that a
- string is parsed equally whether there is a $ or not. The character
- $ is used by convention in user macros. */
+ M4_SYNTAX_SPACE Reads all M4_SYNTAX_SPACE, depending on buffering
+ M4_SYNTAX_ACTIVE Returns a single char as a macro name
+
+ M4_SYNTAX_OPEN } Returned as a single char
+ M4_SYNTAX_CLOSE }
+ M4_SYNTAX_COMMA }
+
+ The $, {, and } are not really a part of m4's input syntax, because a
+ a string is parsed equally whether there is a $ or not. These characters
+ are instead used during user macro expansion.
+
+ M4_SYNTAX_RQUOTE and M4_SYNTAX_ECOMM do not start tokens. */
static bool check_is_single_quotes (m4_syntax_table *);
static bool check_is_single_comments (m4_syntax_table *);
@@ -120,16 +128,18 @@ m4_syntax_create (void)
case '$':
syntax->orig[ch] = M4_SYNTAX_DOLLAR;
break;
+ case '{':
+ syntax->orig[ch] = M4_SYNTAX_LBRACE;
+ break;
+ case '}':
+ syntax->orig[ch] = M4_SYNTAX_RBRACE;
+ break;
case '`':
syntax->orig[ch] = M4_SYNTAX_LQUOTE;
break;
case '#':
syntax->orig[ch] = M4_SYNTAX_BCOMM;
break;
- case '=':
- /* FIXME -revisit the assign syntax attribute. */
- /* syntax->orig[ch] = M4_SYNTAX_ASSIGN; */
- /* break; */
case '\0':
/* FIXME - revisit the ignore syntax attribute. */
/* syntax->orig[ch] = M4_SYNTAX_IGNORE; */
@@ -169,26 +179,26 @@ m4_syntax_code (char ch)
switch (ch)
{
- /* FIXME - revisit the ignore syntax attribute. */
- case 'I': case 'i': code = M4_SYNTAX_IGNORE; break;
- case 'O': case 'o': code = M4_SYNTAX_OTHER; break;
- case 'S': case 's': code = M4_SYNTAX_SPACE; break;
- case 'W': case 'w': code = M4_SYNTAX_ALPHA; break;
- case 'D': case 'd': code = M4_SYNTAX_NUM; break;
-
- case '(': code = M4_SYNTAX_OPEN; break;
- case ')': code = M4_SYNTAX_CLOSE; break;
- case ',': code = M4_SYNTAX_COMMA; break;
- /* FIXME - revisit the assign syntax attribute. */
- case '=': code = M4_SYNTAX_ASSIGN; break;
- case '@': code = M4_SYNTAX_ESCAPE; break;
- case '$': code = M4_SYNTAX_DOLLAR; break;
-
- case 'L': case 'l': code = M4_SYNTAX_LQUOTE; break;
- case 'R': case 'r': code = M4_SYNTAX_RQUOTE; break;
- case 'B': case 'b': code = M4_SYNTAX_BCOMM; break;
- case 'E': case 'e': code = M4_SYNTAX_ECOMM; break;
- case 'A': case 'a': code = M4_SYNTAX_ACTIVE; break;
+ /* Sorted according to the order of M4_SYNTAX_* in m4module.h. */
+ /* FIXME - revisit the ignore syntax attribute. */
+ case 'I': case 'i': code = M4_SYNTAX_IGNORE; break;
+ case '@': code = M4_SYNTAX_ESCAPE; break;
+ case 'W': case 'w': code = M4_SYNTAX_ALPHA; break;
+ case 'L': case 'l': code = M4_SYNTAX_LQUOTE; break;
+ case 'B': case 'b': code = M4_SYNTAX_BCOMM; break;
+ case 'O': case 'o': code = M4_SYNTAX_OTHER; break;
+ case 'D': case 'd': code = M4_SYNTAX_NUM; break;
+ case '$': code = M4_SYNTAX_DOLLAR; break;
+ case '{': code = M4_SYNTAX_LBRACE; break;
+ case '}': code = M4_SYNTAX_RBRACE; break;
+ case 'S': case 's': code = M4_SYNTAX_SPACE; break;
+ case 'A': case 'a': code = M4_SYNTAX_ACTIVE; break;
+ case '(': code = M4_SYNTAX_OPEN; break;
+ case ')': code = M4_SYNTAX_CLOSE; break;
+ case ',': code = M4_SYNTAX_COMMA; break;
+
+ case 'R': case 'r': code = M4_SYNTAX_RQUOTE; break;
+ case 'E': case 'e': code = M4_SYNTAX_ECOMM; break;
default: code = -1; break;
}
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.59
diff -u -p -r1.59 freeze.c
--- src/freeze.c 21 Jan 2007 04:09:06 -0000 1.59
+++ src/freeze.c 23 Jan 2007 14:26:24 -0000
@@ -267,9 +267,9 @@ produce_frozen_state (m4 *context, const
produce_resyntax_dump (context, file);
- /* Dump syntax table. */
+ /* Dump syntax table. */
- str = "IS(),address@hidden";
+ str = "address@hidden(),RE";
while (*str)
produce_syntax_dump (file, M4SYNTAX, *str++);
@@ -492,6 +492,9 @@ reload_frozen_state (m4 *context, const
m4__module_open (context, "traditional", NULL);
else
m4__module_open (context, "gnu", NULL);
+ /* Disable { and } categories, since ${11} was not supported in
+ 1.4.x. */
+ m4_set_syntax (context->syntax, 'O', '+', "{}");
break;
default:
if (version > 2)
Index: tests/freeze.at
===================================================================
RCS file: /sources/m4/m4/tests/freeze.at,v
retrieving revision 1.8
diff -u -p -r1.8 freeze.at
--- tests/freeze.at 31 Aug 2006 03:21:35 -0000 1.8
+++ tests/freeze.at 23 Jan 2007 14:26:24 -0000
@@ -1,5 +1,5 @@
# Hand crafted tests for GNU M4. -*- Autotest -*-
-# Copyright (C) 2006 Free Software Foundation, Inc.
+# Copyright (C) 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
@@ -39,7 +39,7 @@ GNU M4 1.4.5
$ cat frozen.m4
divert(`-1')
define(`foo', `\FOO')
-pushdef(`foo', `bar')
+pushdef(`foo', `bar${1}')
define(`my_define', defn(`define'))
define(`my_changeword', defn(`changeword'))
pushdef(`my_define', `define')
@@ -72,12 +72,12 @@ F9,6
my_definedefine
T3,4
foo\FOO
-T3,3
-foobar
+T3,7
+foobar${1}
F3,3
dnldnl
-D1,4
-bar
+D1,8
+bar${1}
D0,0
@@ -85,7 +85,7 @@ D0,0
]])
AT_DATA([input.m4],
-[[foo /* foo */ popdef([foo])foo
+[[foo([2]) /* foo */ popdef([foo])foo
my_define([bar], [1])[]popdef([my_define]) bar
my_define([bar], [2])[]popdef([my_define]) bar
my_define([bar], [3])[]popdef([my_define]) bar
@@ -93,12 +93,12 @@ my_define([bar], [4])[]popdef([my_define
]])
AT_CHECK_M4([-R frozen.m4f input.m4], [0],
-[[bar /* foo */ \FOO
+[[bar${1} /* foo */ \FOO
1
define 1
3
my_define(bar, 4) 3
-bar
+bar${1}
]],
[[m4:input.m4:5: Warning: popdef: undefined macro `my_define'
]])
@@ -106,9 +106,162 @@ bar
AT_CLEANUP
-## -------------------------- ##
-## Reloading unknown builtins ##
-## -------------------------- ##
+## ---------------- ##
+## loading format 2 ##
+## ---------------- ##
+
+AT_SETUP([loading format 2])
+AT_KEYWORDS([frozen])
+
+AT_DATA([frozen.m4f],
+[[# Handcrafted file, obeying the version 2 spec
+V2
+# missing close quote should be supplied
+Q1,0
+>
+# missing close comment should be supplied
+C1,0
+<
+M2
+m4
+M3
+gnu
+F7,7,3
+builtinbuiltingnu
+# Testing escape sequences
+T4,5
+blah\t\477\040\X5C
+]])
+
+AT_DATA([input.m4],
+[[< comment: builtin()
+builtin(>define', foo, bar)
+foo
+blah
+]])
+
+AT_CHECK_M4([-R frozen.m4f input.m4], [0],
+[[< comment: builtin()
+
+bar
+ '7 \
+]])
+
+AT_CLEANUP
+
+
+## --------- ##
+## changecom ##
+## --------- ##
+
+AT_SETUP([reloading changecom])
+AT_KEYWORDS([frozen])
+
+# Check that changesyntax is maintained across freeze boundaries.
+
+AT_DATA([[frozen.m4]],
+[[changecom`'changequote(<,>)dnl
+]])
+
+AT_DATA([[unfrozen.m4]],
+[[define(<foo>, <bar>)
+foo # foo
+]])
+
+# First generate the `expout' output by running over the sources before
+# freezing.
+AT_CHECK_M4([frozen.m4 unfrozen.m4], [0],
+ [stdout], [stderr])
+
+mv stdout expout
+mv stderr experr
+
+# Now freeze the first source file.
+AT_CHECK_M4([-F frozen.m4f frozen.m4], [0])
+
+# Now rerun the original sequence, but using the frozen file.
+AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0],
+ [expout], [experr])
+
+AT_CLEANUP
+
+
+## ------------ ##
+## changesyntax ##
+## ------------ ##
+
+AT_SETUP([reloading changesyntax])
+AT_KEYWORDS([frozen])
+
+# Check that changesyntax is maintained across freeze boundaries.
+
+AT_DATA([[frozen.m4]],
+[[changesyntax(`W+.', `({', `)}')dnl
+define{`a.b', `hello $1'}dnl
+]])
+
+AT_DATA([[unfrozen.m4]],
+[[a.b{world}
+]])
+
+# First generate the `expout' output by running over the sources before
+# freezing.
+AT_CHECK_M4([frozen.m4 unfrozen.m4], [0],
+ [stdout], [stderr])
+
+mv stdout expout
+mv stderr experr
+
+# Now freeze the first source file.
+AT_CHECK_M4([-F frozen.m4f frozen.m4], [0])
+
+# Now rerun the original sequence, but using the frozen file.
+AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0],
+ [expout], [experr])
+
+AT_CLEANUP
+
+
+## ------------- ##
+## regexp syntax ##
+## ------------- ##
+
+AT_SETUP([reloading regexp syntax])
+AT_KEYWORDS([frozen])
+
+# Check that regular expression syntax is maintained across freeze boundaries.
+
+AT_DATA([[frozen.m4]],
+[[changeresyntax(`POSIX_EXTENDED')dnl
+]])
+
+AT_DATA([[unfrozen.m4]],
+[[regexp(`GNUs not Unix', `\w(\w*)$')
+regexp(`GNUs not Unix', `\w\(\w*\)$', `GNU_M4')
+]])
+
+# First generate the `expout' output by running over the sources before
+# freezing.
+AT_CHECK_M4([frozen.m4 unfrozen.m4], [0],
+ [stdout], [stderr])
+
+mv stdout expout
+mv stderr experr
+
+# Now freeze the first source file.
+AT_CHECK_M4([-F frozen.m4f frozen.m4], [0],
+ [ignore], [ignore])
+
+# Now rerun the original sequence, but using the frozen file.
+AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0],
+ [expout], [experr])
+
+AT_CLEANUP
+
+
+## ---------------- ##
+## unknown builtins ##
+## ---------------- ##
AT_SETUP([reloading unknown builtin])
AT_KEYWORDS([frozen])
@@ -158,39 +311,3 @@ c: `'
]])
AT_CLEANUP
-
-## ---------------------- ##
-## Freezing regexp syntax ##
-## ---------------------- ##
-
-AT_SETUP([regexp syntax])
-AT_KEYWORDS([frozen])
-
-# Check that regular expression syntax is maintained across freeze baundaries.
-
-AT_DATA([[frozen.m4]],
-[[changeresyntax(`POSIX_EXTENDED')dnl
-]])
-
-AT_DATA([[unfrozen.m4]],
-[[regexp(`GNUs not Unix', `\w(\w*)$')
-regexp(`GNUs not Unix', `\w\(\w*\)$', `GNU_M4')
-]])
-
-# First generate the `expout' output by running over the sources before
-# freezing.
-AT_CHECK_M4([frozen.m4 unfrozen.m4], 0,
- [stdout], [stderr])
-
-mv stdout expout
-mv stderr experr
-
-# Now freeze the first source file.
-AT_CHECK_M4([-F frozen.m4f frozen.m4], 0,
- [ignore], [ignore])
-
-# Now rerun the original sequence, but using the frozen file.
-AT_CHECK_M4([-R frozen.m4f unfrozen.m4], 0,
- [expout], [experr])
-
-AT_CLEANUP([frozen.m4f])