diff options
author | Jari Aalto <jari.aalto@cante.net> | 1997-06-05 14:59:13 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:50 +0000 |
commit | d166f048818e10cf3799aa24a174fb22835f1acc (patch) | |
tree | 1ca27f9243900f8b236d0cde6a3862002aea9e19 /expr.c | |
parent | ccc6cda312fea9f0468ee65b8f368e9653e1380b (diff) | |
download | bash-d166f048818e10cf3799aa24a174fb22835f1acc.tar.gz |
Imported from ../bash-2.01.tar.gz.
Diffstat (limited to 'expr.c')
-rw-r--r-- | expr.c | 149 |
1 files changed, 105 insertions, 44 deletions
@@ -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); } |