]>
git.ipfire.org Git - thirdparty/bash.git/blob - expr.c
1 /* expr.c -- arithmetic expression evaluation. */
3 /* Copyright (C) 1990-2012 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
22 All arithmetic is done as intmax_t integers with no checking for overflow
23 (though division by 0 is caught and flagged as an error).
25 The following operators are handled, grouped into a set of levels in
26 order of decreasing precedence.
28 "id++", "id--" [post-increment and post-decrement]
29 "++id", "--id" [pre-increment and pre-decrement]
30 "-", "+" [(unary operators)]
32 "**" [(exponentiation)]
44 "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
47 (Note that most of these operators have special meaning to bash, and an
48 entire expression should be quoted, e.g. "a=$a+1" or "a=a+1" to ensure
49 that it is passed intact to the evaluator when using `let'. When using
50 the $[] or $(( )) forms, the text between the `[' and `]' or `((' and `))'
51 is treated as if in double quotes.)
53 Sub-expressions within parentheses have a precedence level greater than
54 all of the above levels and are evaluated first. Within a single prece-
55 dence group, evaluation is left-to-right, except for the arithmetic
56 assignment operator (`='), which is evaluated right-to-left (as in C).
58 The expression evaluator returns the value of the expression (assignment
59 statements have as a value what is returned by the RHS). The `let'
60 builtin, on the other hand, returns 0 if the last expression evaluates to
61 a non-zero, and 1 otherwise.
63 Implementation is a recursive-descent parser.
74 #if defined (HAVE_UNISTD_H)
76 # include <sys/types.h>
81 #include "chartypes.h"
86 /* Because of the $((...)) construct, expressions may include newlines.
87 Here is a macro which accepts newlines, tabs and spaces as whitespace. */
88 #define cr_whitespace(c) (whitespace(c) || ((c) == '\n'))
90 /* Size be which the expression stack grows when neccessary. */
91 #define EXPR_STACK_GROW_SIZE 10
93 /* Maximum amount of recursion allowed. This prevents a non-integer
94 variable such as "num=num+2" from infinitely adding to itself when
95 "let num=num+2" is given. */
97 #define MAX_EXPR_RECURSION_LEVEL 1024
99 #define MAX_EXPR_RECURSION_LEVEL 16
102 /* The Tokens. Singing "The Lion Sleeps Tonight". */
104 #define EQEQ 1 /* "==" */
105 #define NEQ 2 /* "!=" */
106 #define LEQ 3 /* "<=" */
107 #define GEQ 4 /* ">=" */
108 #define STR 5 /* string */
109 #define NUM 6 /* number */
110 #define LAND 7 /* "&&" Logical AND */
111 #define LOR 8 /* "||" Logical OR */
112 #define LSH 9 /* "<<" Left SHift */
113 #define RSH 10 /* ">>" Right SHift */
114 #define OP_ASSIGN 11 /* op= expassign as in Posix.2 */
115 #define COND 12 /* exp1 ? exp2 : exp3 */
116 #define POWER 13 /* exp1**exp2 */
117 #define PREINC 14 /* ++var */
118 #define PREDEC 15 /* --var */
119 #define POSTINC 16 /* var++ */
120 #define POSTDEC 17 /* var-- */
132 #define BAND '&' /* Bitwise AND */
133 #define BOR '|' /* Bitwise OR. */
134 #define BXOR '^' /* Bitwise eXclusive OR. */
135 #define BNOT '~' /* Bitwise NOT; Two's complement. */
140 /* This should be the function corresponding to the operator with the
141 highest precedence. */
142 #define EXP_HIGHEST expcomma
145 # define MAX_INT_LEN 32
150 char *tokstr
; /* possibly-rewritten lvalue if not NULL */
151 intmax_t tokval
; /* expression evaluated value */
152 SHELL_VAR
*tokvar
; /* variable described by array or var reference */
153 intmax_t ind
; /* array index if not -1 */
156 /* A structure defining a single expression context. */
159 char *expression
, *tp
, *lasttp
;
166 static char *expression
; /* The current expression */
167 static char *tp
; /* token lexical position */
168 static char *lasttp
; /* pointer to last token position */
169 static int curtok
; /* the current token */
170 static int lasttok
; /* the previous token */
171 static int assigntok
; /* the OP in OP= */
172 static char *tokstr
; /* current token string */
173 static intmax_t tokval
; /* current token value */
174 static int noeval
; /* set to 1 if no assignment to be done */
175 static procenv_t evalbuf
;
177 static struct lvalue curlval
= {0, 0, 0, -1};
178 static struct lvalue lastlval
= {0, 0, 0, -1};
180 static int _is_arithop
__P((int));
181 static void readtok
__P((void)); /* lexical analyzer */
183 static void init_lvalue
__P((struct lvalue
*));
184 static struct lvalue
*alloc_lvalue
__P((void));
185 static void free_lvalue
__P((struct lvalue
*));
187 static intmax_t expr_streval
__P((char *, int, struct lvalue
*));
188 static intmax_t strlong
__P((char *));
189 static void evalerror
__P((const char *));
191 static void pushexp
__P((void));
192 static void popexp
__P((void));
193 static void expr_unwind
__P((void));
194 static void expr_bind_variable
__P((char *, char *));
195 #if defined (ARRAY_VARS)
196 static void expr_bind_array_element
__P((char *, arrayind_t
, char *));
199 static intmax_t subexpr
__P((char *));
201 static intmax_t expcomma
__P((void));
202 static intmax_t expassign
__P((void));
203 static intmax_t expcond
__P((void));
204 static intmax_t explor
__P((void));
205 static intmax_t expland
__P((void));
206 static intmax_t expbor
__P((void));
207 static intmax_t expbxor
__P((void));
208 static intmax_t expband
__P((void));
209 static intmax_t exp5
__P((void));
210 static intmax_t exp4
__P((void));
211 static intmax_t expshift
__P((void));
212 static intmax_t exp3
__P((void));
213 static intmax_t exp2
__P((void));
214 static intmax_t exppower
__P((void));
215 static intmax_t exp1
__P((void));
216 static intmax_t exp0
__P((void));
218 /* Global var which contains the stack of expression contexts. */
219 static EXPR_CONTEXT
**expr_stack
;
220 static int expr_depth
; /* Location in the stack. */
221 static int expr_stack_size
; /* Number of slots already allocated. */
223 extern char *this_command_name
;
224 extern int unbound_vars_is_error
, last_command_exit_value
;
226 #if defined (ARRAY_VARS)
227 extern const char * const bash_badsub_errmsg
;
232 (X)->curtok = curtok; \
233 (X)->lasttok = lasttok; \
235 (X)->lasttp = lasttp; \
236 (X)->tokval = tokval; \
237 (X)->tokstr = tokstr; \
238 (X)->noeval = noeval; \
239 (X)->lval = curlval; \
242 #define RESTORETOK(X) \
244 curtok = (X)->curtok; \
245 lasttok = (X)->lasttok; \
247 lasttp = (X)->lasttp; \
248 tokval = (X)->tokval; \
249 tokstr = (X)->tokstr; \
250 noeval = (X)->noeval; \
251 curlval = (X)->lval; \
254 /* Push and save away the contents of the globals describing the
255 current expression context. */
259 EXPR_CONTEXT
*context
;
261 if (expr_depth
>= MAX_EXPR_RECURSION_LEVEL
)
262 evalerror (_("expression recursion level exceeded"));
264 if (expr_depth
>= expr_stack_size
)
266 expr_stack_size
+= EXPR_STACK_GROW_SIZE
;
267 expr_stack
= (EXPR_CONTEXT
**)xrealloc (expr_stack
, expr_stack_size
* sizeof (EXPR_CONTEXT
*));
270 context
= (EXPR_CONTEXT
*)xmalloc (sizeof (EXPR_CONTEXT
));
272 context
->expression
= expression
;
275 expr_stack
[expr_depth
++] = context
;
278 /* Pop the the contents of the expression context stack into the
279 globals describing the current expression context. */
283 EXPR_CONTEXT
*context
;
286 evalerror (_("recursion stack underflow"));
288 context
= expr_stack
[--expr_depth
];
290 expression
= context
->expression
;
291 RESTORETOK (context
);
299 while (--expr_depth
> 0)
301 if (expr_stack
[expr_depth
]->tokstr
)
302 free (expr_stack
[expr_depth
]->tokstr
);
304 if (expr_stack
[expr_depth
]->expression
)
305 free (expr_stack
[expr_depth
]->expression
);
307 free (expr_stack
[expr_depth
]);
309 free (expr_stack
[expr_depth
]); /* free the allocated EXPR_CONTEXT */
311 noeval
= 0; /* XXX */
315 expr_bind_variable (lhs
, rhs
)
320 v
= bind_int_variable (lhs
, rhs
);
321 if (v
&& (readonly_p (v
) || noassign_p (v
)))
322 longjmp (evalbuf
, 1); /* variable assignment error */
323 stupidly_hack_special_variables (lhs
);
326 #if defined (ARRAY_VARS)
327 /* Rewrite tok, which is of the form vname[expression], to vname[ind], where
328 IND is the already-calculated value of expression. */
330 expr_bind_array_element (tok
, ind
, rhs
)
337 char ibuf
[INT_STRLEN_BOUND (arrayind_t
) + 1], *istr
;
339 istr
= fmtumax (ind
, 10, ibuf
, sizeof (ibuf
), 0);
340 vname
= array_variable_name (tok
, (char **)NULL
, (int *)NULL
);
342 llen
= strlen (vname
) + sizeof (ibuf
) + 3;
343 lhs
= xmalloc (llen
);
345 sprintf (lhs
, "%s[%s]", vname
, istr
); /* XXX */
347 /*itrace("expr_bind_array_element: %s=%s", lhs, rhs);*/
348 expr_bind_variable (lhs
, rhs
);
352 #endif /* ARRAY_VARS */
354 /* Evaluate EXPR, and return the arithmetic result. If VALIDP is
355 non-null, a zero is stored into the location to which it points
356 if the expression is invalid, non-zero otherwise. If a non-zero
357 value is returned in *VALIDP, the return value of evalexp() may
360 The `while' loop after the longjmp is caught relies on the above
361 implementation of pushexp and popexp leaving in expr_stack[0] the
362 values that the variables had when the program started. That is,
363 the first things saved are the initial values of the variables that
364 were assigned at program startup or by the compiler. Therefore, it is
365 safe to let the loop terminate when expr_depth == 0, without freeing up
366 any of the expr_depth[0] stuff. */
368 evalexp (expr
, validp
)
379 FASTCOPY (evalbuf
, oevalbuf
, sizeof (evalbuf
));
381 c
= setjmp_nosigs (evalbuf
);
387 tokstr
= expression
= (char *)NULL
;
396 val
= subexpr (expr
);
401 FASTCOPY (oevalbuf
, evalbuf
, sizeof (evalbuf
));
413 for (p
= expr
; p
&& *p
&& cr_whitespace (*p
); p
++)
416 if (p
== NULL
|| *p
== '\0')
420 expression
= savestring (expr
);
423 curtok
= lasttok
= 0;
424 tokstr
= (char *)NULL
;
426 init_lvalue (&curlval
);
431 val
= EXP_HIGHEST ();
434 evalerror (_("syntax error in expression"));
447 register intmax_t value
;
449 value
= expassign ();
450 while (curtok
== COMMA
)
453 value
= expassign ();
462 register intmax_t value
;
465 #if defined (HAVE_IMAXDIV)
470 if (curtok
== EQ
|| curtok
== OP_ASSIGN
)
475 special
= curtok
== OP_ASSIGN
;
478 evalerror (_("attempted assignment to non-variable"));
482 op
= assigntok
; /* a OP= b */
486 /* XXX - watch out for pointer aliasing issues here */
487 lhs
= savestring (tokstr
);
488 /* save ind in case rhs is string var and evaluation overwrites it */
491 value
= expassign ();
495 if ((op
== DIV
|| op
== MOD
) && value
== 0)
498 evalerror (_("division by 0"));
510 if (lvalue
== INTMAX_MIN
&& value
== -1)
511 lvalue
= (op
== DIV
) ? INTMAX_MIN
: 0;
515 idiv
= imaxdiv (lvalue
, value
);
516 lvalue
= (op
== DIV
) ? idiv
.quot
: idiv
.rem
;
519 lvalue
= (op
== DIV
) ? lvalue
/ value
: lvalue
% value
;
545 evalerror (_("bug: bad expassign token"));
554 #if defined (ARRAY_VARS)
556 expr_bind_array_element (lhs
, lind
, rhs
);
559 expr_bind_variable (lhs
, rhs
);
564 tokstr
= (char *)NULL
; /* For freeing on errors. */
570 /* Conditional expression (expr?expr:expr) */
574 intmax_t cval
, val1
, val2
, rval
;
578 rval
= cval
= explor ();
579 if (curtok
== QUES
) /* found conditional expr */
582 if (curtok
== 0 || curtok
== COL
)
583 evalerror (_("expression expected"));
590 val1
= EXP_HIGHEST ();
595 evalerror (_("`:' expected for conditional expression"));
598 evalerror (_("expression expected"));
609 rval
= cval
? val1
: val2
;
619 register intmax_t val1
, val2
;
624 while (curtok
== LOR
)
647 register intmax_t val1
, val2
;
652 while (curtok
== LAND
)
675 register intmax_t val1
, val2
;
679 while (curtok
== BOR
)
693 register intmax_t val1
, val2
;
697 while (curtok
== BXOR
)
711 register intmax_t val1
, val2
;
715 while (curtok
== BAND
)
728 register intmax_t val1
, val2
;
732 while ((curtok
== EQEQ
) || (curtok
== NEQ
))
739 val1
= (val1
== val2
);
741 val1
= (val1
!= val2
);
749 register intmax_t val1
, val2
;
752 while ((curtok
== LEQ
) ||
768 else /* (op == GT) */
774 /* Left and right shifts. */
778 register intmax_t val1
, val2
;
782 while ((curtok
== LSH
) || (curtok
== RSH
))
801 register intmax_t val1
, val2
;
805 while ((curtok
== PLUS
) || (curtok
== MINUS
))
814 else if (op
== MINUS
)
823 register intmax_t val1
, val2
;
824 #if defined (HAVE_IMAXDIV)
830 while ((curtok
== MUL
) ||
840 /* Handle division by 0 and twos-complement arithmetic overflow */
841 if (((op
== DIV
) || (op
== MOD
)) && (val2
== 0))
844 evalerror (_("division by 0"));
848 else if (op
== MOD
&& val1
== INTMAX_MIN
&& val2
== -1)
853 else if (op
== DIV
&& val1
== INTMAX_MIN
&& val2
== -1)
858 else if (op
== DIV
|| op
== MOD
)
859 #if defined (HAVE_IMAXDIV)
861 idiv
= imaxdiv (val1
, val2
);
862 val1
= (op
== DIV
) ? idiv
.quot
: idiv
.rem
;
865 val1
= (op
== DIV
) ? val1
/ val2
: val1
% val2
;
891 register intmax_t val1
, val2
, c
;
894 while (curtok
== POWER
)
897 val2
= exppower (); /* exponentiation is right-associative */
901 evalerror (_("exponent less than 0"));
902 val1
= ipow (val1
, val2
);
910 register intmax_t val
;
917 else if (curtok
== BNOT
)
922 else if (curtok
== MINUS
)
927 else if (curtok
== PLUS
)
941 register intmax_t val
= 0, v2
;
946 /* XXX - might need additional logic here to decide whether or not
947 pre-increment or pre-decrement is legal at this point. */
948 if (curtok
== PREINC
|| curtok
== PREDEC
)
950 stok
= lasttok
= curtok
;
953 /* readtok() catches this */
954 evalerror (_("identifier expected after pre-increment or pre-decrement"));
956 v2
= tokval
+ ((stok
== PREINC
) ? 1 : -1);
960 #if defined (ARRAY_VARS)
961 if (curlval
.ind
!= -1)
962 expr_bind_array_element (curlval
.tokstr
, curlval
.ind
, vincdec
);
965 expr_bind_variable (tokstr
, vincdec
);
970 curtok
= NUM
; /* make sure --x=7 is flagged as an error */
973 else if (curtok
== LPAR
)
975 /* XXX - save curlval here? Or entire expression context? */
977 val
= EXP_HIGHEST ();
979 if (curtok
!= RPAR
) /* ( */
980 evalerror (_("missing `)'"));
982 /* Skip over closing paren. */
985 else if ((curtok
== NUM
) || (curtok
== STR
))
991 tokstr
= (char *)NULL
; /* keep it from being freed */
996 /* post-increment or post-decrement */
997 if (stok
== POSTINC
|| stok
== POSTDEC
)
999 /* restore certain portions of EC */
1003 lasttok
= STR
; /* ec.curtok */
1005 v2
= val
+ ((stok
== POSTINC
) ? 1 : -1);
1006 vincdec
= itos (v2
);
1009 #if defined (ARRAY_VARS)
1010 if (curlval
.ind
!= -1)
1011 expr_bind_array_element (curlval
.tokstr
, curlval
.ind
, vincdec
);
1014 expr_bind_variable (tokstr
, vincdec
);
1017 curtok
= NUM
; /* make sure x++=7 is flagged as an error */
1021 /* XXX - watch out for pointer aliasing issues here */
1022 if (stok
== STR
) /* free new tokstr before old one is restored */
1031 evalerror (_("syntax error: operand expected"));
1042 lv
->tokval
= lv
->ind
= -1;
1045 static struct lvalue
*
1050 lv
= xmalloc (sizeof (struct lvalue
));
1059 free (lv
); /* should be inlined */
1063 expr_streval (tok
, e
, lvalue
)
1066 struct lvalue
*lvalue
;
1071 #if defined (ARRAY_VARS)
1075 /*itrace("expr_streval: %s: noeval = %d", tok, noeval);*/
1076 /* If we are suppressing evaluation, just short-circuit here instead of
1077 going through the rest of the evaluator. */
1082 #if defined (ARRAY_VARS)
1083 v
= (e
== ']') ? array_variable_part (tok
, (char **)0, (int *)0) : find_variable (tok
);
1085 v
= find_variable (tok
);
1088 if ((v
== 0 || invisible_p (v
)) && unbound_vars_is_error
)
1090 #if defined (ARRAY_VARS)
1091 value
= (e
== ']') ? array_variable_name (tok
, (char **)0, (int *)0) : tok
;
1096 last_command_exit_value
= EXECUTION_FAILURE
;
1097 err_unboundvar (value
);
1099 #if defined (ARRAY_VARS)
1101 FREE (value
); /* array_variable_name returns new memory */
1104 if (interactive_shell
)
1107 top_level_cleanup ();
1108 jump_to_top_level (DISCARD
);
1111 jump_to_top_level (FORCE_EOF
);
1114 #if defined (ARRAY_VARS)
1116 /* Second argument of 0 to get_array_value means that we don't allow
1117 references like array[@]. In this case, get_array_value is just
1118 like get_variable_value in that it does not return newly-allocated
1119 memory or quote the results. */
1120 value
= (e
== ']') ? get_array_value (tok
, 0, (int *)NULL
, &ind
) : get_variable_value (v
);
1122 value
= get_variable_value (v
);
1125 tval
= (value
&& *value
) ? subexpr (value
) : 0;
1129 lvalue
->tokstr
= tok
; /* XXX */
1130 lvalue
->tokval
= tval
;
1131 lvalue
->tokvar
= v
; /* XXX */
1132 #if defined (ARRAY_VARS)
1190 return 1; /* operator tokens */
1194 return 1; /* questionable */
1196 return 0; /* anything else is invalid */
1200 /* Lexical analyzer/token reader for the expression evaluator. Reads the
1201 next token and puts its value into curtok, while advancing past it.
1202 Updates value of tp. May also set tokval (for number) or tokstr (for
1207 register char *cp
, *xp
;
1208 register unsigned char c
, c1
;
1212 /* Skip leading whitespace. */
1215 while (cp
&& (c
= *cp
) && (cr_whitespace (c
)))
1228 lasttp
= tp
= cp
- 1;
1230 if (legal_variable_starter (c
))
1232 /* variable names not preceded with a dollar sign are shell variables. */
1237 while (legal_variable_char (c
))
1242 #if defined (ARRAY_VARS)
1245 e
= skipsubscript (cp
, 0, 0);
1253 evalerror (bash_badsub_errmsg
);
1255 #endif /* ARRAY_VARS */
1258 /* XXX - watch out for pointer aliasing issues here */
1259 if (curlval
.tokstr
&& curlval
.tokstr
== tokstr
)
1260 init_lvalue (&curlval
);
1263 tokstr
= savestring (tp
);
1266 /* XXX - make peektok part of saved token state? */
1268 tokstr
= (char *)NULL
; /* keep it from being freed */
1274 if (peektok
== STR
) /* free new tokstr before old one is restored */
1279 /* The tests for PREINC and PREDEC aren't strictly correct, but they
1280 preserve old behavior if a construct like --x=9 is given. */
1281 if (lasttok
== PREINC
|| lasttok
== PREDEC
|| peektok
!= EQ
)
1284 tokval
= expr_streval (tokstr
, e
, &curlval
);
1294 while (ISALNUM (c
) || c
== '#' || c
== '@' || c
== '_')
1300 tokval
= strlong (tp
);
1308 if ((c
== EQ
) && (c1
== EQ
))
1310 else if ((c
== NOT
) && (c1
== EQ
))
1312 else if ((c
== GT
) && (c1
== EQ
))
1314 else if ((c
== LT
) && (c1
== EQ
))
1316 else if ((c
== LT
) && (c1
== LT
))
1318 if (*cp
== '=') /* a <<= b */
1327 else if ((c
== GT
) && (c1
== GT
))
1331 assigntok
= RSH
; /* a >>= b */
1338 else if ((c
== BAND
) && (c1
== BAND
))
1340 else if ((c
== BOR
) && (c1
== BOR
))
1342 else if ((c
== '*') && (c1
== '*'))
1344 else if ((c
== '-' || c
== '+') && c1
== c
&& curtok
== STR
)
1345 c
= (c
== '-') ? POSTDEC
: POSTINC
;
1346 else if ((c
== '-' || c
== '+') && c1
== c
)
1348 /* Quickly scan forward to see if this is followed by optional
1349 whitespace and an identifier. */
1351 while (xp
&& *xp
&& cr_whitespace (*xp
))
1353 if (legal_variable_starter ((unsigned char)*xp
))
1354 c
= (c
== '-') ? PREDEC
: PREINC
;
1356 cp
--; /* not preinc or predec, so unget the character */
1358 else if (c1
== EQ
&& member (c
, "*/%+-&^|"))
1360 assigntok
= c
; /* a OP= b */
1363 else if (_is_arithop (c
) == 0)
1366 /* use curtok, since it hasn't been copied to lasttok yet */
1367 if (curtok
== 0 || _is_arithop (curtok
) || _is_multiop (curtok
))
1368 evalerror (_("syntax error: operand expected"));
1370 evalerror (_("syntax error: invalid arithmetic operator"));
1373 cp
--; /* `unget' the character */
1375 /* Should check here to make sure that the current character is one
1376 of the recognized operators and flag an error if not. Could create
1377 a character map the first time through and check it on subsequent
1391 name
= this_command_name
;
1392 for (t
= expression
; whitespace (*t
); t
++)
1394 internal_error (_("%s%s%s: %s (error token is \"%s\")"),
1395 name
? name
: "", name
? ": " : "", t
,
1396 msg
, (lasttp
&& *lasttp
) ? lasttp
: "");
1397 longjmp (evalbuf
, 1);
1400 /* Convert a string to an intmax_t integer, with an arbitrary base.
1403 Anything else: [base#]number (this is implemented to match ksh93)
1405 Base may be >=2 and <=64. If base is <= 36, the numbers are drawn
1406 from [0-9][a-zA-Z], and lowercase and uppercase letters may be used
1407 interchangably. If base is > 36 and <= 64, the numbers are drawn
1408 from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 --
1409 you get the picture). */
1416 register unsigned char c
;
1417 int base
, foundbase
;
1432 if (*s
== 'x' || *s
== 'X')
1443 for (c
= *s
++; c
; c
= *s
++)
1448 evalerror (_("invalid number"));
1450 /* Illegal base specifications raise an evaluation error. */
1451 if (val
< 2 || val
> 64)
1452 evalerror (_("invalid arithmetic base"));
1458 else if (ISALNUM(c
) || (c
== '_') || (c
== '@'))
1462 else if (c
>= 'a' && c
<= 'z')
1464 else if (c
>= 'A' && c
<= 'Z')
1465 c
-= 'A' - ((base
<= 36) ? 10 : 36);
1472 evalerror (_("value too great for base"));
1474 val
= (val
* base
) + c
;
1483 #if defined (EXPR_TEST)
1488 return (malloc (n
));
1496 return (realloc (s
, n
));
1499 SHELL_VAR
*find_variable () { return 0;}
1500 SHELL_VAR
*bind_variable () { return 0; }
1502 char *get_string_value () { return 0; }
1504 procenv_t top_level
;
1514 if (setjmp (top_level
))
1517 for (i
= 1; i
< argc
; i
++)
1519 v
= evalexp (argv
[i
], &expok
);
1521 fprintf (stderr
, _("%s: expression error\n"), argv
[i
]);
1523 printf ("'%s' -> %ld\n", argv
[i
], v
);
1529 builtin_error (format
, arg1
, arg2
, arg3
, arg4
, arg5
)
1532 fprintf (stderr
, "expr: ");
1533 fprintf (stderr
, format
, arg1
, arg2
, arg3
, arg4
, arg5
);
1534 fprintf (stderr
, "\n");
1545 #endif /* EXPR_TEST */