Imported from ../bash-3.0.tar.gz.

This commit is contained in:
Jari Aalto 2004-07-27 13:29:18 +00:00
commit b80f6443b6
400 changed files with 69247 additions and 13346 deletions

132
expr.c
View file

@ -1,6 +1,6 @@
/* expr.c -- arithmetic expression evaluation. */
/* Copyright (C) 1990-2002 Free Software Foundation, Inc.
/* Copyright (C) 1990-2004 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -42,6 +42,7 @@
"||"
"expr ? expr : expr"
"=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
, [comma]
(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
@ -78,6 +79,7 @@
#endif
#include "chartypes.h"
#include "bashintl.h"
#include "shell.h"
@ -155,6 +157,7 @@ static void evalerror __P((char *));
static void pushexp __P((void));
static void popexp __P((void));
static void expr_unwind __P((void));
static void expr_bind_variable __P((char *, char *));
static intmax_t subexpr __P((char *));
@ -200,6 +203,10 @@ static int expr_stack_size; /* Number of slots already allocated. */
extern char *this_command_name;
extern int unbound_vars_is_error;
#if defined (ARRAY_VARS)
extern char *bash_badsub_errmsg;
#endif
#define SAVETOK(X) \
do { \
(X)->curtok = curtok; \
@ -230,7 +237,7 @@ pushexp ()
EXPR_CONTEXT *context;
if (expr_depth >= MAX_EXPR_RECURSION_LEVEL)
evalerror ("expression recursion level exceeded");
evalerror (_("expression recursion level exceeded"));
if (expr_depth >= expr_stack_size)
{
@ -254,7 +261,7 @@ popexp ()
EXPR_CONTEXT *context;
if (expr_depth == 0)
evalerror ("recursion stack underflow");
evalerror (_("recursion stack underflow"));
context = expr_stack[--expr_depth];
@ -280,6 +287,14 @@ expr_unwind ()
free (expr_stack[expr_depth]); /* free the allocated EXPR_CONTEXT */
}
static void
expr_bind_variable (lhs, rhs)
char *lhs, *rhs;
{
(void)bind_int_variable (lhs, rhs);
stupidly_hack_special_variables (lhs);
}
/* 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
@ -299,10 +314,16 @@ evalexp (expr, validp)
int *validp;
{
intmax_t val;
int c;
procenv_t oevalbuf;
val = 0;
if (setjmp (evalbuf))
FASTCOPY (evalbuf, oevalbuf, sizeof (evalbuf));
c = setjmp (evalbuf);
if (c)
{
FREE (tokstr);
FREE (expression);
@ -320,6 +341,8 @@ evalexp (expr, validp)
if (validp)
*validp = 1;
FASTCOPY (oevalbuf, evalbuf, sizeof (evalbuf));
return (val);
}
@ -349,7 +372,7 @@ subexpr (expr)
val = EXP_HIGHEST ();
if (curtok != 0)
evalerror ("syntax error in expression");
evalerror (_("syntax error in expression"));
FREE (tokstr);
FREE (expression);
@ -389,7 +412,7 @@ expassign ()
special = curtok == OP_ASSIGN;
if (lasttok != STR)
evalerror ("attempted assignment to non-variable");
evalerror (_("attempted assignment to non-variable"));
if (special)
{
@ -410,12 +433,12 @@ expassign ()
break;
case DIV:
if (value == 0)
evalerror ("division by 0");
evalerror (_("division by 0"));
lvalue /= value;
break;
case MOD:
if (value == 0)
evalerror ("division by 0");
evalerror (_("division by 0"));
lvalue %= value;
break;
case PLUS:
@ -441,7 +464,7 @@ expassign ()
break;
default:
free (lhs);
evalerror ("bug: bad expassign token");
evalerror (_("bug: bad expassign token"));
break;
}
value = lvalue;
@ -449,7 +472,7 @@ expassign ()
rhs = itos (value);
if (noeval == 0)
(void)bind_int_variable (lhs, rhs);
expr_bind_variable (lhs, rhs);
free (rhs);
free (lhs);
FREE (tokstr);
@ -471,7 +494,7 @@ expcond ()
{
readtok ();
if (curtok == 0 || curtok == COL)
evalerror ("expression expected");
evalerror (_("expression expected"));
if (cval == 0)
{
set_noeval = 1;
@ -483,10 +506,10 @@ expcond ()
if (set_noeval)
noeval--;
if (curtok != COL)
evalerror ("`:' expected for conditional expression");
evalerror (_("`:' expected for conditional expression"));
readtok ();
if (curtok == 0)
evalerror ("expression expected");
evalerror (_("expression expected"));
set_noeval = 0;
if (cval)
{
@ -725,7 +748,7 @@ exp2 ()
val2 = exppower ();
if (((op == DIV) || (op == MOD)) && (val2 == 0))
evalerror ("division by 0");
evalerror (_("division by 0"));
if (op == MUL)
val1 *= val2;
@ -743,14 +766,14 @@ exppower ()
register intmax_t val1, val2, c;
val1 = exp1 ();
if (curtok == POWER)
while (curtok == POWER)
{
readtok ();
val2 = exp1 ();
if (val2 == 0)
return (1);
if (val2 < 0)
evalerror ("exponent less than 0");
evalerror (_("exponent less than 0"));
for (c = 1; val2--; c *= val1)
;
val1 = c;
@ -785,6 +808,7 @@ exp0 ()
register intmax_t val = 0, v2;
char *vincdec;
int stok;
EXPR_CONTEXT ec;
/* XXX - might need additional logic here to decide whether or not
pre-increment or pre-decrement is legal at this point. */
@ -794,12 +818,12 @@ exp0 ()
readtok ();
if (curtok != STR)
/* readtok() catches this */
evalerror ("identifier expected after pre-increment or pre-decrement");
evalerror (_("identifier expected after pre-increment or pre-decrement"));
v2 = tokval + ((stok == PREINC) ? 1 : -1);
vincdec = itos (v2);
if (noeval == 0)
(void)bind_int_variable (tokstr, vincdec);
expr_bind_variable (tokstr, vincdec);
free (vincdec);
val = v2;
@ -821,8 +845,8 @@ exp0 ()
readtok ();
val = EXP_HIGHEST ();
if (curtok != RPAR)
evalerror ("missing `)'");
if (curtok != RPAR) /* ( */
evalerror (_("missing `)'"));
/* Skip over closing paren. */
readtok ();
@ -830,23 +854,42 @@ exp0 ()
else if ((curtok == NUM) || (curtok == STR))
{
val = tokval;
if (curtok == STR && (*tp == '+' || *tp == '-') && tp[1] == *tp &&
(tp[2] == '\0' || (ISALNUM ((unsigned char)tp[2]) == 0)))
if (curtok == STR)
{
SAVETOK (&ec);
tokstr = (char *)NULL; /* keep it from being freed */
noeval = 1;
readtok ();
stok = curtok;
/* post-increment or post-decrement */
v2 = val + ((*tp == '+') ? 1 : -1);
vincdec = itos (v2);
if (noeval == 0)
(void)bind_int_variable (tokstr, vincdec);
free (vincdec);
tp += 2;
curtok = NUM; /* make sure x++=7 is flagged as an error */
if (stok == POSTINC || stok == POSTDEC)
{
/* restore certain portions of EC */
tokstr = ec.tokstr;
noeval = ec.noeval;
lasttok = STR; /* ec.curtok */
v2 = val + ((stok == POSTINC) ? 1 : -1);
vincdec = itos (v2);
if (noeval == 0)
expr_bind_variable (tokstr, vincdec);
free (vincdec);
curtok = NUM; /* make sure x++=7 is flagged as an error */
}
else
{
if (stok == STR) /* free new tokstr before old one is restored */
FREE (tokstr);
RESTORETOK (&ec);
}
}
readtok ();
}
else
evalerror ("syntax error: operand expected");
evalerror (_("syntax error: operand expected"));
return (val);
}
@ -913,7 +956,7 @@ expr_streval (tok, e)
static void
readtok ()
{
register char *cp;
register char *cp, *xp;
register unsigned char c, c1;
register int e;
@ -959,7 +1002,7 @@ readtok ()
e = ']';
}
else
evalerror ("bad array subscript");
evalerror (bash_badsub_errmsg);
}
#endif /* ARRAY_VARS */
@ -972,6 +1015,7 @@ readtok ()
tokstr = (char *)NULL; /* keep it from being freed */
tp = savecp = cp;
noeval = 1;
curtok = STR;
readtok ();
peektok = curtok;
if (peektok == STR) /* free new tokstr before old one is restored */
@ -1041,10 +1085,20 @@ readtok ()
c = LOR;
else if ((c == '*') && (c1 == '*'))
c = POWER;
else if ((c == '-') && (c1 == '-') && legal_variable_starter ((unsigned char)*cp))
c = PREDEC;
else if ((c == '+') && (c1 == '+') && legal_variable_starter ((unsigned char)*cp))
c = PREINC;
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 */
}
else if (c1 == EQ && member (c, "*/%+-&^|"))
{
assigntok = c; /* a OP= b */
@ -1121,11 +1175,11 @@ strlong (num)
if (c == '#')
{
if (foundbase)
evalerror ("bad number");
evalerror (_("invalid number"));
/* Illegal base specifications raise an evaluation error. */
if (val < 2 || val > 64)
evalerror ("illegal arithmetic base");
evalerror (_("invalid arithmetic base"));
base = val;
val = 0;
@ -1145,7 +1199,7 @@ strlong (num)
c = 63;
if (c >= base)
evalerror ("value too great for base");
evalerror (_("value too great for base"));
val = (val * base) + c;
}