m4-patches
[Top][All Lists]
Advanced

[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)







reply via email to

[Prev in Thread] Current Thread [Next in Thread]