Imported from ../bash-3.0.tar.gz.
This commit is contained in:
parent
7117c2d221
commit
b80f6443b6
400 changed files with 69247 additions and 13346 deletions
132
expr.c
132
expr.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue