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