Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: pws-3.1.6-pws-5: yet more math changes
- X-seq: zsh-workers 7981
- From: Peter Stephenson <pws@xxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx (Zsh hackers list)
- Subject: PATCH: pws-3.1.6-pws-5: yet more math changes
- Date: Tue, 21 Sep 1999 14:50:31 +0200
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
While I'm still on the case, here are some more tweaks to math evaluation.
- The stack of lvalues was clumsy. I've just dupstring'ed them and
stuck the pointer straight into where the LV used to go. (The change
to zsh.h just deletes the LV type, which only affected math.c anyway.)
It's a little known fact that dupstring() is affected by
PERMALLOC/HEAPALLOC, so there's a MUSTUSEHEAP in mathevall()
(callmathfunc() makes this a good idea for the same reason).
- Since I'm hoping the old `unbalanced stack' messages are now unnecessary,
I've removed them as ordinary errors and turned them into wacky debugging
messages so they'll got reported (in theory) and (in theory) fixed.
- The expression `3 ? 2 ? 1' was accepted instead of `3 ? 2 : 1'. I've
made the test stricter. Actually, since a ? in a position where a number
was expected turned into $?, the expression (( ? ? ? ? ? )) was valid
syntax. Now the second last `?' must be a `:'. Note that this means that:
(( 3 ? a = 2 : b = 3 ))
gives
zsh: ':' expected
and you have to use
(( 3 ? (a = 2) : (b = 3) ))
is this OK? I haven't changed the precedence, so it stops parsing where
it always did at the `=', except the old error message was `lvalue
required'.
- I previously introduced a slight bug with `?' because it changed the
value of unary at the wrong point.
- (( 1 ? 2 : 3/0 ))
zsh: division by zero
Not --- at least by usual shell rules, that shouldn't happen. I've
reduced the amount that gets done when not evaluating, while still
trying to keep the syntax checking as strict as before. This involved
re-indenting a large chunk, sorry.
--- Src/math.c.m3 Tue Sep 21 11:25:31 1999
+++ Src/math.c Tue Sep 21 14:23:59 1999
@@ -45,7 +45,7 @@
static char *ptr;
static mnumber yyval;
-static LV yylval;
+static char *yylval;
static int mlevel = 0;
@@ -153,12 +153,12 @@
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 @@
/* 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 @@
case '?':
if (unary) {
yyval.u.l = lastval;
- unary = 0;
return NUM;
}
return QUEST;
@@ -397,10 +389,6 @@
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 @@
}
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 sp = -1; /* stack pointer */
struct mathvalue {
- LV lval;
+ char *lval;
mnumber val;
};
@@ -444,7 +432,7 @@
/**/
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 @@
/**/
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 @@
/**/
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 @@
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 @@
op(int what)
{
mnumber a, b, c, *spval;
- LV lv;
+ char *lv;
int tp = type[what];
if (errflag)
@@ -574,10 +562,8 @@
}
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 @@
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 @@
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 @@
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 @@
(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 @@
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 @@
lastbase = xlastbase;
noeval = xnoeval;
unary = xunary;
- lvc = xlvc;
ptr = xptr;
yyval = xyyval;
yylval = xyylval;
- lvals = xlvals;
sp = xsp;
stack = xstack;
@@ -964,9 +944,10 @@
/**/
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 @@
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 @@
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 @@
}
optr = ptr;
mtok = zzlex();
- checkunary(type[mtok], optr);
+ checkunary(mtok, optr);
}
}
--
Peter Stephenson <pws@xxxxxxxxxxxxxxxxx> Tel: +39 050 844536
WWW: http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy
Messages sorted by:
Reverse Date,
Date,
Thread,
Author