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