| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* expr.c -- arithmetic expression evaluation. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* Copyright (C) 1990-2013 Free Software Foundation, Inc.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |    (at your option) any later version. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Bash is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |    GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |  All arithmetic is done as intmax_t integers with no checking for overflow | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  (though division by 0 is caught and flagged as an error). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  The following operators are handled, grouped into a set of levels in | 
					
						
							|  |  |  |  order of decreasing precedence. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	"id++", "id--"		[post-increment and post-decrement] | 
					
						
							|  |  |  | 	"++id", "--id"		[pre-increment and pre-decrement] | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	"-", "+"		[(unary operators)] | 
					
						
							|  |  |  | 	"!", "~" | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	"**"			[(exponentiation)] | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	"*", "/", "%" | 
					
						
							|  |  |  | 	"+", "-" | 
					
						
							|  |  |  | 	"<<", ">>" | 
					
						
							|  |  |  | 	"<=", ">=", "<", ">" | 
					
						
							|  |  |  | 	"==", "!=" | 
					
						
							|  |  |  | 	"&" | 
					
						
							|  |  |  | 	"^" | 
					
						
							|  |  |  | 	"|" | 
					
						
							|  |  |  | 	"&&" | 
					
						
							|  |  |  | 	"||" | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	"expr ? expr : expr" | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	"=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|=" | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	,			[comma] | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |  (Note that most of these operators have special meaning to bash, and an | 
					
						
							|  |  |  |  entire expression should be quoted, e.g. "a=$a+1" or "a=a+1" to ensure | 
					
						
							|  |  |  |  that it is passed intact to the evaluator when using `let'.  When using | 
					
						
							|  |  |  |  the $[] or $(( )) forms, the text between the `[' and `]' or `((' and `))' | 
					
						
							|  |  |  |  is treated as if in double quotes.) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  Sub-expressions within parentheses have a precedence level greater than | 
					
						
							|  |  |  |  all of the above levels and are evaluated first.  Within a single prece- | 
					
						
							|  |  |  |  dence group, evaluation is left-to-right, except for the arithmetic | 
					
						
							|  |  |  |  assignment operator (`='), which is evaluated right-to-left (as in C). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  The expression evaluator returns the value of the expression (assignment | 
					
						
							|  |  |  |  statements have as a value what is returned by the RHS).  The `let' | 
					
						
							|  |  |  |  builtin, on the other hand, returns 0 if the last expression evaluates to | 
					
						
							|  |  |  |  a non-zero, and 1 otherwise. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  Implementation is a recursive-descent parser. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  Chet Ramey | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |  chet@po.cwru.edu | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include "bashansi.h"
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #  ifdef _MINIX
 | 
					
						
							|  |  |  | #    include <sys/types.h>
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #include "chartypes.h"
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #include "bashintl.h"
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "shell.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #include "typemax.h"		/* INTMAX_MAX, INTMAX_MIN */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Because of the $((...)) construct, expressions may include newlines.
 | 
					
						
							|  |  |  |    Here is a macro which accepts newlines, tabs and spaces as whitespace. */ | 
					
						
							|  |  |  | #define cr_whitespace(c) (whitespace(c) || ((c) == '\n'))
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | /* Size be which the expression stack grows when necessary. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #define EXPR_STACK_GROW_SIZE 10
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Maximum amount of recursion allowed.  This prevents a non-integer
 | 
					
						
							|  |  |  |    variable such as "num=num+2" from infinitely adding to itself when | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    "let num=num+2" is given. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #define MAX_EXPR_RECURSION_LEVEL 1024
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The Tokens.  Singing "The Lion Sleeps Tonight". */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EQEQ	1	/* "==" */
 | 
					
						
							|  |  |  | #define NEQ	2	/* "!=" */
 | 
					
						
							|  |  |  | #define LEQ	3	/* "<=" */
 | 
					
						
							|  |  |  | #define GEQ	4	/* ">=" */
 | 
					
						
							|  |  |  | #define STR	5	/* string */
 | 
					
						
							|  |  |  | #define NUM	6	/* number */
 | 
					
						
							|  |  |  | #define LAND	7	/* "&&" Logical AND */
 | 
					
						
							|  |  |  | #define LOR	8	/* "||" Logical OR */
 | 
					
						
							|  |  |  | #define LSH	9	/* "<<" Left SHift */
 | 
					
						
							|  |  |  | #define RSH    10	/* ">>" Right SHift */
 | 
					
						
							|  |  |  | #define OP_ASSIGN 11	/* op= expassign as in Posix.2 */
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #define COND	12	/* exp1 ? exp2 : exp3 */
 | 
					
						
							|  |  |  | #define POWER	13	/* exp1**exp2 */
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #define PREINC	14	/* ++var */
 | 
					
						
							|  |  |  | #define PREDEC	15	/* --var */
 | 
					
						
							|  |  |  | #define POSTINC	16	/* var++ */
 | 
					
						
							|  |  |  | #define POSTDEC	17	/* var-- */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #define EQ	'='
 | 
					
						
							|  |  |  | #define GT	'>'
 | 
					
						
							|  |  |  | #define LT	'<'
 | 
					
						
							|  |  |  | #define PLUS	'+'
 | 
					
						
							|  |  |  | #define MINUS	'-'
 | 
					
						
							|  |  |  | #define MUL	'*'
 | 
					
						
							|  |  |  | #define DIV	'/'
 | 
					
						
							|  |  |  | #define MOD	'%'
 | 
					
						
							|  |  |  | #define NOT	'!'
 | 
					
						
							|  |  |  | #define LPAR	'('
 | 
					
						
							|  |  |  | #define RPAR	')'
 | 
					
						
							|  |  |  | #define BAND	'&'	/* Bitwise AND */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #define BOR	'|'	/* Bitwise OR. */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #define BXOR	'^'	/* Bitwise eXclusive OR. */
 | 
					
						
							|  |  |  | #define BNOT	'~'	/* Bitwise NOT; Two's complement. */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #define QUES	'?'
 | 
					
						
							|  |  |  | #define COL	':'
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #define COMMA	','
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This should be the function corresponding to the operator with the
 | 
					
						
							|  |  |  |    highest precedence. */ | 
					
						
							|  |  |  | #define EXP_HIGHEST	expcomma
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #ifndef MAX_INT_LEN
 | 
					
						
							|  |  |  | #  define MAX_INT_LEN 32
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct lvalue | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *tokstr;		/* possibly-rewritten lvalue if not NULL */ | 
					
						
							|  |  |  |   intmax_t tokval;	/* expression evaluated value */ | 
					
						
							|  |  |  |   SHELL_VAR *tokvar;	/* variable described by array or var reference */ | 
					
						
							|  |  |  |   intmax_t ind;		/* array index if not -1 */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A structure defining a single expression context. */ | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |   int curtok, lasttok; | 
					
						
							|  |  |  |   char *expression, *tp, *lasttp; | 
					
						
							|  |  |  |   intmax_t tokval; | 
					
						
							|  |  |  |   char *tokstr; | 
					
						
							|  |  |  |   int noeval; | 
					
						
							|  |  |  |   struct lvalue lval; | 
					
						
							|  |  |  | } EXPR_CONTEXT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static char	*expression;	/* The current expression */ | 
					
						
							|  |  |  | static char	*tp;		/* token lexical position */ | 
					
						
							|  |  |  | static char	*lasttp;	/* pointer to last token position */ | 
					
						
							|  |  |  | static int	curtok;		/* the current token */ | 
					
						
							|  |  |  | static int	lasttok;	/* the previous token */ | 
					
						
							|  |  |  | static int	assigntok;	/* the OP in OP= */ | 
					
						
							|  |  |  | static char	*tokstr;	/* current token string */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t	tokval;		/* current token value */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static int	noeval;		/* set to 1 if no assignment to be done */ | 
					
						
							|  |  |  | static procenv_t evalbuf; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | static struct lvalue curlval = {0, 0, 0, -1}; | 
					
						
							|  |  |  | static struct lvalue lastlval = {0, 0, 0, -1}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | static int	_is_arithop __P((int)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static void	readtok __P((void));	/* lexical analyzer */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | static void	init_lvalue __P((struct lvalue *)); | 
					
						
							|  |  |  | static struct lvalue *alloc_lvalue __P((void)); | 
					
						
							|  |  |  | static void	free_lvalue __P((struct lvalue *)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static intmax_t	expr_streval __P((char *, int, struct lvalue *)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t	strlong __P((char *)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static void	evalerror __P((const char *)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void	pushexp __P((void)); | 
					
						
							|  |  |  | static void	popexp __P((void)); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void	expr_unwind __P((void)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static void	expr_bind_variable __P((char *, char *)); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | static void	expr_bind_array_element __P((char *, arrayind_t, char *)); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static intmax_t subexpr __P((char *)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static intmax_t	expcomma __P((void)); | 
					
						
							|  |  |  | static intmax_t expassign __P((void)); | 
					
						
							|  |  |  | static intmax_t	expcond __P((void)); | 
					
						
							|  |  |  | static intmax_t explor __P((void)); | 
					
						
							|  |  |  | static intmax_t expland __P((void)); | 
					
						
							|  |  |  | static intmax_t	expbor __P((void)); | 
					
						
							|  |  |  | static intmax_t	expbxor __P((void)); | 
					
						
							|  |  |  | static intmax_t	expband __P((void)); | 
					
						
							|  |  |  | static intmax_t exp5 __P((void)); | 
					
						
							|  |  |  | static intmax_t exp4 __P((void)); | 
					
						
							|  |  |  | static intmax_t expshift __P((void)); | 
					
						
							|  |  |  | static intmax_t exp3 __P((void)); | 
					
						
							|  |  |  | static intmax_t exp2 __P((void)); | 
					
						
							|  |  |  | static intmax_t	exppower __P((void)); | 
					
						
							|  |  |  | static intmax_t exp1 __P((void)); | 
					
						
							|  |  |  | static intmax_t exp0 __P((void)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Global var which contains the stack of expression contexts. */ | 
					
						
							|  |  |  | static EXPR_CONTEXT **expr_stack; | 
					
						
							|  |  |  | static int expr_depth;		   /* Location in the stack. */ | 
					
						
							|  |  |  | static int expr_stack_size;	   /* Number of slots already allocated. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern char *this_command_name; | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | extern int unbound_vars_is_error, last_command_exit_value; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | extern const char * const bash_badsub_errmsg; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #define SAVETOK(X) \
 | 
					
						
							|  |  |  |   do { \ | 
					
						
							|  |  |  |     (X)->curtok = curtok; \ | 
					
						
							|  |  |  |     (X)->lasttok = lasttok; \ | 
					
						
							|  |  |  |     (X)->tp = tp; \ | 
					
						
							|  |  |  |     (X)->lasttp = lasttp; \ | 
					
						
							|  |  |  |     (X)->tokval = tokval; \ | 
					
						
							|  |  |  |     (X)->tokstr = tokstr; \ | 
					
						
							|  |  |  |     (X)->noeval = noeval; \ | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |     (X)->lval = curlval; \ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   } while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RESTORETOK(X) \
 | 
					
						
							|  |  |  |   do { \ | 
					
						
							|  |  |  |     curtok = (X)->curtok; \ | 
					
						
							|  |  |  |     lasttok = (X)->lasttok; \ | 
					
						
							|  |  |  |     tp = (X)->tp; \ | 
					
						
							|  |  |  |     lasttp = (X)->lasttp; \ | 
					
						
							|  |  |  |     tokval = (X)->tokval; \ | 
					
						
							|  |  |  |     tokstr = (X)->tokstr; \ | 
					
						
							|  |  |  |     noeval = (X)->noeval; \ | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |     curlval = (X)->lval; \ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   } while (0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Push and save away the contents of the globals describing the
 | 
					
						
							|  |  |  |    current expression context. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | pushexp () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   EXPR_CONTEXT *context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (expr_depth >= MAX_EXPR_RECURSION_LEVEL) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     evalerror (_("expression recursion level exceeded")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (expr_depth >= expr_stack_size) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       expr_stack_size += EXPR_STACK_GROW_SIZE; | 
					
						
							|  |  |  |       expr_stack = (EXPR_CONTEXT **)xrealloc (expr_stack, expr_stack_size * sizeof (EXPR_CONTEXT *)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   context = (EXPR_CONTEXT *)xmalloc (sizeof (EXPR_CONTEXT)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   context->expression = expression; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   SAVETOK(context); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   expr_stack[expr_depth++] = context; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Pop the the contents of the expression context stack into the
 | 
					
						
							|  |  |  |    globals describing the current expression context. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | popexp () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   EXPR_CONTEXT *context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (expr_depth == 0) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     evalerror (_("recursion stack underflow")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   context = expr_stack[--expr_depth]; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   expression = context->expression; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   RESTORETOK (context); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   free (context); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | expr_unwind () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   while (--expr_depth > 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (expr_stack[expr_depth]->tokstr) | 
					
						
							|  |  |  | 	free (expr_stack[expr_depth]->tokstr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (expr_stack[expr_depth]->expression) | 
					
						
							|  |  |  | 	free (expr_stack[expr_depth]->expression); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       free (expr_stack[expr_depth]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   free (expr_stack[expr_depth]);	/* free the allocated EXPR_CONTEXT */ | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   noeval = 0;	/* XXX */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | expr_bind_variable (lhs, rhs) | 
					
						
							|  |  |  |      char *lhs, *rhs; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   v = bind_int_variable (lhs, rhs); | 
					
						
							|  |  |  |   if (v && (readonly_p (v) || noassign_p (v))) | 
					
						
							|  |  |  |     longjmp (evalbuf, 1);	/* variable assignment error */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   stupidly_hack_special_variables (lhs); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | /* Rewrite tok, which is of the form vname[expression], to vname[ind], where
 | 
					
						
							|  |  |  |    IND is the already-calculated value of expression. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | expr_bind_array_element (tok, ind, rhs) | 
					
						
							|  |  |  |      char *tok; | 
					
						
							|  |  |  |      arrayind_t ind; | 
					
						
							|  |  |  |      char *rhs; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *lhs, *vname; | 
					
						
							|  |  |  |   size_t llen; | 
					
						
							|  |  |  |   char ibuf[INT_STRLEN_BOUND (arrayind_t) + 1], *istr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   istr = fmtumax (ind, 10, ibuf, sizeof (ibuf), 0); | 
					
						
							|  |  |  |   vname = array_variable_name (tok, (char **)NULL, (int *)NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   llen = strlen (vname) + sizeof (ibuf) + 3; | 
					
						
							|  |  |  |   lhs = xmalloc (llen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sprintf (lhs, "%s[%s]", vname, istr);		/* XXX */ | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  | /*itrace("expr_bind_array_element: %s=%s", lhs, rhs);*/ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   expr_bind_variable (lhs, rhs); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   free (vname); | 
					
						
							|  |  |  |   free (lhs); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif /* ARRAY_VARS */
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | /* Evaluate EXPR, and return the arithmetic result.  If VALIDP is
 | 
					
						
							|  |  |  |    non-null, a zero is stored into the location to which it points | 
					
						
							|  |  |  |    if the expression is invalid, non-zero otherwise.  If a non-zero | 
					
						
							|  |  |  |    value is returned in *VALIDP, the return value of evalexp() may | 
					
						
							|  |  |  |    be used. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    The `while' loop after the longjmp is caught relies on the above | 
					
						
							|  |  |  |    implementation of pushexp and popexp leaving in expr_stack[0] the | 
					
						
							|  |  |  |    values that the variables had when the program started.  That is, | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    the first things saved are the initial values of the variables that | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    were assigned at program startup or by the compiler.  Therefore, it is | 
					
						
							|  |  |  |    safe to let the loop terminate when expr_depth == 0, without freeing up | 
					
						
							|  |  |  |    any of the expr_depth[0] stuff. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | intmax_t | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | evalexp (expr, validp) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *expr; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int *validp; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t val; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   int c; | 
					
						
							|  |  |  |   procenv_t oevalbuf; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   val = 0; | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  |   noeval = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   FASTCOPY (evalbuf, oevalbuf, sizeof (evalbuf)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   c = setjmp_nosigs (evalbuf); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (c) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       FREE (tokstr); | 
					
						
							|  |  |  |       FREE (expression); | 
					
						
							|  |  |  |       tokstr = expression = (char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       expr_unwind (); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (validp) | 
					
						
							|  |  |  | 	*validp = 0; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       return (0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   val = subexpr (expr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (validp) | 
					
						
							|  |  |  |     *validp = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   FASTCOPY (oevalbuf, evalbuf, sizeof (evalbuf)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   return (val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | subexpr (expr) | 
					
						
							|  |  |  |      char *expr; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t val; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (p = expr; p && *p && cr_whitespace (*p); p++) | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (p == NULL || *p == '\0') | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |     return (0); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   pushexp (); | 
					
						
							|  |  |  |   expression = savestring (expr); | 
					
						
							|  |  |  |   tp = expression; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   curtok = lasttok = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   tokstr = (char *)NULL; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   tokval = 0; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   init_lvalue (&curlval); | 
					
						
							|  |  |  |   lastlval = curlval; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   readtok (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   val = EXP_HIGHEST (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (curtok != 0) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     evalerror (_("syntax error in expression")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   FREE (tokstr); | 
					
						
							|  |  |  |   FREE (expression); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   popexp (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   return val; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | expcomma () | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t value; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   value = expassign (); | 
					
						
							|  |  |  |   while (curtok == COMMA) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       readtok (); | 
					
						
							|  |  |  |       value = expassign (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   return value; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | expassign () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t value; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   char *lhs, *rhs; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   arrayind_t lind; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (HAVE_IMAXDIV)
 | 
					
						
							|  |  |  |   imaxdiv_t idiv; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   value = expcond (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   if (curtok == EQ || curtok == OP_ASSIGN) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       int special, op; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       intmax_t lvalue; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       special = curtok == OP_ASSIGN; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       if (lasttok != STR) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	evalerror (_("attempted assignment to non-variable")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (special) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  op = assigntok;		/* a OP= b */ | 
					
						
							|  |  |  | 	  lvalue = value; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* XXX - watch out for pointer aliasing issues here */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       lhs = savestring (tokstr); | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       /* save ind in case rhs is string var and evaluation overwrites it */ | 
					
						
							|  |  |  |       lind = curlval.ind; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       readtok (); | 
					
						
							|  |  |  |       value = expassign (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (special) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-11-22 20:02:56 -05:00
										 |  |  | 	  if ((op == DIV || op == MOD) && value == 0) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (noeval == 0) | 
					
						
							|  |  |  | 		evalerror (_("division by 0")); | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 	        value = 1; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  switch (op) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	    case MUL: | 
					
						
							|  |  |  | 	      lvalue *= value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    case DIV: | 
					
						
							|  |  |  | 	    case MOD: | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	      if (lvalue == INTMAX_MIN && value == -1) | 
					
						
							|  |  |  | 		lvalue = (op == DIV) ? INTMAX_MIN : 0; | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | #if HAVE_IMAXDIV
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  idiv = imaxdiv (lvalue, value); | 
					
						
							|  |  |  | 		  lvalue = (op == DIV) ? idiv.quot : idiv.rem; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	        lvalue = (op == DIV) ? lvalue / value : lvalue % value; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      break; | 
					
						
							|  |  |  | 	    case PLUS: | 
					
						
							|  |  |  | 	      lvalue += value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    case MINUS: | 
					
						
							|  |  |  | 	      lvalue -= value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    case LSH: | 
					
						
							|  |  |  | 	      lvalue <<= value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    case RSH: | 
					
						
							|  |  |  | 	      lvalue >>= value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    case BAND: | 
					
						
							|  |  |  | 	      lvalue &= value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    case BOR: | 
					
						
							|  |  |  | 	      lvalue |= value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	    case BXOR: | 
					
						
							|  |  |  | 	      lvalue ^= value; | 
					
						
							|  |  |  | 	      break; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    default: | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	      free (lhs); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      evalerror (_("bug: bad expassign token")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  value = lvalue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rhs = itos (value); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (noeval == 0) | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	  if (lind != -1) | 
					
						
							|  |  |  | 	    expr_bind_array_element (lhs, lind, rhs); | 
					
						
							|  |  |  | 	  else | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	    expr_bind_variable (lhs, rhs); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       if (curlval.tokstr && curlval.tokstr == tokstr) | 
					
						
							|  |  |  | 	init_lvalue (&curlval); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       free (rhs); | 
					
						
							|  |  |  |       free (lhs); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       FREE (tokstr); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       tokstr = (char *)NULL;		/* For freeing on errors. */ | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Conditional expression (expr?expr:expr) */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | expcond () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t cval, val1, val2, rval; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   int set_noeval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   set_noeval = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   rval = cval = explor (); | 
					
						
							|  |  |  |   if (curtok == QUES)		/* found conditional expr */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       if (curtok == 0 || curtok == COL) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	evalerror (_("expression expected")); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (cval == 0) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  set_noeval = 1; | 
					
						
							|  |  |  | 	  noeval++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       val1 = EXP_HIGHEST (); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (set_noeval) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	noeval--; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (curtok != COL) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	evalerror (_("`:' expected for conditional expression")); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       readtok (); | 
					
						
							|  |  |  |       if (curtok == 0) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	evalerror (_("expression expected")); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       set_noeval = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (cval) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  	{ | 
					
						
							|  |  |  |  	  set_noeval = 1; | 
					
						
							|  |  |  | 	  noeval++; | 
					
						
							|  |  |  |  	} | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       val2 = expcond (); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (set_noeval) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	noeval--; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       rval = cval ? val1 : val2; | 
					
						
							|  |  |  |       lasttok = COND; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return rval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Logical OR. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | explor () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   int set_noeval; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = expland (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (curtok == LOR) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       set_noeval = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (val1 != 0) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  noeval++; | 
					
						
							|  |  |  | 	  set_noeval = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       readtok (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       val2 = expland (); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (set_noeval) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	noeval--; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       val1 = val1 || val2; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       lasttok = LOR; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Logical AND. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | expland () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   int set_noeval; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = expbor (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (curtok == LAND) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       set_noeval = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (val1 == 0) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  set_noeval = 1; | 
					
						
							|  |  |  | 	  noeval++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       readtok (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       val2 = expbor (); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (set_noeval) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	noeval--; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       val1 = val1 && val2; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       lasttok = LAND; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Bitwise OR. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | expbor () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = expbxor (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (curtok == BOR) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val2 = expbxor (); | 
					
						
							|  |  |  |       val1 = val1 | val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Bitwise XOR. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | expbxor () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = expband (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (curtok == BXOR) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val2 = expband (); | 
					
						
							|  |  |  |       val1 = val1 ^ val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Bitwise AND. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | expband () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = exp5 (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (curtok == BAND) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val2 = exp5 (); | 
					
						
							|  |  |  |       val1 = val1 & val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | exp5 () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = exp4 (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while ((curtok == EQEQ) || (curtok == NEQ)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       int op = curtok; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val2 = exp4 (); | 
					
						
							|  |  |  |       if (op == EQEQ) | 
					
						
							|  |  |  | 	val1 = (val1 == val2); | 
					
						
							|  |  |  |       else if (op == NEQ) | 
					
						
							|  |  |  | 	val1 = (val1 != val2); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | exp4 () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = expshift (); | 
					
						
							|  |  |  |   while ((curtok == LEQ) || | 
					
						
							|  |  |  | 	 (curtok == GEQ) || | 
					
						
							|  |  |  | 	 (curtok == LT) || | 
					
						
							|  |  |  | 	 (curtok == GT)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       int op = curtok; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val2 = expshift (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (op == LEQ) | 
					
						
							|  |  |  | 	val1 = val1 <= val2; | 
					
						
							|  |  |  |       else if (op == GEQ) | 
					
						
							|  |  |  | 	val1 = val1 >= val2; | 
					
						
							|  |  |  |       else if (op == LT) | 
					
						
							|  |  |  | 	val1 = val1 < val2; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       else			/* (op == GT) */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	val1 = val1 > val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Left and right shifts. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | expshift () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = exp3 (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while ((curtok == LSH) || (curtok == RSH)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       int op = curtok; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val2 = exp3 (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (op == LSH) | 
					
						
							|  |  |  | 	val1 = val1 << val2; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	val1 = val1 >> val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | exp3 () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = exp2 (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while ((curtok == PLUS) || (curtok == MINUS)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       int op = curtok; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val2 = exp2 (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (op == PLUS) | 
					
						
							|  |  |  | 	val1 += val2; | 
					
						
							|  |  |  |       else if (op == MINUS) | 
					
						
							|  |  |  | 	val1 -= val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | exp2 () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (HAVE_IMAXDIV)
 | 
					
						
							|  |  |  |   imaxdiv_t idiv; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   val1 = exppower (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   while ((curtok == MUL) || | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	 (curtok == DIV) || | 
					
						
							|  |  |  | 	 (curtok == MOD)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       int op = curtok; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       char *stp, *sltp; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       stp = tp; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       readtok (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       val2 = exppower (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* Handle division by 0 and twos-complement arithmetic overflow */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       if (((op == DIV) || (op == MOD)) && (val2 == 0)) | 
					
						
							| 
									
										
										
										
											2011-11-22 20:02:56 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  if (noeval == 0) | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      sltp = lasttp; | 
					
						
							|  |  |  | 	      lasttp = stp; | 
					
						
							|  |  |  | 	      while (lasttp && *lasttp && whitespace (*lasttp)) | 
					
						
							|  |  |  | 		lasttp++; | 
					
						
							|  |  |  | 	      evalerror (_("division by 0")); | 
					
						
							|  |  |  | 	      lasttp = sltp; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2011-11-22 20:02:56 -05:00
										 |  |  | 	  else | 
					
						
							|  |  |  | 	    val2 = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       else if (op == MOD && val1 == INTMAX_MIN && val2 == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  val1 = 0; | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else if (op == DIV && val1 == INTMAX_MIN && val2 == -1) | 
					
						
							|  |  |  | 	val2 = 1; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (op == MUL) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	val1 *= val2; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       else if (op == DIV || op == MOD) | 
					
						
							|  |  |  | #if defined (HAVE_IMAXDIV)
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  idiv = imaxdiv (val1, val2); | 
					
						
							|  |  |  | 	  val1 = (op == DIV) ? idiv.quot : idiv.rem; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	val1 = (op == DIV) ? val1 / val2 : val1 % val2; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | static intmax_t | 
					
						
							|  |  |  | ipow (base, exp) | 
					
						
							|  |  |  |      intmax_t base, exp; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   intmax_t result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   result = 1; | 
					
						
							|  |  |  |   while (exp) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (exp & 1) | 
					
						
							|  |  |  | 	result *= base; | 
					
						
							|  |  |  |       exp >>= 1; | 
					
						
							|  |  |  |       base *= base; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | exppower () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val1, val2, c; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   val1 = exp1 (); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   while (curtok == POWER) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       val2 = exppower ();	/* exponentiation is right-associative */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       if (val2 == 0) | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	return (1); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       if (val2 < 0) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	evalerror (_("exponent less than 0")); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       val1 = ipow (val1, val2); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return (val1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | exp1 () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (curtok == NOT) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val = !exp1 (); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else if (curtok == BNOT) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val = ~exp1 (); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   else if (curtok == MINUS) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val = - exp1 (); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |     } | 
					
						
							|  |  |  |   else if (curtok == PLUS) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       val = exp1 (); | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       lasttok = NUM; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     val = exp0 (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | exp0 () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   register intmax_t val = 0, v2; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |   char *vincdec; | 
					
						
							|  |  |  |   int stok; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   EXPR_CONTEXT ec; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* XXX - might need additional logic here to decide whether or not
 | 
					
						
							|  |  |  | 	   pre-increment or pre-decrement is legal at this point. */ | 
					
						
							|  |  |  |   if (curtok == PREINC || curtok == PREDEC) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       stok = lasttok = curtok; | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |       if (curtok != STR) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	/* readtok() catches this */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	evalerror (_("identifier expected after pre-increment or pre-decrement")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       v2 = tokval + ((stok == PREINC) ? 1 : -1); | 
					
						
							|  |  |  |       vincdec = itos (v2); | 
					
						
							|  |  |  |       if (noeval == 0) | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	  if (curlval.ind != -1) | 
					
						
							|  |  |  | 	    expr_bind_array_element (curlval.tokstr, curlval.ind, vincdec); | 
					
						
							|  |  |  | 	  else | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 	    expr_bind_variable (tokstr, vincdec); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       free (vincdec); | 
					
						
							|  |  |  |       val = v2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       curtok = NUM;	/* make sure --x=7 is flagged as an error */ | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   else if (curtok == LPAR) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |       /* XXX - save curlval here?  Or entire expression context? */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       readtok (); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       val = EXP_HIGHEST (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (curtok != RPAR) /* ( */ | 
					
						
							|  |  |  | 	evalerror (_("missing `)'")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* Skip over closing paren. */ | 
					
						
							|  |  |  |       readtok (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if ((curtok == NUM) || (curtok == STR)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       val = tokval; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       if (curtok == STR) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  SAVETOK (&ec); | 
					
						
							|  |  |  | 	  tokstr = (char *)NULL;	/* keep it from being freed */ | 
					
						
							|  |  |  |           noeval = 1; | 
					
						
							|  |  |  |           readtok (); | 
					
						
							|  |  |  |           stok = curtok; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	  /* post-increment or post-decrement */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |  	  if (stok == POSTINC || stok == POSTDEC) | 
					
						
							|  |  |  |  	    { | 
					
						
							|  |  |  |  	      /* restore certain portions of EC */ | 
					
						
							|  |  |  |  	      tokstr = ec.tokstr; | 
					
						
							|  |  |  |  	      noeval = ec.noeval; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |  	      curlval = ec.lval; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |  	      lasttok = STR;	/* ec.curtok */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	      v2 = val + ((stok == POSTINC) ? 1 : -1); | 
					
						
							|  |  |  | 	      vincdec = itos (v2); | 
					
						
							|  |  |  | 	      if (noeval == 0) | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 		  if (curlval.ind != -1) | 
					
						
							|  |  |  | 		    expr_bind_array_element (curlval.tokstr, curlval.ind, vincdec); | 
					
						
							|  |  |  | 		  else | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | 		    expr_bind_variable (tokstr, vincdec); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      free (vincdec); | 
					
						
							|  |  |  | 	      curtok = NUM;	/* make sure x++=7 is flagged as an error */ | 
					
						
							|  |  |  |  	    } | 
					
						
							|  |  |  |  	  else | 
					
						
							|  |  |  |  	    { | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | 	      /* XXX - watch out for pointer aliasing issues here */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      if (stok == STR)	/* free new tokstr before old one is restored */ | 
					
						
							|  |  |  | 		FREE (tokstr); | 
					
						
							|  |  |  | 	      RESTORETOK (&ec); | 
					
						
							|  |  |  |  	    } | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	   | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       readtok (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     evalerror (_("syntax error: operand expected")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return (val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | static void | 
					
						
							|  |  |  | init_lvalue (lv) | 
					
						
							|  |  |  |      struct lvalue *lv; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   lv->tokstr = 0; | 
					
						
							|  |  |  |   lv->tokvar = 0; | 
					
						
							|  |  |  |   lv->tokval = lv->ind = -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct lvalue * | 
					
						
							|  |  |  | alloc_lvalue () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct lvalue *lv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   lv = xmalloc (sizeof (struct lvalue)); | 
					
						
							|  |  |  |   init_lvalue (lv); | 
					
						
							|  |  |  |   return (lv); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | free_lvalue (lv) | 
					
						
							|  |  |  |      struct lvalue *lv; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   free (lv);		/* should be inlined */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | expr_streval (tok, e, lvalue) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      char *tok; | 
					
						
							|  |  |  |      int e; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |      struct lvalue *lvalue; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   SHELL_VAR *v; | 
					
						
							|  |  |  |   char *value; | 
					
						
							|  |  |  |   intmax_t tval; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   arrayind_t ind; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-02 10:06:20 -04:00
										 |  |  | /*itrace("expr_streval: %s: noeval = %d", tok, noeval);*/ | 
					
						
							|  |  |  |   /* If we are suppressing evaluation, just short-circuit here instead of
 | 
					
						
							|  |  |  |      going through the rest of the evaluator. */ | 
					
						
							|  |  |  |   if (noeval) | 
					
						
							|  |  |  |     return (0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   /* [[[[[ */ | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |   v = (e == ']') ? array_variable_part (tok, (char **)0, (int *)0) : find_variable (tok); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   v = find_variable (tok); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((v == 0 || invisible_p (v)) && unbound_vars_is_error) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       value = (e == ']') ? array_variable_name (tok, (char **)0, (int *)0) : tok; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |       value = tok; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  |       last_command_exit_value = EXECUTION_FAILURE; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       err_unboundvar (value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       if (e == ']') | 
					
						
							|  |  |  | 	FREE (value);	/* array_variable_name returns new memory */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (interactive_shell) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  expr_unwind (); | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  | 	  top_level_cleanup (); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  jump_to_top_level (DISCARD); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	jump_to_top_level (FORCE_EOF); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  |   ind = -1; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   /* Second argument of 0 to get_array_value means that we don't allow
 | 
					
						
							|  |  |  |      references like array[@].  In this case, get_array_value is just | 
					
						
							|  |  |  |      like get_variable_value in that it does not return newly-allocated | 
					
						
							|  |  |  |      memory or quote the results. */ | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   value = (e == ']') ? get_array_value (tok, 0, (int *)NULL, &ind) : get_variable_value (v); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   value = get_variable_value (v); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tval = (value && *value) ? subexpr (value) : 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   if (lvalue) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       lvalue->tokstr = tok;	/* XXX */ | 
					
						
							|  |  |  |       lvalue->tokval = tval; | 
					
						
							|  |  |  |       lvalue->tokvar = v;	/* XXX */ | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       lvalue->ind = ind; | 
					
						
							| 
									
										
										
										
											2014-02-26 09:36:43 -05:00
										 |  |  | #else
 | 
					
						
							|  |  |  |       lvalue->ind = -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 	   | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   return (tval); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | _is_multiop (c) | 
					
						
							|  |  |  |      int c; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (c) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case EQEQ: | 
					
						
							|  |  |  |     case NEQ: | 
					
						
							|  |  |  |     case LEQ: | 
					
						
							|  |  |  |     case GEQ: | 
					
						
							|  |  |  |     case LAND: | 
					
						
							|  |  |  |     case LOR: | 
					
						
							|  |  |  |     case LSH: | 
					
						
							|  |  |  |     case RSH: | 
					
						
							|  |  |  |     case OP_ASSIGN: | 
					
						
							|  |  |  |     case COND: | 
					
						
							|  |  |  |     case POWER: | 
					
						
							|  |  |  |     case PREINC: | 
					
						
							|  |  |  |     case PREDEC: | 
					
						
							|  |  |  |     case POSTINC: | 
					
						
							|  |  |  |     case POSTDEC: | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | _is_arithop (c) | 
					
						
							|  |  |  |      int c; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (c) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case EQ: | 
					
						
							|  |  |  |     case GT: | 
					
						
							|  |  |  |     case LT: | 
					
						
							|  |  |  |     case PLUS: | 
					
						
							|  |  |  |     case MINUS: | 
					
						
							|  |  |  |     case MUL: | 
					
						
							|  |  |  |     case DIV: | 
					
						
							|  |  |  |     case MOD: | 
					
						
							|  |  |  |     case NOT: | 
					
						
							|  |  |  |     case LPAR: | 
					
						
							|  |  |  |     case RPAR: | 
					
						
							|  |  |  |     case BAND: | 
					
						
							|  |  |  |     case BOR: | 
					
						
							|  |  |  |     case BXOR: | 
					
						
							|  |  |  |     case BNOT: | 
					
						
							|  |  |  |       return 1;		/* operator tokens */ | 
					
						
							|  |  |  |     case QUES: | 
					
						
							|  |  |  |     case COL: | 
					
						
							|  |  |  |     case COMMA: | 
					
						
							|  |  |  |       return 1;		/* questionable */ | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return 0;		/* anything else is invalid */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Lexical analyzer/token reader for the expression evaluator.  Reads the
 | 
					
						
							|  |  |  |    next token and puts its value into curtok, while advancing past it. | 
					
						
							|  |  |  |    Updates value of tp.  May also set tokval (for number) or tokstr (for | 
					
						
							|  |  |  |    string). */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | readtok () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   register char *cp, *xp; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   register unsigned char c, c1; | 
					
						
							|  |  |  |   register int e; | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |   struct lvalue lval; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Skip leading whitespace. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   cp = tp; | 
					
						
							|  |  |  |   c = e = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   while (cp && (c = *cp) && (cr_whitespace (c))) | 
					
						
							|  |  |  |     cp++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (c) | 
					
						
							|  |  |  |     cp++; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   if (c == '\0') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       lasttok = curtok; | 
					
						
							|  |  |  |       curtok = 0; | 
					
						
							|  |  |  |       tp = cp; | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   lasttp = tp = cp - 1; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (legal_variable_starter (c)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       /* variable names not preceded with a dollar sign are shell variables. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       char *savecp; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       EXPR_CONTEXT ec; | 
					
						
							|  |  |  |       int peektok; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       while (legal_variable_char (c)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	c = *cp++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       c = *--cp; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (ARRAY_VARS)
 | 
					
						
							|  |  |  |       if (c == '[') | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-11-21 20:51:19 -05:00
										 |  |  | 	  e = skipsubscript (cp, 0, 0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (cp[e] == ']') | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      cp += e + 1; | 
					
						
							|  |  |  | 	      c = *cp; | 
					
						
							|  |  |  | 	      e = ']'; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	    evalerror (bash_badsub_errmsg); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | #endif /* ARRAY_VARS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       *cp = '\0'; | 
					
						
							| 
									
										
										
										
											2012-11-02 10:06:20 -04:00
										 |  |  |       /* XXX - watch out for pointer aliasing issues here */ | 
					
						
							|  |  |  |       if (curlval.tokstr && curlval.tokstr == tokstr) | 
					
						
							|  |  |  | 	init_lvalue (&curlval); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       FREE (tokstr); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       tokstr = savestring (tp); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       *cp = c; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |       /* XXX - make peektok part of saved token state? */ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       SAVETOK (&ec); | 
					
						
							|  |  |  |       tokstr = (char *)NULL;	/* keep it from being freed */ | 
					
						
							|  |  |  |       tp = savecp = cp; | 
					
						
							|  |  |  |       noeval = 1; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       curtok = STR; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       readtok (); | 
					
						
							|  |  |  |       peektok = curtok; | 
					
						
							|  |  |  |       if (peektok == STR)	/* free new tokstr before old one is restored */ | 
					
						
							|  |  |  | 	FREE (tokstr); | 
					
						
							|  |  |  |       RESTORETOK (&ec); | 
					
						
							|  |  |  |       cp = savecp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* The tests for PREINC and PREDEC aren't strictly correct, but they
 | 
					
						
							|  |  |  | 	 preserve old behavior if a construct like --x=9 is given. */ | 
					
						
							|  |  |  |       if (lasttok == PREINC || lasttok == PREDEC || peektok != EQ) | 
					
						
							| 
									
										
										
										
											2011-11-22 19:11:26 -05:00
										 |  |  |         { | 
					
						
							|  |  |  |           lastlval = curlval; | 
					
						
							|  |  |  | 	  tokval = expr_streval (tokstr, e, &curlval); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	tokval = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       lasttok = curtok; | 
					
						
							|  |  |  |       curtok = STR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   else if (DIGIT(c)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       while (ISALNUM (c) || c == '#' || c == '@' || c == '_') | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	c = *cp++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       c = *--cp; | 
					
						
							|  |  |  |       *cp = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       tokval = strlong (tp); | 
					
						
							|  |  |  |       *cp = c; | 
					
						
							|  |  |  |       lasttok = curtok; | 
					
						
							|  |  |  |       curtok = NUM; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       c1 = *cp++; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if ((c == EQ) && (c1 == EQ)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	c = EQEQ; | 
					
						
							|  |  |  |       else if ((c == NOT) && (c1 == EQ)) | 
					
						
							|  |  |  | 	c = NEQ; | 
					
						
							|  |  |  |       else if ((c == GT) && (c1 == EQ)) | 
					
						
							|  |  |  | 	c = GEQ; | 
					
						
							|  |  |  |       else if ((c == LT) && (c1 == EQ)) | 
					
						
							|  |  |  | 	c = LEQ; | 
					
						
							|  |  |  |       else if ((c == LT) && (c1 == LT)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (*cp == '=')	/* a <<= b */ | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      assigntok = LSH; | 
					
						
							|  |  |  | 	      c = OP_ASSIGN; | 
					
						
							|  |  |  | 	      cp++; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    c = LSH; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else if ((c == GT) && (c1 == GT)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (*cp == '=') | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      assigntok = RSH;	/* a >>= b */ | 
					
						
							|  |  |  | 	      c = OP_ASSIGN; | 
					
						
							|  |  |  | 	      cp++; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    c = RSH; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else if ((c == BAND) && (c1 == BAND)) | 
					
						
							|  |  |  | 	c = LAND; | 
					
						
							|  |  |  |       else if ((c == BOR) && (c1 == BOR)) | 
					
						
							|  |  |  | 	c = LOR; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       else if ((c == '*') && (c1 == '*')) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	c = POWER; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       else if ((c == '-' || c == '+') && c1 == c && curtok == STR) | 
					
						
							|  |  |  | 	c = (c == '-') ? POSTDEC : POSTINC; | 
					
						
							|  |  |  |       else if ((c == '-' || c == '+') && c1 == c) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* Quickly scan forward to see if this is followed by optional
 | 
					
						
							|  |  |  | 	     whitespace and an identifier. */ | 
					
						
							|  |  |  | 	  xp = cp; | 
					
						
							|  |  |  | 	  while (xp && *xp && cr_whitespace (*xp)) | 
					
						
							|  |  |  | 	    xp++; | 
					
						
							|  |  |  | 	  if (legal_variable_starter ((unsigned char)*xp)) | 
					
						
							|  |  |  | 	    c = (c == '-') ? PREDEC : PREINC; | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    cp--;	/* not preinc or predec, so unget the character */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       else if (c1 == EQ && member (c, "*/%+-&^|")) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  assigntok = c;	/* a OP= b */ | 
					
						
							|  |  |  | 	  c = OP_ASSIGN; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |       else if (_is_arithop (c) == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  cp--; | 
					
						
							|  |  |  | 	  /* use curtok, since it hasn't been copied to lasttok yet */ | 
					
						
							|  |  |  | 	  if (curtok == 0 || _is_arithop (curtok) || _is_multiop (curtok)) | 
					
						
							|  |  |  | 	    evalerror (_("syntax error: operand expected")); | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    evalerror (_("syntax error: invalid arithmetic operator")); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	cp--;			/* `unget' the character */ | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* Should check here to make sure that the current character is one
 | 
					
						
							|  |  |  | 	 of the recognized operators and flag an error if not.  Could create | 
					
						
							|  |  |  | 	 a character map the first time through and check it on subsequent | 
					
						
							|  |  |  | 	 calls. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       lasttok = curtok; | 
					
						
							|  |  |  |       curtok = c; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   tp = cp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | evalerror (msg) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      const char *msg; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   char *name, *t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   name = this_command_name; | 
					
						
							|  |  |  |   for (t = expression; whitespace (*t); t++) | 
					
						
							|  |  |  |     ; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   internal_error (_("%s%s%s: %s (error token is \"%s\")"), | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 		   name ? name : "", name ? ": " : "", t, | 
					
						
							|  |  |  | 		   msg, (lasttp && *lasttp) ? lasttp : ""); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   longjmp (evalbuf, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Convert a string to an intmax_t integer, with an arbitrary base.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    0nnn -> base 8 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |    0[Xx]nn -> base 16 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    Anything else: [base#]number (this is implemented to match ksh93) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Base may be >=2 and <=64.  If base is <= 36, the numbers are drawn | 
					
						
							|  |  |  |    from [0-9][a-zA-Z], and lowercase and uppercase letters may be used | 
					
						
							|  |  |  |    interchangably.  If base is > 36 and <= 64, the numbers are drawn | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |    from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 -- | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    you get the picture). */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static intmax_t | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | strlong (num) | 
					
						
							|  |  |  |      char *num; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   register char *s; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   register unsigned char c; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   int base, foundbase; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t val; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   s = num; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   base = 10; | 
					
						
							|  |  |  |   foundbase = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   if (*s == '0') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       s++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       if (*s == '\0') | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |        /* Base 16? */ | 
					
						
							|  |  |  |       if (*s == 'x' || *s == 'X') | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  base = 16; | 
					
						
							|  |  |  | 	  s++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	base = 8; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       foundbase++; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   val = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   for (c = *s++; c; c = *s++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (c == '#') | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (foundbase) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	    evalerror (_("invalid number")); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  /* Illegal base specifications raise an evaluation error. */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  if (val < 2 || val > 64) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	    evalerror (_("invalid arithmetic base")); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  base = val; | 
					
						
							|  |  |  | 	  val = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  foundbase++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       else if (ISALNUM(c) || (c == '_') || (c == '@')) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  if (DIGIT(c)) | 
					
						
							|  |  |  | 	    c = TODIGIT(c); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  else if (c >= 'a' && c <= 'z') | 
					
						
							|  |  |  | 	    c -= 'a' - 10; | 
					
						
							|  |  |  | 	  else if (c >= 'A' && c <= 'Z') | 
					
						
							|  |  |  | 	    c -= 'A' - ((base <= 36) ? 10 : 36); | 
					
						
							|  |  |  | 	  else if (c == '@') | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	    c = 62; | 
					
						
							|  |  |  | 	  else if (c == '_') | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    c = 63; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  if (c >= base) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	    evalerror (_("value too great for base")); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  val = (val * base) + c; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	break; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (EXPR_TEST)
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | void * | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | xmalloc (n) | 
					
						
							|  |  |  |      int n; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (malloc (n)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | void * | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | xrealloc (s, n) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  |      int n; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return (realloc (s, n)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SHELL_VAR *find_variable () { return 0;} | 
					
						
							|  |  |  | SHELL_VAR *bind_variable () { return 0; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *get_string_value () { return 0; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | procenv_t top_level; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | main (argc, argv) | 
					
						
							|  |  |  |      int argc; | 
					
						
							|  |  |  |      char **argv; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   intmax_t v; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   int expok; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (setjmp (top_level)) | 
					
						
							|  |  |  |     exit (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 1; i < argc; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       v = evalexp (argv[i], &expok); | 
					
						
							|  |  |  |       if (expok == 0) | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	fprintf (stderr, _("%s: expression error\n"), argv[i]); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	printf ("'%s' -> %ld\n", argv[i], v); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   exit (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | builtin_error (format, arg1, arg2, arg3, arg4, arg5) | 
					
						
							|  |  |  |      char *format; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   fprintf (stderr, "expr: "); | 
					
						
							|  |  |  |   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | 
					
						
							|  |  |  |   fprintf (stderr, "\n"); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char * | 
					
						
							|  |  |  | itos (n) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |      intmax_t n; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   return ("42"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* EXPR_TEST */
 |