m4-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-82-


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-82-g4e14996
Date: Wed, 24 Dec 2008 21:50:03 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU M4 source repository".

http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=4e149960673934a405b3dec721b2a1d2e88b2f8d

The branch, branch-1.6 has been updated
       via  4e149960673934a405b3dec721b2a1d2e88b2f8d (commit)
      from  6a95d853eb3c7493345ea093e8efa9f35a49c143 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4e149960673934a405b3dec721b2a1d2e88b2f8d
Author: Eric Blake <address@hidden>
Date:   Wed Dec 24 14:15:13 2008 -0700

    Enhance eval, as allowed by POSIX 2008.
    
    * src/eval.c (enum eval_token): Add QUESTION and COLON.
    (enum eval_error): Add MISSING_COLON.
    (condition_term): New function.
    (eval_lex, simple_term): Support new operator.
    (evaluate): Likewise.  Warn, not error, on invalid operator.
    * doc/m4.texinfo (Eval): Update documentation.
    (Improved forloop): Adjust test.
    * NEWS: Document the change.
    
    Signed-off-by: Eric Blake <address@hidden>

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog      |   12 +++++++++
 NEWS           |    4 +++
 doc/m4.texinfo |   30 ++++++++++++++--------
 src/eval.c     |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 103 insertions(+), 18 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7f3bde2..d15e52a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-12-24  Eric Blake  <address@hidden>
+
+       Enhance eval, as allowed by POSIX 2008.
+       * src/eval.c (enum eval_token): Add QUESTION and COLON.
+       (enum eval_error): Add MISSING_COLON.
+       (condition_term): New function.
+       (eval_lex, simple_term): Support new operator.
+       (evaluate): Likewise.  Warn, not error, on invalid operator.
+       * doc/m4.texinfo (Eval): Update documentation.
+       (Improved forloop): Adjust test.
+       * NEWS: Document the change.
+
 2008-12-23  Eric Blake  <address@hidden>
 
        Issue deprecation warning for -o/--error-output.
diff --git a/NEWS b/NEWS
index ebd2cbb..2e1a286 100644
--- a/NEWS
+++ b/NEWS
@@ -107,6 +107,10 @@ Foundation, Inc.
    context of a macro name, rather than acting on the empty string.  This
    was already done for `define', `pushdef', `builtin', and `indir'.
 
+** Enhance the `eval' builtin to understand the `?:' operator, and
+   downgrade a failed parse due to an unknown operator from an error to a
+   warning.
+
 ** A number of portability improvements inherited from gnulib.
 
 * Noteworthy changes in Version 1.4.10b (2008-02-25) [beta]
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 2ab7290..93adb64 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -6670,6 +6670,8 @@ Bitwise or
 Logical and
 @item ||
 Logical or
address@hidden ?:
+Conditional ternary
 @end table
 
 The macro @code{eval} is recognized only with parameters.
@@ -6678,7 +6680,7 @@ The macro @code{eval} is recognized only with parameters.
 All binary operators, except exponentiation, are left associative.  C
 operators that perform variable assignment, such as @samp{+=} or
 @samp{--}, are not implemented, since @code{eval} only operates on
-constants, not variables.  Attempting to use them results in an error.
+constants, not variables.  Attempting to use them results in a warning.
 However, since traditional implementations treated @samp{=} 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
@@ -6686,16 +6688,15 @@ 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
 @example
 eval(`2 = 2')
 @error{}m4:stdin:1: Warning: eval: recommend ==, not =, for equality
 @result{}1
 eval(`++0')
address@hidden:stdin:2: eval: invalid operator: ++0
address@hidden:stdin:2: Warning: eval: invalid operator: `++0'
 @result{}
 eval(`0 |= 1')
address@hidden:stdin:3: eval: invalid operator: 0 |= 1
address@hidden:stdin:3: Warning: eval: invalid operator: `0 |= 1'
 @result{}
 @end example
 
@@ -6738,12 +6739,12 @@ eval(`+ + - ~ ! ~ 0')
 eval(`2 || 1 / 0')
 @result{}1
 eval(`0 || 1 / 0')
address@hidden:stdin:9: Warning: eval: divide by zero: 0 || 1 / 0
address@hidden:stdin:9: Warning: eval: divide by zero: `0 || 1 / 0'
 @result{}
 eval(`0 && 1 % 0')
 @result{}0
 eval(`2 && 1 % 0')
address@hidden:stdin:11: Warning: eval: modulo by zero: 2 && 1 % 0
address@hidden:stdin:11: Warning: eval: modulo by zero: `2 && 1 % 0'
 @result{}
 @end example
 
@@ -6751,7 +6752,8 @@ eval(`2 && 1 % 0')
 As a @acronym{GNU} extension, the operator @samp{**} performs integral
 exponentiation.  The operator is right-associative, and if evaluated,
 the exponent must be non-negative, and at least one of the arguments
-must be non-zero, or a warning is issued.
+must be non-zero, or a warning is issued.  Also, the C operator
address@hidden:} is supported.
 
 @example
 eval(`2 ** 3 ** 2')
@@ -6764,10 +6766,16 @@ eval(`2 ** 0')
 @result{}1
 eval(`0 ** 0')
 @result{}
address@hidden:stdin:5: Warning: eval: divide by zero: 0 ** 0
address@hidden:stdin:5: Warning: eval: divide by zero: `0 ** 0'
 eval(`4 ** -2')
address@hidden:stdin:6: Warning: eval: negative exponent: 4 ** -2
address@hidden:stdin:6: Warning: eval: negative exponent: `4 ** -2'
 @result{}
+eval(`0 ? 2 : 3')
address@hidden
+eval(`1 ? 2 : 1/0')
address@hidden
+eval(`0 ? 1/0 : 3')
address@hidden
 @end example
 
 Within @var{expression}, (but not @var{radix} or @var{width}), numbers
@@ -6811,7 +6819,7 @@ square(square(`5')` + 1')
 define(`foo', `666')
 @result{}
 eval(`foo / 6')
address@hidden:stdin:11: Warning: eval: bad expression: foo / 6
address@hidden:stdin:11: Warning: eval: bad expression: `foo / 6'
 @result{}
 eval(foo / 6)
 @result{}111
@@ -8254,7 +8262,7 @@ forloop(`', `1', `2', ` odd iterator name')
 forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')')
 @result{} 0xa 0xb 0xc
 forloop(`i', `a', `b', `non-numeric bounds')
address@hidden:stdin:6: Warning: eval: bad expression (bad input): (a) <= (b)
address@hidden:stdin:6: Warning: eval: bad input: `(a) <= (b)'
 @result{}
 @end example
 
diff --git a/src/eval.c b/src/eval.c
index 1b617ed..c5ad30d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -39,6 +39,7 @@ typedef enum eval_token
     LNOT, LAND, LOR,
     NOT, AND, OR, XOR,
     LEFTP, RIGHTP,
+    QUESTION, COLON,
     NUMBER, EOTEXT
   }
 eval_token;
@@ -56,6 +57,7 @@ typedef enum eval_error
        about a syntax error.  */
     SYNTAX_ERROR,
     MISSING_RIGHT,
+    MISSING_COLON,
     UNKNOWN_INPUT,
     EXCESS_INPUT,
     INVALID_OPERATOR,
@@ -63,6 +65,7 @@ typedef enum eval_error
   }
 eval_error;
 
+static eval_error condition_term (const call_info *, eval_token, int32_t *);
 static eval_error logical_or_term (const call_info *, eval_token, int32_t *);
 static eval_error logical_and_term (const call_info *, eval_token, int32_t *);
 static eval_error or_term (const call_info *, eval_token, int32_t *);
@@ -283,6 +286,10 @@ eval_lex (int32_t *val)
       return LEFTP;
     case ')':
       return RIGHTP;
+    case '?':
+      return QUESTION;
+    case ':':
+      return COLON;
     default:
       return ERROR;
     }
@@ -303,7 +310,7 @@ evaluate (const call_info *me, const char *expr, size_t 
len, int32_t *val)
   if (et == EOTEXT)
     err = EMPTY_ARGUMENT;
   else
-    err = logical_or_term (me, et, val);
+    err = condition_term (me, et, val);
 
   if (err == NO_ERROR && *eval_text != '\0')
     {
@@ -313,6 +320,8 @@ evaluate (const call_info *me, const char *expr, size_t 
len, int32_t *val)
        err = EXCESS_INPUT;
     }
 
+  if (err != NO_ERROR)
+    expr = quotearg_style_mem (locale_quoting_style, expr, len);
   switch (err)
     {
       /* Cases where result is printed.  */
@@ -325,8 +334,11 @@ evaluate (const call_info *me, const char *expr, size_t 
len, int32_t *val)
 
       /* Cases where error makes result meaningless.  */
     case MISSING_RIGHT:
-      m4_warn (0, me, _("bad expression (missing right parenthesis): %s"),
-              expr);
+      m4_warn (0, me, _("missing right parenthesis: %s"), expr);
+      break;
+
+    case MISSING_COLON:
+      m4_warn (0, me, _("missing colon: %s"), expr);
       break;
 
     case SYNTAX_ERROR:
@@ -334,15 +346,15 @@ evaluate (const call_info *me, const char *expr, size_t 
len, int32_t *val)
       break;
 
     case UNKNOWN_INPUT:
-      m4_warn (0, me, _("bad expression (bad input): %s"), expr);
+      m4_warn (0, me, _("bad input: %s"), expr);
       break;
 
     case EXCESS_INPUT:
-      m4_warn (0, me, _("bad expression (excess input): %s"), expr);
+      m4_warn (0, me, _("excess input: %s"), expr);
       break;
 
     case INVALID_OPERATOR:
-      m4_error (0, 0, me, _("invalid operator: %s"), expr);
+      m4_warn (0, me, _("invalid operator: %s"), expr);
       break;
 
     case DIVIDE_ZERO:
@@ -370,6 +382,55 @@ evaluate (const call_info *me, const char *expr, size_t 
len, int32_t *val)
 `---------------------------*/
 
 static eval_error
+condition_term (const call_info *me, eval_token et, int32_t *v1)
+{
+  int32_t v2;
+  int32_t v3;
+  eval_error er;
+
+  if ((er = logical_or_term (me, et, v1)) != NO_ERROR)
+    return er;
+
+  if ((et = eval_lex (&v2)) == QUESTION)
+    {
+      et = eval_lex (&v2);
+      if (et == ERROR)
+       return UNKNOWN_INPUT;
+
+      /* Implement short-circuiting of valid syntax.  */
+      /* C requires 'logical_or_term ? expression : condition_term';
+        if we ever introduce assignment_term or comma_term, then
+        condition_term and expression are no longer synonymous.  */
+      er = condition_term (me, et, &v2);
+      if (er != NO_ERROR
+         && !(*v1 == 0 && er < SYNTAX_ERROR))
+       return er;
+
+      et = eval_lex (&v3);
+      if (et == ERROR)
+       return UNKNOWN_INPUT;
+      if (et != COLON)
+       return MISSING_COLON;
+
+      et = eval_lex (&v3);
+      if (et == ERROR)
+       return UNKNOWN_INPUT;
+
+      er = condition_term (me, et, &v3);
+      if (er != NO_ERROR
+         && !(*v1 != 0 && er < SYNTAX_ERROR))
+       return er;
+
+      *v1 = *v1 ? v2 : v3;
+    }
+  if (et == ERROR)
+    return UNKNOWN_INPUT;
+
+  eval_undo ();
+  return NO_ERROR;
+}
+
+static eval_error
 logical_or_term (const call_info *me, eval_token et, int32_t *v1)
 {
   int32_t v2;
@@ -832,7 +893,7 @@ simple_term (const call_info *me, eval_token et, int32_t 
*v1)
       if (et == ERROR)
        return UNKNOWN_INPUT;
 
-      if ((er = logical_or_term (me, et, v1)) != NO_ERROR)
+      if ((er = condition_term (me, et, v1)) != NO_ERROR)
        return er;
 
       et = eval_lex (&v2);


hooks/post-receive
--
GNU M4 source repository




reply via email to

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