diff options
author | Jim Meyering <jim@meyering.net> | 2004-02-22 14:56:58 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2004-02-22 14:56:58 +0000 |
commit | fdb3c26e8ec63b94924ebd181b145ee8f2e3dd63 (patch) | |
tree | 21f68d28889173f715924f28179b23de91a17cbf /src | |
parent | 5c8d1ad4f03a797ca48c784cb2f6d4f0fe770e73 (diff) | |
download | coreutils-fdb3c26e8ec63b94924ebd181b145ee8f2e3dd63.tar.xz |
(eval, eval7, eval6, eval5, eval4, eval3, eval2, eval1):
Accept a bool argument specifying whether to evaluate the
expression. This is to allow short-circuit evaluation. All
callers changed.
(null): Report that a string is zero even if it has
a form like "-0" or "00".
(eval1, eval): Use short-circuit evaluation for | and &.
(eval): Return 0 if both arguments are null or zero, instead
of returning the first argument.
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 138 |
1 files changed, 86 insertions, 52 deletions
diff --git a/src/expr.c b/src/expr.c index b4827c418..d085b4be7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -86,7 +86,7 @@ static char **args; /* The name this program was run with. */ char *program_name; -static VALUE *eval (void); +static VALUE *eval (bool); static bool nomoreargs (void); static bool null (VALUE *v); static void printv (VALUE *v); @@ -202,7 +202,7 @@ main (int argc, char **argv) args = argv + 1; - v = eval (); + v = eval (true); if (!nomoreargs ()) syntax_error (); printv (v); @@ -279,7 +279,22 @@ null (VALUE *v) case integer: return v->u.i == 0; case string: - return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0; + { + char const *cp = v->u.s; + if (*cp == '\0') + return true; + + cp += (*cp == '-'); + + do + { + if (*cp != '0') + return false; + } + while (*++cp); + + return true; + } default: abort (); } @@ -448,7 +463,7 @@ of the basic regular expression is not portable; it is being ignored"), /* Handle bare operands and ( expr ) syntax. */ static VALUE * -eval7 (void) +eval7 (bool evaluate) { VALUE *v; @@ -460,7 +475,7 @@ eval7 (void) if (nextarg ("(")) { - v = eval (); + v = eval (evaluate); if (!nextarg (")")) syntax_error (); return v; @@ -475,7 +490,7 @@ eval7 (void) /* Handle match, substr, index, and length keywords, and quoting "+". */ static VALUE * -eval6 (void) +eval6 (bool evaluate) { VALUE *l; VALUE *r; @@ -494,7 +509,7 @@ eval6 (void) } else if (nextarg ("length")) { - r = eval6 (); + r = eval6 (evaluate); tostring (r); v = int_value (strlen (r->u.s)); freev (r); @@ -502,17 +517,22 @@ eval6 (void) } else if (nextarg ("match")) { - l = eval6 (); - r = eval6 (); - v = docolon (l, r); - freev (l); + l = eval6 (evaluate); + r = eval6 (evaluate); + if (evaluate) + { + v = docolon (l, r); + freev (l); + } + else + v = l; freev (r); return v; } else if (nextarg ("index")) { - l = eval6 (); - r = eval6 (); + l = eval6 (evaluate); + r = eval6 (evaluate); tostring (l); tostring (r); v = int_value (strcspn (l->u.s, r->u.s) + 1); @@ -524,9 +544,9 @@ eval6 (void) } else if (nextarg ("substr")) { - l = eval6 (); - i1 = eval6 (); - i2 = eval6 (); + l = eval6 (evaluate); + i1 = eval6 (evaluate); + i2 = eval6 (evaluate); tostring (l); if (!toarith (i1) || !toarith (i2) || strlen (l->u.s) < i1->u.i @@ -546,14 +566,14 @@ eval6 (void) return v; } else - return eval7 (); + return eval7 (evaluate); } /* Handle : operator (pattern matching). Calls docolon to do the real work. */ static VALUE * -eval5 (void) +eval5 (bool evaluate) { VALUE *l; VALUE *r; @@ -562,16 +582,19 @@ eval5 (void) #ifdef EVAL_TRACE trace ("eval5"); #endif - l = eval6 (); + l = eval6 (evaluate); while (1) { if (nextarg (":")) { - r = eval6 (); - v = docolon (l, r); - freev (l); + r = eval6 (evaluate); + if (evaluate) + { + v = docolon (l, r); + freev (l); + l = v; + } freev (r); - l = v; } else return l; @@ -581,17 +604,17 @@ eval5 (void) /* Handle *, /, % operators. */ static VALUE * -eval4 (void) +eval4 (bool evaluate) { VALUE *l; VALUE *r; enum { multiply, divide, mod } fxn; - intmax_t val; + intmax_t val = 0; #ifdef EVAL_TRACE trace ("eval4"); #endif - l = eval5 (); + l = eval5 (evaluate); while (1) { if (nextarg ("*")) @@ -602,16 +625,19 @@ eval4 (void) fxn = mod; else return l; - r = eval5 (); - if (!toarith (l) || !toarith (r)) - error (EXPR_FAILURE, 0, _("non-numeric argument")); - if (fxn == multiply) - val = l->u.i * r->u.i; - else + r = eval5 (evaluate); + if (evaluate) { - if (r->u.i == 0) - error (EXPR_FAILURE, 0, _("division by zero")); - val = fxn == divide ? l->u.i / r->u.i : l->u.i % r->u.i; + if (!toarith (l) || !toarith (r)) + error (EXPR_FAILURE, 0, _("non-numeric argument")); + if (fxn == multiply) + val = l->u.i * r->u.i; + else + { + if (r->u.i == 0) + error (EXPR_FAILURE, 0, _("division by zero")); + val = fxn == divide ? l->u.i / r->u.i : l->u.i % r->u.i; + } } freev (l); freev (r); @@ -622,17 +648,17 @@ eval4 (void) /* Handle +, - operators. */ static VALUE * -eval3 (void) +eval3 (bool evaluate) { VALUE *l; VALUE *r; enum { plus, minus } fxn; - intmax_t val; + intmax_t val = 0; #ifdef EVAL_TRACE trace ("eval3"); #endif - l = eval4 (); + l = eval4 (evaluate); while (1) { if (nextarg ("+")) @@ -641,10 +667,13 @@ eval3 (void) fxn = minus; else return l; - r = eval4 (); - if (!toarith (l) || !toarith (r)) - error (EXPR_FAILURE, 0, _("non-numeric argument")); - val = fxn == plus ? l->u.i + r->u.i : l->u.i - r->u.i; + r = eval4 (evaluate); + if (evaluate) + { + if (!toarith (l) || !toarith (r)) + error (EXPR_FAILURE, 0, _("non-numeric argument")); + val = fxn == plus ? l->u.i + r->u.i : l->u.i - r->u.i; + } freev (l); freev (r); l = int_value (val); @@ -654,7 +683,7 @@ eval3 (void) /* Handle comparisons. */ static VALUE * -eval2 (void) +eval2 (bool evaluate) { VALUE *l; VALUE *r; @@ -671,7 +700,7 @@ eval2 (void) #ifdef EVAL_TRACE trace ("eval2"); #endif - l = eval3 (); + l = eval3 (evaluate); while (1) { if (nextarg ("<")) @@ -688,7 +717,7 @@ eval2 (void) fxn = greater_than; else return l; - r = eval3 (); + r = eval3 (evaluate); tostring (l); tostring (r); @@ -706,7 +735,7 @@ eval2 (void) lval = l->u.i; rval = r->u.i; } - else if (collation_errno) + else if (collation_errno && evaluate) { error (0, collation_errno, _("string comparison failed")); error (0, 0, _("Set LC_ALL='C' to work around the problem.")); @@ -736,7 +765,7 @@ eval2 (void) /* Handle &. */ static VALUE * -eval1 (void) +eval1 (bool evaluate) { VALUE *l; VALUE *r; @@ -744,12 +773,12 @@ eval1 (void) #ifdef EVAL_TRACE trace ("eval1"); #endif - l = eval2 (); + l = eval2 (evaluate); while (1) { if (nextarg ("&")) { - r = eval2 (); + r = eval2 (evaluate & ~ null (l)); if (null (l) || null (r)) { freev (l); @@ -767,7 +796,7 @@ eval1 (void) /* Handle |. */ static VALUE * -eval (void) +eval (bool evaluate) { VALUE *l; VALUE *r; @@ -775,16 +804,21 @@ eval (void) #ifdef EVAL_TRACE trace ("eval"); #endif - l = eval1 (); + l = eval1 (evaluate); while (1) { if (nextarg ("|")) { - r = eval1 (); + r = eval1 (evaluate & null (l)); if (null (l)) { freev (l); l = r; + if (null (l)) + { + freev (l); + l = int_value (0); + } } else freev (r); |