[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-82-g4e14996,
Eric Blake <=