/* 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);
args = argv + 1;
- v = eval ();
+ v = eval (true);
if (!nomoreargs ())
syntax_error ();
printv (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 ();
}
/* Handle bare operands and ( expr ) syntax. */
static VALUE *
-eval7 (void)
+eval7 (bool evaluate)
{
VALUE *v;
if (nextarg ("("))
{
- v = eval ();
+ v = eval (evaluate);
if (!nextarg (")"))
syntax_error ();
return v;
/* Handle match, substr, index, and length keywords, and quoting "+". */
static VALUE *
-eval6 (void)
+eval6 (bool evaluate)
{
VALUE *l;
VALUE *r;
}
else if (nextarg ("length"))
{
- r = eval6 ();
+ r = eval6 (evaluate);
tostring (r);
v = int_value (strlen (r->u.s));
freev (r);
}
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);
}
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
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;
#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;
/* 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 ("*"))
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);
/* 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 ("+"))
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);
/* Handle comparisons. */
static VALUE *
-eval2 (void)
+eval2 (bool evaluate)
{
VALUE *l;
VALUE *r;
#ifdef EVAL_TRACE
trace ("eval2");
#endif
- l = eval3 ();
+ l = eval3 (evaluate);
while (1)
{
if (nextarg ("<"))
fxn = greater_than;
else
return l;
- r = eval3 ();
+ r = eval3 (evaluate);
tostring (l);
tostring (r);
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."));
/* Handle &. */
static VALUE *
-eval1 (void)
+eval1 (bool evaluate)
{
VALUE *l;
VALUE *r;
#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);
/* Handle |. */
static VALUE *
-eval (void)
+eval (bool evaluate)
{
VALUE *l;
VALUE *r;
#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);