LCOV - code coverage report
Current view: top level - bash-4.4.23 - expr.c (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 285 606 47.0 %
Date: 2020-10-29 14:49:28 Functions: 25 28 89.3 %

          Line data    Source code
       1             : /* expr.c -- arithmetic expression evaluation. */
       2             : 
       3             : /* Copyright (C) 1990-2015 Free Software Foundation, Inc.
       4             : 
       5             :    This file is part of GNU Bash, the Bourne Again SHell.
       6             : 
       7             :    Bash is free software: you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation, either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    Bash is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : /*
      22             :  All arithmetic is done as intmax_t integers with no checking for overflow
      23             :  (though division by 0 is caught and flagged as an error).
      24             : 
      25             :  The following operators are handled, grouped into a set of levels in
      26             :  order of decreasing precedence.
      27             : 
      28             :         "id++", "id--"              [post-increment and post-decrement]
      29             :         "++id", "--id"              [pre-increment and pre-decrement]
      30             :         "-", "+"            [(unary operators)]
      31             :         "!", "~"
      32             :         "**"                  [(exponentiation)]
      33             :         "*", "/", "%"
      34             :         "+", "-"
      35             :         "<<", ">>"
      36             :         "<=", ">=", "<", ">"
      37             :         "==", "!="
      38             :         "&"
      39             :         "^"
      40             :         "|"
      41             :         "&&"
      42             :         "||"
      43             :         "expr ? expr : expr"
      44             :         "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
      45             :         ,                       [comma]
      46             : 
      47             :  (Note that most of these operators have special meaning to bash, and an
      48             :  entire expression should be quoted, e.g. "a=$a+1" or "a=a+1" to ensure
      49             :  that it is passed intact to the evaluator when using `let'.  When using
      50             :  the $[] or $(( )) forms, the text between the `[' and `]' or `((' and `))'
      51             :  is treated as if in double quotes.)
      52             : 
      53             :  Sub-expressions within parentheses have a precedence level greater than
      54             :  all of the above levels and are evaluated first.  Within a single prece-
      55             :  dence group, evaluation is left-to-right, except for the arithmetic
      56             :  assignment operator (`='), which is evaluated right-to-left (as in C).
      57             : 
      58             :  The expression evaluator returns the value of the expression (assignment
      59             :  statements have as a value what is returned by the RHS).  The `let'
      60             :  builtin, on the other hand, returns 0 if the last expression evaluates to
      61             :  a non-zero, and 1 otherwise.
      62             : 
      63             :  Implementation is a recursive-descent parser.
      64             : 
      65             :  Chet Ramey
      66             :  chet@po.cwru.edu
      67             : */
      68             : 
      69             : #include "config.h"
      70             : 
      71             : #include <stdio.h>
      72             : #include "bashansi.h"
      73             : 
      74             : #if defined (HAVE_UNISTD_H)
      75             : #  ifdef _MINIX
      76             : #    include <sys/types.h>
      77             : #  endif
      78             : #  include <unistd.h>
      79             : #endif
      80             : 
      81             : #include "chartypes.h"
      82             : #include "bashintl.h"
      83             : 
      84             : #include "shell.h"
      85             : #include "typemax.h"          /* INTMAX_MAX, INTMAX_MIN */
      86             : 
      87             : /* Because of the $((...)) construct, expressions may include newlines.
      88             :    Here is a macro which accepts newlines, tabs and spaces as whitespace. */
      89             : #define cr_whitespace(c) (whitespace(c) || ((c) == '\n'))
      90             : 
      91             : /* Size be which the expression stack grows when necessary. */
      92             : #define EXPR_STACK_GROW_SIZE 10
      93             : 
      94             : /* Maximum amount of recursion allowed.  This prevents a non-integer
      95             :    variable such as "num=num+2" from infinitely adding to itself when
      96             :    "let num=num+2" is given. */
      97             : #define MAX_EXPR_RECURSION_LEVEL 1024
      98             : 
      99             : /* The Tokens.  Singing "The Lion Sleeps Tonight". */
     100             : 
     101             : #define EQEQ    1       /* "==" */
     102             : #define NEQ     2       /* "!=" */
     103             : #define LEQ     3       /* "<=" */
     104             : #define GEQ     4       /* ">=" */
     105             : #define STR     5       /* string */
     106             : #define NUM     6       /* number */
     107             : #define LAND    7       /* "&&" Logical AND */
     108             : #define LOR     8       /* "||" Logical OR */
     109             : #define LSH     9       /* "<<" Left SHift */
     110             : #define RSH    10       /* ">>" Right SHift */
     111             : #define OP_ASSIGN 11    /* op= expassign as in Posix.2 */
     112             : #define COND    12      /* exp1 ? exp2 : exp3 */
     113             : #define POWER   13      /* exp1**exp2 */
     114             : #define PREINC  14      /* ++var */
     115             : #define PREDEC  15      /* --var */
     116             : #define POSTINC 16      /* var++ */
     117             : #define POSTDEC 17      /* var-- */
     118             : #define EQ      '='
     119             : #define GT      '>'
     120             : #define LT      '<'
     121             : #define PLUS    '+'
     122             : #define MINUS   '-'
     123             : #define MUL     '*'
     124             : #define DIV     '/'
     125             : #define MOD     '%'
     126             : #define NOT     '!'
     127             : #define LPAR    '('
     128             : #define RPAR    ')'
     129             : #define BAND    '&' /* Bitwise AND */
     130             : #define BOR     '|'     /* Bitwise OR. */
     131             : #define BXOR    '^'     /* Bitwise eXclusive OR. */
     132             : #define BNOT    '~'     /* Bitwise NOT; Two's complement. */
     133             : #define QUES    '?'
     134             : #define COL     ':'
     135             : #define COMMA   ','
     136             : 
     137             : /* This should be the function corresponding to the operator with the
     138             :    highest precedence. */
     139             : #define EXP_HIGHEST     expcomma
     140             : 
     141             : #ifndef MAX_INT_LEN
     142             : #  define MAX_INT_LEN 32
     143             : #endif
     144             : 
     145             : struct lvalue
     146             : {
     147             :   char *tokstr;         /* possibly-rewritten lvalue if not NULL */
     148             :   intmax_t tokval;      /* expression evaluated value */
     149             :   SHELL_VAR *tokvar;    /* variable described by array or var reference */
     150             :   intmax_t ind;         /* array index if not -1 */
     151             : };
     152             : 
     153             : /* A structure defining a single expression context. */
     154             : typedef struct {
     155             :   int curtok, lasttok;
     156             :   char *expression, *tp, *lasttp;
     157             :   intmax_t tokval;
     158             :   char *tokstr;
     159             :   int noeval;
     160             :   struct lvalue lval;
     161             : } EXPR_CONTEXT;
     162             : 
     163             : static char     *expression;    /* The current expression */
     164             : static char     *tp;            /* token lexical position */
     165             : static char     *lasttp;        /* pointer to last token position */
     166             : static int      curtok;         /* the current token */
     167             : static int      lasttok;        /* the previous token */
     168             : static int      assigntok;      /* the OP in OP= */
     169             : static char     *tokstr;        /* current token string */
     170             : static intmax_t tokval;         /* current token value */
     171             : static int      noeval;         /* set to 1 if no assignment to be done */
     172             : static procenv_t evalbuf;
     173             : 
     174             : static struct lvalue curlval = {0, 0, 0, -1};
     175             : static struct lvalue lastlval = {0, 0, 0, -1};
     176             : 
     177             : static int      _is_arithop __P((int));
     178             : static void     readtok __P((void));    /* lexical analyzer */
     179             : 
     180             : static void     init_lvalue __P((struct lvalue *));
     181             : #if 0
     182             : static struct lvalue *alloc_lvalue __P((void));
     183             : static void     free_lvalue __P((struct lvalue *));
     184             : #endif
     185             : 
     186             : static intmax_t expr_streval __P((char *, int, struct lvalue *));
     187             : static intmax_t strlong __P((char *));
     188             : static void     evalerror __P((const char *));
     189             : 
     190             : static void     pushexp __P((void));
     191             : static void     popexp __P((void));
     192             : static void     expr_unwind __P((void));
     193             : static void     expr_bind_variable __P((char *, char *));
     194             : #if defined (ARRAY_VARS)
     195             : static void     expr_bind_array_element __P((char *, arrayind_t, char *));
     196             : #endif
     197             : 
     198             : static intmax_t subexpr __P((char *));
     199             : 
     200             : static intmax_t expcomma __P((void));
     201             : static intmax_t expassign __P((void));
     202             : static intmax_t expcond __P((void));
     203             : static intmax_t explor __P((void));
     204             : static intmax_t expland __P((void));
     205             : static intmax_t expbor __P((void));
     206             : static intmax_t expbxor __P((void));
     207             : static intmax_t expband __P((void));
     208             : static intmax_t exp5 __P((void));
     209             : static intmax_t exp4 __P((void));
     210             : static intmax_t expshift __P((void));
     211             : static intmax_t exp3 __P((void));
     212             : static intmax_t bash_exp2 __P((void));
     213             : static intmax_t exppower __P((void));
     214             : static intmax_t exp1 __P((void));
     215             : static intmax_t exp0 __P((void));
     216             : 
     217             : /* Global var which contains the stack of expression contexts. */
     218             : static EXPR_CONTEXT **expr_stack;
     219             : static int expr_depth;             /* Location in the stack. */
     220             : static int expr_stack_size;        /* Number of slots already allocated. */
     221             : 
     222             : extern char *this_command_name;
     223             : extern int unbound_vars_is_error, last_command_exit_value;
     224             : 
     225             : #if defined (ARRAY_VARS)
     226             : extern const char * const bash_badsub_errmsg;
     227             : #endif
     228             : 
     229             : #define SAVETOK(X) \
     230             :   do { \
     231             :     (X)->curtok = curtok; \
     232             :     (X)->lasttok = lasttok; \
     233             :     (X)->tp = tp; \
     234             :     (X)->lasttp = lasttp; \
     235             :     (X)->tokval = tokval; \
     236             :     (X)->tokstr = tokstr; \
     237             :     (X)->noeval = noeval; \
     238             :     (X)->lval = curlval; \
     239             :   } while (0)
     240             : 
     241             : #define RESTORETOK(X) \
     242             :   do { \
     243             :     curtok = (X)->curtok; \
     244             :     lasttok = (X)->lasttok; \
     245             :     tp = (X)->tp; \
     246             :     lasttp = (X)->lasttp; \
     247             :     tokval = (X)->tokval; \
     248             :     tokstr = (X)->tokstr; \
     249             :     noeval = (X)->noeval; \
     250             :     curlval = (X)->lval; \
     251             :   } while (0)
     252             : 
     253             : /* Push and save away the contents of the globals describing the
     254             :    current expression context. */
     255             : static void
     256         101 : pushexp ()
     257             : {
     258         101 :   EXPR_CONTEXT *context;
     259             : 
     260         101 :   if (expr_depth >= MAX_EXPR_RECURSION_LEVEL)
     261           0 :     evalerror (_("expression recursion level exceeded"));
     262             : 
     263         101 :   if (expr_depth >= expr_stack_size)
     264             :     {
     265          83 :       expr_stack_size += EXPR_STACK_GROW_SIZE;
     266          83 :       expr_stack = (EXPR_CONTEXT **)xrealloc (expr_stack, expr_stack_size * sizeof (EXPR_CONTEXT *));
     267             :     }
     268             : 
     269         101 :   context = (EXPR_CONTEXT *)xmalloc (sizeof (EXPR_CONTEXT));
     270             : 
     271         101 :   context->expression = expression;
     272         101 :   SAVETOK(context);
     273             : 
     274         101 :   expr_stack[expr_depth++] = context;
     275         101 : }
     276             : 
     277             : /* Pop the the contents of the expression context stack into the
     278             :    globals describing the current expression context. */
     279             : static void
     280          36 : popexp ()
     281             : {
     282          36 :   EXPR_CONTEXT *context;
     283             : 
     284          36 :   if (expr_depth == 0)
     285           0 :     evalerror (_("recursion stack underflow"));
     286             : 
     287          36 :   context = expr_stack[--expr_depth];
     288             : 
     289          36 :   expression = context->expression;
     290          36 :   RESTORETOK (context);
     291             : 
     292          36 :   free (context);
     293          36 : }
     294             : 
     295             : static void
     296          65 : expr_unwind ()
     297             : {
     298          65 :   while (--expr_depth > 0)
     299             :     {
     300           0 :       if (expr_stack[expr_depth]->tokstr)
     301           0 :         free (expr_stack[expr_depth]->tokstr);
     302             : 
     303           0 :       if (expr_stack[expr_depth]->expression)
     304           0 :         free (expr_stack[expr_depth]->expression);
     305             : 
     306           0 :       free (expr_stack[expr_depth]);
     307             :     }
     308          65 :   free (expr_stack[expr_depth]);        /* free the allocated EXPR_CONTEXT */
     309             : 
     310          65 :   noeval = 0;   /* XXX */
     311          65 : }
     312             : 
     313             : static void
     314           0 : expr_bind_variable (lhs, rhs)
     315             :      char *lhs, *rhs;
     316             : {
     317           0 :   SHELL_VAR *v;
     318             : 
     319           0 :   v = bind_int_variable (lhs, rhs);
     320           0 :   if (v && (readonly_p (v) || noassign_p (v)))
     321           0 :     sh_longjmp (evalbuf, 1);    /* variable assignment error */
     322           0 :   stupidly_hack_special_variables (lhs);
     323           0 : }
     324             : 
     325             : #if defined (ARRAY_VARS)
     326             : /* Rewrite tok, which is of the form vname[expression], to vname[ind], where
     327             :    IND is the already-calculated value of expression. */
     328             : static void
     329           0 : expr_bind_array_element (tok, ind, rhs)
     330             :      char *tok;
     331             :      arrayind_t ind;
     332             :      char *rhs;
     333             : {
     334           0 :   char *lhs, *vname;
     335           0 :   size_t llen;
     336           0 :   char ibuf[INT_STRLEN_BOUND (arrayind_t) + 1], *istr;
     337             : 
     338           0 :   istr = fmtumax (ind, 10, ibuf, sizeof (ibuf), 0);
     339           0 :   vname = array_variable_name (tok, (char **)NULL, (int *)NULL);
     340             : 
     341           0 :   llen = strlen (vname) + sizeof (ibuf) + 3;
     342           0 :   lhs = xmalloc (llen);
     343             : 
     344           0 :   sprintf (lhs, "%s[%s]", vname, istr);               /* XXX */
     345             :   
     346             : /*itrace("expr_bind_array_element: %s=%s", lhs, rhs);*/
     347           0 :   expr_bind_variable (lhs, rhs);
     348           0 :   free (vname);
     349           0 :   free (lhs);
     350           0 : }
     351             : #endif /* ARRAY_VARS */
     352             : 
     353             : /* Evaluate EXPR, and return the arithmetic result.  If VALIDP is
     354             :    non-null, a zero is stored into the location to which it points
     355             :    if the expression is invalid, non-zero otherwise.  If a non-zero
     356             :    value is returned in *VALIDP, the return value of evalexp() may
     357             :    be used.
     358             : 
     359             :    The `while' loop after the longjmp is caught relies on the above
     360             :    implementation of pushexp and popexp leaving in expr_stack[0] the
     361             :    values that the variables had when the program started.  That is,
     362             :    the first things saved are the initial values of the variables that
     363             :    were assigned at program startup or by the compiler.  Therefore, it is
     364             :    safe to let the loop terminate when expr_depth == 0, without freeing up
     365             :    any of the expr_depth[0] stuff. */
     366             : intmax_t
     367         101 : evalexp (expr, validp)
     368             :      char *expr;
     369             :      int *validp;
     370             : {
     371         101 :   intmax_t val;
     372         101 :   int c;
     373         101 :   procenv_t oevalbuf;
     374             : 
     375         101 :   val = 0;
     376         101 :   noeval = 0;
     377             : 
     378         101 :   FASTCOPY (evalbuf, oevalbuf, sizeof (evalbuf));
     379             : 
     380         166 :   c = setjmp_nosigs (evalbuf);
     381             : 
     382         166 :   if (c)
     383             :     {
     384          65 :       FREE (tokstr);
     385          65 :       FREE (expression);
     386          65 :       tokstr = expression = (char *)NULL;
     387             : 
     388          65 :       expr_unwind ();
     389             : 
     390          65 :       if (validp)
     391          65 :         *validp = 0;
     392          65 :       return (0);
     393             :     }
     394             : 
     395         101 :   val = subexpr (expr);
     396             : 
     397          36 :   if (validp)
     398          36 :     *validp = 1;
     399             : 
     400          36 :   FASTCOPY (oevalbuf, evalbuf, sizeof (evalbuf));
     401             : 
     402          36 :   return (val);
     403             : }
     404             : 
     405             : static intmax_t
     406         101 : subexpr (expr)
     407             :      char *expr;
     408             : {
     409         101 :   intmax_t val;
     410         101 :   char *p;
     411             : 
     412         137 :   for (p = expr; p && *p && cr_whitespace (*p); p++)
     413          36 :     ;
     414             : 
     415         101 :   if (p == NULL || *p == '\0')
     416             :     return (0);
     417             : 
     418         101 :   pushexp ();
     419         101 :   expression = savestring (expr);
     420         101 :   tp = expression;
     421             : 
     422         101 :   curtok = lasttok = 0;
     423         101 :   tokstr = (char *)NULL;
     424         101 :   tokval = 0;
     425         202 :   init_lvalue (&curlval);
     426         101 :   lastlval = curlval;
     427             : 
     428         101 :   readtok ();
     429             : 
     430          63 :   val = EXP_HIGHEST ();
     431             : 
     432          36 :   if (curtok != 0)
     433           0 :     evalerror (_("syntax error in expression"));
     434             : 
     435          36 :   FREE (tokstr);
     436          36 :   FREE (expression);
     437             : 
     438          36 :   popexp ();
     439             : 
     440          36 :   return val;
     441             : }
     442             : 
     443             : static intmax_t
     444          63 : expcomma ()
     445             : {
     446          63 :   register intmax_t value;
     447             : 
     448          63 :   value = expassign ();
     449          63 :   while (curtok == COMMA)
     450             :     {
     451           0 :       readtok ();
     452           0 :       value = expassign ();
     453             :     }
     454             : 
     455          36 :   return value;
     456             : }
     457             :   
     458             : static intmax_t
     459          63 : expassign ()
     460             : {
     461          63 :   register intmax_t value;
     462          63 :   char *lhs, *rhs;
     463          63 :   arrayind_t lind;
     464             : #if defined (HAVE_IMAXDIV)
     465          63 :   imaxdiv_t idiv;
     466             : #endif
     467             : 
     468          63 :   value = expcond ();
     469          36 :   if (curtok == EQ || curtok == OP_ASSIGN)
     470             :     {
     471           0 :       int special, op;
     472           0 :       intmax_t lvalue;
     473             : 
     474           0 :       special = curtok == OP_ASSIGN;
     475             : 
     476           0 :       if (lasttok != STR)
     477           0 :         evalerror (_("attempted assignment to non-variable"));
     478             : 
     479           0 :       if (special)
     480             :         {
     481           0 :           op = assigntok;               /* a OP= b */
     482           0 :           lvalue = value;
     483             :         }
     484             : 
     485             :       /* XXX - watch out for pointer aliasing issues here */
     486           0 :       lhs = savestring (tokstr);
     487             :       /* save ind in case rhs is string var and evaluation overwrites it */
     488           0 :       lind = curlval.ind;
     489           0 :       readtok ();
     490           0 :       value = expassign ();
     491             : 
     492           0 :       if (special)
     493             :         {
     494           0 :           if ((op == DIV || op == MOD) && value == 0)
     495             :             {
     496           0 :               if (noeval == 0)
     497           0 :                 evalerror (_("division by 0"));
     498             :               else
     499             :                 value = 1;
     500             :             }
     501             : 
     502           0 :           switch (op)
     503             :             {
     504           0 :             case MUL:
     505           0 :               lvalue *= value;
     506           0 :               break;
     507           0 :             case DIV:
     508             :             case MOD:
     509           0 :               if (lvalue == INTMAX_MIN && value == -1)
     510           0 :                 lvalue = (op == DIV) ? INTMAX_MIN : 0;
     511             :               else
     512             : #if HAVE_IMAXDIV
     513             :                 {
     514           0 :                   idiv = imaxdiv (lvalue, value);
     515           0 :                   lvalue = (op == DIV) ? idiv.quot : idiv.rem;
     516             :                 }
     517             : #else
     518             :                 lvalue = (op == DIV) ? lvalue / value : lvalue % value;
     519             : #endif
     520             :               break;
     521           0 :             case PLUS:
     522           0 :               lvalue += value;
     523           0 :               break;
     524           0 :             case MINUS:
     525           0 :               lvalue -= value;
     526           0 :               break;
     527           0 :             case LSH:
     528           0 :               lvalue <<= value;
     529           0 :               break;
     530           0 :             case RSH:
     531           0 :               lvalue >>= value;
     532           0 :               break;
     533           0 :             case BAND:
     534           0 :               lvalue &= value;
     535           0 :               break;
     536           0 :             case BOR:
     537           0 :               lvalue |= value;
     538           0 :               break;
     539           0 :             case BXOR:
     540           0 :               lvalue ^= value;
     541           0 :               break;
     542           0 :             default:
     543           0 :               free (lhs);
     544           0 :               evalerror (_("bug: bad expassign token"));
     545             :               break;
     546             :             }
     547             :           value = lvalue;
     548             :         }
     549             : 
     550           0 :       rhs = itos (value);
     551           0 :       if (noeval == 0)
     552             :         {
     553             : #if defined (ARRAY_VARS)
     554           0 :           if (lind != -1)
     555           0 :             expr_bind_array_element (lhs, lind, rhs);
     556             :           else
     557             : #endif
     558           0 :             expr_bind_variable (lhs, rhs);
     559             :         }
     560           0 :       if (curlval.tokstr && curlval.tokstr == tokstr)
     561           0 :         init_lvalue (&curlval);
     562             : 
     563           0 :       free (rhs);
     564           0 :       free (lhs);
     565           0 :       FREE (tokstr);
     566           0 :       tokstr = (char *)NULL;            /* For freeing on errors. */
     567             :     }
     568             : 
     569          36 :   return (value);
     570             : }
     571             : 
     572             : /* Conditional expression (expr?expr:expr) */
     573             : static intmax_t
     574          63 : expcond ()
     575             : {
     576          63 :   intmax_t cval, val1, val2, rval;
     577          63 :   int set_noeval;
     578             : 
     579          63 :   set_noeval = 0;
     580          63 :   rval = cval = explor ();
     581          36 :   if (curtok == QUES)           /* found conditional expr */
     582             :     {
     583           0 :       if (cval == 0)
     584             :         {
     585           0 :           set_noeval = 1;
     586           0 :           noeval++;
     587             :         }
     588             : 
     589           0 :       readtok ();
     590           0 :       if (curtok == 0 || curtok == COL)
     591           0 :         evalerror (_("expression expected"));
     592             : 
     593           0 :       val1 = EXP_HIGHEST ();
     594             : 
     595           0 :       if (set_noeval)
     596           0 :         noeval--;
     597           0 :       if (curtok != COL)
     598           0 :         evalerror (_("`:' expected for conditional expression"));
     599             : 
     600           0 :       set_noeval = 0;
     601           0 :       if (cval)
     602             :         {
     603           0 :           set_noeval = 1;
     604           0 :           noeval++;
     605             :         }
     606             : 
     607           0 :       readtok ();
     608           0 :       if (curtok == 0)
     609           0 :         evalerror (_("expression expected"));
     610           0 :       val2 = expcond ();
     611             : 
     612           0 :       if (set_noeval)
     613           0 :         noeval--;
     614           0 :       rval = cval ? val1 : val2;
     615           0 :       lasttok = COND;
     616             :     }
     617          36 :   return rval;
     618             : }
     619             : 
     620             : /* Logical OR. */
     621             : static intmax_t
     622          63 : explor ()
     623             : {
     624          63 :   register intmax_t val1, val2;
     625          63 :   int set_noeval;
     626             : 
     627          63 :   val1 = expland ();
     628             : 
     629          63 :   while (curtok == LOR)
     630             :     {
     631           0 :       set_noeval = 0;
     632           0 :       if (val1 != 0)
     633             :         {
     634           0 :           noeval++;
     635           0 :           set_noeval = 1;
     636             :         }
     637           0 :       readtok ();
     638           0 :       val2 = expland ();
     639           0 :       if (set_noeval)
     640           0 :         noeval--;
     641           0 :       val1 = val1 || val2;
     642           0 :       lasttok = LOR;
     643             :     }
     644             : 
     645          36 :   return (val1);
     646             : }
     647             : 
     648             : /* Logical AND. */
     649             : static intmax_t
     650          63 : expland ()
     651             : {
     652          63 :   register intmax_t val1, val2;
     653          63 :   int set_noeval;
     654             : 
     655          63 :   val1 = expbor ();
     656             : 
     657          63 :   while (curtok == LAND)
     658             :     {
     659           0 :       set_noeval = 0;
     660           0 :       if (val1 == 0)
     661             :         {
     662           0 :           set_noeval = 1;
     663           0 :           noeval++;
     664             :         }
     665           0 :       readtok ();
     666           0 :       val2 = expbor ();
     667           0 :       if (set_noeval)
     668           0 :         noeval--;
     669           0 :       val1 = val1 && val2;
     670           0 :       lasttok = LAND;
     671             :     }
     672             : 
     673          36 :   return (val1);
     674             : }
     675             : 
     676             : /* Bitwise OR. */
     677             : static intmax_t
     678          63 : expbor ()
     679             : {
     680          63 :   register intmax_t val1, val2;
     681             : 
     682          63 :   val1 = expbxor ();
     683             : 
     684          63 :   while (curtok == BOR)
     685             :     {
     686           0 :       readtok ();
     687           0 :       val2 = expbxor ();
     688           0 :       val1 = val1 | val2;
     689           0 :       lasttok = NUM;
     690             :     }
     691             : 
     692          36 :   return (val1);
     693             : }
     694             : 
     695             : /* Bitwise XOR. */
     696             : static intmax_t
     697          63 : expbxor ()
     698             : {
     699          63 :   register intmax_t val1, val2;
     700             : 
     701          63 :   val1 = expband ();
     702             : 
     703          63 :   while (curtok == BXOR)
     704             :     {
     705           0 :       readtok ();
     706           0 :       val2 = expband ();
     707           0 :       val1 = val1 ^ val2;
     708           0 :       lasttok = NUM;
     709             :     }
     710             : 
     711          36 :   return (val1);
     712             : }
     713             : 
     714             : /* Bitwise AND. */
     715             : static intmax_t
     716          63 : expband ()
     717             : {
     718          63 :   register intmax_t val1, val2;
     719             : 
     720          63 :   val1 = exp5 ();
     721             : 
     722          63 :   while (curtok == BAND)
     723             :     {
     724           0 :       readtok ();
     725           0 :       val2 = exp5 ();
     726           0 :       val1 = val1 & val2;
     727           0 :       lasttok = NUM;
     728             :     }
     729             : 
     730          36 :   return (val1);
     731             : }
     732             : 
     733             : static intmax_t
     734          63 : exp5 ()
     735             : {
     736          63 :   register intmax_t val1, val2;
     737             : 
     738          63 :   val1 = exp4 ();
     739             : 
     740          63 :   while ((curtok == EQEQ) || (curtok == NEQ))
     741             :     {
     742           0 :       int op = curtok;
     743             : 
     744           0 :       readtok ();
     745           0 :       val2 = exp4 ();
     746           0 :       if (op == EQEQ)
     747           0 :         val1 = (val1 == val2);
     748           0 :       else if (op == NEQ)
     749           0 :         val1 = (val1 != val2);
     750           0 :       lasttok = NUM;
     751             :     }
     752          36 :   return (val1);
     753             : }
     754             : 
     755             : static intmax_t
     756          63 : exp4 ()
     757             : {
     758          63 :   register intmax_t val1, val2;
     759             : 
     760          63 :   val1 = expshift ();
     761          63 :   while ((curtok == LEQ) ||
     762          36 :          (curtok == GEQ) ||
     763          36 :          (curtok == LT) ||
     764             :          (curtok == GT))
     765             :     {
     766           0 :       int op = curtok;
     767             : 
     768           0 :       readtok ();
     769           0 :       val2 = expshift ();
     770             : 
     771           0 :       if (op == LEQ)
     772           0 :         val1 = val1 <= val2;
     773           0 :       else if (op == GEQ)
     774           0 :         val1 = val1 >= val2;
     775           0 :       else if (op == LT)
     776           0 :         val1 = val1 < val2;
     777             :       else                      /* (op == GT) */
     778           0 :         val1 = val1 > val2;
     779           0 :       lasttok = NUM;
     780             :     }
     781          36 :   return (val1);
     782             : }
     783             : 
     784             : /* Left and right shifts. */
     785             : static intmax_t
     786          63 : expshift ()
     787             : {
     788          63 :   register intmax_t val1, val2;
     789             : 
     790          63 :   val1 = exp3 ();
     791             : 
     792          63 :   while ((curtok == LSH) || (curtok == RSH))
     793             :     {
     794           0 :       int op = curtok;
     795             : 
     796           0 :       readtok ();
     797           0 :       val2 = exp3 ();
     798             : 
     799           0 :       if (op == LSH)
     800           0 :         val1 = val1 << val2;
     801             :       else
     802           0 :         val1 = val1 >> val2;
     803           0 :       lasttok = NUM;
     804             :     }
     805             : 
     806          36 :   return (val1);
     807             : }
     808             : 
     809             : static intmax_t
     810          63 : exp3 ()
     811             : {
     812          63 :   register intmax_t val1, val2;
     813             : 
     814          63 :   val1 = bash_exp2 ();
     815             : 
     816          63 :   while ((curtok == PLUS) || (curtok == MINUS))
     817             :     {
     818           0 :       int op = curtok;
     819             : 
     820           0 :       readtok ();
     821           0 :       val2 = bash_exp2 ();
     822             : 
     823           0 :       if (op == PLUS)
     824           0 :         val1 += val2;
     825           0 :       else if (op == MINUS)
     826           0 :         val1 -= val2;
     827           0 :       lasttok = NUM;
     828             :     }
     829          36 :   return (val1);
     830             : }
     831             : 
     832             : static intmax_t
     833          63 : bash_exp2 ()
     834             : {
     835          63 :   register intmax_t val1, val2;
     836             : #if defined (HAVE_IMAXDIV)
     837          63 :   imaxdiv_t idiv;
     838             : #endif
     839             : 
     840          63 :   val1 = exppower ();
     841             : 
     842          63 :   while ((curtok == MUL) ||
     843          36 :          (curtok == DIV) ||
     844             :          (curtok == MOD))
     845             :     {
     846          27 :       int op = curtok;
     847          27 :       char *stp, *sltp;
     848             : 
     849          27 :       stp = tp;
     850          27 :       readtok ();
     851             : 
     852          27 :       val2 = exppower ();
     853             : 
     854             :       /* Handle division by 0 and twos-complement arithmetic overflow */
     855          27 :       if (((op == DIV) || (op == MOD)) && (val2 == 0))
     856             :         {
     857          27 :           if (noeval == 0)
     858             :             {
     859          27 :               sltp = lasttp;
     860          27 :               lasttp = stp;
     861          27 :               while (lasttp && *lasttp && whitespace (*lasttp))
     862           0 :                 lasttp++;
     863          27 :               evalerror (_("division by 0"));
     864             :               lasttp = sltp;
     865             :             }
     866             :           else
     867             :             val2 = 1;
     868             :         }
     869           0 :       else if (op == MOD && val1 == INTMAX_MIN && val2 == -1)
     870             :         {
     871             :           val1 = 0;
     872             :           continue;
     873             :         }
     874           0 :       else if (op == DIV && val1 == INTMAX_MIN && val2 == -1)
     875           0 :         val2 = 1;
     876             : 
     877           0 :       if (op == MUL)
     878           0 :         val1 *= val2;
     879           0 :       else if (op == DIV || op == MOD)
     880             : #if defined (HAVE_IMAXDIV)
     881             :         {
     882           0 :           idiv = imaxdiv (val1, val2);
     883           0 :           val1 = (op == DIV) ? idiv.quot : idiv.rem;
     884             :         }
     885             : #else
     886             :         val1 = (op == DIV) ? val1 / val2 : val1 % val2;
     887             : #endif
     888           0 :       lasttok = NUM;
     889             :     }
     890          36 :   return (val1);
     891             : }
     892             : 
     893             : static intmax_t
     894             : ipow (base, exp)
     895             :      intmax_t base, exp;
     896             : {
     897             :   intmax_t result;
     898             : 
     899             :   result = 1;
     900           0 :   while (exp)
     901             :     {
     902           0 :       if (exp & 1)
     903           0 :         result *= base;
     904           0 :       exp >>= 1;
     905           0 :       base *= base;
     906             :     }
     907             :   return result;
     908             : }
     909             : 
     910             : static intmax_t
     911          90 : exppower ()
     912             : {
     913          90 :   register intmax_t val1, val2;
     914             : 
     915          90 :   val1 = exp1 ();
     916          90 :   while (curtok == POWER)
     917             :     {
     918           0 :       readtok ();
     919           0 :       val2 = exppower ();       /* exponentiation is right-associative */
     920           0 :       lasttok = NUM;
     921           0 :       if (val2 == 0)
     922             :         return (1);
     923           0 :       if (val2 < 0)
     924           0 :         evalerror (_("exponent less than 0"));
     925             :       val1 = ipow (val1, val2);
     926             :     }
     927             :   return (val1);
     928             : }
     929             : 
     930             : static intmax_t
     931         126 : exp1 ()
     932             : {
     933         126 :   register intmax_t val;
     934             : 
     935         126 :   if (curtok == NOT)
     936             :     {
     937           0 :       readtok ();
     938           0 :       val = !exp1 ();
     939           0 :       lasttok = NUM;
     940             :     }
     941         126 :   else if (curtok == BNOT)
     942             :     {
     943           0 :       readtok ();
     944           0 :       val = ~exp1 ();
     945           0 :       lasttok = NUM;
     946             :     }
     947         126 :   else if (curtok == MINUS)
     948             :     {
     949          36 :       readtok ();
     950          36 :       val = - exp1 ();
     951          36 :       lasttok = NUM;
     952             :     }
     953          90 :   else if (curtok == PLUS)
     954             :     {
     955           0 :       readtok ();
     956           0 :       val = exp1 ();
     957           0 :       lasttok = NUM;
     958             :     }
     959             :   else
     960          90 :     val = exp0 ();
     961             : 
     962         126 :   return (val);
     963             : }
     964             : 
     965             : static intmax_t
     966          90 : exp0 ()
     967             : {
     968          90 :   register intmax_t val = 0, v2;
     969          90 :   char *vincdec;
     970          90 :   int stok;
     971          90 :   EXPR_CONTEXT ec;
     972             : 
     973             :   /* XXX - might need additional logic here to decide whether or not
     974             :            pre-increment or pre-decrement is legal at this point. */
     975          90 :   if (curtok == PREINC || curtok == PREDEC)
     976             :     {
     977           0 :       stok = lasttok = curtok;
     978           0 :       readtok ();
     979           0 :       if (curtok != STR)
     980             :         /* readtok() catches this */
     981           0 :         evalerror (_("identifier expected after pre-increment or pre-decrement"));
     982             : 
     983           0 :       v2 = tokval + ((stok == PREINC) ? 1 : -1);
     984           0 :       vincdec = itos (v2);
     985           0 :       if (noeval == 0)
     986             :         {
     987             : #if defined (ARRAY_VARS)
     988           0 :           if (curlval.ind != -1)
     989           0 :             expr_bind_array_element (curlval.tokstr, curlval.ind, vincdec);
     990             :           else
     991             : #endif
     992           0 :             expr_bind_variable (tokstr, vincdec);
     993             :         }
     994           0 :       free (vincdec);
     995           0 :       val = v2;
     996             : 
     997           0 :       curtok = NUM;     /* make sure --x=7 is flagged as an error */
     998           0 :       readtok ();
     999             :     }
    1000          90 :   else if (curtok == LPAR)
    1001             :     {
    1002             :       /* XXX - save curlval here?  Or entire expression context? */
    1003           0 :       readtok ();
    1004           0 :       val = EXP_HIGHEST ();
    1005             : 
    1006           0 :       if (curtok != RPAR) /* ( */
    1007           0 :         evalerror (_("missing `)'"));
    1008             : 
    1009             :       /* Skip over closing paren. */
    1010           0 :       readtok ();
    1011             :     }
    1012          90 :   else if ((curtok == NUM) || (curtok == STR))
    1013             :     {
    1014          90 :       val = tokval;
    1015          90 :       if (curtok == STR)
    1016             :         {
    1017          90 :           SAVETOK (&ec);
    1018          90 :           tokstr = (char *)NULL;        /* keep it from being freed */
    1019          90 :           noeval = 1;
    1020          90 :           readtok ();
    1021          90 :           stok = curtok;
    1022             : 
    1023             :           /* post-increment or post-decrement */
    1024          90 :           if (stok == POSTINC || stok == POSTDEC)
    1025             :             {
    1026             :               /* restore certain portions of EC */
    1027           0 :               tokstr = ec.tokstr;
    1028           0 :               noeval = ec.noeval;
    1029           0 :               curlval = ec.lval;
    1030           0 :               lasttok = STR;    /* ec.curtok */
    1031             : 
    1032           0 :               v2 = val + ((stok == POSTINC) ? 1 : -1);
    1033           0 :               vincdec = itos (v2);
    1034           0 :               if (noeval == 0)
    1035             :                 {
    1036             : #if defined (ARRAY_VARS)
    1037           0 :                   if (curlval.ind != -1)
    1038           0 :                     expr_bind_array_element (curlval.tokstr, curlval.ind, vincdec);
    1039             :                   else
    1040             : #endif
    1041           0 :                     expr_bind_variable (tokstr, vincdec);
    1042             :                 }
    1043           0 :               free (vincdec);
    1044           0 :               curtok = NUM;     /* make sure x++=7 is flagged as an error */
    1045             :             }
    1046             :           else
    1047             :             {
    1048             :               /* XXX - watch out for pointer aliasing issues here */
    1049          90 :               if (stok == STR)  /* free new tokstr before old one is restored */
    1050           0 :                 FREE (tokstr);
    1051          90 :               RESTORETOK (&ec);
    1052             :             }
    1053             :         }
    1054             :           
    1055          90 :       readtok ();
    1056             :     }
    1057             :   else
    1058           0 :     evalerror (_("syntax error: operand expected"));
    1059             : 
    1060          90 :   return (val);
    1061             : }
    1062             : 
    1063             : static void
    1064             : init_lvalue (lv)
    1065             :      struct lvalue *lv;
    1066             : {
    1067         128 :   lv->tokstr = 0;
    1068         128 :   lv->tokvar = 0;
    1069         101 :   lv->tokval = lv->ind = -1;
    1070             : }
    1071             : 
    1072             : #if 0
    1073             : static struct lvalue *
    1074             : alloc_lvalue ()
    1075             : {
    1076             :   struct lvalue *lv;
    1077             : 
    1078             :   lv = xmalloc (sizeof (struct lvalue));
    1079             :   init_lvalue (lv);
    1080             :   return (lv);
    1081             : }
    1082             : #endif
    1083             : 
    1084             : #if 0
    1085             : static void
    1086             : free_lvalue (lv)
    1087             :      struct lvalue *lv;
    1088             : {
    1089             :   free (lv);            /* should be inlined */
    1090             : }
    1091             : #endif
    1092             : 
    1093             : static intmax_t
    1094          90 : expr_streval (tok, e, lvalue)
    1095             :      char *tok;
    1096             :      int e;
    1097             :      struct lvalue *lvalue;
    1098             : {
    1099          90 :   SHELL_VAR *v;
    1100          90 :   char *value;
    1101          90 :   intmax_t tval;
    1102             : #if defined (ARRAY_VARS)
    1103          90 :   arrayind_t ind;
    1104             : #endif
    1105             : 
    1106             : /*itrace("expr_streval: %s: noeval = %d", tok, noeval);*/
    1107             :   /* If we are suppressing evaluation, just short-circuit here instead of
    1108             :      going through the rest of the evaluator. */
    1109          90 :   if (noeval)
    1110             :     return (0);
    1111             : 
    1112             :   /* [[[[[ */
    1113             : #if defined (ARRAY_VARS)
    1114          90 :   v = (e == ']') ? array_variable_part (tok, (char **)0, (int *)0) : find_variable (tok);
    1115             : #else
    1116             :   v = find_variable (tok);
    1117             : #endif
    1118             : 
    1119          90 :   if ((v == 0 || invisible_p (v)) && unbound_vars_is_error)
    1120             :     {
    1121             : #if defined (ARRAY_VARS)
    1122           0 :       value = (e == ']') ? array_variable_name (tok, (char **)0, (int *)0) : tok;
    1123             : #else
    1124             :       value = tok;
    1125             : #endif
    1126             : 
    1127           0 :       last_command_exit_value = EXECUTION_FAILURE;
    1128           0 :       err_unboundvar (value);
    1129             : 
    1130             : #if defined (ARRAY_VARS)
    1131           0 :       if (e == ']')
    1132           0 :         FREE (value);   /* array_variable_name returns new memory */
    1133             : #endif
    1134             : 
    1135           0 :       if (no_longjmp_on_fatal_error && interactive_shell)
    1136           0 :         sh_longjmp (evalbuf, 1);
    1137             : 
    1138           0 :       if (interactive_shell)
    1139             :         {
    1140           0 :           expr_unwind ();
    1141           0 :           top_level_cleanup ();
    1142           0 :           jump_to_top_level (DISCARD);
    1143             :         }
    1144             :       else
    1145           0 :         jump_to_top_level (FORCE_EOF);
    1146             :     }
    1147             : 
    1148             : #if defined (ARRAY_VARS)
    1149          90 :   ind = -1;
    1150             :   /* Second argument of 0 to get_array_value means that we don't allow
    1151             :      references like array[@].  In this case, get_array_value is just
    1152             :      like get_variable_value in that it does not return newly-allocated
    1153             :      memory or quote the results. */
    1154          90 :   value = (e == ']') ? get_array_value (tok, 0, (int *)NULL, &ind) : get_variable_value (v);
    1155             : #else
    1156             :   value = get_variable_value (v);
    1157             : #endif
    1158             : 
    1159          90 :   tval = (value && *value) ? subexpr (value) : 0;
    1160             : 
    1161          90 :   if (lvalue)
    1162             :     {
    1163          90 :       lvalue->tokstr = tok;  /* XXX */
    1164          90 :       lvalue->tokval = tval;
    1165          90 :       lvalue->tokvar = v;    /* XXX */
    1166             : #if defined (ARRAY_VARS)
    1167          90 :       lvalue->ind = ind;
    1168             : #else
    1169             :       lvalue->ind = -1;
    1170             : #endif
    1171             :     }
    1172             :           
    1173             :   return (tval);
    1174             : }
    1175             : 
    1176             : static int
    1177             : _is_multiop (c)
    1178             :      int c;
    1179             : {
    1180           9 :   switch (c)
    1181             :     {
    1182             :     case EQEQ:
    1183             :     case NEQ:
    1184             :     case LEQ:
    1185             :     case GEQ:
    1186             :     case LAND:
    1187             :     case LOR:
    1188             :     case LSH:
    1189             :     case RSH:
    1190             :     case OP_ASSIGN:
    1191             :     case COND:
    1192             :     case POWER:
    1193             :     case PREINC:
    1194             :     case PREDEC:
    1195             :     case POSTINC:
    1196             :     case POSTDEC:
    1197             :       return 1;
    1198             :     default:
    1199             :       return 0;
    1200             :     }
    1201             : }
    1202             : 
    1203             : static int
    1204         245 : _is_arithop (c)
    1205             :      int c;
    1206             : {
    1207         245 :   switch (c)
    1208             :     {
    1209             :     case EQ:
    1210             :     case GT:
    1211             :     case LT:
    1212             :     case PLUS:
    1213             :     case MINUS:
    1214             :     case MUL:
    1215             :     case DIV:
    1216             :     case MOD:
    1217             :     case NOT:
    1218             :     case LPAR:
    1219             :     case RPAR:
    1220             :     case BAND:
    1221             :     case BOR:
    1222             :     case BXOR:
    1223             :     case BNOT:
    1224             :       return 1;         /* operator tokens */
    1225             :     case QUES:
    1226             :     case COL:
    1227             :     case COMMA:
    1228             :       return 1;         /* questionable */
    1229          47 :     default:
    1230          47 :       return 0;         /* anything else is invalid */
    1231             :     }
    1232             : }
    1233             : 
    1234             : /* Lexical analyzer/token reader for the expression evaluator.  Reads the
    1235             :    next token and puts its value into curtok, while advancing past it.
    1236             :    Updates value of tp.  May also set tokval (for number) or tokstr (for
    1237             :    string). */
    1238             : static void
    1239         443 : readtok ()
    1240             : {
    1241         443 :   register char *cp, *xp;
    1242         443 :   register unsigned char c, c1;
    1243         443 :   register int e;
    1244             : 
    1245             :   /* Skip leading whitespace. */
    1246         443 :   cp = tp;
    1247         443 :   c = e = 0;
    1248         614 :   while (cp && (c = *cp) && (cr_whitespace (c)))
    1249         171 :     cp++;
    1250             : 
    1251         443 :   if (c)
    1252         335 :     cp++;
    1253             : 
    1254         443 :   if (c == '\0')
    1255             :     {
    1256         108 :       lasttok = curtok;
    1257         108 :       curtok = 0;
    1258         108 :       tp = cp;
    1259         108 :       return;
    1260             :     }
    1261         335 :   lasttp = tp = cp - 1;
    1262             : 
    1263         335 :   if (legal_variable_starter (c))
    1264          90 :     {
    1265             :       /* variable names not preceded with a dollar sign are shell variables. */
    1266             :       char *savecp;
    1267             :       EXPR_CONTEXT ec;
    1268             :       int peektok;
    1269             : 
    1270         351 :       while (legal_variable_char (c))
    1271         252 :         c = *cp++;
    1272             : 
    1273          99 :       c = *--cp;
    1274             : 
    1275             : #if defined (ARRAY_VARS)
    1276          99 :       if (c == '[')
    1277             :         {
    1278           0 :           e = skipsubscript (cp, 0, 0);
    1279           0 :           if (cp[e] == ']')
    1280             :             {
    1281           0 :               cp += e + 1;
    1282           0 :               c = *cp;
    1283           0 :               e = ']';
    1284             :             }
    1285             :           else
    1286           0 :             evalerror (bash_badsub_errmsg);
    1287             :         }
    1288             : #endif /* ARRAY_VARS */
    1289             : 
    1290          99 :       *cp = '\0';
    1291             :       /* XXX - watch out for pointer aliasing issues here */
    1292          99 :       if (curlval.tokstr && curlval.tokstr == tokstr)
    1293          27 :         init_lvalue (&curlval);
    1294             : 
    1295          99 :       FREE (tokstr);
    1296          99 :       tokstr = savestring (tp);
    1297          99 :       *cp = c;
    1298             : 
    1299             :       /* XXX - make peektok part of saved token state? */
    1300          99 :       SAVETOK (&ec);
    1301          99 :       tokstr = (char *)NULL;    /* keep it from being freed */
    1302          99 :       tp = savecp = cp;
    1303          99 :       noeval = 1;
    1304          99 :       curtok = STR;
    1305          99 :       readtok ();
    1306          90 :       peektok = curtok;
    1307          90 :       if (peektok == STR)       /* free new tokstr before old one is restored */
    1308           0 :         FREE (tokstr);
    1309          90 :       RESTORETOK (&ec);
    1310          90 :       cp = savecp;
    1311             : 
    1312             :       /* The tests for PREINC and PREDEC aren't strictly correct, but they
    1313             :          preserve old behavior if a construct like --x=9 is given. */
    1314          90 :       if (lasttok == PREINC || lasttok == PREDEC || peektok != EQ)
    1315             :         {
    1316          90 :           lastlval = curlval;
    1317          90 :           tokval = expr_streval (tokstr, e, &curlval);
    1318             :         }
    1319             :       else
    1320           0 :         tokval = 0;
    1321             : 
    1322          90 :       lasttok = curtok;
    1323          90 :       curtok = STR;
    1324             :     }
    1325         236 :   else if (DIGIT(c))
    1326             :     {
    1327           0 :       while (ISALNUM (c) || c == '#' || c == '@' || c == '_')
    1328           0 :         c = *cp++;
    1329             : 
    1330           0 :       c = *--cp;
    1331           0 :       *cp = '\0';
    1332             : 
    1333           0 :       tokval = strlong (tp);
    1334           0 :       *cp = c;
    1335           0 :       lasttok = curtok;
    1336           0 :       curtok = NUM;
    1337             :     }
    1338             :   else
    1339             :     {
    1340         236 :       c1 = *cp++;
    1341         236 :       if ((c == EQ) && (c1 == EQ))
    1342             :         c = EQEQ;
    1343         236 :       else if ((c == NOT) && (c1 == EQ))
    1344             :         c = NEQ;
    1345         236 :       else if ((c == GT) && (c1 == EQ))
    1346             :         c = GEQ;
    1347         236 :       else if ((c == LT) && (c1 == EQ))
    1348             :         c = LEQ;
    1349         236 :       else if ((c == LT) && (c1 == LT))
    1350             :         {
    1351           0 :           if (*cp == '=')       /* a <<= b */
    1352             :             {
    1353           0 :               assigntok = LSH;
    1354           0 :               c = OP_ASSIGN;
    1355           0 :               cp++;
    1356             :             }
    1357             :           else
    1358             :             c = LSH;
    1359             :         }
    1360         236 :       else if ((c == GT) && (c1 == GT))
    1361             :         {
    1362           0 :           if (*cp == '=')
    1363             :             {
    1364           0 :               assigntok = RSH;  /* a >>= b */
    1365           0 :               c = OP_ASSIGN;
    1366           0 :               cp++;
    1367             :             }
    1368             :           else
    1369             :             c = RSH;
    1370             :         }
    1371         236 :       else if ((c == BAND) && (c1 == BAND))
    1372             :         c = LAND;
    1373         236 :       else if ((c == BOR) && (c1 == BOR))
    1374             :         c = LOR;
    1375         236 :       else if ((c == '*') && (c1 == '*'))
    1376             :         c = POWER;
    1377         236 :       else if ((c == '-' || c == '+') && c1 == c && curtok == STR)
    1378           0 :         c = (c == '-') ? POSTDEC : POSTINC;
    1379         236 :       else if ((c == '-' || c == '+') && c1 == c)
    1380             :         {
    1381             :           /* Quickly scan forward to see if this is followed by optional
    1382             :              whitespace and an identifier. */
    1383             :           xp = cp;
    1384           0 :           while (xp && *xp && cr_whitespace (*xp))
    1385           0 :             xp++;
    1386           0 :           if (legal_variable_starter ((unsigned char)*xp))
    1387           0 :             c = (c == '-') ? PREDEC : PREINC;
    1388             :           else
    1389             :             cp--;       /* not preinc or predec, so unget the character */
    1390             :         }
    1391         236 :       else if (c1 == EQ && member (c, "*/%+-&^|"))
    1392             :         {
    1393           0 :           assigntok = c;        /* a OP= b */
    1394           0 :           c = OP_ASSIGN;
    1395             :         }
    1396         236 :       else if (_is_arithop (c) == 0)
    1397             :         {
    1398          38 :           cp--;
    1399             :           /* use curtok, since it hasn't been copied to lasttok yet */
    1400          38 :           if (curtok == 0 || _is_arithop (curtok) || _is_multiop (curtok))
    1401          29 :             evalerror (_("syntax error: operand expected"));
    1402             :           else
    1403           9 :             evalerror (_("syntax error: invalid arithmetic operator"));
    1404             :         }
    1405             :       else
    1406             :         cp--;                   /* `unget' the character */
    1407             : 
    1408             :       /* Should check here to make sure that the current character is one
    1409             :          of the recognized operators and flag an error if not.  Could create
    1410             :          a character map the first time through and check it on subsequent
    1411             :          calls. */
    1412         198 :       lasttok = curtok;
    1413         198 :       curtok = c;
    1414             :     }
    1415         288 :   tp = cp;
    1416             : }
    1417             : 
    1418             : static void
    1419          65 : evalerror (msg)
    1420             :      const char *msg;
    1421             : {
    1422          65 :   char *name, *t;
    1423             : 
    1424          65 :   name = this_command_name;
    1425          92 :   for (t = expression; whitespace (*t); t++)
    1426          27 :     ;
    1427         153 :   internal_error (_("%s%s%s: %s (error token is \"%s\")"),
    1428             :                    name ? name : "", name ? ": " : "", t,
    1429          65 :                    msg, (lasttp && *lasttp) ? lasttp : "");
    1430          65 :   sh_longjmp (evalbuf, 1);
    1431             : }
    1432             : 
    1433             : /* Convert a string to an intmax_t integer, with an arbitrary base.
    1434             :    0nnn -> base 8
    1435             :    0[Xx]nn -> base 16
    1436             :    Anything else: [base#]number (this is implemented to match ksh93)
    1437             : 
    1438             :    Base may be >=2 and <=64.  If base is <= 36, the numbers are drawn
    1439             :    from [0-9][a-zA-Z], and lowercase and uppercase letters may be used
    1440             :    interchangably.  If base is > 36 and <= 64, the numbers are drawn
    1441             :    from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 --
    1442             :    you get the picture). */
    1443             : 
    1444             : static intmax_t
    1445           0 : strlong (num)
    1446             :      char *num;
    1447             : {
    1448           0 :   register char *s;
    1449           0 :   register unsigned char c;
    1450           0 :   int base, foundbase;
    1451           0 :   intmax_t val;
    1452             : 
    1453           0 :   s = num;
    1454             : 
    1455           0 :   base = 10;
    1456           0 :   foundbase = 0;
    1457           0 :   if (*s == '0')
    1458             :     {
    1459           0 :       s++;
    1460             : 
    1461           0 :       if (*s == '\0')
    1462             :         return 0;
    1463             : 
    1464             :        /* Base 16? */
    1465           0 :       if (*s == 'x' || *s == 'X')
    1466             :         {
    1467           0 :           base = 16;
    1468           0 :           s++;
    1469             :         }
    1470             :       else
    1471             :         base = 8;
    1472             :       foundbase++;
    1473             :     }
    1474             : 
    1475           0 :   val = 0;
    1476           0 :   for (c = *s++; c; c = *s++)
    1477             :     {
    1478           0 :       if (c == '#')
    1479             :         {
    1480           0 :           if (foundbase)
    1481           0 :             evalerror (_("invalid number"));
    1482             : 
    1483             :           /* Illegal base specifications raise an evaluation error. */
    1484           0 :           if (val < 2 || val > 64)
    1485           0 :             evalerror (_("invalid arithmetic base"));
    1486             : 
    1487           0 :           base = val;
    1488           0 :           val = 0;
    1489           0 :           foundbase++;
    1490             :         }
    1491           0 :       else if (ISALNUM(c) || (c == '_') || (c == '@'))
    1492             :         {
    1493           0 :           if (DIGIT(c))
    1494             :             c = TODIGIT(c);
    1495           0 :           else if (c >= 'a' && c <= 'z')
    1496           0 :             c -= 'a' - 10;
    1497           0 :           else if (c >= 'A' && c <= 'Z')
    1498           0 :             c -= 'A' - ((base <= 36) ? 10 : 36);
    1499           0 :           else if (c == '@')
    1500             :             c = 62;
    1501           0 :           else if (c == '_')
    1502           0 :             c = 63;
    1503             : 
    1504           0 :           if (c >= base)
    1505           0 :             evalerror (_("value too great for base"));
    1506             : 
    1507           0 :           val = (val * base) + c;
    1508             :         }
    1509             :       else
    1510             :         break;
    1511             :     }
    1512             : 
    1513             :   return (val);
    1514             : }
    1515             : 
    1516             : #if defined (EXPR_TEST)
    1517             : void *
    1518             : xmalloc (n)
    1519             :      int n;
    1520             : {
    1521             :   return (malloc (n));
    1522             : }
    1523             : 
    1524             : void *
    1525             : xrealloc (s, n)
    1526             :      char *s;
    1527             :      int n;
    1528             : {
    1529             :   return (realloc (s, n));
    1530             : }
    1531             : 
    1532             : SHELL_VAR *find_variable () { return 0;}
    1533             : SHELL_VAR *bind_variable () { return 0; }
    1534             : 
    1535             : char *get_string_value () { return 0; }
    1536             : 
    1537             : procenv_t top_level;
    1538             : 
    1539             : main (argc, argv)
    1540             :      int argc;
    1541             :      char **argv;
    1542             : {
    1543             :   register int i;
    1544             :   intmax_t v;
    1545             :   int expok;
    1546             : 
    1547             :   if (setjmp (top_level))
    1548             :     exit (0);
    1549             : 
    1550             :   for (i = 1; i < argc; i++)
    1551             :     {
    1552             :       v = evalexp (argv[i], &expok);
    1553             :       if (expok == 0)
    1554             :         fprintf (stderr, _("%s: expression error\n"), argv[i]);
    1555             :       else
    1556             :         printf ("'%s' -> %ld\n", argv[i], v);
    1557             :     }
    1558             :   exit (0);
    1559             : }
    1560             : 
    1561             : int
    1562             : builtin_error (format, arg1, arg2, arg3, arg4, arg5)
    1563             :      char *format;
    1564             : {
    1565             :   fprintf (stderr, "expr: ");
    1566             :   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
    1567             :   fprintf (stderr, "\n");
    1568             :   return 0;
    1569             : }
    1570             : 
    1571             : char *
    1572             : itos (n)
    1573             :      intmax_t n;
    1574             : {
    1575             :   return ("42");
    1576             : }
    1577             : 
    1578             : #endif /* EXPR_TEST */

Generated by: LCOV version 1.14.0.6.4058