about summary refs log tree commit diff
path: root/Src/math.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/math.c')
-rw-r--r--Src/math.c125
1 files changed, 48 insertions, 77 deletions
diff --git a/Src/math.c b/Src/math.c
index e044cbd9f..f91a58ea8 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -57,37 +57,24 @@ static int unary = 1;
  * RL = right-to-left associativity *
  * BOOL = short-circuiting boolean   */
 
-#define LR   0x0000
-#define RL   0x0001
-#define BOOL 0x0002
+#define LR 0
+#define RL 1
+#define BOOL 2
 
 #define MTYPE(x)  ((x) & 3)
 
 /*
- * OP_A2    2 arguments
- * OP_A2IR  2 arguments, return integer
- * OP_A2IO  2 arguments, must be integer, return integer
- * OP_E2    2 arguments with assignment
- * OP_E2IO  2 arguments with assignment, must be integer, return integer
- * OP_OP    None of the above, but occurs where we are expecting an operator
- *          rather than an operand.
- * OP_OPF   Followed by an operator, not an operand.
- *
- * OP_A2*, OP_E2*, OP_OP*:
- *   Occur when we need an operator; the next object must be an operand,
- *   unless OP_OPF is also supplied.
- *
- * Others:
- *   Occur when we need an operand; the next object must also be an operand,
- *   unless OP_OPF is also supplied.
+ * OP_A2 2 argument
+ * OP_A2IR 2 argument with return type integer
+ * OP_A2IO 2 arguments, must be integer, returning integer
+ * OP_E2 2 argument with assignment
+ * OP_E2IO 2 arguments with assignment, must be integer, return integer
  */
-#define OP_A2   0x0004
-#define OP_A2IR 0x0008
-#define OP_A2IO 0x0010
-#define OP_E2   0x0020
-#define OP_E2IO 0x0040
-#define OP_OP   0x0080
-#define OP_OPF  0x0100
+#define OP_A2   4
+#define OP_A2IR 8
+#define OP_A2IO 16
+#define OP_E2   32
+#define OP_E2IO 64
 
 #define M_INPAR 0
 #define M_OUTPAR 1
@@ -165,17 +152,17 @@ static int prec[TOKCOUNT] =
 
 static int type[TOKCOUNT] =
 {
-/*  0 */  LR, LR|OP_OP|OP_OPF, RL, RL, RL|OP_OP|OP_OPF,
-/*  5 */  RL|OP_OP|OP_OPF, RL, RL, LR|OP_A2IO, LR|OP_A2IO,
-/* 10 */  LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2IO, LR|OP_A2,
-/* 15 */  LR|OP_A2, LR|OP_A2IO, LR|OP_A2IO, LR|OP_A2IR, LR|OP_A2IR,
-/* 20 */  LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, BOOL|OP_A2IO,
-/* 25 */  BOOL|OP_A2IO, LR|OP_A2IO, RL|OP_OP, RL|OP_OP, RL|OP_E2,
-/* 30 */  RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2IO,
-/* 35 */  RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO,
-/* 40 */  BOOL|OP_E2IO, BOOL|OP_E2IO, RL|OP_A2IO, RL|OP_A2, RL|OP_OP,
-/* 45 */  RL, RL, LR|OP_OPF, LR|OP_OPF, RL|OP_A2,
-/* 50 */  LR|OP_OPF, RL|OP_E2
+/*  0 */    LR, LR, RL, RL, RL,
+/*  5 */    RL, RL, RL, LR|OP_A2IO, LR|OP_A2IO,
+/* 10 */    LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2IO, LR|OP_A2,
+/* 15 */    LR|OP_A2, LR|OP_A2IO, LR|OP_A2IO, LR|OP_A2IR, LR|OP_A2IR,
+/* 20 */    LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, BOOL|OP_A2IO,
+/* 25 */    BOOL|OP_A2IO, LR|OP_A2IO, RL, RL, RL|OP_E2,
+/* 30 */    RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2IO,
+/* 35 */    RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO,
+/* 40 */    BOOL|OP_E2IO, BOOL|OP_E2IO, RL|OP_A2IO, RL|OP_A2, RL,
+/* 45 */    RL, RL, LR, LR, RL|OP_A2,
+/* 50 */    LR, RL|OP_E2
 };
 
 #define LVCOUNT 32
@@ -201,6 +188,7 @@ zzlex(void)
 		return (unary) ? PREPLUS : POSTPLUS;
 	    }
 	    if (*ptr == '=') {
+		unary = 1;
 		ptr++;
 		return PLUSEQ;
 	    }
@@ -211,16 +199,19 @@ zzlex(void)
 		return (unary) ? PREMINUS : POSTMINUS;
 	    }
 	    if (*ptr == '=') {
+		unary = 1;
 		ptr++;
 		return MINUSEQ;
 	    }
 	    return (unary) ? UMINUS : MINUS;
 	case '(':
+	    unary = 1;
 	    return M_INPAR;
 	case ')':
 	    return M_OUTPAR;
 	case '!':
 	    if (*ptr == '=') {
+		unary = 1;
 		ptr++;
 		return NEQ;
 	    }
@@ -228,6 +219,7 @@ zzlex(void)
 	case '~':
 	    return COMP;
 	case '&':
+	    unary = 1;
 	    if (*ptr == '&') {
 		if (*++ptr == '=') {
 		    ptr++;
@@ -240,6 +232,7 @@ zzlex(void)
 	    }
 	    return AND;
 	case '|':
+	    unary = 1;
 	    if (*ptr == '|') {
 		if (*++ptr == '=') {
 		    ptr++;
@@ -252,6 +245,7 @@ zzlex(void)
 	    }
 	    return OR;
 	case '^':
+	    unary = 1;
 	    if (*ptr == '^') {
 		if (*++ptr == '=') {
 		    ptr++;
@@ -264,6 +258,7 @@ zzlex(void)
 	    }
 	    return XOR;
 	case '*':
+	    unary = 1;
 	    if (*ptr == '*') {
 		if (*++ptr == '=') {
 		    ptr++;
@@ -277,18 +272,21 @@ zzlex(void)
 	    }
 	    return MUL;
 	case '/':
+	    unary = 1;
 	    if (*ptr == '=') {
 		ptr++;
 		return DIVEQ;
 	    }
 	    return DIV;
 	case '%':
+	    unary = 1;
 	    if (*ptr == '=') {
 		ptr++;
 		return MODEQ;
 	    }
 	    return MOD;
 	case '<':
+	    unary = 1;
 	    if (*ptr == '<') {
 		if (*++ptr == '=') {
 		    ptr++;
@@ -301,6 +299,7 @@ zzlex(void)
 	    }
 	    return LES;
 	case '>':
+	    unary = 1;
 	    if (*ptr == '>') {
 		if (*++ptr == '=') {
 		    ptr++;
@@ -313,12 +312,14 @@ zzlex(void)
 	    }
 	    return GRE;
 	case '=':
+	    unary = 1;
 	    if (*ptr == '=') {
 		ptr++;
 		return DEQ;
 	    }
 	    return EQ;
 	case '$':
+	    unary = 0;
 	    yyval.u.l = mypid;
 	    return NUM;
 	case '?':
@@ -327,15 +328,20 @@ zzlex(void)
 		unary = 0;
 		return NUM;
 	    }
+	    unary = 1;
 	    return QUEST;
 	case ':':
+	    unary = 1;
 	    return COLON;
 	case ',':
+	    unary = 1;
 	    return COMMA;
 	case '\0':
+	    unary = 1;
 	    ptr--;
 	    return EOI;
 	case '[':
+	    unary = 0;
 	    {
 		int base = zstrtol(ptr, &ptr, 10);
 
@@ -350,6 +356,7 @@ zzlex(void)
 	    break;
 	case '0':
 	    if (*ptr == 'x' || *ptr == 'X') {
+		unary = 0;
 		/* Should we set lastbase here? */
 		yyval.u.l = zstrtol(++ptr, &ptr, lastbase = 16);
 		return NUM;
@@ -358,6 +365,7 @@ zzlex(void)
 	default:
 	    if (idigit(*--ptr) || *ptr == '.') {
 		char *nptr;
+		unary = 0;
 		for (nptr = ptr; idigit(*nptr); nptr++);
 
 		if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') {
@@ -387,6 +395,7 @@ zzlex(void)
 		    ptr++;
 		    ptr = getkeystring(ptr, NULL, 6, &v);
 		    yyval.u.l = v;
+		    unary = 0;
 		    return NUM;
 		}
 		cct = 1;
@@ -399,6 +408,7 @@ zzlex(void)
 		    zerr("too many identifiers (complain to author)", NULL, 0);
 		    return EOI;
 		}
+		unary = 0;
 		while (iident(*++ptr));
 		if (*ptr == '[') {
 		    int l;
@@ -419,6 +429,7 @@ zzlex(void)
 	    }
 	    else if (cct) {
 		yyval.u.l = poundgetfn(NULL);
+		unary = 0;
 		return NUM;
 	    }
 	    return EOI;
@@ -504,8 +515,6 @@ op(int what)
     LV lv;
     int tp = type[what];
 
-    if (errflag)
-	return;
     if (sp < 0) {
 	zerr("bad math expression: stack empty", NULL, 0);
 	return;
@@ -895,40 +904,6 @@ mathevalarg(char *s, char **ss)
     return (x.type & MN_FLOAT) ? (zlong)x.u.d : x.u.l;
 }
 
-/*
- * Make sure we have an operator or an operand, whatever is expected.
- * For this purpose, unary operators constitute part of an operand.
- */
-
-/**/
-static void
-checkunary(int tp, char *ptr)
-{
-    int errmsg = 0;
-    if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO|OP_OP)) {
-	if (unary)
-	    errmsg = 1;
-    } else {
-	if (!unary)
-	    errmsg = 2;
-    }
-    if (errmsg) {
-	char errbuf[40];
-	int len, over = 0;
-	while (inblank(*ptr))
-	    ptr++;
-	len = strlen(ptr);
-	if (len > 10) {
-	    len = 10;
-	    over = 1;
-	}
-	sprintf(errbuf, "bad math expression: %s expected at `%%l%s'",
-		errmsg == 2 ? "operator" : "operand",
-		over ? "..." : ""); 
-	zerr(errbuf, ptr, len);
-    }
-    unary = !(tp & OP_OPF);
-}
 
 /* operator-precedence parse the string and execute */
 
@@ -938,12 +913,10 @@ mathparse(int pc)
 {
     zlong q;
     int otok, onoeval;
-    char *optr = ptr;
 
     if (errflag)
 	return;
     mtok = zzlex();
-    checkunary(type[mtok], optr);
     while (prec[mtok] <= pc) {
 	if (errflag)
 	    return;
@@ -991,8 +964,6 @@ mathparse(int pc)
 	    op(otok);
 	    continue;
 	}
-	optr = ptr;
 	mtok = zzlex();
-	checkunary(type[mtok], optr);
     }
 }