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