[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: format and eval
From: |
Eric Blake |
Subject: |
Re: format and eval |
Date: |
Tue, 9 Jan 2007 16:11:46 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
Gary V. Vaughan <gary <at> gnu.org> writes:
Hi Gary,
> On Sat, 06 Jan 2007 12:52:50 -0700, "Eric Blake" <ebb9 <at> byu.net> said:
> > I'm not sure if any
> > existing m4 scripts depended on this undocumented behavior. If you think
> > it wise, I could do a followup patch to edit the branch to issue a
> > warning
> > but still perform the equality test, rather than this patch's behavior of
> > treating = as a hard error.
>
> Yes, we should not introduce regressions in a maintenance release. HEAD
> on the other hand is free to DTRT.
Done as follows; part 4 in this patch series.
2007-01-09 Eric Blake <address@hidden>
* src/eval.c (ASSIGN): New enumerator.
(eval_lex): Recognize '='.
(equality_term): Treat '=' like '==', but warn that it is
deprecated.
* doc/m4.texinfo (Eval): Document and test this.
(Incompatibilities): Document the POSIX incompatibility.
* NEWS: Document this change.
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.1.1.1.2.87
diff -u -r1.1.1.1.2.87 NEWS
--- NEWS 6 Jan 2007 19:56:11 -0000 1.1.1.1.2.87
+++ NEWS 9 Jan 2007 16:08:04 -0000
@@ -8,11 +8,11 @@
files larger than 2GiB on some platforms.
* Fix a regression introduced in 1.4.8 that made m4 dump core when
invoked as 'm4 -- file'.
-* The `eval' builtin now follows C precedence rules. Additionally,
- short-circuit operators correctly short-circuit division by zero.
- The undocumented alias of '=' meaning '==' in eval now triggers
- an error, so that a future version of M4 can implement a form of
- variable assignment as an extension.
+* The `eval' builtin now follows C precedence rules. Additionally, the
+ short-circuit operators correctly short-circuit division by zero. The
+ previously undocumented alias of '=' meaning '==' in eval now triggers a
+ deprecation warning, so that a future version of M4 can implement a form
+ of variable assignment as an extension.
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.106
diff -u -r1.1.1.1.2.106 m4.texinfo
--- doc/m4.texinfo 6 Jan 2007 19:56:11 -0000 1.1.1.1.2.106
+++ doc/m4.texinfo 9 Jan 2007 16:08:04 -0000
@@ -4466,10 +4466,28 @@
@end deffn
All binary operators, except exponentiation, are left associative. C
-operators that perform variable assignment, such as @samp{=} or
+operators that perform variable assignment, such as @samp{+=} or
@samp{--}, are forbidden by @acronym{POSIX}, since @code{eval} only
operates on constants, not variables. Attempting to use them results
-in an error.
+in an error. However, since traditional implementations treated
address@hidden as an undocumented alias for @samp{==} as opposed to an
+assignment operator, this usage is supported as a special case. Be
+aware that a future version of @acronym{GNU} M4 may support assignment
+semantics as an extension when @acronym{POSIX} mode is not requested,
+and that using @samp{=} to check equality is not portable.
+
address@hidden status: 1
address@hidden
+eval(`2 = 2')
address@hidden:stdin:1: Warning: recommend ==, not =, for equality operator
address@hidden
+eval(`++0')
address@hidden:stdin:2: invalid operator in eval: ++0
address@hidden
+eval(`0 |= 1')
address@hidden:stdin:3: invalid operator in eval: 0 |= 1
address@hidden
address@hidden example
Note that some older @code{m4} implementations use @samp{^} as an
alternate operator for the exponentiation, although @acronym{POSIX}
@@ -4492,7 +4510,6 @@
implementations of @code{m4} require explicit parentheses to get the
correct result:
address@hidden status: 1
@example
eval(`1 == 2 > 0')
@result{}1
@@ -4508,24 +4525,15 @@
@result{}0
eval(`+ + - ~ ! ~ 0')
@result{}1
-eval(`++0')
address@hidden:stdin:8: invalid operator in eval: ++0
address@hidden
-eval(`1 = 1')
address@hidden:stdin:9: invalid operator in eval: 1 = 1
address@hidden
-eval(`0 |= 1')
address@hidden:stdin:10: invalid operator in eval: 0 |= 1
address@hidden
eval(`2 || 1 / 0')
@result{}1
eval(`0 || 1 / 0')
address@hidden:stdin:12: divide by zero in eval: 0 || 1 / 0
address@hidden:stdin:9: divide by zero in eval: 0 || 1 / 0
@result{}
eval(`0 && 1 % 0')
@result{}0
eval(`2 && 1 % 0')
address@hidden:stdin:14: modulo by zero in eval: 2 && 1 % 0
address@hidden:stdin:11: modulo by zero in eval: 2 && 1 % 0
@result{}
@end example
@@ -5672,7 +5680,9 @@
ensure proper precedence. As extensions to @acronym{POSIX},
@acronym{GNU} @code{m4} gives well-defined semantics to operations that
C leaves undefined, such as when overflow occurs, when shifting negative
-numbers, or when performing division by zero.
+numbers, or when performing division by zero. @acronym{POSIX} also
+requires @samp{=} to cause an error, but many traditional
+implementations allowed it as an alias for @samp{==}.
@item
@acronym{POSIX} requires @code{translit} (@pxref{Translit}) to treat
Index: src/eval.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/eval.c,v
retrieving revision 1.1.1.1.2.8
diff -u -r1.1.1.1.2.8 eval.c
--- src/eval.c 6 Jan 2007 19:56:11 -0000 1.1.1.1.2.8
+++ src/eval.c 9 Jan 2007 16:08:04 -0000
@@ -34,7 +34,7 @@
PLUS, MINUS,
EXPONENT,
TIMES, DIVIDE, MODULO,
- EQ, NOTEQ, GT, GTEQ, LS, LSEQ,
+ ASSIGN, EQ, NOTEQ, GT, GTEQ, LS, LSEQ,
LSHIFT, RSHIFT,
LNOT, LAND, LOR,
NOT, AND, OR, XOR,
@@ -215,7 +215,7 @@
eval_text++;
return EQ;
}
- return BADOP;
+ return ASSIGN;
case '!':
if (*eval_text == '=')
{
@@ -517,7 +517,10 @@
if ((er = cmp_term (et, v1)) != NO_ERROR)
return er;
- while ((op = eval_lex (&v2)) == EQ || op == NOTEQ)
+ /* In the 1.4.x series, we maintain the traditional behavior that
+ '=' is a synonym for '=='; however, this is contrary to POSIX and
+ we hope to convert '=' to mean assignment in 2.0. */
+ while ((op = eval_lex (&v2)) == EQ || op == NOTEQ || op == ASSIGN)
{
et = eval_lex (&v2);
if (et == ERROR)
@@ -525,6 +528,13 @@
if ((er = cmp_term (et, &v2)) != NO_ERROR)
return er;
+
+ if (op == ASSIGN)
+ {
+ M4ERROR ((warning_status, 0, "\
+Warning: recommend ==, not =, for equality operator"));
+ op = EQ;
+ }
*v1 = (op == EQ) == (*v1 == v2);
}
if (op == ERROR)