summaryrefslogtreecommitdiffstats
path: root/Src/math.c
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-09-22 13:10:37 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-09-22 13:10:37 +0000
commit9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f (patch)
treee824561d8a4acdbc2c9222425127e53e7f948998 /Src/math.c
parentzsh-workers/7978 (diff)
downloadzsh-9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f.tar
zsh-9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f.tar.gz
zsh-9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f.tar.bz2
zsh-9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f.tar.lz
zsh-9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f.tar.xz
zsh-9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f.tar.zst
zsh-9878bf492b9a93e7eae5dfd330dbe3f6a8a61b6f.zip
zsh-workers/7981
Diffstat (limited to 'Src/math.c')
-rw-r--r--Src/math.c364
1 files changed, 175 insertions, 189 deletions
diff --git a/Src/math.c b/Src/math.c
index 3fb741854..836e0c671 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -45,7 +45,7 @@ int lastbase;
static char *ptr;
static mnumber yyval;
-static LV yylval;
+static char *yylval;
static int mlevel = 0;
@@ -153,12 +153,12 @@ static int prec[TOKCOUNT] =
6, 8, 8, 8, 9,
9, 3, 3, 10, 10,
10, 10, 11, 11, 12,
- 13, 13, 14, 14, 15,
- 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15,
- 15, 15, 15, 16, 200,
+ 13, 13, 14, 15, 16,
+ 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16,
+ 16, 16, 16, 17, 200,
2, 2, 0, 0, 7,
- 0, 15, 0
+ 0, 16, 0
};
#define TOPPREC 16
@@ -179,13 +179,6 @@ static int type[TOKCOUNT] =
/* 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
@@ -325,7 +318,6 @@ zzlex(void)
case '?':
if (unary) {
yyval.u.l = lastval;
- unary = 0;
return NUM;
}
return QUEST;
@@ -397,10 +389,6 @@ zzlex(void)
char *p, q;
p = ptr;
- if (lvc == LVCOUNT) {
- zerr("too many identifiers (complain to author)", NULL, 0);
- return EOI;
- }
while (iident(*++ptr));
if (*ptr == '[' || (!cct && *ptr == '(')) {
char op = *ptr, cp = ((*ptr == '[') ? ']' : ')');
@@ -417,7 +405,7 @@ zzlex(void)
}
q = *ptr;
*ptr = '\0';
- lvals[yylval = lvc++] = ztrdup(p);
+ yylval = dupstring(p);
*ptr = q;
return (func ? FUNC : (cct ? CID : ID));
}
@@ -436,7 +424,7 @@ static int mtok; /* last token */
static int sp = -1; /* stack pointer */
struct mathvalue {
- LV lval;
+ char *lval;
mnumber val;
};
@@ -444,7 +432,7 @@ static struct mathvalue *stack;
/**/
static void
-push(mnumber val, LV lval)
+push(mnumber val, char *lval)
{
if (sp == STACKSZ - 1)
zerr("stack overflow", NULL, 0);
@@ -457,13 +445,13 @@ push(mnumber val, LV lval)
/**/
static mnumber
-getcvar(LV s)
+getcvar(char *s)
{
char *t;
mnumber mn;
mn.type = MN_INTEGER;
- if (!(t = getsparam(lvals[s])))
+ if (!(t = getsparam(s)))
mn.u.l = 0;
else
mn.u.l = STOUC(*t == Meta ? t[1] ^ 32 : *t);
@@ -473,16 +461,16 @@ getcvar(LV s)
/**/
static mnumber
-setvar(LV s, mnumber v)
+setvar(char *s, mnumber v)
{
- if (s == -1 || s >= lvc) {
+ if (!s) {
zerr("lvalue required", NULL, 0);
v.type = MN_INTEGER;
v.u.l = 0;
}
if (noeval)
return v;
- setnparam(lvals[s], v);
+ setnparam(s, v);
return v;
}
@@ -507,7 +495,7 @@ callmathfunc(char *o)
return f->sfunc(n, a, f->funcid);
else {
int argc = 0;
- mnumber *argv, *q;
+ mnumber *argv = NULL, *q;
LinkList l = newlinklist();
LinkNode node;
char *p;
@@ -563,7 +551,7 @@ void
op(int what)
{
mnumber a, b, c, *spval;
- LV lv;
+ char *lv;
int tp = type[what];
if (errflag)
@@ -574,10 +562,8 @@ op(int what)
}
if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO)) {
- if (sp < 1) {
- zerr("bad math expression: unbalanced stack", NULL, 0); \
- return;
- }
+ /* Make sure anyone seeing this message reports it. */
+ DPUTS(sp < 1, "BUG: math: not enough wallabies in outback.");
b = stack[sp--].val;
a = stack[sp--].val;
@@ -610,141 +596,147 @@ op(int what)
b.u.d = (double)b.u.l;
}
}
- /*
- * type for operation: usually same as operands, but e.g.
- * (a == b) returns int.
- */
- c.type = (tp & OP_A2IR) ? MN_INTEGER : a.type;
- switch(what) {
- case AND:
- case ANDEQ:
- c.u.l = a.u.l & b.u.l;
- break;
- case XOR:
- case XOREQ:
- c.u.l = a.u.l ^ b.u.l;
- break;
- case OR:
- case OREQ:
- c.u.l = a.u.l | b.u.l;
- break;
- case MUL:
- case MULEQ:
- if (c.type == MN_FLOAT)
- c.u.d = a.u.d * b.u.d;
- else
- c.u.l = a.u.l * b.u.l;
- break;
- case DIV:
- case DIVEQ:
- if (!notzero(b))
- return;
- if (c.type == MN_FLOAT)
- c.u.d = a.u.d / b.u.d;
- else
- c.u.l = a.u.l / b.u.l;
- break;
- case MOD:
- case MODEQ:
- if (!notzero(b))
- return;
- c.u.l = a.u.l % b.u.l;
- break;
- case PLUS:
- case PLUSEQ:
- if (c.type == MN_FLOAT)
- c.u.d = a.u.d + b.u.d;
- else
- c.u.l = a.u.l + b.u.l;
- break;
- case MINUS:
- case MINUSEQ:
- if (c.type == MN_FLOAT)
- c.u.d = a.u.d - b.u.d;
- else
- c.u.l = a.u.l - b.u.l;
- break;
- case SHLEFT:
- case SHLEFTEQ:
- c.u.l = a.u.l << b.u.l;
- break;
- case SHRIGHT:
- case SHRIGHTEQ:
- c.u.l = a.u.l >> b.u.l;
- break;
- case LES:
- c.u.l = (zlong)
- (a.type == MN_FLOAT ? (a.u.d < b.u.d) : (a.u.l < b.u.l));
- break;
- case LEQ:
- c.u.l = (zlong)
- (a.type == MN_FLOAT ? (a.u.d <= b.u.d) : (a.u.l <= b.u.l));
- break;
- case GRE:
- c.u.l = (zlong)
- (a.type == MN_FLOAT ? (a.u.d > b.u.d) : (a.u.l > b.u.l));
- break;
- case GEQ:
- c.u.l = (zlong)
- (a.type == MN_FLOAT ? (a.u.d >= b.u.d) : (a.u.l >= b.u.l));
- break;
- case DEQ:
- c.u.l = (zlong)
- (a.type == MN_FLOAT ? (a.u.d == b.u.d) : (a.u.l == b.u.l));
- break;
- case NEQ:
- c.u.l = (zlong)
- (a.type == MN_FLOAT ? (a.u.d != b.u.d) : (a.u.l != b.u.l));
- break;
- case DAND:
- case DANDEQ:
- c.u.l = (zlong)(a.u.l && b.u.l);
- break;
- case DOR:
- case DOREQ:
- c.u.l = (zlong)(a.u.l || b.u.l);
- break;
- case DXOR:
- case DXOREQ:
- c.u.l = (zlong)((a.u.l && !b.u.l) || (!a.u.l && b.u.l));
- break;
- case COMMA:
- c = b;
- break;
- case POWER:
- case POWEREQ:
- if (c.type == MN_INTEGER && b.u.l < 0) {
- /* produces a real result, so cast to real. */
- a.type = b.type = c.type = MN_FLOAT;
- a.u.d = (double) a.u.l;
- b.u.d = (double) b.u.l;
- }
- if (c.type == MN_INTEGER) {
- for (c.u.l = 1; b.u.l--; c.u.l *= a.u.l);
- } else {
- if (b.u.d <= 0 && !notzero(a))
+ if (noeval) {
+ c.type = MN_INTEGER;
+ c.u.l = 0;
+ } else {
+ /*
+ * type for operation: usually same as operands, but e.g.
+ * (a == b) returns int.
+ */
+ c.type = (tp & OP_A2IR) ? MN_INTEGER : a.type;
+
+ switch(what) {
+ case AND:
+ case ANDEQ:
+ c.u.l = a.u.l & b.u.l;
+ break;
+ case XOR:
+ case XOREQ:
+ c.u.l = a.u.l ^ b.u.l;
+ break;
+ case OR:
+ case OREQ:
+ c.u.l = a.u.l | b.u.l;
+ break;
+ case MUL:
+ case MULEQ:
+ if (c.type == MN_FLOAT)
+ c.u.d = a.u.d * b.u.d;
+ else
+ c.u.l = a.u.l * b.u.l;
+ break;
+ case DIV:
+ case DIVEQ:
+ if (!notzero(b))
+ return;
+ if (c.type == MN_FLOAT)
+ c.u.d = a.u.d / b.u.d;
+ else
+ c.u.l = a.u.l / b.u.l;
+ break;
+ case MOD:
+ case MODEQ:
+ if (!notzero(b))
return;
- if (a.u.d < 0) {
- /* Error if (-num ** b) and b is not an integer */
- double tst = (double)(zlong)b.u.d;
- if (tst != b.u.d) {
- zerr("imaginary power", NULL, 0);
+ c.u.l = a.u.l % b.u.l;
+ break;
+ case PLUS:
+ case PLUSEQ:
+ if (c.type == MN_FLOAT)
+ c.u.d = a.u.d + b.u.d;
+ else
+ c.u.l = a.u.l + b.u.l;
+ break;
+ case MINUS:
+ case MINUSEQ:
+ if (c.type == MN_FLOAT)
+ c.u.d = a.u.d - b.u.d;
+ else
+ c.u.l = a.u.l - b.u.l;
+ break;
+ case SHLEFT:
+ case SHLEFTEQ:
+ c.u.l = a.u.l << b.u.l;
+ break;
+ case SHRIGHT:
+ case SHRIGHTEQ:
+ c.u.l = a.u.l >> b.u.l;
+ break;
+ case LES:
+ c.u.l = (zlong)
+ (a.type == MN_FLOAT ? (a.u.d < b.u.d) : (a.u.l < b.u.l));
+ break;
+ case LEQ:
+ c.u.l = (zlong)
+ (a.type == MN_FLOAT ? (a.u.d <= b.u.d) : (a.u.l <= b.u.l));
+ break;
+ case GRE:
+ c.u.l = (zlong)
+ (a.type == MN_FLOAT ? (a.u.d > b.u.d) : (a.u.l > b.u.l));
+ break;
+ case GEQ:
+ c.u.l = (zlong)
+ (a.type == MN_FLOAT ? (a.u.d >= b.u.d) : (a.u.l >= b.u.l));
+ break;
+ case DEQ:
+ c.u.l = (zlong)
+ (a.type == MN_FLOAT ? (a.u.d == b.u.d) : (a.u.l == b.u.l));
+ break;
+ case NEQ:
+ c.u.l = (zlong)
+ (a.type == MN_FLOAT ? (a.u.d != b.u.d) : (a.u.l != b.u.l));
+ break;
+ case DAND:
+ case DANDEQ:
+ c.u.l = (zlong)(a.u.l && b.u.l);
+ break;
+ case DOR:
+ case DOREQ:
+ c.u.l = (zlong)(a.u.l || b.u.l);
+ break;
+ case DXOR:
+ case DXOREQ:
+ c.u.l = (zlong)((a.u.l && !b.u.l) || (!a.u.l && b.u.l));
+ break;
+ case COMMA:
+ c = b;
+ break;
+ case POWER:
+ case POWEREQ:
+ if (c.type == MN_INTEGER && b.u.l < 0) {
+ /* produces a real result, so cast to real. */
+ a.type = b.type = c.type = MN_FLOAT;
+ a.u.d = (double) a.u.l;
+ b.u.d = (double) b.u.l;
+ }
+ if (c.type == MN_INTEGER) {
+ for (c.u.l = 1; b.u.l--; c.u.l *= a.u.l);
+ } else {
+ if (b.u.d <= 0 && !notzero(a))
return;
+ if (a.u.d < 0) {
+ /* Error if (-num ** b) and b is not an integer */
+ double tst = (double)(zlong)b.u.d;
+ if (tst != b.u.d) {
+ zerr("imaginary power", NULL, 0);
+ return;
+ }
}
+ c.u.d = pow(a.u.d, b.u.d);
}
- c.u.d = pow(a.u.d, b.u.d);
+ break;
+ case EQ:
+ c = b;
+ break;
}
- break;
- case EQ:
- c = b;
- break;
}
if (tp & (OP_E2|OP_E2IO)) {
lv = stack[sp+1].lval;
push(setvar(lv,c), lv);
} else
- push(c,-1);
+ push(c,NULL);
return;
}
@@ -756,7 +748,7 @@ op(int what)
spval->type = MN_INTEGER;
} else
spval->u.l = !spval->u.l;
- stack[sp].lval = -1;
+ stack[sp].lval = NULL;
break;
case COMP:
if (spval->type & MN_FLOAT) {
@@ -764,7 +756,7 @@ op(int what)
spval->type = MN_INTEGER;
} else
spval->u.l = ~spval->u.l;
- stack[sp].lval = -1;
+ stack[sp].lval = NULL;
break;
case POSTPLUS:
a = *spval;
@@ -783,25 +775,22 @@ op(int what)
(void)setvar(stack[sp].lval, a);
break;
case UPLUS:
- stack[sp].lval = -1;
+ stack[sp].lval = NULL;
break;
case UMINUS:
if (spval->type & MN_FLOAT)
spval->u.d = -spval->u.d;
else
spval->u.l = -spval->u.l;
- stack[sp].lval = -1;
+ stack[sp].lval = NULL;
break;
case QUEST:
- if (sp < 2) {
- zerr("bad math expression: unbalanced stack", NULL, 0);
- return;
- }
+ DPUTS(sp < 2, "BUG: math: three shall be the number of the counting.");
c = stack[sp--].val;
b = stack[sp--].val;
a = stack[sp--].val;
/* 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;
case COLON:
break;
@@ -852,48 +841,41 @@ bop(int tk)
static mnumber
mathevall(char *s, int prek, char **ep)
{
- int t0;
- int xlastbase, xnoeval, xunary, xlvc;
+ int xlastbase, xnoeval, xunary;
char *xptr;
mnumber xyyval;
- LV xyylval;
- char **xlvals = 0, *nlvals[LVCOUNT];
+ char *xyylval;
int xsp;
struct mathvalue *xstack = 0, nstack[STACKSZ];
mnumber ret;
+ MUSTUSEHEAP("mathevall");
if (mlevel++) {
xlastbase = lastbase;
xnoeval = noeval;
xunary = unary;
- xlvc = lvc;
xptr = ptr;
xyyval = yyval;
xyylval = yylval;
- xlvals = lvals;
xsp = sp;
xstack = stack;
} else {
- xlastbase = xnoeval = xunary = xlvc = xyylval = xsp = 0;
+ xlastbase = xnoeval = xunary = xsp = 0;
xyyval.type = MN_INTEGER;
xyyval.u.l = 0;
+ xyylval = NULL;
xptr = NULL;
}
stack = nstack;
lastbase = -1;
- memset(nlvals, 0, LVCOUNT*sizeof(char *));
- lvals = nlvals;
- lvc = 0;
ptr = s;
sp = -1;
unary = 1;
mathparse(prek);
*ep = ptr;
- if (sp)
- zerr("bad math expression: unbalanced stack", NULL, 0);
- for (t0 = 0; t0 != lvc; t0++)
- zsfree(lvals[t0]);
+ DPUTS(!errflag && sp,
+ "BUG: math: wallabies roaming too freely in outback");
ret = stack[0].val;
@@ -901,11 +883,9 @@ mathevall(char *s, int prek, char **ep)
lastbase = xlastbase;
noeval = xnoeval;
unary = xunary;
- lvc = xlvc;
ptr = xptr;
yyval = xyyval;
yylval = xyylval;
- lvals = xlvals;
sp = xsp;
stack = xstack;
@@ -964,9 +944,10 @@ mathevalarg(char *s, char **ss)
/**/
static void
-checkunary(int tp, char *ptr)
+checkunary(int mtokc, char *ptr)
{
int errmsg = 0;
+ int tp = type[mtokc];
if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO|OP_OP)) {
if (unary)
errmsg = 1;
@@ -1005,22 +986,22 @@ mathparse(int pc)
if (errflag)
return;
mtok = zzlex();
- checkunary(type[mtok], optr);
+ checkunary(mtok, optr);
while (prec[mtok] <= pc) {
if (errflag)
return;
switch (mtok) {
case NUM:
- push(yyval, -1);
+ push(yyval, NULL);
break;
case ID:
- push(getnparam(lvals[yylval]), yylval);
+ push(getnparam(yylval), yylval);
break;
case CID:
push(getcvar(yylval), yylval);
break;
case FUNC:
- push(callmathfunc(lvals[yylval]), yylval);
+ push(callmathfunc(yylval), yylval);
break;
case M_INPAR:
mathparse(TOPPREC);
@@ -1036,10 +1017,15 @@ mathparse(int pc)
if (!q)
noeval++;
- mathparse(prec[QUEST] - 1);
+ mathparse(prec[COLON] - 1);
if (!q)
noeval--;
- else
+ if (mtok != COLON) {
+ if (!errflag)
+ zerr("':' expected", NULL, 0);
+ return;
+ }
+ if (q)
noeval++;
mathparse(prec[QUEST]);
if (q)
@@ -1058,6 +1044,6 @@ mathparse(int pc)
}
optr = ptr;
mtok = zzlex();
- checkunary(type[mtok], optr);
+ checkunary(mtok, optr);
}
}