Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: pws-3.1.6-pws-5: yet more math changes



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