1 /* expr.c -- arithmetic expression evaluation. */
3 /* Copyright (C) 1990-2015 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"
85 #include "typemax.h" /* INTMAX_MAX, INTMAX_MIN */
87 /* Because of the $((...)) construct, expressions may include newlines.
88 Here is a macro which accepts newlines, tabs and spaces as whitespace. */
89 #define cr_whitespace(c) (whitespace(c) || ((c) == '\n'))
91 /* Size be which the expression stack grows when necessary. */
92 #define EXPR_STACK_GROW_SIZE 10
94 /* Maximum amount of recursion allowed. This prevents a non-integer
95 variable such as "num=num+2" from infinitely adding to itself when
96 "let num=num+2" is given. */
97 #define MAX_EXPR_RECURSION_LEVEL 1024
99 /* The Tokens. Singing "The Lion Sleeps Tonight". */
101 #define EQEQ 1 /* "==" */
102 #define NEQ 2 /* "!=" */
103 #define LEQ 3 /* "<=" */
104 #define GEQ 4 /* ">=" */
105 #define STR 5 /* string */
106 #define NUM 6 /* number */
107 #define LAND 7 /* "&&" Logical AND */
108 #define LOR 8 /* "||" Logical OR */
109 #define LSH 9 /* "<<" Left SHift */
110 #define RSH 10 /* ">>" Right SHift */
111 #define OP_ASSIGN 11 /* op= expassign as in Posix.2 */
112 #define COND 12 /* exp1 ? exp2 : exp3 */
113 #define POWER 13 /* exp1**exp2 */
114 #define PREINC 14 /* ++var */
115 #define PREDEC 15 /* --var */
116 #define POSTINC 16 /* var++ */
117 #define POSTDEC 17 /* var-- */
129 #define BAND '&' /* Bitwise AND */
130 #define BOR '|' /* Bitwise OR. */
131 #define BXOR '^' /* Bitwise eXclusive OR. */
132 #define BNOT '~' /* Bitwise NOT; Two's complement. */
137 /* This should be the function corresponding to the operator with the
138 highest precedence. */
139 #define EXP_HIGHEST expcomma
142 # define MAX_INT_LEN 32
147 char *tokstr
; /* possibly-rewritten lvalue if not NULL */
148 intmax_t tokval
; /* expression evaluated value */
149 SHELL_VAR
*tokvar
; /* variable described by array or var reference */
150 intmax_t ind
; /* array index if not -1 */
153 /* A structure defining a single expression context. */
156 char *expression
, *tp
, *lasttp
;
163 static char *expression
; /* The current expression */
164 static char *tp
; /* token lexical position */
165 static char *lasttp
; /* pointer to last token position */
166 static int curtok
; /* the current token */
167 static int lasttok
; /* the previous token */
168 static int assigntok
; /* the OP in OP= */
169 static char *tokstr
; /* current token string */
170 static intmax_t tokval
; /* current token value */
171 static int noeval
; /* set to 1 if no assignment to be done */
172 static procenv_t evalbuf
;
174 static struct lvalue curlval
= {0, 0, 0, -1};
175 static struct lvalue lastlval
= {0, 0, 0, -1};
177 static int _is_arithop
__P((int));
178 static void readtok
__P((void)); /* lexical analyzer */
180 static void init_lvalue
__P((struct lvalue
*));
181 static struct lvalue
*alloc_lvalue
__P((void));
182 static void free_lvalue
__P((struct lvalue
*));
184 static intmax_t expr_streval
__P((char *, int, struct lvalue
*));
185 static intmax_t strlong
__P((char *));
186 static void evalerror
__P((const char *));
188 static void pushexp
__P((void));
189 static void popexp
__P((void));
190 static void expr_unwind
__P((void));
191 static void expr_bind_variable
__P((char *, char *));
192 #if defined (ARRAY_VARS)
193 static void expr_bind_array_element
__P((char *, arrayind_t
, char *));
196 static intmax_t subexpr
__P((char *));
198 static intmax_t expcomma
__P((void));
199 static intmax_t expassign
__P((void));
200 static intmax_t expcond
__P((void));
201 static intmax_t explor
__P((void));
202 static intmax_t expland
__P((void));
203 static intmax_t expbor
__P((void));
204 static intmax_t expbxor
__P((void));
205 static intmax_t expband
__P((void));
206 static intmax_t exp5
__P((void));
207 static intmax_t exp4
__P((void));
208 static intmax_t expshift
__P((void));
209 static intmax_t exp3
__P((void));
210 static intmax_t exp2
__P((void));
211 static intmax_t exppower
__P((void));
212 static intmax_t exp1
__P((void));
213 static intmax_t exp0
__P((void));
215 /* Global var which contains the stack of expression contexts. */
216 static EXPR_CONTEXT
**expr_stack
;
217 static int expr_depth
; /* Location in the stack. */
218 static int expr_stack_size
; /* Number of slots already allocated. */
220 extern char *this_command_name
;
221 extern int unbound_vars_is_error
, last_command_exit_value
;
223 #if defined (ARRAY_VARS)
224 extern const char * const bash_badsub_errmsg
;
229 (X)->curtok = curtok; \
230 (X)->lasttok = lasttok; \
232 (X)->lasttp = lasttp; \
233 (X)->tokval = tokval; \
234 (X)->tokstr = tokstr; \
235 (X)->noeval = noeval; \
236 (X)->lval = curlval; \
239 #define RESTORETOK(X) \
241 curtok = (X)->curtok; \
242 lasttok = (X)->lasttok; \
244 lasttp = (X)->lasttp; \
245 tokval = (X)->tokval; \
246 tokstr = (X)->tokstr; \
247 noeval = (X)->noeval; \
248 curlval = (X)->lval; \
251 /* Push and save away the contents of the globals describing the
252 current expression context. */
256 EXPR_CONTEXT
*context
;
258 if (expr_depth
>= MAX_EXPR_RECURSION_LEVEL
)
259 evalerror (_("expression recursion level exceeded"));
261 if (expr_depth
>= expr_stack_size
)
263 expr_stack_size
+= EXPR_STACK_GROW_SIZE
;
264 expr_stack
= (EXPR_CONTEXT
**)xrealloc (expr_stack
, expr_stack_size
* sizeof (EXPR_CONTEXT
*));
267 context
= (EXPR_CONTEXT
*)xmalloc (sizeof (EXPR_CONTEXT
));
269 context
->expression
= expression
;
272 expr_stack
[expr_depth
++] = context
;
275 /* Pop the the contents of the expression context stack into the
276 globals describing the current expression context. */
280 EXPR_CONTEXT
*context
;
283 evalerror (_("recursion stack underflow"));
285 context
= expr_stack
[--expr_depth
];
287 expression
= context
->expression
;
288 RESTORETOK (context
);
296 while (--expr_depth
> 0)
298 if (expr_stack
[expr_depth
]->tokstr
)
299 free (expr_stack
[expr_depth
]->tokstr
);
301 if (expr_stack
[expr_depth
]->expression
)
302 free (expr_stack
[expr_depth
]->expression
);
304 free (expr_stack
[expr_depth
]);
306 free (expr_stack
[expr_depth
]); /* free the allocated EXPR_CONTEXT */
308 noeval
= 0; /* XXX */
312 expr_bind_variable (lhs
, rhs
)
317 v
= bind_int_variable (lhs
, rhs
);
318 if (v
&& (readonly_p (v
) || noassign_p (v
)))
319 sh_longjmp (evalbuf
, 1); /* variable assignment error */
320 stupidly_hack_special_variables (lhs
);
323 #if defined (ARRAY_VARS)
324 /* Rewrite tok, which is of the form vname[expression], to vname[ind], where
325 IND is the already-calculated value of expression. */
327 expr_bind_array_element (tok
, ind
, rhs
)
334 char ibuf
[INT_STRLEN_BOUND (arrayind_t
) + 1], *istr
;
336 istr
= fmtumax (ind
, 10, ibuf
, sizeof (ibuf
), 0);
337 vname
= array_variable_name (tok
, (char **)NULL
, (int *)NULL
);
339 llen
= strlen (vname
) + sizeof (ibuf
) + 3;
340 lhs
= xmalloc (llen
);
342 sprintf (lhs
, "%s[%s]", vname
, istr
); /* XXX */
344 /*itrace("expr_bind_array_element: %s=%s", lhs, rhs);*/
345 expr_bind_variable (lhs
, rhs
);
349 #endif /* ARRAY_VARS */
351 /* Evaluate EXPR, and return the arithmetic result. If VALIDP is
352 non-null, a zero is stored into the location to which it points
353 if the expression is invalid, non-zero otherwise. If a non-zero
354 value is returned in *VALIDP, the return value of evalexp() may
357 The `while' loop after the longjmp is caught relies on the above
358 implementation of pushexp and popexp leaving in expr_stack[0] the
359 values that the variables had when the program started. That is,
360 the first things saved are the initial values of the variables that
361 were assigned at program startup or by the compiler. Therefore, it is
362 safe to let the loop terminate when expr_depth == 0, without freeing up
363 any of the expr_depth[0] stuff. */
365 evalexp (expr
, validp
)
376 FASTCOPY (evalbuf
, oevalbuf
, sizeof (evalbuf
));
378 c
= setjmp_nosigs (evalbuf
);
384 tokstr
= expression
= (char *)NULL
;
393 val
= subexpr (expr
);
398 FASTCOPY (oevalbuf
, evalbuf
, sizeof (evalbuf
));
410 for (p
= expr
; p
&& *p
&& cr_whitespace (*p
); p
++)
413 if (p
== NULL
|| *p
== '\0')
417 expression
= savestring (expr
);
420 curtok
= lasttok
= 0;
421 tokstr
= (char *)NULL
;
423 init_lvalue (&curlval
);
428 val
= EXP_HIGHEST ();
431 evalerror (_("syntax error in expression"));
444 register intmax_t value
;
446 value
= expassign ();
447 while (curtok
== COMMA
)
450 value
= expassign ();
459 register intmax_t value
;
462 #if defined (HAVE_IMAXDIV)
467 if (curtok
== EQ
|| curtok
== OP_ASSIGN
)
472 special
= curtok
== OP_ASSIGN
;
475 evalerror (_("attempted assignment to non-variable"));
479 op
= assigntok
; /* a OP= b */
483 /* XXX - watch out for pointer aliasing issues here */
484 lhs
= savestring (tokstr
);
485 /* save ind in case rhs is string var and evaluation overwrites it */
488 value
= expassign ();
492 if ((op
== DIV
|| op
== MOD
) && value
== 0)
495 evalerror (_("division by 0"));
507 if (lvalue
== INTMAX_MIN
&& value
== -1)
508 lvalue
= (op
== DIV
) ? INTMAX_MIN
: 0;
512 idiv
= imaxdiv (lvalue
, value
);
513 lvalue
= (op
== DIV
) ? idiv
.quot
: idiv
.rem
;
516 lvalue
= (op
== DIV
) ? lvalue
/ value
: lvalue
% value
;
542 evalerror (_("bug: bad expassign token"));
551 #if defined (ARRAY_VARS)
553 expr_bind_array_element (lhs
, lind
, rhs
);
556 expr_bind_variable (lhs
, rhs
);
558 if (curlval
.tokstr
&& curlval
.tokstr
== tokstr
)
559 init_lvalue (&curlval
);
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 */
588 if (curtok
== 0 || curtok
== COL
)
589 evalerror (_("expression expected"));
591 val1
= EXP_HIGHEST ();
596 evalerror (_("`:' expected for conditional expression"));
607 evalerror (_("expression expected"));
612 rval
= cval
? val1
: val2
;
622 register intmax_t val1
, val2
;
627 while (curtok
== LOR
)
650 register intmax_t val1
, val2
;
655 while (curtok
== LAND
)
678 register intmax_t val1
, val2
;
682 while (curtok
== BOR
)
697 register intmax_t val1
, val2
;
701 while (curtok
== BXOR
)
716 register intmax_t val1
, val2
;
720 while (curtok
== BAND
)
734 register intmax_t val1
, val2
;
738 while ((curtok
== EQEQ
) || (curtok
== NEQ
))
745 val1
= (val1
== val2
);
747 val1
= (val1
!= val2
);
756 register intmax_t val1
, val2
;
759 while ((curtok
== LEQ
) ||
775 else /* (op == GT) */
782 /* Left and right shifts. */
786 register intmax_t val1
, val2
;
790 while ((curtok
== LSH
) || (curtok
== RSH
))
810 register intmax_t val1
, val2
;
814 while ((curtok
== PLUS
) || (curtok
== MINUS
))
823 else if (op
== MINUS
)
833 register intmax_t val1
, val2
;
834 #if defined (HAVE_IMAXDIV)
840 while ((curtok
== MUL
) ||
852 /* Handle division by 0 and twos-complement arithmetic overflow */
853 if (((op
== DIV
) || (op
== MOD
)) && (val2
== 0))
859 while (lasttp
&& *lasttp
&& whitespace (*lasttp
))
861 evalerror (_("division by 0"));
867 else if (op
== MOD
&& val1
== INTMAX_MIN
&& val2
== -1)
872 else if (op
== DIV
&& val1
== INTMAX_MIN
&& val2
== -1)
877 else if (op
== DIV
|| op
== MOD
)
878 #if defined (HAVE_IMAXDIV)
880 idiv
= imaxdiv (val1
, val2
);
881 val1
= (op
== DIV
) ? idiv
.quot
: idiv
.rem
;
884 val1
= (op
== DIV
) ? val1
/ val2
: val1
% val2
;
911 register intmax_t val1
, val2
, c
;
914 while (curtok
== POWER
)
917 val2
= exppower (); /* exponentiation is right-associative */
922 evalerror (_("exponent less than 0"));
923 val1
= ipow (val1
, val2
);
931 register intmax_t val
;
939 else if (curtok
== BNOT
)
945 else if (curtok
== MINUS
)
951 else if (curtok
== PLUS
)
966 register intmax_t val
= 0, v2
;
971 /* XXX - might need additional logic here to decide whether or not
972 pre-increment or pre-decrement is legal at this point. */
973 if (curtok
== PREINC
|| curtok
== PREDEC
)
975 stok
= lasttok
= curtok
;
978 /* readtok() catches this */
979 evalerror (_("identifier expected after pre-increment or pre-decrement"));
981 v2
= tokval
+ ((stok
== PREINC
) ? 1 : -1);
985 #if defined (ARRAY_VARS)
986 if (curlval
.ind
!= -1)
987 expr_bind_array_element (curlval
.tokstr
, curlval
.ind
, vincdec
);
990 expr_bind_variable (tokstr
, vincdec
);
995 curtok
= NUM
; /* make sure --x=7 is flagged as an error */
998 else if (curtok
== LPAR
)
1000 /* XXX - save curlval here? Or entire expression context? */
1002 val
= EXP_HIGHEST ();
1004 if (curtok
!= RPAR
) /* ( */
1005 evalerror (_("missing `)'"));
1007 /* Skip over closing paren. */
1010 else if ((curtok
== NUM
) || (curtok
== STR
))
1016 tokstr
= (char *)NULL
; /* keep it from being freed */
1021 /* post-increment or post-decrement */
1022 if (stok
== POSTINC
|| stok
== POSTDEC
)
1024 /* restore certain portions of EC */
1028 lasttok
= STR
; /* ec.curtok */
1030 v2
= val
+ ((stok
== POSTINC
) ? 1 : -1);
1031 vincdec
= itos (v2
);
1034 #if defined (ARRAY_VARS)
1035 if (curlval
.ind
!= -1)
1036 expr_bind_array_element (curlval
.tokstr
, curlval
.ind
, vincdec
);
1039 expr_bind_variable (tokstr
, vincdec
);
1042 curtok
= NUM
; /* make sure x++=7 is flagged as an error */
1046 /* XXX - watch out for pointer aliasing issues here */
1047 if (stok
== STR
) /* free new tokstr before old one is restored */
1056 evalerror (_("syntax error: operand expected"));
1067 lv
->tokval
= lv
->ind
= -1;
1070 static struct lvalue
*
1075 lv
= xmalloc (sizeof (struct lvalue
));
1084 free (lv
); /* should be inlined */
1088 expr_streval (tok
, e
, lvalue
)
1091 struct lvalue
*lvalue
;
1096 #if defined (ARRAY_VARS)
1100 /*itrace("expr_streval: %s: noeval = %d", tok, noeval);*/
1101 /* If we are suppressing evaluation, just short-circuit here instead of
1102 going through the rest of the evaluator. */
1107 #if defined (ARRAY_VARS)
1108 v
= (e
== ']') ? array_variable_part (tok
, (char **)0, (int *)0) : find_variable (tok
);
1110 v
= find_variable (tok
);
1113 if ((v
== 0 || invisible_p (v
)) && unbound_vars_is_error
)
1115 #if defined (ARRAY_VARS)
1116 value
= (e
== ']') ? array_variable_name (tok
, (char **)0, (int *)0) : tok
;
1121 last_command_exit_value
= EXECUTION_FAILURE
;
1122 err_unboundvar (value
);
1124 #if defined (ARRAY_VARS)
1126 FREE (value
); /* array_variable_name returns new memory */
1129 if (no_longjmp_on_fatal_error
&& interactive_shell
)
1130 sh_longjmp (evalbuf
, 1);
1132 if (interactive_shell
)
1135 top_level_cleanup ();
1136 jump_to_top_level (DISCARD
);
1139 jump_to_top_level (FORCE_EOF
);
1142 #if defined (ARRAY_VARS)
1144 /* Second argument of 0 to get_array_value means that we don't allow
1145 references like array[@]. In this case, get_array_value is just
1146 like get_variable_value in that it does not return newly-allocated
1147 memory or quote the results. */
1148 value
= (e
== ']') ? get_array_value (tok
, 0, (int *)NULL
, &ind
) : get_variable_value (v
);
1150 value
= get_variable_value (v
);
1153 tval
= (value
&& *value
) ? subexpr (value
) : 0;
1157 lvalue
->tokstr
= tok
; /* XXX */
1158 lvalue
->tokval
= tval
;
1159 lvalue
->tokvar
= v
; /* XXX */
1160 #if defined (ARRAY_VARS)
1218 return 1; /* operator tokens */
1222 return 1; /* questionable */
1224 return 0; /* anything else is invalid */
1228 /* Lexical analyzer/token reader for the expression evaluator. Reads the
1229 next token and puts its value into curtok, while advancing past it.
1230 Updates value of tp. May also set tokval (for number) or tokstr (for
1235 register char *cp
, *xp
;
1236 register unsigned char c
, c1
;
1240 /* Skip leading whitespace. */
1243 while (cp
&& (c
= *cp
) && (cr_whitespace (c
)))
1256 lasttp
= tp
= cp
- 1;
1258 if (legal_variable_starter (c
))
1260 /* variable names not preceded with a dollar sign are shell variables. */
1265 while (legal_variable_char (c
))
1270 #if defined (ARRAY_VARS)
1273 e
= skipsubscript (cp
, 0, 0);
1281 evalerror (bash_badsub_errmsg
);
1283 #endif /* ARRAY_VARS */
1286 /* XXX - watch out for pointer aliasing issues here */
1287 if (curlval
.tokstr
&& curlval
.tokstr
== tokstr
)
1288 init_lvalue (&curlval
);
1291 tokstr
= savestring (tp
);
1294 /* XXX - make peektok part of saved token state? */
1296 tokstr
= (char *)NULL
; /* keep it from being freed */
1302 if (peektok
== STR
) /* free new tokstr before old one is restored */
1307 /* The tests for PREINC and PREDEC aren't strictly correct, but they
1308 preserve old behavior if a construct like --x=9 is given. */
1309 if (lasttok
== PREINC
|| lasttok
== PREDEC
|| peektok
!= EQ
)
1312 tokval
= expr_streval (tokstr
, e
, &curlval
);
1322 while (ISALNUM (c
) || c
== '#' || c
== '@' || c
== '_')
1328 tokval
= strlong (tp
);
1336 if ((c
== EQ
) && (c1
== EQ
))
1338 else if ((c
== NOT
) && (c1
== EQ
))
1340 else if ((c
== GT
) && (c1
== EQ
))
1342 else if ((c
== LT
) && (c1
== EQ
))
1344 else if ((c
== LT
) && (c1
== LT
))
1346 if (*cp
== '=') /* a <<= b */
1355 else if ((c
== GT
) && (c1
== GT
))
1359 assigntok
= RSH
; /* a >>= b */
1366 else if ((c
== BAND
) && (c1
== BAND
))
1368 else if ((c
== BOR
) && (c1
== BOR
))
1370 else if ((c
== '*') && (c1
== '*'))
1372 else if ((c
== '-' || c
== '+') && c1
== c
&& curtok
== STR
)
1373 c
= (c
== '-') ? POSTDEC
: POSTINC
;
1374 else if ((c
== '-' || c
== '+') && c1
== c
)
1376 /* Quickly scan forward to see if this is followed by optional
1377 whitespace and an identifier. */
1379 while (xp
&& *xp
&& cr_whitespace (*xp
))
1381 if (legal_variable_starter ((unsigned char)*xp
))
1382 c
= (c
== '-') ? PREDEC
: PREINC
;
1384 cp
--; /* not preinc or predec, so unget the character */
1386 else if (c1
== EQ
&& member (c
, "*/%+-&^|"))
1388 assigntok
= c
; /* a OP= b */
1391 else if (_is_arithop (c
) == 0)
1394 /* use curtok, since it hasn't been copied to lasttok yet */
1395 if (curtok
== 0 || _is_arithop (curtok
) || _is_multiop (curtok
))
1396 evalerror (_("syntax error: operand expected"));
1398 evalerror (_("syntax error: invalid arithmetic operator"));
1401 cp
--; /* `unget' the character */
1403 /* Should check here to make sure that the current character is one
1404 of the recognized operators and flag an error if not. Could create
1405 a character map the first time through and check it on subsequent
1419 name
= this_command_name
;
1420 for (t
= expression
; whitespace (*t
); t
++)
1422 internal_error (_("%s%s%s: %s (error token is \"%s\")"),
1423 name
? name
: "", name
? ": " : "", t
,
1424 msg
, (lasttp
&& *lasttp
) ? lasttp
: "");
1425 sh_longjmp (evalbuf
, 1);
1428 /* Convert a string to an intmax_t integer, with an arbitrary base.
1431 Anything else: [base#]number (this is implemented to match ksh93)
1433 Base may be >=2 and <=64. If base is <= 36, the numbers are drawn
1434 from [0-9][a-zA-Z], and lowercase and uppercase letters may be used
1435 interchangably. If base is > 36 and <= 64, the numbers are drawn
1436 from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 --
1437 you get the picture). */
1444 register unsigned char c
;
1445 int base
, foundbase
;
1460 if (*s
== 'x' || *s
== 'X')
1471 for (c
= *s
++; c
; c
= *s
++)
1476 evalerror (_("invalid number"));
1478 /* Illegal base specifications raise an evaluation error. */
1479 if (val
< 2 || val
> 64)
1480 evalerror (_("invalid arithmetic base"));
1486 else if (ISALNUM(c
) || (c
== '_') || (c
== '@'))
1490 else if (c
>= 'a' && c
<= 'z')
1492 else if (c
>= 'A' && c
<= 'Z')
1493 c
-= 'A' - ((base
<= 36) ? 10 : 36);
1500 evalerror (_("value too great for base"));
1502 val
= (val
* base
) + c
;
1511 #if defined (EXPR_TEST)
1516 return (malloc (n
));
1524 return (realloc (s
, n
));
1527 SHELL_VAR
*find_variable () { return 0;}
1528 SHELL_VAR
*bind_variable () { return 0; }
1530 char *get_string_value () { return 0; }
1532 procenv_t top_level
;
1542 if (setjmp (top_level
))
1545 for (i
= 1; i
< argc
; i
++)
1547 v
= evalexp (argv
[i
], &expok
);
1549 fprintf (stderr
, _("%s: expression error\n"), argv
[i
]);
1551 printf ("'%s' -> %ld\n", argv
[i
], v
);
1557 builtin_error (format
, arg1
, arg2
, arg3
, arg4
, arg5
)
1560 fprintf (stderr
, "expr: ");
1561 fprintf (stderr
, format
, arg1
, arg2
, arg3
, arg4
, arg5
);
1562 fprintf (stderr
, "\n");
1573 #endif /* EXPR_TEST */