1 /* expr.c -- arithmetic expression evaluation. */
3 /* Copyright (C) 1990-2021 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
22 All arithmetic is done as intmax_t integers with no checking for overflow
23 (though division by 0 is caught and flagged as an error).
25 The following operators are handled, grouped into a set of levels in
26 order of decreasing precedence.
28 "id++", "id--" [post-increment and post-decrement]
29 "-", "+" [(unary operators)]
30 "++id", "--id" [pre-increment and pre-decrement]
32 "**" [(exponentiation)]
44 "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
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.)
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).
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.
63 Implementation is a recursive-descent parser.
74 #if defined (HAVE_UNISTD_H)
76 # include <sys/types.h>
81 #include "chartypes.h"
85 #include "arrayfunc.h"
86 #include "execute_cmd.h"
89 #include "typemax.h" /* INTMAX_MAX, INTMAX_MIN */
91 /* Because of the $((...)) construct, expressions may include newlines.
92 Here is a macro which accepts newlines, tabs and spaces as whitespace. */
93 #define cr_whitespace(c) (whitespace(c) || ((c) == '\n'))
95 /* Size be which the expression stack grows when necessary. */
96 #define EXPR_STACK_GROW_SIZE 10
98 /* Maximum amount of recursion allowed. This prevents a non-integer
99 variable such as "num=num+2" from infinitely adding to itself when
100 "let num=num+2" is given. */
101 #define MAX_EXPR_RECURSION_LEVEL 1024
103 /* The Tokens. Singing "The Lion Sleeps Tonight". */
105 #define EQEQ 1 /* "==" */
106 #define NEQ 2 /* "!=" */
107 #define LEQ 3 /* "<=" */
108 #define GEQ 4 /* ">=" */
109 #define STR 5 /* string */
110 #define NUM 6 /* number */
111 #define LAND 7 /* "&&" Logical AND */
112 #define LOR 8 /* "||" Logical OR */
113 #define LSH 9 /* "<<" Left SHift */
114 #define RSH 10 /* ">>" Right SHift */
115 #define OP_ASSIGN 11 /* op= expassign as in Posix.2 */
116 #define COND 12 /* exp1 ? exp2 : exp3 */
117 #define POWER 13 /* exp1**exp2 */
118 #define PREINC 14 /* ++var */
119 #define PREDEC 15 /* --var */
120 #define POSTINC 16 /* var++ */
121 #define POSTDEC 17 /* var-- */
133 #define BAND '&' /* Bitwise AND */
134 #define BOR '|' /* Bitwise OR. */
135 #define BXOR '^' /* Bitwise eXclusive OR. */
136 #define BNOT '~' /* Bitwise NOT; Two's complement. */
141 /* This should be the function corresponding to the operator with the
142 lowest precedence. */
143 #define EXP_LOWEST expcomma
146 # define MAX_INT_LEN 32
151 char *tokstr
; /* possibly-rewritten lvalue if not NULL */
152 intmax_t tokval
; /* expression evaluated value */
153 SHELL_VAR
*tokvar
; /* variable described by array or var reference */
154 intmax_t ind
; /* array index if not -1 */
157 /* A structure defining a single expression context. */
160 char *expression
, *tp
, *lasttp
;
167 static char *expression
; /* The current expression */
168 static char *tp
; /* token lexical position */
169 static char *lasttp
; /* pointer to last token position */
170 static int curtok
; /* the current token */
171 static int lasttok
; /* the previous token */
172 static int assigntok
; /* the OP in OP= */
173 static char *tokstr
; /* current token string */
174 static intmax_t tokval
; /* current token value */
175 static int noeval
; /* set to 1 if no assignment to be done */
176 static procenv_t evalbuf
;
178 /* set to 1 if the expression has already been run through word expansion */
179 static int already_expanded
;
181 static struct lvalue curlval
= {0, 0, 0, -1};
182 static struct lvalue lastlval
= {0, 0, 0, -1};
184 static int _is_arithop
PARAMS((int));
185 static void readtok
PARAMS((void)); /* lexical analyzer */
187 static void init_lvalue
PARAMS((struct lvalue
*));
188 static struct lvalue
*alloc_lvalue
PARAMS((void));
189 static void free_lvalue
PARAMS((struct lvalue
*));
191 static intmax_t expr_streval
PARAMS((char *, int, struct lvalue
*));
192 static intmax_t strlong
PARAMS((char *));
193 static void evalerror
PARAMS((const char *));
195 static void pushexp
PARAMS((void));
196 static void popexp
PARAMS((void));
197 static void expr_unwind
PARAMS((void));
198 static void expr_bind_variable
PARAMS((char *, char *));
199 #if defined (ARRAY_VARS)
200 static void expr_bind_array_element
PARAMS((char *, arrayind_t
, char *));
203 static intmax_t subexpr
PARAMS((char *));
205 static intmax_t expcomma
PARAMS((void));
206 static intmax_t expassign
PARAMS((void));
207 static intmax_t expcond
PARAMS((void));
208 static intmax_t explor
PARAMS((void));
209 static intmax_t expland
PARAMS((void));
210 static intmax_t expbor
PARAMS((void));
211 static intmax_t expbxor
PARAMS((void));
212 static intmax_t expband
PARAMS((void));
213 static intmax_t exp5
PARAMS((void));
214 static intmax_t exp4
PARAMS((void));
215 static intmax_t expshift
PARAMS((void));
216 static intmax_t exp3
PARAMS((void));
217 static intmax_t expmuldiv
PARAMS((void));
218 static intmax_t exppower
PARAMS((void));
219 static intmax_t exp1
PARAMS((void));
220 static intmax_t exp0
PARAMS((void));
222 /* Global var which contains the stack of expression contexts. */
223 static EXPR_CONTEXT
**expr_stack
;
224 static int expr_depth
; /* Location in the stack. */
225 static int expr_stack_size
; /* Number of slots already allocated. */
227 #if defined (ARRAY_VARS)
228 extern const char * const bash_badsub_errmsg
;
233 (X)->curtok = curtok; \
234 (X)->lasttok = lasttok; \
236 (X)->lasttp = lasttp; \
237 (X)->tokval = tokval; \
238 (X)->tokstr = tokstr; \
239 (X)->noeval = noeval; \
240 (X)->lval = curlval; \
243 #define RESTORETOK(X) \
245 curtok = (X)->curtok; \
246 lasttok = (X)->lasttok; \
248 lasttp = (X)->lasttp; \
249 tokval = (X)->tokval; \
250 tokstr = (X)->tokstr; \
251 noeval = (X)->noeval; \
252 curlval = (X)->lval; \
255 /* Push and save away the contents of the globals describing the
256 current expression context. */
260 EXPR_CONTEXT
*context
;
262 if (expr_depth
>= MAX_EXPR_RECURSION_LEVEL
)
263 evalerror (_("expression recursion level exceeded"));
265 if (expr_depth
>= expr_stack_size
)
267 expr_stack_size
+= EXPR_STACK_GROW_SIZE
;
268 expr_stack
= (EXPR_CONTEXT
**)xrealloc (expr_stack
, expr_stack_size
* sizeof (EXPR_CONTEXT
*));
271 context
= (EXPR_CONTEXT
*)xmalloc (sizeof (EXPR_CONTEXT
));
273 context
->expression
= expression
;
276 expr_stack
[expr_depth
++] = context
;
279 /* Pop the the contents of the expression context stack into the
280 globals describing the current expression context. */
284 EXPR_CONTEXT
*context
;
288 /* See the comment at the top of evalexp() for an explanation of why
290 expression
= lasttp
= 0;
291 evalerror (_("recursion stack underflow"));
294 context
= expr_stack
[--expr_depth
];
296 expression
= context
->expression
;
297 RESTORETOK (context
);
305 while (--expr_depth
> 0)
307 if (expr_stack
[expr_depth
]->tokstr
)
308 free (expr_stack
[expr_depth
]->tokstr
);
310 if (expr_stack
[expr_depth
]->expression
)
311 free (expr_stack
[expr_depth
]->expression
);
313 free (expr_stack
[expr_depth
]);
316 free (expr_stack
[expr_depth
]); /* free the allocated EXPR_CONTEXT */
318 noeval
= 0; /* XXX */
322 expr_bind_variable (lhs
, rhs
)
328 if (lhs
== 0 || *lhs
== 0)
331 #if defined (ARRAY_VARS)
332 aflags
= (assoc_expand_once
&& already_expanded
) ? ASS_NOEXPAND
: 0;
333 aflags
|= ASS_ALLOWALLSUB
; /* allow assoc[@]=value */
337 v
= bind_int_variable (lhs
, rhs
, aflags
);
338 if (v
&& (readonly_p (v
) || noassign_p (v
)))
339 sh_longjmp (evalbuf
, 1); /* variable assignment error */
340 stupidly_hack_special_variables (lhs
);
343 #if defined (ARRAY_VARS)
344 /* This is similar to the logic in arrayfunc.c:valid_array_reference when
345 you pass VA_NOEXPAND. */
347 expr_skipsubscript (vp
, cp
)
355 if (assoc_expand_once
& already_expanded
)
358 isassoc
= legal_identifier (vp
) && (entry
= find_variable (vp
)) && assoc_p (entry
);
361 flags
= (isassoc
&& assoc_expand_once
&& already_expanded
) ? VA_NOEXPAND
: 0;
362 return (skipsubscript (cp
, 0, flags
));
365 /* Rewrite tok, which is of the form vname[expression], to vname[ind], where
366 IND is the already-calculated value of expression. */
368 expr_bind_array_element (tok
, ind
, rhs
)
375 char ibuf
[INT_STRLEN_BOUND (arrayind_t
) + 1], *istr
;
377 istr
= fmtumax (ind
, 10, ibuf
, sizeof (ibuf
), 0);
378 vname
= array_variable_name (tok
, 0, (char **)NULL
, (int *)NULL
);
380 llen
= strlen (vname
) + sizeof (ibuf
) + 3;
381 lhs
= xmalloc (llen
);
383 sprintf (lhs
, "%s[%s]", vname
, istr
); /* XXX */
385 /*itrace("expr_bind_array_element: %s=%s", lhs, rhs);*/
386 expr_bind_variable (lhs
, rhs
);
390 #endif /* ARRAY_VARS */
392 /* Evaluate EXPR, and return the arithmetic result. If VALIDP is
393 non-null, a zero is stored into the location to which it points
394 if the expression is invalid, non-zero otherwise. If a non-zero
395 value is returned in *VALIDP, the return value of evalexp() may
398 The `while' loop after the longjmp is caught relies on the above
399 implementation of pushexp and popexp leaving in expr_stack[0] the
400 values that the variables had when the program started. That is,
401 the first things saved are the initial values of the variables that
402 were assigned at program startup or by the compiler. Therefore, it is
403 safe to let the loop terminate when expr_depth == 0, without freeing up
404 any of the expr_depth[0] stuff. */
406 evalexp (expr
, flags
, validp
)
417 already_expanded
= (flags
&EXP_EXPANDED
);
419 FASTCOPY (evalbuf
, oevalbuf
, sizeof (evalbuf
));
421 c
= setjmp_nosigs (evalbuf
);
427 tokstr
= expression
= (char *)NULL
;
430 expr_depth
= 0; /* XXX - make sure */
432 /* We copy in case we've called evalexp recursively */
433 FASTCOPY (oevalbuf
, evalbuf
, sizeof (evalbuf
));
440 val
= subexpr (expr
);
445 FASTCOPY (oevalbuf
, evalbuf
, sizeof (evalbuf
));
457 for (p
= expr
; p
&& *p
&& cr_whitespace (*p
); p
++)
460 if (p
== NULL
|| *p
== '\0')
464 expression
= savestring (expr
);
467 curtok
= lasttok
= 0;
468 tokstr
= (char *)NULL
;
470 init_lvalue (&curlval
);
477 /*TAG:bash-5.3 make it clear that these are arithmetic syntax errors */
479 evalerror (_("syntax error in expression"));
492 register intmax_t value
;
494 value
= expassign ();
495 while (curtok
== COMMA
)
498 value
= expassign ();
507 register intmax_t value
;
510 #if defined (HAVE_IMAXDIV)
515 if (curtok
== EQ
|| curtok
== OP_ASSIGN
)
520 special
= curtok
== OP_ASSIGN
;
523 evalerror (_("attempted assignment to non-variable"));
527 op
= assigntok
; /* a OP= b */
532 evalerror (_("syntax error in variable assignment"));
534 /* XXX - watch out for pointer aliasing issues here */
535 lhs
= savestring (tokstr
);
536 /* save ind in case rhs is string var and evaluation overwrites it */
539 value
= expassign ();
543 if ((op
== DIV
|| op
== MOD
) && value
== 0)
546 evalerror (_("division by 0"));
554 /* Handle INTMAX_MIN and INTMAX_MAX * -1 specially here? */
559 if (lvalue
== INTMAX_MIN
&& value
== -1)
560 lvalue
= (op
== DIV
) ? INTMAX_MIN
: 0;
564 idiv
= imaxdiv (lvalue
, value
);
565 lvalue
= (op
== DIV
) ? idiv
.quot
: idiv
.rem
;
568 lvalue
= (op
== DIV
) ? lvalue
/ value
: lvalue
% value
;
594 evalerror (_("bug: bad expassign token"));
603 #if defined (ARRAY_VARS)
605 expr_bind_array_element (lhs
, lind
, rhs
);
608 expr_bind_variable (lhs
, rhs
);
610 if (curlval
.tokstr
&& curlval
.tokstr
== tokstr
)
611 init_lvalue (&curlval
);
616 tokstr
= (char *)NULL
; /* For freeing on errors. */
622 /* Conditional expression (expr?expr:expr) */
626 intmax_t cval
, val1
, val2
, rval
;
630 rval
= cval
= explor ();
631 if (curtok
== QUES
) /* found conditional expr */
640 if (curtok
== 0 || curtok
== COL
)
641 evalerror (_("expression expected"));
643 val1
= EXP_LOWEST ();
648 evalerror (_("`:' expected for conditional expression"));
659 evalerror (_("expression expected"));
664 rval
= cval
? val1
: val2
;
674 register intmax_t val1
, val2
;
679 while (curtok
== LOR
)
702 register intmax_t val1
, val2
;
707 while (curtok
== LAND
)
730 register intmax_t val1
, val2
;
734 while (curtok
== BOR
)
749 register intmax_t val1
, val2
;
753 while (curtok
== BXOR
)
768 register intmax_t val1
, val2
;
772 while (curtok
== BAND
)
786 register intmax_t val1
, val2
;
790 while ((curtok
== EQEQ
) || (curtok
== NEQ
))
797 val1
= (val1
== val2
);
799 val1
= (val1
!= val2
);
808 register intmax_t val1
, val2
;
811 while ((curtok
== LEQ
) ||
827 else /* (op == GT) */
834 /* Left and right shifts. */
838 register intmax_t val1
, val2
;
842 while ((curtok
== LSH
) || (curtok
== RSH
))
862 register intmax_t val1
, val2
;
866 while ((curtok
== PLUS
) || (curtok
== MINUS
))
875 else if (op
== MINUS
)
885 register intmax_t val1
, val2
;
886 #if defined (HAVE_IMAXDIV)
892 while ((curtok
== MUL
) ||
904 /* Handle division by 0 and twos-complement arithmetic overflow */
905 if (((op
== DIV
) || (op
== MOD
)) && (val2
== 0))
911 while (lasttp
&& *lasttp
&& whitespace (*lasttp
))
913 evalerror (_("division by 0"));
919 else if (op
== MOD
&& val1
== INTMAX_MIN
&& val2
== -1)
924 else if (op
== DIV
&& val1
== INTMAX_MIN
&& val2
== -1)
929 else if (op
== DIV
|| op
== MOD
)
930 #if defined (HAVE_IMAXDIV)
932 idiv
= imaxdiv (val1
, val2
);
933 val1
= (op
== DIV
) ? idiv
.quot
: idiv
.rem
;
936 val1
= (op
== DIV
) ? val1
/ val2
: val1
% val2
;
963 register intmax_t val1
, val2
, c
;
966 while (curtok
== POWER
)
969 val2
= exppower (); /* exponentiation is right-associative */
974 evalerror (_("exponent less than 0"));
975 val1
= ipow (val1
, val2
);
983 register intmax_t val
;
991 else if (curtok
== BNOT
)
997 else if (curtok
== MINUS
)
1003 else if (curtok
== PLUS
)
1018 register intmax_t val
= 0, v2
;
1023 /* XXX - might need additional logic here to decide whether or not
1024 pre-increment or pre-decrement is legal at this point. */
1025 if (curtok
== PREINC
|| curtok
== PREDEC
)
1027 stok
= lasttok
= curtok
;
1030 /* readtok() catches this */
1031 evalerror (_("identifier expected after pre-increment or pre-decrement"));
1033 v2
= tokval
+ ((stok
== PREINC
) ? 1 : -1);
1034 vincdec
= itos (v2
);
1037 #if defined (ARRAY_VARS)
1038 if (curlval
.ind
!= -1)
1039 expr_bind_array_element (curlval
.tokstr
, curlval
.ind
, vincdec
);
1043 expr_bind_variable (tokstr
, vincdec
);
1048 curtok
= NUM
; /* make sure --x=7 is flagged as an error */
1051 else if (curtok
== LPAR
)
1053 /* XXX - save curlval here? Or entire expression context? */
1055 val
= EXP_LOWEST ();
1057 if (curtok
!= RPAR
) /* ( */
1058 evalerror (_("missing `)'"));
1060 /* Skip over closing paren. */
1063 else if ((curtok
== NUM
) || (curtok
== STR
))
1069 tokstr
= (char *)NULL
; /* keep it from being freed */
1074 /* post-increment or post-decrement */
1075 if (stok
== POSTINC
|| stok
== POSTDEC
)
1077 /* restore certain portions of EC */
1081 lasttok
= STR
; /* ec.curtok */
1083 v2
= val
+ ((stok
== POSTINC
) ? 1 : -1);
1084 vincdec
= itos (v2
);
1087 #if defined (ARRAY_VARS)
1088 if (curlval
.ind
!= -1)
1089 expr_bind_array_element (curlval
.tokstr
, curlval
.ind
, vincdec
);
1092 expr_bind_variable (tokstr
, vincdec
);
1095 curtok
= NUM
; /* make sure x++=7 is flagged as an error */
1099 /* XXX - watch out for pointer aliasing issues here */
1100 if (stok
== STR
) /* free new tokstr before old one is restored */
1109 evalerror (_("syntax error: operand expected"));
1120 lv
->tokval
= lv
->ind
= -1;
1123 static struct lvalue
*
1128 lv
= xmalloc (sizeof (struct lvalue
));
1137 free (lv
); /* should be inlined */
1141 expr_streval (tok
, e
, lvalue
)
1144 struct lvalue
*lvalue
;
1150 #if defined (ARRAY_VARS)
1153 array_eltstate_t es
;
1156 /*itrace("expr_streval: %s: noeval = %d expanded=%d", tok, noeval, already_expanded);*/
1157 /* If we are suppressing evaluation, just short-circuit here instead of
1158 going through the rest of the evaluator. */
1162 initial_depth
= expr_depth
;
1164 #if defined (ARRAY_VARS)
1165 tflag
= (assoc_expand_once
&& already_expanded
) ? AV_NOEXPAND
: 0; /* for a start */
1169 #if defined (ARRAY_VARS)
1170 aflag
= tflag
; /* use a different variable for now */
1171 if (shell_compatibility_level
> 51)
1172 aflag
|= AV_ATSTARKEYS
;
1173 v
= (e
== ']') ? array_variable_part (tok
, tflag
, (char **)0, (int *)0) : find_variable (tok
);
1175 v
= find_variable (tok
);
1177 if (v
== 0 && e
!= ']')
1178 v
= find_variable_last_nameref (tok
, 0);
1180 if ((v
== 0 || invisible_p (v
)) && unbound_vars_is_error
)
1182 #if defined (ARRAY_VARS)
1183 value
= (e
== ']') ? array_variable_name (tok
, tflag
, (char **)0, (int *)0) : tok
;
1188 set_exit_status (EXECUTION_FAILURE
);
1189 err_unboundvar (value
);
1191 #if defined (ARRAY_VARS)
1193 FREE (value
); /* array_variable_name returns new memory */
1196 if (no_longjmp_on_fatal_error
&& interactive_shell
)
1197 sh_longjmp (evalbuf
, 1);
1199 if (interactive_shell
)
1202 top_level_cleanup ();
1203 jump_to_top_level (DISCARD
);
1206 jump_to_top_level (FORCE_EOF
);
1209 #if defined (ARRAY_VARS)
1210 init_eltstate (&es
);
1212 /* If the second argument to get_array_value doesn't include AV_ALLOWALL,
1213 we don't allow references like array[@]. In this case, get_array_value
1214 is just like get_variable_value in that it does not return newly-allocated
1215 memory or quote the results. AFLAG is set above and is either AV_NOEXPAND
1217 value
= (e
== ']') ? get_array_value (tok
, aflag
, &es
) : get_variable_value (v
);
1219 flush_eltstate (&es
);
1221 value
= get_variable_value (v
);
1224 if (expr_depth
< initial_depth
)
1226 if (no_longjmp_on_fatal_error
&& interactive_shell
)
1227 sh_longjmp (evalbuf
, 1);
1231 tval
= (value
&& *value
) ? subexpr (value
) : 0;
1235 lvalue
->tokstr
= tok
; /* XXX */
1236 lvalue
->tokval
= tval
;
1237 lvalue
->tokvar
= v
; /* XXX */
1238 #if defined (ARRAY_VARS)
1296 return 1; /* operator tokens */
1300 return 1; /* questionable */
1302 return 0; /* anything else is invalid */
1306 /* Lexical analyzer/token reader for the expression evaluator. Reads the
1307 next token and puts its value into curtok, while advancing past it.
1308 Updates value of tp. May also set tokval (for number) or tokstr (for
1313 register char *cp
, *xp
;
1314 register unsigned char c
, c1
;
1318 /* Skip leading whitespace. */
1321 while (cp
&& (c
= *cp
) && (cr_whitespace (c
)))
1334 lasttp
= tp
= cp
- 1;
1336 if (legal_variable_starter (c
))
1338 /* variable names not preceded with a dollar sign are shell variables. */
1343 while (legal_variable_char (c
))
1348 #if defined (ARRAY_VARS)
1351 e
= expr_skipsubscript (tp
, cp
); /* XXX - was skipsubscript */
1359 evalerror (bash_badsub_errmsg
);
1361 #endif /* ARRAY_VARS */
1364 /* XXX - watch out for pointer aliasing issues here */
1365 if (curlval
.tokstr
&& curlval
.tokstr
== tokstr
)
1366 init_lvalue (&curlval
);
1369 tokstr
= savestring (tp
);
1372 /* XXX - make peektok part of saved token state? */
1374 tokstr
= (char *)NULL
; /* keep it from being freed */
1380 if (peektok
== STR
) /* free new tokstr before old one is restored */
1385 /* The tests for PREINC and PREDEC aren't strictly correct, but they
1386 preserve old behavior if a construct like --x=9 is given. */
1387 if (lasttok
== PREINC
|| lasttok
== PREDEC
|| peektok
!= EQ
)
1390 tokval
= expr_streval (tokstr
, e
, &curlval
);
1400 while (ISALNUM (c
) || c
== '#' || c
== '@' || c
== '_')
1406 tokval
= strlong (tp
);
1414 if ((c
== EQ
) && (c1
== EQ
))
1416 else if ((c
== NOT
) && (c1
== EQ
))
1418 else if ((c
== GT
) && (c1
== EQ
))
1420 else if ((c
== LT
) && (c1
== EQ
))
1422 else if ((c
== LT
) && (c1
== LT
))
1424 if (*cp
== '=') /* a <<= b */
1433 else if ((c
== GT
) && (c1
== GT
))
1437 assigntok
= RSH
; /* a >>= b */
1444 else if ((c
== BAND
) && (c1
== BAND
))
1446 else if ((c
== BOR
) && (c1
== BOR
))
1448 else if ((c
== '*') && (c1
== '*'))
1450 else if ((c
== '-' || c
== '+') && c1
== c
&& curtok
== STR
)
1451 c
= (c
== '-') ? POSTDEC
: POSTINC
;
1452 #if STRICT_ARITH_PARSING
1453 else if ((c
== '-' || c
== '+') && c1
== c
&& curtok
== NUM
)
1455 else if ((c
== '-' || c
== '+') && c1
== c
&& curtok
== NUM
&& (lasttok
== PREINC
|| lasttok
== PREDEC
))
1458 /* This catches something like --FOO++ */
1459 /* TAG:bash-5.3 add gettext calls here or make this a separate function */
1461 evalerror ("--: assignment requires lvalue");
1463 evalerror ("++: assignment requires lvalue");
1465 else if ((c
== '-' || c
== '+') && c1
== c
)
1467 /* Quickly scan forward to see if this is followed by optional
1468 whitespace and an identifier. */
1470 while (xp
&& *xp
&& cr_whitespace (*xp
))
1472 if (legal_variable_starter ((unsigned char)*xp
))
1473 c
= (c
== '-') ? PREDEC
: PREINC
;
1475 /* Could force parsing as preinc or predec and throw an error */
1476 #if STRICT_ARITH_PARSING
1478 /* Posix says unary plus and minus have higher priority than
1479 preinc and predec. */
1480 /* This catches something like --4++ */
1482 evalerror ("--: assignment requires lvalue");
1484 evalerror ("++: assignment requires lvalue");
1487 cp
--; /* not preinc or predec, so unget the character */
1490 else if (c1
== EQ
&& member (c
, "*/%+-&^|"))
1492 assigntok
= c
; /* a OP= b */
1495 else if (_is_arithop (c
) == 0)
1498 /* use curtok, since it hasn't been copied to lasttok yet */
1499 if (curtok
== 0 || _is_arithop (curtok
) || _is_multiop (curtok
))
1500 evalerror (_("syntax error: operand expected"));
1502 evalerror (_("syntax error: invalid arithmetic operator"));
1505 cp
--; /* `unget' the character */
1507 /* Should check here to make sure that the current character is one
1508 of the recognized operators and flag an error if not. Could create
1509 a character map the first time through and check it on subsequent
1523 name
= this_command_name
;
1524 for (t
= expression
; t
&& whitespace (*t
); t
++)
1526 internal_error (_("%s%s%s: %s (error token is \"%s\")"),
1527 name
? name
: "", name
? ": " : "",
1528 t
? t
: "", msg
, (lasttp
&& *lasttp
) ? lasttp
: "");
1529 sh_longjmp (evalbuf
, 1);
1532 /* Convert a string to an intmax_t integer, with an arbitrary base.
1535 Anything else: [base#]number (this is implemented to match ksh93)
1537 Base may be >=2 and <=64. If base is <= 36, the numbers are drawn
1538 from [0-9][a-zA-Z], and lowercase and uppercase letters may be used
1539 interchangeably. If base is > 36 and <= 64, the numbers are drawn
1540 from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 --
1541 you get the picture). */
1543 #define VALID_NUMCHAR(c) (ISALNUM(c) || ((c) == '_') || ((c) == '@'))
1550 register unsigned char c
;
1551 int base
, foundbase
;
1566 if (*s
== 'x' || *s
== 'X')
1570 #if STRICT_ARITH_PARSING
1572 evalerror (_("invalid number"));
1581 for (c
= *s
++; c
; c
= *s
++)
1586 evalerror (_("invalid number"));
1588 /* Illegal base specifications raise an evaluation error. */
1589 if (val
< 2 || val
> 64)
1590 evalerror (_("invalid arithmetic base"));
1596 /* Make sure a base# is followed by a character that can compose a
1597 valid integer constant. Jeremy Townshend <jeremy.townshend@gmail.com> */
1598 if (VALID_NUMCHAR (*s
) == 0)
1599 evalerror (_("invalid integer constant"));
1601 else if (VALID_NUMCHAR (c
))
1605 else if (c
>= 'a' && c
<= 'z')
1607 else if (c
>= 'A' && c
<= 'Z')
1608 c
-= 'A' - ((base
<= 36) ? 10 : 36);
1615 evalerror (_("value too great for base"));
1617 #ifdef CHECK_OVERFLOW
1619 val
= (val
* base
) + c
;
1620 if (val
< 0 || val
< pval
) /* overflow */
1623 val
= (val
* base
) + c
;
1633 #if defined (EXPR_TEST)
1638 return (malloc (n
));
1646 return (realloc (s
, n
));
1649 SHELL_VAR
*find_variable () { return 0;}
1650 SHELL_VAR
*bind_variable () { return 0; }
1652 char *get_string_value () { return 0; }
1654 procenv_t top_level
;
1664 if (setjmp (top_level
))
1667 for (i
= 1; i
< argc
; i
++)
1669 v
= evalexp (argv
[i
], 0, &expok
);
1671 fprintf (stderr
, _("%s: expression error\n"), argv
[i
]);
1673 printf ("'%s' -> %ld\n", argv
[i
], v
);
1679 builtin_error (format
, arg1
, arg2
, arg3
, arg4
, arg5
)
1682 fprintf (stderr
, "expr: ");
1683 fprintf (stderr
, format
, arg1
, arg2
, arg3
, arg4
, arg5
);
1684 fprintf (stderr
, "\n");
1695 #endif /* EXPR_TEST */