]> git.ipfire.org Git - thirdparty/bash.git/blame - expr.c
Imported from ../bash-3.2.tar.gz.
[thirdparty/bash.git] / expr.c
CommitLineData
726f6388
JA
1/* expr.c -- arithmetic expression evaluation. */
2
b80f6443 3/* Copyright (C) 1990-2004 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 "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
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
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"
b80f6443 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
0628567a 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 *));
f73dda09
JA
156static void evalerror __P((char *));
157
158static void pushexp __P((void));
159static void popexp __P((void));
7117c2d2 160static void expr_unwind __P((void));
b80f6443 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
b80f6443
JA
207#if defined (ARRAY_VARS)
208extern char *bash_badsub_errmsg;
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)
b80f6443 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)
b80f6443 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 */
289}
290
b80f6443
JA
291static void
292expr_bind_variable (lhs, rhs)
293 char *lhs, *rhs;
294{
295 (void)bind_int_variable (lhs, rhs);
296 stupidly_hack_special_variables (lhs);
297}
298
d166f048
JA
299/* Evaluate EXPR, and return the arithmetic result. If VALIDP is
300 non-null, a zero is stored into the location to which it points
301 if the expression is invalid, non-zero otherwise. If a non-zero
302 value is returned in *VALIDP, the return value of evalexp() may
303 be used.
726f6388
JA
304
305 The `while' loop after the longjmp is caught relies on the above
306 implementation of pushexp and popexp leaving in expr_stack[0] the
307 values that the variables had when the program started. That is,
ccc6cda3 308 the first things saved are the initial values of the variables that
726f6388
JA
309 were assigned at program startup or by the compiler. Therefore, it is
310 safe to let the loop terminate when expr_depth == 0, without freeing up
311 any of the expr_depth[0] stuff. */
7117c2d2 312intmax_t
d166f048 313evalexp (expr, validp)
726f6388 314 char *expr;
d166f048 315 int *validp;
726f6388 316{
7117c2d2 317 intmax_t val;
b80f6443
JA
318 int c;
319 procenv_t oevalbuf;
726f6388 320
f73dda09 321 val = 0;
726f6388 322
b80f6443
JA
323 FASTCOPY (evalbuf, oevalbuf, sizeof (evalbuf));
324
325 c = setjmp (evalbuf);
326
327 if (c)
726f6388 328 {
d166f048
JA
329 FREE (tokstr);
330 FREE (expression);
331 tokstr = expression = (char *)NULL;
726f6388 332
7117c2d2 333 expr_unwind ();
d166f048
JA
334
335 if (validp)
336 *validp = 0;
f73dda09 337 return (0);
726f6388
JA
338 }
339
d166f048
JA
340 val = subexpr (expr);
341
d166f048
JA
342 if (validp)
343 *validp = 1;
344
b80f6443
JA
345 FASTCOPY (oevalbuf, evalbuf, sizeof (evalbuf));
346
d166f048
JA
347 return (val);
348}
349
7117c2d2 350static intmax_t
d166f048
JA
351subexpr (expr)
352 char *expr;
353{
7117c2d2 354 intmax_t val;
d166f048
JA
355 char *p;
356
357 for (p = expr; p && *p && cr_whitespace (*p); p++)
358 ;
359
360 if (p == NULL || *p == '\0')
f73dda09 361 return (0);
d166f048 362
726f6388
JA
363 pushexp ();
364 curtok = lasttok = 0;
365 expression = savestring (expr);
366 tp = expression;
367
368 tokstr = (char *)NULL;
f73dda09 369 tokval = 0;
726f6388
JA
370
371 readtok ();
372
bb70624e 373 val = EXP_HIGHEST ();
726f6388 374
ccc6cda3 375 if (curtok != 0)
b80f6443 376 evalerror (_("syntax error in expression"));
726f6388 377
d166f048
JA
378 FREE (tokstr);
379 FREE (expression);
726f6388
JA
380
381 popexp ();
382
d166f048 383 return val;
726f6388
JA
384}
385
7117c2d2 386static intmax_t
bb70624e 387expcomma ()
726f6388 388{
7117c2d2 389 register intmax_t value;
726f6388 390
bb70624e
JA
391 value = expassign ();
392 while (curtok == COMMA)
726f6388 393 {
bb70624e
JA
394 readtok ();
395 value = expassign ();
726f6388
JA
396 }
397
bb70624e 398 return value;
726f6388 399}
bb70624e 400
7117c2d2 401static intmax_t
726f6388
JA
402expassign ()
403{
7117c2d2 404 register intmax_t value;
726f6388
JA
405 char *lhs, *rhs;
406
ccc6cda3 407 value = expcond ();
726f6388
JA
408 if (curtok == EQ || curtok == OP_ASSIGN)
409 {
ccc6cda3 410 int special, op;
7117c2d2 411 intmax_t lvalue;
726f6388 412
ccc6cda3
JA
413 special = curtok == OP_ASSIGN;
414
726f6388 415 if (lasttok != STR)
b80f6443 416 evalerror (_("attempted assignment to non-variable"));
726f6388
JA
417
418 if (special)
419 {
420 op = assigntok; /* a OP= b */
421 lvalue = value;
422 }
423
424 lhs = savestring (tokstr);
425 readtok ();
426 value = expassign ();
427
428 if (special)
429 {
430 switch (op)
431 {
432 case MUL:
433 lvalue *= value;
434 break;
435 case DIV:
7117c2d2 436 if (value == 0)
b80f6443 437 evalerror (_("division by 0"));
726f6388
JA
438 lvalue /= value;
439 break;
440 case MOD:
7117c2d2 441 if (value == 0)
b80f6443 442 evalerror (_("division by 0"));
726f6388
JA
443 lvalue %= value;
444 break;
445 case PLUS:
446 lvalue += value;
447 break;
448 case MINUS:
449 lvalue -= value;
450 break;
451 case LSH:
452 lvalue <<= value;
453 break;
454 case RSH:
455 lvalue >>= value;
456 break;
457 case BAND:
458 lvalue &= value;
459 break;
460 case BOR:
461 lvalue |= value;
462 break;
28ef6c31
JA
463 case BXOR:
464 lvalue ^= value;
465 break;
726f6388 466 default:
d166f048 467 free (lhs);
b80f6443 468 evalerror (_("bug: bad expassign token"));
726f6388
JA
469 break;
470 }
471 value = lvalue;
472 }
473
474 rhs = itos (value);
ccc6cda3 475 if (noeval == 0)
b80f6443 476 expr_bind_variable (lhs, rhs);
726f6388
JA
477 free (rhs);
478 free (lhs);
d166f048 479 FREE (tokstr);
726f6388
JA
480 tokstr = (char *)NULL; /* For freeing on errors. */
481 }
482 return (value);
483}
484
ccc6cda3 485/* Conditional expression (expr?expr:expr) */
7117c2d2 486static intmax_t
ccc6cda3
JA
487expcond ()
488{
7117c2d2 489 intmax_t cval, val1, val2, rval;
d166f048
JA
490 int set_noeval;
491
492 set_noeval = 0;
ccc6cda3
JA
493 rval = cval = explor ();
494 if (curtok == QUES) /* found conditional expr */
495 {
496 readtok ();
497 if (curtok == 0 || curtok == COL)
b80f6443 498 evalerror (_("expression expected"));
ccc6cda3 499 if (cval == 0)
d166f048
JA
500 {
501 set_noeval = 1;
502 noeval++;
503 }
f73dda09 504
bb70624e 505 val1 = EXP_HIGHEST ();
f73dda09 506
d166f048 507 if (set_noeval)
28ef6c31 508 noeval--;
ccc6cda3 509 if (curtok != COL)
b80f6443 510 evalerror (_("`:' expected for conditional expression"));
ccc6cda3
JA
511 readtok ();
512 if (curtok == 0)
b80f6443 513 evalerror (_("expression expected"));
d166f048 514 set_noeval = 0;
ccc6cda3 515 if (cval)
d166f048
JA
516 {
517 set_noeval = 1;
518 noeval++;
519 }
ccc6cda3 520 val2 = explor ();
d166f048 521 if (set_noeval)
28ef6c31 522 noeval--;
ccc6cda3
JA
523 rval = cval ? val1 : val2;
524 lasttok = COND;
525 }
526 return rval;
527}
528
726f6388 529/* Logical OR. */
7117c2d2 530static intmax_t
726f6388
JA
531explor ()
532{
7117c2d2 533 register intmax_t val1, val2;
d166f048 534 int set_noeval;
726f6388
JA
535
536 val1 = expland ();
537
538 while (curtok == LOR)
539 {
d166f048 540 set_noeval = 0;
ccc6cda3 541 if (val1 != 0)
d166f048
JA
542 {
543 noeval++;
544 set_noeval = 1;
545 }
546 readtok ();
726f6388 547 val2 = expland ();
d166f048 548 if (set_noeval)
ccc6cda3 549 noeval--;
726f6388 550 val1 = val1 || val2;
d166f048 551 lasttok = LOR;
726f6388
JA
552 }
553
554 return (val1);
555}
556
557/* Logical AND. */
7117c2d2 558static intmax_t
726f6388
JA
559expland ()
560{
7117c2d2 561 register intmax_t val1, val2;
d166f048 562 int set_noeval;
726f6388
JA
563
564 val1 = expbor ();
565
566 while (curtok == LAND)
567 {
d166f048 568 set_noeval = 0;
ccc6cda3 569 if (val1 == 0)
d166f048
JA
570 {
571 set_noeval = 1;
572 noeval++;
573 }
574 readtok ();
726f6388 575 val2 = expbor ();
d166f048 576 if (set_noeval)
ccc6cda3 577 noeval--;
726f6388 578 val1 = val1 && val2;
d166f048 579 lasttok = LAND;
726f6388
JA
580 }
581
582 return (val1);
583}
584
585/* Bitwise OR. */
7117c2d2 586static intmax_t
726f6388
JA
587expbor ()
588{
7117c2d2 589 register intmax_t val1, val2;
726f6388
JA
590
591 val1 = expbxor ();
592
593 while (curtok == BOR)
594 {
595 readtok ();
596 val2 = expbxor ();
597 val1 = val1 | val2;
598 }
599
600 return (val1);
601}
602
603/* Bitwise XOR. */
7117c2d2 604static intmax_t
726f6388
JA
605expbxor ()
606{
7117c2d2 607 register intmax_t val1, val2;
726f6388
JA
608
609 val1 = expband ();
610
611 while (curtok == BXOR)
612 {
613 readtok ();
614 val2 = expband ();
615 val1 = val1 ^ val2;
616 }
617
618 return (val1);
619}
620
621/* Bitwise AND. */
7117c2d2 622static intmax_t
726f6388
JA
623expband ()
624{
7117c2d2 625 register intmax_t val1, val2;
726f6388
JA
626
627 val1 = exp5 ();
628
629 while (curtok == BAND)
630 {
631 readtok ();
632 val2 = exp5 ();
633 val1 = val1 & val2;
634 }
635
636 return (val1);
637}
638
7117c2d2 639static intmax_t
726f6388
JA
640exp5 ()
641{
7117c2d2 642 register intmax_t val1, val2;
726f6388
JA
643
644 val1 = exp4 ();
645
646 while ((curtok == EQEQ) || (curtok == NEQ))
647 {
648 int op = curtok;
649
650 readtok ();
651 val2 = exp4 ();
652 if (op == EQEQ)
653 val1 = (val1 == val2);
654 else if (op == NEQ)
655 val1 = (val1 != val2);
656 }
657 return (val1);
658}
659
7117c2d2 660static intmax_t
726f6388
JA
661exp4 ()
662{
7117c2d2 663 register intmax_t val1, val2;
726f6388
JA
664
665 val1 = expshift ();
666 while ((curtok == LEQ) ||
667 (curtok == GEQ) ||
668 (curtok == LT) ||
669 (curtok == GT))
670 {
671 int op = curtok;
672
673 readtok ();
674 val2 = expshift ();
675
676 if (op == LEQ)
677 val1 = val1 <= val2;
678 else if (op == GEQ)
679 val1 = val1 >= val2;
680 else if (op == LT)
681 val1 = val1 < val2;
d166f048 682 else /* (op == GT) */
726f6388
JA
683 val1 = val1 > val2;
684 }
685 return (val1);
686}
687
688/* Left and right shifts. */
7117c2d2 689static intmax_t
726f6388
JA
690expshift ()
691{
7117c2d2 692 register intmax_t val1, val2;
726f6388
JA
693
694 val1 = exp3 ();
695
696 while ((curtok == LSH) || (curtok == RSH))
697 {
698 int op = curtok;
699
700 readtok ();
701 val2 = exp3 ();
702
703 if (op == LSH)
704 val1 = val1 << val2;
705 else
706 val1 = val1 >> val2;
707 }
708
709 return (val1);
710}
711
7117c2d2 712static intmax_t
726f6388
JA
713exp3 ()
714{
7117c2d2 715 register intmax_t val1, val2;
726f6388
JA
716
717 val1 = exp2 ();
718
719 while ((curtok == PLUS) || (curtok == MINUS))
720 {
721 int op = curtok;
722
723 readtok ();
724 val2 = exp2 ();
725
726 if (op == PLUS)
727 val1 += val2;
728 else if (op == MINUS)
729 val1 -= val2;
730 }
731 return (val1);
732}
733
7117c2d2 734static intmax_t
726f6388
JA
735exp2 ()
736{
7117c2d2 737 register intmax_t val1, val2;
726f6388 738
cce855bc 739 val1 = exppower ();
726f6388
JA
740
741 while ((curtok == MUL) ||
28ef6c31
JA
742 (curtok == DIV) ||
743 (curtok == MOD))
726f6388
JA
744 {
745 int op = curtok;
746
747 readtok ();
748
cce855bc 749 val2 = exppower ();
726f6388
JA
750
751 if (((op == DIV) || (op == MOD)) && (val2 == 0))
b80f6443 752 evalerror (_("division by 0"));
726f6388
JA
753
754 if (op == MUL)
28ef6c31 755 val1 *= val2;
726f6388 756 else if (op == DIV)
28ef6c31 757 val1 /= val2;
726f6388 758 else if (op == MOD)
28ef6c31 759 val1 %= val2;
726f6388
JA
760 }
761 return (val1);
762}
763
7117c2d2 764static intmax_t
cce855bc
JA
765exppower ()
766{
7117c2d2 767 register intmax_t val1, val2, c;
cce855bc
JA
768
769 val1 = exp1 ();
b80f6443 770 while (curtok == POWER)
cce855bc
JA
771 {
772 readtok ();
95732b49 773 val2 = exppower (); /* exponentiation is right-associative */
cce855bc 774 if (val2 == 0)
f73dda09 775 return (1);
bb70624e 776 if (val2 < 0)
b80f6443 777 evalerror (_("exponent less than 0"));
cce855bc
JA
778 for (c = 1; val2--; c *= val1)
779 ;
780 val1 = c;
781 }
782 return (val1);
783}
784
7117c2d2 785static intmax_t
726f6388
JA
786exp1 ()
787{
7117c2d2 788 register intmax_t val;
726f6388
JA
789
790 if (curtok == NOT)
791 {
792 readtok ();
793 val = !exp1 ();
794 }
795 else if (curtok == BNOT)
796 {
797 readtok ();
798 val = ~exp1 ();
799 }
800 else
801 val = exp0 ();
802
803 return (val);
804}
805
7117c2d2 806static intmax_t
726f6388
JA
807exp0 ()
808{
7117c2d2 809 register intmax_t val = 0, v2;
bb70624e
JA
810 char *vincdec;
811 int stok;
b80f6443 812 EXPR_CONTEXT ec;
bb70624e
JA
813
814 /* XXX - might need additional logic here to decide whether or not
815 pre-increment or pre-decrement is legal at this point. */
816 if (curtok == PREINC || curtok == PREDEC)
817 {
818 stok = lasttok = curtok;
819 readtok ();
820 if (curtok != STR)
28ef6c31 821 /* readtok() catches this */
b80f6443 822 evalerror (_("identifier expected after pre-increment or pre-decrement"));
726f6388 823
bb70624e
JA
824 v2 = tokval + ((stok == PREINC) ? 1 : -1);
825 vincdec = itos (v2);
826 if (noeval == 0)
b80f6443 827 expr_bind_variable (tokstr, vincdec);
bb70624e
JA
828 free (vincdec);
829 val = v2;
830
831 curtok = NUM; /* make sure --x=7 is flagged as an error */
832 readtok ();
833 }
834 else if (curtok == MINUS)
726f6388
JA
835 {
836 readtok ();
837 val = - exp0 ();
838 }
839 else if (curtok == PLUS)
840 {
841 readtok ();
842 val = exp0 ();
843 }
844 else if (curtok == LPAR)
845 {
846 readtok ();
bb70624e 847 val = EXP_HIGHEST ();
726f6388 848
b80f6443
JA
849 if (curtok != RPAR) /* ( */
850 evalerror (_("missing `)'"));
726f6388
JA
851
852 /* Skip over closing paren. */
853 readtok ();
854 }
855 else if ((curtok == NUM) || (curtok == STR))
856 {
857 val = tokval;
b80f6443 858 if (curtok == STR)
bb70624e 859 {
b80f6443
JA
860 SAVETOK (&ec);
861 tokstr = (char *)NULL; /* keep it from being freed */
862 noeval = 1;
863 readtok ();
864 stok = curtok;
865
bb70624e 866 /* post-increment or post-decrement */
b80f6443
JA
867 if (stok == POSTINC || stok == POSTDEC)
868 {
869 /* restore certain portions of EC */
870 tokstr = ec.tokstr;
871 noeval = ec.noeval;
872 lasttok = STR; /* ec.curtok */
873
874 v2 = val + ((stok == POSTINC) ? 1 : -1);
875 vincdec = itos (v2);
876 if (noeval == 0)
877 expr_bind_variable (tokstr, vincdec);
878 free (vincdec);
879 curtok = NUM; /* make sure x++=7 is flagged as an error */
880 }
881 else
882 {
883 if (stok == STR) /* free new tokstr before old one is restored */
884 FREE (tokstr);
885 RESTORETOK (&ec);
886 }
887
bb70624e
JA
888 }
889
726f6388
JA
890 readtok ();
891 }
892 else
b80f6443 893 evalerror (_("syntax error: operand expected"));
726f6388
JA
894
895 return (val);
896}
897
7117c2d2
JA
898static intmax_t
899expr_streval (tok, e)
900 char *tok;
901 int e;
902{
903 SHELL_VAR *v;
904 char *value;
905 intmax_t tval;
906
907 /* [[[[[ */
908#if defined (ARRAY_VARS)
909 v = (e == ']') ? array_variable_part (tok, (char **)0, (int *)0) : find_variable (tok);
910#else
911 v = find_variable (tok);
912#endif
913
914 if ((v == 0 || invisible_p (v)) && unbound_vars_is_error)
915 {
916#if defined (ARRAY_VARS)
917 value = (e == ']') ? array_variable_name (tok, (char **)0, (int *)0) : tok;
918#else
919 value = tok;
920#endif
921
922 err_unboundvar (value);
923
924#if defined (ARRAY_VARS)
925 if (e == ']')
926 FREE (value); /* array_variable_name returns new memory */
927#endif
928
929 if (interactive_shell)
930 {
931 expr_unwind ();
932 jump_to_top_level (DISCARD);
933 }
934 else
935 jump_to_top_level (FORCE_EOF);
936 }
937
938#if defined (ARRAY_VARS)
939 /* Second argument of 0 to get_array_value means that we don't allow
940 references like array[@]. In this case, get_array_value is just
941 like get_variable_value in that it does not return newly-allocated
942 memory or quote the results. */
943 value = (e == ']') ? get_array_value (tok, 0, (int *)NULL) : get_variable_value (v);
944#else
945 value = get_variable_value (v);
946#endif
947
948 tval = (value && *value) ? subexpr (value) : 0;
949
950 return (tval);
951}
952
0628567a
JA
953static int
954_is_multiop (c)
955 int c;
956{
957 switch (c)
958 {
959 case EQEQ:
960 case NEQ:
961 case LEQ:
962 case GEQ:
963 case LAND:
964 case LOR:
965 case LSH:
966 case RSH:
967 case OP_ASSIGN:
968 case COND:
969 case POWER:
970 case PREINC:
971 case PREDEC:
972 case POSTINC:
973 case POSTDEC:
974 return 1;
975 default:
976 return 0;
977 }
978}
979
980static int
981_is_arithop (c)
982 int c;
983{
984 switch (c)
985 {
986 case EQ:
987 case GT:
988 case LT:
989 case PLUS:
990 case MINUS:
991 case MUL:
992 case DIV:
993 case MOD:
994 case NOT:
995 case LPAR:
996 case RPAR:
997 case BAND:
998 case BOR:
999 case BXOR:
1000 case BNOT:
1001 return 1; /* operator tokens */
1002 case QUES:
1003 case COL:
1004 case COMMA:
1005 return 1; /* questionable */
1006 default:
1007 return 0; /* anything else is invalid */
1008 }
1009}
1010
726f6388
JA
1011/* Lexical analyzer/token reader for the expression evaluator. Reads the
1012 next token and puts its value into curtok, while advancing past it.
1013 Updates value of tp. May also set tokval (for number) or tokstr (for
1014 string). */
1015static void
1016readtok ()
1017{
b80f6443 1018 register char *cp, *xp;
f73dda09
JA
1019 register unsigned char c, c1;
1020 register int e;
726f6388
JA
1021
1022 /* Skip leading whitespace. */
ccc6cda3
JA
1023 cp = tp;
1024 c = e = 0;
726f6388
JA
1025 while (cp && (c = *cp) && (cr_whitespace (c)))
1026 cp++;
1027
1028 if (c)
1029 cp++;
ccc6cda3 1030
726f6388
JA
1031 lasttp = tp = cp - 1;
1032
1033 if (c == '\0')
1034 {
1035 lasttok = curtok;
1036 curtok = 0;
1037 tp = cp;
1038 return;
1039 }
1040
ccc6cda3 1041 if (legal_variable_starter (c))
726f6388 1042 {
bb70624e 1043 /* variable names not preceded with a dollar sign are shell variables. */
7117c2d2 1044 char *savecp;
bb70624e
JA
1045 EXPR_CONTEXT ec;
1046 int peektok;
726f6388 1047
ccc6cda3 1048 while (legal_variable_char (c))
726f6388
JA
1049 c = *cp++;
1050
1051 c = *--cp;
ccc6cda3
JA
1052
1053#if defined (ARRAY_VARS)
1054 if (c == '[')
1055 {
1056 e = skipsubscript (cp, 0);
1057 if (cp[e] == ']')
1058 {
1059 cp += e + 1;
1060 c = *cp;
1061 e = ']';
1062 }
1063 else
b80f6443 1064 evalerror (bash_badsub_errmsg);
ccc6cda3
JA
1065 }
1066#endif /* ARRAY_VARS */
1067
726f6388 1068 *cp = '\0';
ccc6cda3 1069 FREE (tokstr);
726f6388 1070 tokstr = savestring (tp);
bb70624e 1071 *cp = c;
ccc6cda3 1072
bb70624e
JA
1073 SAVETOK (&ec);
1074 tokstr = (char *)NULL; /* keep it from being freed */
1075 tp = savecp = cp;
1076 noeval = 1;
b80f6443 1077 curtok = STR;
bb70624e
JA
1078 readtok ();
1079 peektok = curtok;
1080 if (peektok == STR) /* free new tokstr before old one is restored */
1081 FREE (tokstr);
1082 RESTORETOK (&ec);
1083 cp = savecp;
1084
1085 /* The tests for PREINC and PREDEC aren't strictly correct, but they
1086 preserve old behavior if a construct like --x=9 is given. */
1087 if (lasttok == PREINC || lasttok == PREDEC || peektok != EQ)
7117c2d2 1088 tokval = expr_streval (tokstr, e);
bb70624e 1089 else
28ef6c31 1090 tokval = 0;
726f6388 1091
726f6388
JA
1092 lasttok = curtok;
1093 curtok = STR;
1094 }
f73dda09 1095 else if (DIGIT(c))
726f6388 1096 {
f73dda09 1097 while (ISALNUM (c) || c == '#' || c == '@' || c == '_')
726f6388
JA
1098 c = *cp++;
1099
1100 c = *--cp;
1101 *cp = '\0';
1102
1103 tokval = strlong (tp);
1104 *cp = c;
1105 lasttok = curtok;
1106 curtok = NUM;
1107 }
1108 else
1109 {
1110 c1 = *cp++;
ccc6cda3 1111 if ((c == EQ) && (c1 == EQ))
726f6388
JA
1112 c = EQEQ;
1113 else if ((c == NOT) && (c1 == EQ))
1114 c = NEQ;
1115 else if ((c == GT) && (c1 == EQ))
1116 c = GEQ;
1117 else if ((c == LT) && (c1 == EQ))
1118 c = LEQ;
1119 else if ((c == LT) && (c1 == LT))
1120 {
1121 if (*cp == '=') /* a <<= b */
1122 {
1123 assigntok = LSH;
1124 c = OP_ASSIGN;
1125 cp++;
1126 }
1127 else
1128 c = LSH;
1129 }
1130 else if ((c == GT) && (c1 == GT))
1131 {
1132 if (*cp == '=')
1133 {
1134 assigntok = RSH; /* a >>= b */
1135 c = OP_ASSIGN;
1136 cp++;
1137 }
1138 else
1139 c = RSH;
1140 }
1141 else if ((c == BAND) && (c1 == BAND))
1142 c = LAND;
1143 else if ((c == BOR) && (c1 == BOR))
1144 c = LOR;
cce855bc 1145 else if ((c == '*') && (c1 == '*'))
28ef6c31 1146 c = POWER;
b80f6443
JA
1147 else if ((c == '-' || c == '+') && c1 == c && curtok == STR)
1148 c = (c == '-') ? POSTDEC : POSTINC;
1149 else if ((c == '-' || c == '+') && c1 == c)
1150 {
1151 /* Quickly scan forward to see if this is followed by optional
1152 whitespace and an identifier. */
1153 xp = cp;
1154 while (xp && *xp && cr_whitespace (*xp))
1155 xp++;
1156 if (legal_variable_starter ((unsigned char)*xp))
1157 c = (c == '-') ? PREDEC : PREINC;
1158 else
1159 cp--; /* not preinc or predec, so unget the character */
1160 }
28ef6c31 1161 else if (c1 == EQ && member (c, "*/%+-&^|"))
726f6388
JA
1162 {
1163 assigntok = c; /* a OP= b */
1164 c = OP_ASSIGN;
1165 }
0628567a
JA
1166 else if (_is_arithop (c) == 0)
1167 {
1168 cp--;
1169 /* use curtok, since it hasn't been copied to lasttok yet */
1170 if (curtok == 0 || _is_arithop (curtok) || _is_multiop (curtok))
1171 evalerror (_("syntax error: operand expected"));
1172 else
1173 evalerror (_("syntax error: invalid arithmetic operator"));
1174 }
726f6388
JA
1175 else
1176 cp--; /* `unget' the character */
0628567a
JA
1177
1178 /* Should check here to make sure that the current character is one
1179 of the recognized operators and flag an error if not. Could create
1180 a character map the first time through and check it on subsequent
1181 calls. */
726f6388
JA
1182 lasttok = curtok;
1183 curtok = c;
1184 }
1185 tp = cp;
1186}
1187
1188static void
1189evalerror (msg)
1190 char *msg;
1191{
1192 char *name, *t;
1193
1194 name = this_command_name;
726f6388
JA
1195 for (t = expression; whitespace (*t); t++)
1196 ;
ccc6cda3
JA
1197 internal_error ("%s%s%s: %s (error token is \"%s\")",
1198 name ? name : "", name ? ": " : "", t,
1199 msg, (lasttp && *lasttp) ? lasttp : "");
726f6388
JA
1200 longjmp (evalbuf, 1);
1201}
1202
7117c2d2 1203/* Convert a string to an intmax_t integer, with an arbitrary base.
726f6388 1204 0nnn -> base 8
cce855bc 1205 0[Xx]nn -> base 16
ccc6cda3
JA
1206 Anything else: [base#]number (this is implemented to match ksh93)
1207
1208 Base may be >=2 and <=64. If base is <= 36, the numbers are drawn
1209 from [0-9][a-zA-Z], and lowercase and uppercase letters may be used
1210 interchangably. If base is > 36 and <= 64, the numbers are drawn
95732b49 1211 from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 --
ccc6cda3
JA
1212 you get the picture). */
1213
7117c2d2 1214static intmax_t
726f6388
JA
1215strlong (num)
1216 char *num;
1217{
ccc6cda3 1218 register char *s;
f73dda09 1219 register unsigned char c;
ccc6cda3 1220 int base, foundbase;
7117c2d2 1221 intmax_t val;
726f6388 1222
ccc6cda3 1223 s = num;
726f6388 1224
ccc6cda3
JA
1225 base = 10;
1226 foundbase = 0;
726f6388
JA
1227 if (*s == '0')
1228 {
1229 s++;
1230
f73dda09
JA
1231 if (*s == '\0')
1232 return 0;
ccc6cda3 1233
726f6388
JA
1234 /* Base 16? */
1235 if (*s == 'x' || *s == 'X')
1236 {
1237 base = 16;
1238 s++;
1239 }
1240 else
1241 base = 8;
ccc6cda3 1242 foundbase++;
726f6388
JA
1243 }
1244
f73dda09 1245 val = 0;
726f6388
JA
1246 for (c = *s++; c; c = *s++)
1247 {
1248 if (c == '#')
1249 {
ccc6cda3 1250 if (foundbase)
b80f6443 1251 evalerror (_("invalid number"));
ccc6cda3 1252
ccc6cda3 1253 /* Illegal base specifications raise an evaluation error. */
f73dda09 1254 if (val < 2 || val > 64)
b80f6443 1255 evalerror (_("invalid arithmetic base"));
726f6388 1256
f73dda09
JA
1257 base = val;
1258 val = 0;
ccc6cda3
JA
1259 foundbase++;
1260 }
f73dda09 1261 else if (ISALNUM(c) || (c == '_') || (c == '@'))
ccc6cda3 1262 {
f73dda09
JA
1263 if (DIGIT(c))
1264 c = TODIGIT(c);
ccc6cda3
JA
1265 else if (c >= 'a' && c <= 'z')
1266 c -= 'a' - 10;
1267 else if (c >= 'A' && c <= 'Z')
1268 c -= 'A' - ((base <= 36) ? 10 : 36);
ccc6cda3 1269 else if (c == '@')
f73dda09
JA
1270 c = 62;
1271 else if (c == '_')
ccc6cda3
JA
1272 c = 63;
1273
1274 if (c >= base)
b80f6443 1275 evalerror (_("value too great for base"));
ccc6cda3
JA
1276
1277 val = (val * base) + c;
726f6388
JA
1278 }
1279 else
ccc6cda3 1280 break;
726f6388 1281 }
95732b49 1282
726f6388
JA
1283 return (val);
1284}
1285
1286#if defined (EXPR_TEST)
f73dda09 1287void *
726f6388
JA
1288xmalloc (n)
1289 int n;
1290{
1291 return (malloc (n));
1292}
1293
f73dda09 1294void *
726f6388
JA
1295xrealloc (s, n)
1296 char *s;
1297 int n;
1298{
1299 return (realloc (s, n));
1300}
1301
1302SHELL_VAR *find_variable () { return 0;}
1303SHELL_VAR *bind_variable () { return 0; }
1304
1305char *get_string_value () { return 0; }
1306
ccc6cda3 1307procenv_t top_level;
726f6388
JA
1308
1309main (argc, argv)
1310 int argc;
1311 char **argv;
1312{
1313 register int i;
7117c2d2 1314 intmax_t v;
d166f048 1315 int expok;
726f6388
JA
1316
1317 if (setjmp (top_level))
1318 exit (0);
1319
1320 for (i = 1; i < argc; i++)
1321 {
d166f048
JA
1322 v = evalexp (argv[i], &expok);
1323 if (expok == 0)
28ef6c31 1324 fprintf (stderr, "%s: expression error\n", argv[i]);
d166f048 1325 else
28ef6c31 1326 printf ("'%s' -> %ld\n", argv[i], v);
726f6388
JA
1327 }
1328 exit (0);
1329}
1330
1331int
1332builtin_error (format, arg1, arg2, arg3, arg4, arg5)
1333 char *format;
1334{
1335 fprintf (stderr, "expr: ");
1336 fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
1337 fprintf (stderr, "\n");
1338 return 0;
1339}
1340
1341char *
1342itos (n)
7117c2d2 1343 intmax_t n;
726f6388
JA
1344{
1345 return ("42");
1346}
1347
1348#endif /* EXPR_TEST */