Bash-4.2 distribution sources and documentation
This commit is contained in:
parent
30d188c293
commit
495aee441b
341 changed files with 108751 additions and 36060 deletions
178
expr.c
178
expr.c
|
|
@ -1,6 +1,6 @@
|
|||
/* expr.c -- arithmetic expression evaluation. */
|
||||
|
||||
/* Copyright (C) 1990-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1990-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -137,6 +137,28 @@
|
|||
highest precedence. */
|
||||
#define EXP_HIGHEST expcomma
|
||||
|
||||
#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;
|
||||
|
||||
static char *expression; /* The current expression */
|
||||
static char *tp; /* token lexical position */
|
||||
static char *lasttp; /* pointer to last token position */
|
||||
|
|
@ -148,10 +170,17 @@ static intmax_t tokval; /* current token value */
|
|||
static int noeval; /* set to 1 if no assignment to be done */
|
||||
static procenv_t evalbuf;
|
||||
|
||||
static struct lvalue curlval = {0, 0, 0, -1};
|
||||
static struct lvalue lastlval = {0, 0, 0, -1};
|
||||
|
||||
static int _is_arithop __P((int));
|
||||
static void readtok __P((void)); /* lexical analyzer */
|
||||
|
||||
static intmax_t expr_streval __P((char *, int));
|
||||
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 *));
|
||||
static intmax_t strlong __P((char *));
|
||||
static void evalerror __P((const char *));
|
||||
|
||||
|
|
@ -159,6 +188,7 @@ 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 void expr_bind_array_element __P((char *, arrayind_t, char *));
|
||||
|
||||
static intmax_t subexpr __P((char *));
|
||||
|
||||
|
|
@ -179,23 +209,6 @@ static intmax_t exppower __P((void));
|
|||
static intmax_t exp1 __P((void));
|
||||
static intmax_t exp0 __P((void));
|
||||
|
||||
/* A structure defining a single expression context. */
|
||||
typedef struct {
|
||||
int curtok, lasttok;
|
||||
char *expression, *tp, *lasttp;
|
||||
intmax_t tokval;
|
||||
char *tokstr;
|
||||
int noeval;
|
||||
} EXPR_CONTEXT;
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* Not used yet. */
|
||||
typedef struct {
|
||||
char *tokstr;
|
||||
intmax_t tokval;
|
||||
} LVALUE;
|
||||
#endif
|
||||
|
||||
/* Global var which contains the stack of expression contexts. */
|
||||
static EXPR_CONTEXT **expr_stack;
|
||||
static int expr_depth; /* Location in the stack. */
|
||||
|
|
@ -217,6 +230,7 @@ extern const char * const bash_badsub_errmsg;
|
|||
(X)->tokval = tokval; \
|
||||
(X)->tokstr = tokstr; \
|
||||
(X)->noeval = noeval; \
|
||||
(X)->lval = curlval; \
|
||||
} while (0)
|
||||
|
||||
#define RESTORETOK(X) \
|
||||
|
|
@ -228,6 +242,7 @@ extern const char * const bash_badsub_errmsg;
|
|||
tokval = (X)->tokval; \
|
||||
tokstr = (X)->tokstr; \
|
||||
noeval = (X)->noeval; \
|
||||
curlval = (X)->lval; \
|
||||
} while (0)
|
||||
|
||||
/* Push and save away the contents of the globals describing the
|
||||
|
|
@ -298,6 +313,32 @@ expr_bind_variable (lhs, rhs)
|
|||
stupidly_hack_special_variables (lhs);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
expr_bind_variable (lhs, rhs);
|
||||
/*itrace("expr_bind_array_element: %s=%s", lhs, rhs);*/
|
||||
free (vname);
|
||||
free (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
|
||||
|
|
@ -364,12 +405,14 @@ subexpr (expr)
|
|||
return (0);
|
||||
|
||||
pushexp ();
|
||||
curtok = lasttok = 0;
|
||||
expression = savestring (expr);
|
||||
tp = expression;
|
||||
|
||||
curtok = lasttok = 0;
|
||||
tokstr = (char *)NULL;
|
||||
tokval = 0;
|
||||
init_lvalue (&curlval);
|
||||
lastlval = curlval;
|
||||
|
||||
readtok ();
|
||||
|
||||
|
|
@ -406,6 +449,7 @@ expassign ()
|
|||
{
|
||||
register intmax_t value;
|
||||
char *lhs, *rhs;
|
||||
arrayind_t lind;
|
||||
|
||||
value = expcond ();
|
||||
if (curtok == EQ || curtok == OP_ASSIGN)
|
||||
|
|
@ -425,6 +469,8 @@ expassign ()
|
|||
}
|
||||
|
||||
lhs = savestring (tokstr);
|
||||
/* save ind in case rhs is string var and evaluation overwrites it */
|
||||
lind = curlval.ind;
|
||||
readtok ();
|
||||
value = expassign ();
|
||||
|
||||
|
|
@ -476,7 +522,12 @@ expassign ()
|
|||
|
||||
rhs = itos (value);
|
||||
if (noeval == 0)
|
||||
expr_bind_variable (lhs, rhs);
|
||||
{
|
||||
if (lind != -1)
|
||||
expr_bind_array_element (lhs, lind, rhs);
|
||||
else
|
||||
expr_bind_variable (lhs, rhs);
|
||||
}
|
||||
free (rhs);
|
||||
free (lhs);
|
||||
FREE (tokstr);
|
||||
|
|
@ -801,6 +852,16 @@ exp1 ()
|
|||
readtok ();
|
||||
val = ~exp1 ();
|
||||
}
|
||||
else if (curtok == MINUS)
|
||||
{
|
||||
readtok ();
|
||||
val = - exp1 ();
|
||||
}
|
||||
else if (curtok == PLUS)
|
||||
{
|
||||
readtok ();
|
||||
val = exp1 ();
|
||||
}
|
||||
else
|
||||
val = exp0 ();
|
||||
|
||||
|
|
@ -828,23 +889,18 @@ exp0 ()
|
|||
v2 = tokval + ((stok == PREINC) ? 1 : -1);
|
||||
vincdec = itos (v2);
|
||||
if (noeval == 0)
|
||||
expr_bind_variable (tokstr, vincdec);
|
||||
{
|
||||
if (curlval.ind != -1)
|
||||
expr_bind_array_element (curlval.tokstr, curlval.ind, vincdec);
|
||||
else
|
||||
expr_bind_variable (tokstr, vincdec);
|
||||
}
|
||||
free (vincdec);
|
||||
val = v2;
|
||||
|
||||
curtok = NUM; /* make sure --x=7 is flagged as an error */
|
||||
readtok ();
|
||||
}
|
||||
else if (curtok == MINUS)
|
||||
{
|
||||
readtok ();
|
||||
val = - exp0 ();
|
||||
}
|
||||
else if (curtok == PLUS)
|
||||
{
|
||||
readtok ();
|
||||
val = exp0 ();
|
||||
}
|
||||
else if (curtok == LPAR)
|
||||
{
|
||||
readtok ();
|
||||
|
|
@ -873,12 +929,18 @@ exp0 ()
|
|||
/* restore certain portions of EC */
|
||||
tokstr = ec.tokstr;
|
||||
noeval = ec.noeval;
|
||||
curlval = ec.lval;
|
||||
lasttok = STR; /* ec.curtok */
|
||||
|
||||
v2 = val + ((stok == POSTINC) ? 1 : -1);
|
||||
vincdec = itos (v2);
|
||||
if (noeval == 0)
|
||||
expr_bind_variable (tokstr, vincdec);
|
||||
{
|
||||
if (curlval.ind != -1)
|
||||
expr_bind_array_element (curlval.tokstr, curlval.ind, vincdec);
|
||||
else
|
||||
expr_bind_variable (tokstr, vincdec);
|
||||
}
|
||||
free (vincdec);
|
||||
curtok = NUM; /* make sure x++=7 is flagged as an error */
|
||||
}
|
||||
|
|
@ -899,14 +961,44 @@ exp0 ()
|
|||
return (val);
|
||||
}
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
static intmax_t
|
||||
expr_streval (tok, e)
|
||||
expr_streval (tok, e, lvalue)
|
||||
char *tok;
|
||||
int e;
|
||||
struct lvalue *lvalue;
|
||||
{
|
||||
SHELL_VAR *v;
|
||||
char *value;
|
||||
intmax_t tval;
|
||||
#if defined (ARRAY_VARS)
|
||||
arrayind_t ind;
|
||||
#endif
|
||||
|
||||
/* [[[[[ */
|
||||
#if defined (ARRAY_VARS)
|
||||
|
|
@ -941,18 +1033,27 @@ expr_streval (tok, e)
|
|||
jump_to_top_level (FORCE_EOF);
|
||||
}
|
||||
|
||||
ind = -1;
|
||||
#if defined (ARRAY_VARS)
|
||||
/* 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. */
|
||||
value = (e == ']') ? get_array_value (tok, 0, (int *)NULL) : get_variable_value (v);
|
||||
value = (e == ']') ? get_array_value (tok, 0, (int *)NULL, &ind) : get_variable_value (v);
|
||||
#else
|
||||
value = get_variable_value (v);
|
||||
#endif
|
||||
|
||||
tval = (value && *value) ? subexpr (value) : 0;
|
||||
|
||||
if (lvalue)
|
||||
{
|
||||
lvalue->tokstr = tok; /* XXX */
|
||||
lvalue->tokval = tval;
|
||||
lvalue->tokvar = v; /* XXX */
|
||||
lvalue->ind = ind;
|
||||
}
|
||||
|
||||
return (tval);
|
||||
}
|
||||
|
||||
|
|
@ -1024,6 +1125,7 @@ readtok ()
|
|||
register char *cp, *xp;
|
||||
register unsigned char c, c1;
|
||||
register int e;
|
||||
struct lvalue lval;
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
cp = tp;
|
||||
|
|
@ -1075,6 +1177,7 @@ readtok ()
|
|||
tokstr = savestring (tp);
|
||||
*cp = c;
|
||||
|
||||
/* XXX - make peektok part of saved token state? */
|
||||
SAVETOK (&ec);
|
||||
tokstr = (char *)NULL; /* keep it from being freed */
|
||||
tp = savecp = cp;
|
||||
|
|
@ -1090,7 +1193,10 @@ readtok ()
|
|||
/* 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)
|
||||
tokval = expr_streval (tokstr, e);
|
||||
{
|
||||
lastlval = curlval;
|
||||
tokval = expr_streval (tokstr, e, &curlval);
|
||||
}
|
||||
else
|
||||
tokval = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue