]> git.ipfire.org Git - thirdparty/bash.git/blame - expr.c
commit bash-20080410 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 }
ccc6cda3 523 val2 = explor ();
d166f048 524 if (set_noeval)
28ef6c31 525 noeval--;
ccc6cda3
JA
526 rval = cval ? val1 : val2;
527 lasttok = COND;
528 }
529 return rval;
530}
531
726f6388 532/* Logical OR. */
7117c2d2 533static intmax_t
726f6388
JA
534explor ()
535{
7117c2d2 536 register intmax_t val1, val2;
d166f048 537 int set_noeval;
726f6388
JA
538
539 val1 = expland ();
540
541 while (curtok == LOR)
542 {
d166f048 543 set_noeval = 0;
ccc6cda3 544 if (val1 != 0)
d166f048
JA
545 {
546 noeval++;
547 set_noeval = 1;
548 }
549 readtok ();
726f6388 550 val2 = expland ();
d166f048 551 if (set_noeval)
ccc6cda3 552 noeval--;
726f6388 553 val1 = val1 || val2;
d166f048 554 lasttok = LOR;
726f6388
JA
555 }
556
557 return (val1);
558}
559
560/* Logical AND. */
7117c2d2 561static intmax_t
726f6388
JA
562expland ()
563{
7117c2d2 564 register intmax_t val1, val2;
d166f048 565 int set_noeval;
726f6388
JA
566
567 val1 = expbor ();
568
569 while (curtok == LAND)
570 {
d166f048 571 set_noeval = 0;
ccc6cda3 572 if (val1 == 0)
d166f048
JA
573 {
574 set_noeval = 1;
575 noeval++;
576 }
577 readtok ();
726f6388 578 val2 = expbor ();
d166f048 579 if (set_noeval)
ccc6cda3 580 noeval--;
726f6388 581 val1 = val1 && val2;
d166f048 582 lasttok = LAND;
726f6388
JA
583 }
584
585 return (val1);
586}
587
588/* Bitwise OR. */
7117c2d2 589static intmax_t
726f6388
JA
590expbor ()
591{
7117c2d2 592 register intmax_t val1, val2;
726f6388
JA
593
594 val1 = expbxor ();
595
596 while (curtok == BOR)
597 {
598 readtok ();
599 val2 = expbxor ();
600 val1 = val1 | val2;
601 }
602
603 return (val1);
604}
605
606/* Bitwise XOR. */
7117c2d2 607static intmax_t
726f6388
JA
608expbxor ()
609{
7117c2d2 610 register intmax_t val1, val2;
726f6388
JA
611
612 val1 = expband ();
613
614 while (curtok == BXOR)
615 {
616 readtok ();
617 val2 = expband ();
618 val1 = val1 ^ val2;
619 }
620
621 return (val1);
622}
623
624/* Bitwise AND. */
7117c2d2 625static intmax_t
726f6388
JA
626expband ()
627{
7117c2d2 628 register intmax_t val1, val2;
726f6388
JA
629
630 val1 = exp5 ();
631
632 while (curtok == BAND)
633 {
634 readtok ();
635 val2 = exp5 ();
636 val1 = val1 & val2;
637 }
638
639 return (val1);
640}
641
7117c2d2 642static intmax_t
726f6388
JA
643exp5 ()
644{
7117c2d2 645 register intmax_t val1, val2;
726f6388
JA
646
647 val1 = exp4 ();
648
649 while ((curtok == EQEQ) || (curtok == NEQ))
650 {
651 int op = curtok;
652
653 readtok ();
654 val2 = exp4 ();
655 if (op == EQEQ)
656 val1 = (val1 == val2);
657 else if (op == NEQ)
658 val1 = (val1 != val2);
659 }
660 return (val1);
661}
662
7117c2d2 663static intmax_t
726f6388
JA
664exp4 ()
665{
7117c2d2 666 register intmax_t val1, val2;
726f6388
JA
667
668 val1 = expshift ();
669 while ((curtok == LEQ) ||
670 (curtok == GEQ) ||
671 (curtok == LT) ||
672 (curtok == GT))
673 {
674 int op = curtok;
675
676 readtok ();
677 val2 = expshift ();
678
679 if (op == LEQ)
680 val1 = val1 <= val2;
681 else if (op == GEQ)
682 val1 = val1 >= val2;
683 else if (op == LT)
684 val1 = val1 < val2;
d166f048 685 else /* (op == GT) */
726f6388
JA
686 val1 = val1 > val2;
687 }
688 return (val1);
689}
690
691/* Left and right shifts. */
7117c2d2 692static intmax_t
726f6388
JA
693expshift ()
694{
7117c2d2 695 register intmax_t val1, val2;
726f6388
JA
696
697 val1 = exp3 ();
698
699 while ((curtok == LSH) || (curtok == RSH))
700 {
701 int op = curtok;
702
703 readtok ();
704 val2 = exp3 ();
705
706 if (op == LSH)
707 val1 = val1 << val2;
708 else
709 val1 = val1 >> val2;
710 }
711
712 return (val1);
713}
714
7117c2d2 715static intmax_t
726f6388
JA
716exp3 ()
717{
7117c2d2 718 register intmax_t val1, val2;
726f6388
JA
719
720 val1 = exp2 ();
721
722 while ((curtok == PLUS) || (curtok == MINUS))
723 {
724 int op = curtok;
725
726 readtok ();
727 val2 = exp2 ();
728
729 if (op == PLUS)
730 val1 += val2;
731 else if (op == MINUS)
732 val1 -= val2;
733 }
734 return (val1);
735}
736
7117c2d2 737static intmax_t
726f6388
JA
738exp2 ()
739{
7117c2d2 740 register intmax_t val1, val2;
726f6388 741
cce855bc 742 val1 = exppower ();
726f6388
JA
743
744 while ((curtok == MUL) ||
28ef6c31
JA
745 (curtok == DIV) ||
746 (curtok == MOD))
726f6388
JA
747 {
748 int op = curtok;
749
750 readtok ();
751
cce855bc 752 val2 = exppower ();
726f6388
JA
753
754 if (((op == DIV) || (op == MOD)) && (val2 == 0))
5e13499c 755 evalerror (_("division by 0"));
726f6388
JA
756
757 if (op == MUL)
28ef6c31 758 val1 *= val2;
726f6388 759 else if (op == DIV)
28ef6c31 760 val1 /= val2;
726f6388 761 else if (op == MOD)
28ef6c31 762 val1 %= val2;
726f6388
JA
763 }
764 return (val1);
765}
766
7117c2d2 767static intmax_t
cce855bc
JA
768exppower ()
769{
7117c2d2 770 register intmax_t val1, val2, c;
cce855bc
JA
771
772 val1 = exp1 ();
5565fb1a 773 while (curtok == POWER)
cce855bc
JA
774 {
775 readtok ();
b66cc816 776 val2 = exppower (); /* exponentiation is right-associative */
cce855bc 777 if (val2 == 0)
f73dda09 778 return (1);
bb70624e 779 if (val2 < 0)
5e13499c 780 evalerror (_("exponent less than 0"));
cce855bc
JA
781 for (c = 1; val2--; c *= val1)
782 ;
783 val1 = c;
784 }
785 return (val1);
786}
787
7117c2d2 788static intmax_t
726f6388
JA
789exp1 ()
790{
7117c2d2 791 register intmax_t val;
726f6388
JA
792
793 if (curtok == NOT)
794 {
795 readtok ();
796 val = !exp1 ();
797 }
798 else if (curtok == BNOT)
799 {
800 readtok ();
801 val = ~exp1 ();
802 }
803 else
804 val = exp0 ();
805
806 return (val);
807}
808
7117c2d2 809static intmax_t
726f6388
JA
810exp0 ()
811{
7117c2d2 812 register intmax_t val = 0, v2;
bb70624e
JA
813 char *vincdec;
814 int stok;
762a763b 815 EXPR_CONTEXT ec;
bb70624e
JA
816
817 /* XXX - might need additional logic here to decide whether or not
818 pre-increment or pre-decrement is legal at this point. */
819 if (curtok == PREINC || curtok == PREDEC)
820 {
821 stok = lasttok = curtok;
822 readtok ();
823 if (curtok != STR)
28ef6c31 824 /* readtok() catches this */
5e13499c 825 evalerror (_("identifier expected after pre-increment or pre-decrement"));
726f6388 826
bb70624e
JA
827 v2 = tokval + ((stok == PREINC) ? 1 : -1);
828 vincdec = itos (v2);
829 if (noeval == 0)
d3a24ed2 830 expr_bind_variable (tokstr, vincdec);
bb70624e
JA
831 free (vincdec);
832 val = v2;
833
834 curtok = NUM; /* make sure --x=7 is flagged as an error */
835 readtok ();
836 }
837 else if (curtok == MINUS)
726f6388
JA
838 {
839 readtok ();
840 val = - exp0 ();
841 }
842 else if (curtok == PLUS)
843 {
844 readtok ();
845 val = exp0 ();
846 }
847 else if (curtok == LPAR)
848 {
849 readtok ();
bb70624e 850 val = EXP_HIGHEST ();
726f6388 851
5e13499c
CR
852 if (curtok != RPAR) /* ( */
853 evalerror (_("missing `)'"));
726f6388
JA
854
855 /* Skip over closing paren. */
856 readtok ();
857 }
858 else if ((curtok == NUM) || (curtok == STR))
859 {
860 val = tokval;
762a763b 861 if (curtok == STR)
bb70624e 862 {
762a763b
CR
863 SAVETOK (&ec);
864 tokstr = (char *)NULL; /* keep it from being freed */
865 noeval = 1;
866 readtok ();
867 stok = curtok;
868
bb70624e 869 /* post-increment or post-decrement */
762a763b
CR
870 if (stok == POSTINC || stok == POSTDEC)
871 {
872 /* restore certain portions of EC */
873 tokstr = ec.tokstr;
874 noeval = ec.noeval;
875 lasttok = STR; /* ec.curtok */
876
877 v2 = val + ((stok == POSTINC) ? 1 : -1);
878 vincdec = itos (v2);
879 if (noeval == 0)
880 expr_bind_variable (tokstr, vincdec);
881 free (vincdec);
882 curtok = NUM; /* make sure x++=7 is flagged as an error */
883 }
884 else
885 {
886 if (stok == STR) /* free new tokstr before old one is restored */
887 FREE (tokstr);
888 RESTORETOK (&ec);
889 }
890
bb70624e
JA
891 }
892
726f6388
JA
893 readtok ();
894 }
895 else
5e13499c 896 evalerror (_("syntax error: operand expected"));
726f6388
JA
897
898 return (val);
899}
900
7117c2d2
JA
901static intmax_t
902expr_streval (tok, e)
903 char *tok;
904 int e;
905{
906 SHELL_VAR *v;
907 char *value;
908 intmax_t tval;
909
910 /* [[[[[ */
911#if defined (ARRAY_VARS)
912 v = (e == ']') ? array_variable_part (tok, (char **)0, (int *)0) : find_variable (tok);
913#else
914 v = find_variable (tok);
915#endif
916
917 if ((v == 0 || invisible_p (v)) && unbound_vars_is_error)
918 {
919#if defined (ARRAY_VARS)
920 value = (e == ']') ? array_variable_name (tok, (char **)0, (int *)0) : tok;
921#else
922 value = tok;
923#endif
924
925 err_unboundvar (value);
926
927#if defined (ARRAY_VARS)
928 if (e == ']')
929 FREE (value); /* array_variable_name returns new memory */
930#endif
931
932 if (interactive_shell)
933 {
934 expr_unwind ();
c184f645 935 top_level_cleanup ();
7117c2d2
JA
936 jump_to_top_level (DISCARD);
937 }
938 else
939 jump_to_top_level (FORCE_EOF);
940 }
941
942#if defined (ARRAY_VARS)
943 /* Second argument of 0 to get_array_value means that we don't allow
944 references like array[@]. In this case, get_array_value is just
945 like get_variable_value in that it does not return newly-allocated
946 memory or quote the results. */
947 value = (e == ']') ? get_array_value (tok, 0, (int *)NULL) : get_variable_value (v);
948#else
949 value = get_variable_value (v);
950#endif
951
952 tval = (value && *value) ? subexpr (value) : 0;
953
954 return (tval);
955}
956
dc8fbaf9
CR
957static int
958_is_multiop (c)
959 int c;
960{
961 switch (c)
962 {
963 case EQEQ:
964 case NEQ:
965 case LEQ:
966 case GEQ:
967 case LAND:
968 case LOR:
969 case LSH:
970 case RSH:
971 case OP_ASSIGN:
972 case COND:
973 case POWER:
974 case PREINC:
975 case PREDEC:
976 case POSTINC:
977 case POSTDEC:
978 return 1;
979 default:
980 return 0;
981 }
982}
983
984static int
985_is_arithop (c)
986 int c;
987{
988 switch (c)
989 {
990 case EQ:
991 case GT:
992 case LT:
993 case PLUS:
994 case MINUS:
995 case MUL:
996 case DIV:
997 case MOD:
998 case NOT:
999 case LPAR:
1000 case RPAR:
1001 case BAND:
1002 case BOR:
1003 case BXOR:
1004 case BNOT:
1005 return 1; /* operator tokens */
1006 case QUES:
1007 case COL:
1008 case COMMA:
1009 return 1; /* questionable */
1010 default:
1011 return 0; /* anything else is invalid */
1012 }
1013}
1014
726f6388
JA
1015/* Lexical analyzer/token reader for the expression evaluator. Reads the
1016 next token and puts its value into curtok, while advancing past it.
1017 Updates value of tp. May also set tokval (for number) or tokstr (for
1018 string). */
1019static void
1020readtok ()
1021{
762a763b 1022 register char *cp, *xp;
f73dda09
JA
1023 register unsigned char c, c1;
1024 register int e;
726f6388
JA
1025
1026 /* Skip leading whitespace. */
ccc6cda3
JA
1027 cp = tp;
1028 c = e = 0;
726f6388
JA
1029 while (cp && (c = *cp) && (cr_whitespace (c)))
1030 cp++;
1031
1032 if (c)
1033 cp++;
ccc6cda3 1034
726f6388
JA
1035 if (c == '\0')
1036 {
1037 lasttok = curtok;
1038 curtok = 0;
1039 tp = cp;
1040 return;
1041 }
cc12da02 1042 lasttp = tp = cp - 1;
726f6388 1043
ccc6cda3 1044 if (legal_variable_starter (c))
726f6388 1045 {
bb70624e 1046 /* variable names not preceded with a dollar sign are shell variables. */
7117c2d2 1047 char *savecp;
bb70624e
JA
1048 EXPR_CONTEXT ec;
1049 int peektok;
726f6388 1050
ccc6cda3 1051 while (legal_variable_char (c))
726f6388
JA
1052 c = *cp++;
1053
1054 c = *--cp;
ccc6cda3
JA
1055
1056#if defined (ARRAY_VARS)
1057 if (c == '[')
1058 {
1059 e = skipsubscript (cp, 0);
1060 if (cp[e] == ']')
1061 {
1062 cp += e + 1;
1063 c = *cp;
1064 e = ']';
1065 }
1066 else
5e13499c 1067 evalerror (bash_badsub_errmsg);
ccc6cda3
JA
1068 }
1069#endif /* ARRAY_VARS */
1070
726f6388 1071 *cp = '\0';
ccc6cda3 1072 FREE (tokstr);
726f6388 1073 tokstr = savestring (tp);
bb70624e 1074 *cp = c;
ccc6cda3 1075
bb70624e
JA
1076 SAVETOK (&ec);
1077 tokstr = (char *)NULL; /* keep it from being freed */
1078 tp = savecp = cp;
1079 noeval = 1;
762a763b 1080 curtok = STR;
bb70624e
JA
1081 readtok ();
1082 peektok = curtok;
1083 if (peektok == STR) /* free new tokstr before old one is restored */
1084 FREE (tokstr);
1085 RESTORETOK (&ec);
1086 cp = savecp;
1087
1088 /* The tests for PREINC and PREDEC aren't strictly correct, but they
1089 preserve old behavior if a construct like --x=9 is given. */
1090 if (lasttok == PREINC || lasttok == PREDEC || peektok != EQ)
7117c2d2 1091 tokval = expr_streval (tokstr, e);
bb70624e 1092 else
28ef6c31 1093 tokval = 0;
726f6388 1094
726f6388
JA
1095 lasttok = curtok;
1096 curtok = STR;
1097 }
f73dda09 1098 else if (DIGIT(c))
726f6388 1099 {
f73dda09 1100 while (ISALNUM (c) || c == '#' || c == '@' || c == '_')
726f6388
JA
1101 c = *cp++;
1102
1103 c = *--cp;
1104 *cp = '\0';
1105
1106 tokval = strlong (tp);
1107 *cp = c;
1108 lasttok = curtok;
1109 curtok = NUM;
1110 }
1111 else
1112 {
1113 c1 = *cp++;
ccc6cda3 1114 if ((c == EQ) && (c1 == EQ))
726f6388
JA
1115 c = EQEQ;
1116 else if ((c == NOT) && (c1 == EQ))
1117 c = NEQ;
1118 else if ((c == GT) && (c1 == EQ))
1119 c = GEQ;
1120 else if ((c == LT) && (c1 == EQ))
1121 c = LEQ;
1122 else if ((c == LT) && (c1 == LT))
1123 {
1124 if (*cp == '=') /* a <<= b */
1125 {
1126 assigntok = LSH;
1127 c = OP_ASSIGN;
1128 cp++;
1129 }
1130 else
1131 c = LSH;
1132 }
1133 else if ((c == GT) && (c1 == GT))
1134 {
1135 if (*cp == '=')
1136 {
1137 assigntok = RSH; /* a >>= b */
1138 c = OP_ASSIGN;
1139 cp++;
1140 }
1141 else
1142 c = RSH;
1143 }
1144 else if ((c == BAND) && (c1 == BAND))
1145 c = LAND;
1146 else if ((c == BOR) && (c1 == BOR))
1147 c = LOR;
cce855bc 1148 else if ((c == '*') && (c1 == '*'))
28ef6c31 1149 c = POWER;
762a763b
CR
1150 else if ((c == '-' || c == '+') && c1 == c && curtok == STR)
1151 c = (c == '-') ? POSTDEC : POSTINC;
1152 else if ((c == '-' || c == '+') && c1 == c)
1153 {
1154 /* Quickly scan forward to see if this is followed by optional
1155 whitespace and an identifier. */
1156 xp = cp;
1157 while (xp && *xp && cr_whitespace (*xp))
1158 xp++;
1159 if (legal_variable_starter ((unsigned char)*xp))
1160 c = (c == '-') ? PREDEC : PREINC;
1161 else
1162 cp--; /* not preinc or predec, so unget the character */
1163 }
28ef6c31 1164 else if (c1 == EQ && member (c, "*/%+-&^|"))
726f6388
JA
1165 {
1166 assigntok = c; /* a OP= b */
1167 c = OP_ASSIGN;
1168 }
dc8fbaf9
CR
1169 else if (_is_arithop (c) == 0)
1170 {
1171 cp--;
1172 /* use curtok, since it hasn't been copied to lasttok yet */
1173 if (curtok == 0 || _is_arithop (curtok) || _is_multiop (curtok))
1174 evalerror (_("syntax error: operand expected"));
1175 else
1176 evalerror (_("syntax error: invalid arithmetic operator"));
1177 }
726f6388
JA
1178 else
1179 cp--; /* `unget' the character */
dc8fbaf9
CR
1180
1181 /* Should check here to make sure that the current character is one
1182 of the recognized operators and flag an error if not. Could create
1183 a character map the first time through and check it on subsequent
1184 calls. */
726f6388
JA
1185 lasttok = curtok;
1186 curtok = c;
1187 }
1188 tp = cp;
1189}
1190
1191static void
1192evalerror (msg)
d3ad40de 1193 const char *msg;
726f6388
JA
1194{
1195 char *name, *t;
1196
1197 name = this_command_name;
726f6388
JA
1198 for (t = expression; whitespace (*t); t++)
1199 ;
d3ad40de 1200 internal_error (_("%s%s%s: %s (error token is \"%s\")"),
ccc6cda3
JA
1201 name ? name : "", name ? ": " : "", t,
1202 msg, (lasttp && *lasttp) ? lasttp : "");
726f6388
JA
1203 longjmp (evalbuf, 1);
1204}
1205
7117c2d2 1206/* Convert a string to an intmax_t integer, with an arbitrary base.
726f6388 1207 0nnn -> base 8
cce855bc 1208 0[Xx]nn -> base 16
ccc6cda3
JA
1209 Anything else: [base#]number (this is implemented to match ksh93)
1210
1211 Base may be >=2 and <=64. If base is <= 36, the numbers are drawn
1212 from [0-9][a-zA-Z], and lowercase and uppercase letters may be used
1213 interchangably. If base is > 36 and <= 64, the numbers are drawn
2206f89a 1214 from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 --
ccc6cda3
JA
1215 you get the picture). */
1216
7117c2d2 1217static intmax_t
726f6388
JA
1218strlong (num)
1219 char *num;
1220{
ccc6cda3 1221 register char *s;
f73dda09 1222 register unsigned char c;
ccc6cda3 1223 int base, foundbase;
7117c2d2 1224 intmax_t val;
726f6388 1225
ccc6cda3 1226 s = num;
726f6388 1227
ccc6cda3
JA
1228 base = 10;
1229 foundbase = 0;
726f6388
JA
1230 if (*s == '0')
1231 {
1232 s++;
1233
f73dda09
JA
1234 if (*s == '\0')
1235 return 0;
ccc6cda3 1236
726f6388
JA
1237 /* Base 16? */
1238 if (*s == 'x' || *s == 'X')
1239 {
1240 base = 16;
1241 s++;
1242 }
1243 else
1244 base = 8;
ccc6cda3 1245 foundbase++;
726f6388
JA
1246 }
1247
f73dda09 1248 val = 0;
726f6388
JA
1249 for (c = *s++; c; c = *s++)
1250 {
1251 if (c == '#')
1252 {
ccc6cda3 1253 if (foundbase)
5e13499c 1254 evalerror (_("invalid number"));
ccc6cda3 1255
ccc6cda3 1256 /* Illegal base specifications raise an evaluation error. */
f73dda09 1257 if (val < 2 || val > 64)
5e13499c 1258 evalerror (_("invalid arithmetic base"));
726f6388 1259
f73dda09
JA
1260 base = val;
1261 val = 0;
ccc6cda3
JA
1262 foundbase++;
1263 }
f73dda09 1264 else if (ISALNUM(c) || (c == '_') || (c == '@'))
ccc6cda3 1265 {
f73dda09
JA
1266 if (DIGIT(c))
1267 c = TODIGIT(c);
ccc6cda3
JA
1268 else if (c >= 'a' && c <= 'z')
1269 c -= 'a' - 10;
1270 else if (c >= 'A' && c <= 'Z')
1271 c -= 'A' - ((base <= 36) ? 10 : 36);
ccc6cda3 1272 else if (c == '@')
f73dda09
JA
1273 c = 62;
1274 else if (c == '_')
ccc6cda3
JA
1275 c = 63;
1276
1277 if (c >= base)
5e13499c 1278 evalerror (_("value too great for base"));
ccc6cda3
JA
1279
1280 val = (val * base) + c;
726f6388
JA
1281 }
1282 else
ccc6cda3 1283 break;
726f6388 1284 }
2206f89a 1285
726f6388
JA
1286 return (val);
1287}
1288
1289#if defined (EXPR_TEST)
f73dda09 1290void *
726f6388
JA
1291xmalloc (n)
1292 int n;
1293{
1294 return (malloc (n));
1295}
1296
f73dda09 1297void *
726f6388
JA
1298xrealloc (s, n)
1299 char *s;
1300 int n;
1301{
1302 return (realloc (s, n));
1303}
1304
1305SHELL_VAR *find_variable () { return 0;}
1306SHELL_VAR *bind_variable () { return 0; }
1307
1308char *get_string_value () { return 0; }
1309
ccc6cda3 1310procenv_t top_level;
726f6388
JA
1311
1312main (argc, argv)
1313 int argc;
1314 char **argv;
1315{
1316 register int i;
7117c2d2 1317 intmax_t v;
d166f048 1318 int expok;
726f6388
JA
1319
1320 if (setjmp (top_level))
1321 exit (0);
1322
1323 for (i = 1; i < argc; i++)
1324 {
d166f048
JA
1325 v = evalexp (argv[i], &expok);
1326 if (expok == 0)
d3ad40de 1327 fprintf (stderr, _("%s: expression error\n"), argv[i]);
d166f048 1328 else
28ef6c31 1329 printf ("'%s' -> %ld\n", argv[i], v);
726f6388
JA
1330 }
1331 exit (0);
1332}
1333
1334int
1335builtin_error (format, arg1, arg2, arg3, arg4, arg5)
1336 char *format;
1337{
1338 fprintf (stderr, "expr: ");
1339 fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
1340 fprintf (stderr, "\n");
1341 return 0;
1342}
1343
1344char *
1345itos (n)
7117c2d2 1346 intmax_t n;
726f6388
JA
1347{
1348 return ("42");
1349}
1350
1351#endif /* EXPR_TEST */