mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-01 07:31:20 +02:00
zsh-workers/7981
This commit is contained in:
parent
f98b1581a4
commit
9878bf492b
1 changed files with 177 additions and 191 deletions
118
Src/math.c
118
Src/math.c
|
@ -45,7 +45,7 @@ int lastbase;
|
||||||
static char *ptr;
|
static char *ptr;
|
||||||
|
|
||||||
static mnumber yyval;
|
static mnumber yyval;
|
||||||
static LV yylval;
|
static char *yylval;
|
||||||
|
|
||||||
static int mlevel = 0;
|
static int mlevel = 0;
|
||||||
|
|
||||||
|
@ -153,12 +153,12 @@ static int prec[TOKCOUNT] =
|
||||||
6, 8, 8, 8, 9,
|
6, 8, 8, 8, 9,
|
||||||
9, 3, 3, 10, 10,
|
9, 3, 3, 10, 10,
|
||||||
10, 10, 11, 11, 12,
|
10, 10, 11, 11, 12,
|
||||||
13, 13, 14, 14, 15,
|
13, 13, 14, 15, 16,
|
||||||
15, 15, 15, 15, 15,
|
16, 16, 16, 16, 16,
|
||||||
15, 15, 15, 15, 15,
|
16, 16, 16, 16, 16,
|
||||||
15, 15, 15, 16, 200,
|
16, 16, 16, 17, 200,
|
||||||
2, 2, 0, 0, 7,
|
2, 2, 0, 0, 7,
|
||||||
0, 15, 0
|
0, 16, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TOPPREC 16
|
#define TOPPREC 16
|
||||||
|
@ -179,13 +179,6 @@ static int type[TOKCOUNT] =
|
||||||
/* 50 */ LR|OP_OPF, RL|OP_E2, LR|OP_OPF
|
/* 50 */ LR|OP_OPF, RL|OP_E2, LR|OP_OPF
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LVCOUNT 32
|
|
||||||
|
|
||||||
/* list of lvalues (variables) */
|
|
||||||
|
|
||||||
static int lvc;
|
|
||||||
static char **lvals;
|
|
||||||
|
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static int
|
static int
|
||||||
|
@ -325,7 +318,6 @@ zzlex(void)
|
||||||
case '?':
|
case '?':
|
||||||
if (unary) {
|
if (unary) {
|
||||||
yyval.u.l = lastval;
|
yyval.u.l = lastval;
|
||||||
unary = 0;
|
|
||||||
return NUM;
|
return NUM;
|
||||||
}
|
}
|
||||||
return QUEST;
|
return QUEST;
|
||||||
|
@ -397,10 +389,6 @@ zzlex(void)
|
||||||
char *p, q;
|
char *p, q;
|
||||||
|
|
||||||
p = ptr;
|
p = ptr;
|
||||||
if (lvc == LVCOUNT) {
|
|
||||||
zerr("too many identifiers (complain to author)", NULL, 0);
|
|
||||||
return EOI;
|
|
||||||
}
|
|
||||||
while (iident(*++ptr));
|
while (iident(*++ptr));
|
||||||
if (*ptr == '[' || (!cct && *ptr == '(')) {
|
if (*ptr == '[' || (!cct && *ptr == '(')) {
|
||||||
char op = *ptr, cp = ((*ptr == '[') ? ']' : ')');
|
char op = *ptr, cp = ((*ptr == '[') ? ']' : ')');
|
||||||
|
@ -417,7 +405,7 @@ zzlex(void)
|
||||||
}
|
}
|
||||||
q = *ptr;
|
q = *ptr;
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
lvals[yylval = lvc++] = ztrdup(p);
|
yylval = dupstring(p);
|
||||||
*ptr = q;
|
*ptr = q;
|
||||||
return (func ? FUNC : (cct ? CID : ID));
|
return (func ? FUNC : (cct ? CID : ID));
|
||||||
}
|
}
|
||||||
|
@ -436,7 +424,7 @@ static int mtok; /* last token */
|
||||||
static int sp = -1; /* stack pointer */
|
static int sp = -1; /* stack pointer */
|
||||||
|
|
||||||
struct mathvalue {
|
struct mathvalue {
|
||||||
LV lval;
|
char *lval;
|
||||||
mnumber val;
|
mnumber val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -444,7 +432,7 @@ static struct mathvalue *stack;
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static void
|
static void
|
||||||
push(mnumber val, LV lval)
|
push(mnumber val, char *lval)
|
||||||
{
|
{
|
||||||
if (sp == STACKSZ - 1)
|
if (sp == STACKSZ - 1)
|
||||||
zerr("stack overflow", NULL, 0);
|
zerr("stack overflow", NULL, 0);
|
||||||
|
@ -457,13 +445,13 @@ push(mnumber val, LV lval)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static mnumber
|
static mnumber
|
||||||
getcvar(LV s)
|
getcvar(char *s)
|
||||||
{
|
{
|
||||||
char *t;
|
char *t;
|
||||||
mnumber mn;
|
mnumber mn;
|
||||||
mn.type = MN_INTEGER;
|
mn.type = MN_INTEGER;
|
||||||
|
|
||||||
if (!(t = getsparam(lvals[s])))
|
if (!(t = getsparam(s)))
|
||||||
mn.u.l = 0;
|
mn.u.l = 0;
|
||||||
else
|
else
|
||||||
mn.u.l = STOUC(*t == Meta ? t[1] ^ 32 : *t);
|
mn.u.l = STOUC(*t == Meta ? t[1] ^ 32 : *t);
|
||||||
|
@ -473,16 +461,16 @@ getcvar(LV s)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static mnumber
|
static mnumber
|
||||||
setvar(LV s, mnumber v)
|
setvar(char *s, mnumber v)
|
||||||
{
|
{
|
||||||
if (s == -1 || s >= lvc) {
|
if (!s) {
|
||||||
zerr("lvalue required", NULL, 0);
|
zerr("lvalue required", NULL, 0);
|
||||||
v.type = MN_INTEGER;
|
v.type = MN_INTEGER;
|
||||||
v.u.l = 0;
|
v.u.l = 0;
|
||||||
}
|
}
|
||||||
if (noeval)
|
if (noeval)
|
||||||
return v;
|
return v;
|
||||||
setnparam(lvals[s], v);
|
setnparam(s, v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +495,7 @@ callmathfunc(char *o)
|
||||||
return f->sfunc(n, a, f->funcid);
|
return f->sfunc(n, a, f->funcid);
|
||||||
else {
|
else {
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
mnumber *argv, *q;
|
mnumber *argv = NULL, *q;
|
||||||
LinkList l = newlinklist();
|
LinkList l = newlinklist();
|
||||||
LinkNode node;
|
LinkNode node;
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -563,7 +551,7 @@ void
|
||||||
op(int what)
|
op(int what)
|
||||||
{
|
{
|
||||||
mnumber a, b, c, *spval;
|
mnumber a, b, c, *spval;
|
||||||
LV lv;
|
char *lv;
|
||||||
int tp = type[what];
|
int tp = type[what];
|
||||||
|
|
||||||
if (errflag)
|
if (errflag)
|
||||||
|
@ -574,10 +562,8 @@ op(int what)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO)) {
|
if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO)) {
|
||||||
if (sp < 1) {
|
/* Make sure anyone seeing this message reports it. */
|
||||||
zerr("bad math expression: unbalanced stack", NULL, 0); \
|
DPUTS(sp < 1, "BUG: math: not enough wallabies in outback.");
|
||||||
return;
|
|
||||||
}
|
|
||||||
b = stack[sp--].val;
|
b = stack[sp--].val;
|
||||||
a = stack[sp--].val;
|
a = stack[sp--].val;
|
||||||
|
|
||||||
|
@ -610,6 +596,11 @@ op(int what)
|
||||||
b.u.d = (double)b.u.l;
|
b.u.d = (double)b.u.l;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (noeval) {
|
||||||
|
c.type = MN_INTEGER;
|
||||||
|
c.u.l = 0;
|
||||||
|
} else {
|
||||||
/*
|
/*
|
||||||
* type for operation: usually same as operands, but e.g.
|
* type for operation: usually same as operands, but e.g.
|
||||||
* (a == b) returns int.
|
* (a == b) returns int.
|
||||||
|
@ -740,11 +731,12 @@ op(int what)
|
||||||
c = b;
|
c = b;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (tp & (OP_E2|OP_E2IO)) {
|
if (tp & (OP_E2|OP_E2IO)) {
|
||||||
lv = stack[sp+1].lval;
|
lv = stack[sp+1].lval;
|
||||||
push(setvar(lv,c), lv);
|
push(setvar(lv,c), lv);
|
||||||
} else
|
} else
|
||||||
push(c,-1);
|
push(c,NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +748,7 @@ op(int what)
|
||||||
spval->type = MN_INTEGER;
|
spval->type = MN_INTEGER;
|
||||||
} else
|
} else
|
||||||
spval->u.l = !spval->u.l;
|
spval->u.l = !spval->u.l;
|
||||||
stack[sp].lval = -1;
|
stack[sp].lval = NULL;
|
||||||
break;
|
break;
|
||||||
case COMP:
|
case COMP:
|
||||||
if (spval->type & MN_FLOAT) {
|
if (spval->type & MN_FLOAT) {
|
||||||
|
@ -764,7 +756,7 @@ op(int what)
|
||||||
spval->type = MN_INTEGER;
|
spval->type = MN_INTEGER;
|
||||||
} else
|
} else
|
||||||
spval->u.l = ~spval->u.l;
|
spval->u.l = ~spval->u.l;
|
||||||
stack[sp].lval = -1;
|
stack[sp].lval = NULL;
|
||||||
break;
|
break;
|
||||||
case POSTPLUS:
|
case POSTPLUS:
|
||||||
a = *spval;
|
a = *spval;
|
||||||
|
@ -783,25 +775,22 @@ op(int what)
|
||||||
(void)setvar(stack[sp].lval, a);
|
(void)setvar(stack[sp].lval, a);
|
||||||
break;
|
break;
|
||||||
case UPLUS:
|
case UPLUS:
|
||||||
stack[sp].lval = -1;
|
stack[sp].lval = NULL;
|
||||||
break;
|
break;
|
||||||
case UMINUS:
|
case UMINUS:
|
||||||
if (spval->type & MN_FLOAT)
|
if (spval->type & MN_FLOAT)
|
||||||
spval->u.d = -spval->u.d;
|
spval->u.d = -spval->u.d;
|
||||||
else
|
else
|
||||||
spval->u.l = -spval->u.l;
|
spval->u.l = -spval->u.l;
|
||||||
stack[sp].lval = -1;
|
stack[sp].lval = NULL;
|
||||||
break;
|
break;
|
||||||
case QUEST:
|
case QUEST:
|
||||||
if (sp < 2) {
|
DPUTS(sp < 2, "BUG: math: three shall be the number of the counting.");
|
||||||
zerr("bad math expression: unbalanced stack", NULL, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
c = stack[sp--].val;
|
c = stack[sp--].val;
|
||||||
b = stack[sp--].val;
|
b = stack[sp--].val;
|
||||||
a = stack[sp--].val;
|
a = stack[sp--].val;
|
||||||
/* b and c can stay different types in this case. */
|
/* b and c can stay different types in this case. */
|
||||||
push(((a.type & MN_FLOAT) ? a.u.d : a.u.l) ? b : c, -1);
|
push(((a.type & MN_FLOAT) ? a.u.d : a.u.l) ? b : c, NULL);
|
||||||
break;
|
break;
|
||||||
case COLON:
|
case COLON:
|
||||||
break;
|
break;
|
||||||
|
@ -852,48 +841,41 @@ bop(int tk)
|
||||||
static mnumber
|
static mnumber
|
||||||
mathevall(char *s, int prek, char **ep)
|
mathevall(char *s, int prek, char **ep)
|
||||||
{
|
{
|
||||||
int t0;
|
int xlastbase, xnoeval, xunary;
|
||||||
int xlastbase, xnoeval, xunary, xlvc;
|
|
||||||
char *xptr;
|
char *xptr;
|
||||||
mnumber xyyval;
|
mnumber xyyval;
|
||||||
LV xyylval;
|
char *xyylval;
|
||||||
char **xlvals = 0, *nlvals[LVCOUNT];
|
|
||||||
int xsp;
|
int xsp;
|
||||||
struct mathvalue *xstack = 0, nstack[STACKSZ];
|
struct mathvalue *xstack = 0, nstack[STACKSZ];
|
||||||
mnumber ret;
|
mnumber ret;
|
||||||
|
|
||||||
|
MUSTUSEHEAP("mathevall");
|
||||||
if (mlevel++) {
|
if (mlevel++) {
|
||||||
xlastbase = lastbase;
|
xlastbase = lastbase;
|
||||||
xnoeval = noeval;
|
xnoeval = noeval;
|
||||||
xunary = unary;
|
xunary = unary;
|
||||||
xlvc = lvc;
|
|
||||||
xptr = ptr;
|
xptr = ptr;
|
||||||
xyyval = yyval;
|
xyyval = yyval;
|
||||||
xyylval = yylval;
|
xyylval = yylval;
|
||||||
xlvals = lvals;
|
|
||||||
|
|
||||||
xsp = sp;
|
xsp = sp;
|
||||||
xstack = stack;
|
xstack = stack;
|
||||||
} else {
|
} else {
|
||||||
xlastbase = xnoeval = xunary = xlvc = xyylval = xsp = 0;
|
xlastbase = xnoeval = xunary = xsp = 0;
|
||||||
xyyval.type = MN_INTEGER;
|
xyyval.type = MN_INTEGER;
|
||||||
xyyval.u.l = 0;
|
xyyval.u.l = 0;
|
||||||
|
xyylval = NULL;
|
||||||
xptr = NULL;
|
xptr = NULL;
|
||||||
}
|
}
|
||||||
stack = nstack;
|
stack = nstack;
|
||||||
lastbase = -1;
|
lastbase = -1;
|
||||||
memset(nlvals, 0, LVCOUNT*sizeof(char *));
|
|
||||||
lvals = nlvals;
|
|
||||||
lvc = 0;
|
|
||||||
ptr = s;
|
ptr = s;
|
||||||
sp = -1;
|
sp = -1;
|
||||||
unary = 1;
|
unary = 1;
|
||||||
mathparse(prek);
|
mathparse(prek);
|
||||||
*ep = ptr;
|
*ep = ptr;
|
||||||
if (sp)
|
DPUTS(!errflag && sp,
|
||||||
zerr("bad math expression: unbalanced stack", NULL, 0);
|
"BUG: math: wallabies roaming too freely in outback");
|
||||||
for (t0 = 0; t0 != lvc; t0++)
|
|
||||||
zsfree(lvals[t0]);
|
|
||||||
|
|
||||||
ret = stack[0].val;
|
ret = stack[0].val;
|
||||||
|
|
||||||
|
@ -901,11 +883,9 @@ mathevall(char *s, int prek, char **ep)
|
||||||
lastbase = xlastbase;
|
lastbase = xlastbase;
|
||||||
noeval = xnoeval;
|
noeval = xnoeval;
|
||||||
unary = xunary;
|
unary = xunary;
|
||||||
lvc = xlvc;
|
|
||||||
ptr = xptr;
|
ptr = xptr;
|
||||||
yyval = xyyval;
|
yyval = xyyval;
|
||||||
yylval = xyylval;
|
yylval = xyylval;
|
||||||
lvals = xlvals;
|
|
||||||
|
|
||||||
sp = xsp;
|
sp = xsp;
|
||||||
stack = xstack;
|
stack = xstack;
|
||||||
|
@ -964,9 +944,10 @@ mathevalarg(char *s, char **ss)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static void
|
static void
|
||||||
checkunary(int tp, char *ptr)
|
checkunary(int mtokc, char *ptr)
|
||||||
{
|
{
|
||||||
int errmsg = 0;
|
int errmsg = 0;
|
||||||
|
int tp = type[mtokc];
|
||||||
if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO|OP_OP)) {
|
if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO|OP_OP)) {
|
||||||
if (unary)
|
if (unary)
|
||||||
errmsg = 1;
|
errmsg = 1;
|
||||||
|
@ -1005,22 +986,22 @@ mathparse(int pc)
|
||||||
if (errflag)
|
if (errflag)
|
||||||
return;
|
return;
|
||||||
mtok = zzlex();
|
mtok = zzlex();
|
||||||
checkunary(type[mtok], optr);
|
checkunary(mtok, optr);
|
||||||
while (prec[mtok] <= pc) {
|
while (prec[mtok] <= pc) {
|
||||||
if (errflag)
|
if (errflag)
|
||||||
return;
|
return;
|
||||||
switch (mtok) {
|
switch (mtok) {
|
||||||
case NUM:
|
case NUM:
|
||||||
push(yyval, -1);
|
push(yyval, NULL);
|
||||||
break;
|
break;
|
||||||
case ID:
|
case ID:
|
||||||
push(getnparam(lvals[yylval]), yylval);
|
push(getnparam(yylval), yylval);
|
||||||
break;
|
break;
|
||||||
case CID:
|
case CID:
|
||||||
push(getcvar(yylval), yylval);
|
push(getcvar(yylval), yylval);
|
||||||
break;
|
break;
|
||||||
case FUNC:
|
case FUNC:
|
||||||
push(callmathfunc(lvals[yylval]), yylval);
|
push(callmathfunc(yylval), yylval);
|
||||||
break;
|
break;
|
||||||
case M_INPAR:
|
case M_INPAR:
|
||||||
mathparse(TOPPREC);
|
mathparse(TOPPREC);
|
||||||
|
@ -1036,10 +1017,15 @@ mathparse(int pc)
|
||||||
|
|
||||||
if (!q)
|
if (!q)
|
||||||
noeval++;
|
noeval++;
|
||||||
mathparse(prec[QUEST] - 1);
|
mathparse(prec[COLON] - 1);
|
||||||
if (!q)
|
if (!q)
|
||||||
noeval--;
|
noeval--;
|
||||||
else
|
if (mtok != COLON) {
|
||||||
|
if (!errflag)
|
||||||
|
zerr("':' expected", NULL, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (q)
|
||||||
noeval++;
|
noeval++;
|
||||||
mathparse(prec[QUEST]);
|
mathparse(prec[QUEST]);
|
||||||
if (q)
|
if (q)
|
||||||
|
@ -1058,6 +1044,6 @@ mathparse(int pc)
|
||||||
}
|
}
|
||||||
optr = ptr;
|
optr = ptr;
|
||||||
mtok = zzlex();
|
mtok = zzlex();
|
||||||
checkunary(type[mtok], optr);
|
checkunary(mtok, optr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue