summaryrefslogtreecommitdiff
path: root/expr.c
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>1997-06-05 14:59:13 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:50 +0000
commitd166f048818e10cf3799aa24a174fb22835f1acc (patch)
tree1ca27f9243900f8b236d0cde6a3862002aea9e19 /expr.c
parentccc6cda312fea9f0468ee65b8f368e9653e1380b (diff)
downloadbash-d166f048818e10cf3799aa24a174fb22835f1acc.tar.gz
Imported from ../bash-2.01.tar.gz.
Diffstat (limited to 'expr.c')
-rw-r--r--expr.c149
1 files changed, 105 insertions, 44 deletions
diff --git a/expr.c b/expr.c
index eb080541..0930789d 100644
--- a/expr.c
+++ b/expr.c
@@ -130,7 +130,7 @@ static int noeval; /* set to 1 if no assignment to be done */
static procenv_t evalbuf;
static void readtok (); /* lexical analyzer */
-static long expassign (), exp0 (), exp1 (), exp2 (), exp3 (),
+static long subexpr (), expassign (), exp0 (), exp1 (), exp2 (), exp3 (),
exp4 (), exp5 (), expshift (), expland (), explor (),
expband (), expbor (), expbxor (), expcond ();
static long strlong ();
@@ -158,8 +158,6 @@ pushexp ()
{
EXPR_CONTEXT *context;
- context = (EXPR_CONTEXT *)xmalloc (sizeof (EXPR_CONTEXT));
-
if (expr_depth >= MAX_EXPR_RECURSION_LEVEL)
evalerror ("expression recursion level exceeded");
@@ -170,6 +168,8 @@ pushexp ()
* sizeof (EXPR_CONTEXT *));
}
+ context = (EXPR_CONTEXT *)xmalloc (sizeof (EXPR_CONTEXT));
+
context->curtok = curtok;
context->lasttok = lasttok;
context->expression = expression;
@@ -199,7 +199,11 @@ popexp ()
free (context);
}
-/* Evaluate EXPR, and return the arithmetic result.
+/* Evaluate EXPR, and return the arithmetic result. If VALIDP is
+ non-null, a zero is stored into the location to which it points
+ if the expression is invalid, non-zero otherwise. If a non-zero
+ value is returned in *VALIDP, the return value of evalexp() may
+ be used.
The `while' loop after the longjmp is caught relies on the above
implementation of pushexp and popexp leaving in expr_stack[0] the
@@ -209,49 +213,80 @@ popexp ()
safe to let the loop terminate when expr_depth == 0, without freeing up
any of the expr_depth[0] stuff. */
long
-evalexp (expr)
+evalexp (expr, validp)
char *expr;
+ int *validp;
{
- long val = 0L;
+ long val;
+#if 0
procenv_t old_evalbuf;
- char *p;
-
- for (p = expr; p && *p && cr_whitespace (*p); p++)
- ;
+#endif
- if (p == NULL || *p == '\0')
- return (0);
+ val = 0L;
+#if 0
/* Save the value of evalbuf to protect it around possible recursive
calls to evalexp (). */
COPY_PROCENV (evalbuf, old_evalbuf);
+#endif
if (setjmp (evalbuf))
{
- if (tokstr) /* Clean up local allocation. */
- free (tokstr);
-
- if (expression)
- free (expression);
+ FREE (tokstr);
+ FREE (expression);
+ tokstr = expression = (char *)NULL;
- while (--expr_depth)
+ while (--expr_depth > 0)
{
if (expr_stack[expr_depth]->tokstr)
free (expr_stack[expr_depth]->tokstr);
if (expr_stack[expr_depth]->expression)
free (expr_stack[expr_depth]->expression);
+
+ free (expr_stack[expr_depth]);
}
- jump_to_top_level (DISCARD);
+ free (expr_stack[expr_depth]); /* free the allocated EXPR_CONTEXT */
+
+ if (validp)
+ *validp = 0;
+ return (0L);
}
+ val = subexpr (expr);
+
+#if 0
+ /* Restore the value of evalbuf so that any subsequent longjmp calls
+ will have a valid location to jump to. */
+ COPY_PROCENV (old_evalbuf, evalbuf);
+#endif
+
+ if (validp)
+ *validp = 1;
+
+ return (val);
+}
+
+static long
+subexpr (expr)
+ char *expr;
+{
+ long val;
+ char *p;
+
+ for (p = expr; p && *p && cr_whitespace (*p); p++)
+ ;
+
+ if (p == NULL || *p == '\0')
+ return (0L);
+
pushexp ();
curtok = lasttok = 0;
expression = savestring (expr);
tp = expression;
tokstr = (char *)NULL;
- tokval = 0l;
+ tokval = 0L;
readtok ();
@@ -260,18 +295,12 @@ evalexp (expr)
if (curtok != 0)
evalerror ("syntax error in expression");
- if (tokstr)
- free (tokstr);
- if (expression)
- free (expression);
+ FREE (tokstr);
+ FREE (expression);
popexp ();
- /* Restore the value of evalbuf so that any subsequent longjmp calls
- will have a valid location to jump to. */
- COPY_PROCENV (old_evalbuf, evalbuf);
-
- return (val);
+ return val;
}
/* Bind/create a shell variable with the name LHS to the RHS.
@@ -362,6 +391,7 @@ expassign ()
lvalue |= value;
break;
default:
+ free (lhs);
evalerror ("bug: bad expassign token");
break;
}
@@ -373,7 +403,7 @@ expassign ()
bind_int_variable (lhs, rhs);
free (rhs);
free (lhs);
- free (tokstr);
+ FREE (tokstr);
tokstr = (char *)NULL; /* For freeing on errors. */
}
return (value);
@@ -384,6 +414,9 @@ static long
expcond ()
{
long cval, val1, val2, rval;
+ int set_noeval;
+
+ set_noeval = 0;
rval = cval = explor ();
if (curtok == QUES) /* found conditional expr */
{
@@ -391,23 +424,30 @@ expcond ()
if (curtok == 0 || curtok == COL)
evalerror ("expression expected");
if (cval == 0)
- noeval++;
+ {
+ set_noeval = 1;
+ noeval++;
+ }
#if 0
val1 = explor ();
#else
val1 = expassign ();
#endif
- if (cval == 0)
+ if (set_noeval)
noeval--;
if (curtok != COL)
evalerror ("`:' expected for conditional expression");
readtok ();
if (curtok == 0)
evalerror ("expression expected");
+ set_noeval = 0;
if (cval)
- noeval++;
+ {
+ set_noeval = 1;
+ noeval++;
+ }
val2 = explor ();
- if (cval)
+ if (set_noeval)
noeval--;
rval = cval ? val1 : val2;
lasttok = COND;
@@ -420,18 +460,24 @@ static long
explor ()
{
register long val1, val2;
+ int set_noeval;
val1 = expland ();
while (curtok == LOR)
{
- readtok ();
+ set_noeval = 0;
if (val1 != 0)
- noeval++;
+ {
+ noeval++;
+ set_noeval = 1;
+ }
+ readtok ();
val2 = expland ();
- if (val1 != 0)
+ if (set_noeval)
noeval--;
val1 = val1 || val2;
+ lasttok = LOR;
}
return (val1);
@@ -442,18 +488,24 @@ static long
expland ()
{
register long val1, val2;
+ int set_noeval;
val1 = expbor ();
while (curtok == LAND)
{
- readtok ();
+ set_noeval = 0;
if (val1 == 0)
- noeval++;
+ {
+ set_noeval = 1;
+ noeval++;
+ }
+ readtok ();
val2 = expbor ();
- if (val1 == 0)
+ if (set_noeval)
noeval--;
val1 = val1 && val2;
+ lasttok = LAND;
}
return (val1);
@@ -556,7 +608,7 @@ exp4 ()
val1 = val1 >= val2;
else if (op == LT)
val1 = val1 < val2;
- else if (op == GT)
+ else /* (op == GT) */
val1 = val1 > val2;
}
return (val1);
@@ -762,7 +814,12 @@ readtok ()
value = get_string_value (tokstr);
#endif
- tokval = (value && *value) ? evalexp (value) : 0;
+ tokval = (value && *value) ? subexpr (value) : 0;
+
+#if defined (ARRAY_VARS)
+ if (e == ']')
+ FREE (value); /* get_array_value returns newly-allocated memory */
+#endif
*cp = c;
lasttok = curtok;
@@ -960,14 +1017,18 @@ main (argc, argv)
{
register int i;
long v;
+ int expok;
if (setjmp (top_level))
exit (0);
for (i = 1; i < argc; i++)
{
- v = evalexp (argv[i]);
- printf ("'%s' -> %ld\n", argv[i], v);
+ v = evalexp (argv[i], &expok);
+ if (expok == 0)
+ fprintf (stderr, "%s: expression error\n", argv[i]);
+ else
+ printf ("'%s' -> %ld\n", argv[i], v);
}
exit (0);
}