changeset 249:1f1a28b797e1

Add trap for divide by zero in expression library Added a trap for division by zero in the expression library and adjusted lwasm to use it and report division by zero errors instead of crashing with a cryptic "arithmetic exception" or even more mysterious "floating point exception".
author William Astle <lost@l-w.ca>
date Fri, 25 Jan 2013 21:48:01 -0700
parents 891bab942b5a
children 644f8abf87dc
files lwasm/lwasm.c lwasm/main.c lwlib/lw_expr.c lwlib/lw_expr.h
diffstat 4 files changed, 37 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/lwasm.c	Thu Jan 24 21:24:32 2013 -0700
+++ b/lwasm/lwasm.c	Fri Jan 25 21:48:01 2013 -0700
@@ -44,6 +44,12 @@
 	return 0;
 }
 
+void lwasm_dividezero(void *priv)
+{
+	asmstate_t *as = (asmstate_t *)priv;
+	lwasm_register_error(as, as -> cl, "Division by zero");
+}
+
 lw_expr_t lwasm_evaluate_var(char *var, void *priv)
 {
 	asmstate_t *as = (asmstate_t *)priv;
--- a/lwasm/main.c	Thu Jan 24 21:24:32 2013 -0700
+++ b/lwasm/main.c	Fri Jan 25 21:48:01 2013 -0700
@@ -222,6 +222,7 @@
 extern lw_expr_t lwasm_evaluate_special(int t, void *ptr, void *priv);
 extern lw_expr_t lwasm_evaluate_var(char *var, void *priv);
 extern lw_expr_t lwasm_parse_term(char **p, void *priv);
+extern void lwasm_dividezero(void *priv);
 
 struct passlist_s
 {
@@ -251,6 +252,7 @@
 	lw_expr_set_special_handler(lwasm_evaluate_special);
 	lw_expr_set_var_handler(lwasm_evaluate_var);
 	lw_expr_set_term_parser(lwasm_parse_term);
+	lw_expr_setdivzero(lwasm_dividezero);
 
 	/* initialize assembler state */
 	asmstate.include_list = lw_stringlist_create();
--- a/lwlib/lw_expr.c	Thu Jan 24 21:24:32 2013 -0700
+++ b/lwlib/lw_expr.c	Fri Jan 25 21:48:01 2013 -0700
@@ -38,6 +38,21 @@
 static int level = 0;
 static int bailing = 0;
 
+static void (*divzero)(void *priv) = NULL;
+
+void lw_expr_setdivzero(void (*fn)(void *priv))
+{
+	divzero = fn;
+}
+
+static void lw_expr_divzero(void *priv)
+{
+	if (divzero)
+		(*divzero)(priv);
+	else
+		fprintf(stderr, "Divide by zero in lw_expr!\n");
+}
+
 int lw_expr_istype(lw_expr_t e, int t)
 {
 	/* NULL expression is never of any type */
@@ -719,6 +734,12 @@
 			break;
 
 		case lw_expr_oper_divide:
+			if (E -> operands -> next -> p -> value == 0)
+			{
+				tr = 0;
+				lw_expr_divzero(priv);
+				break;
+			}
 			tr = E -> operands -> p -> value / E -> operands -> next -> p -> value;
 			break;
 		
@@ -727,6 +748,12 @@
 			break;
 		
 		case lw_expr_oper_intdiv:
+			if (E -> operands -> next -> p -> value == 0)
+			{
+				tr = 0;
+				lw_expr_divzero(priv);
+				break;
+			}
 			tr = E -> operands -> p -> value / E -> operands -> next -> p -> value;
 			break;
 
--- a/lwlib/lw_expr.h	Thu Jan 24 21:24:32 2013 -0700
+++ b/lwlib/lw_expr.h	Fri Jan 25 21:48:01 2013 -0700
@@ -112,6 +112,8 @@
 // zero
 extern int lw_expr_testterms(lw_expr_t e, lw_expr_testfn_t *fn, void *priv);
 
+extern void lw_expr_setdivzero(void (*fn)(void *priv));
+
 #endif /* def ___lw_expr_c_seen___ */
 
 #endif /* ___lw_expr_h_seen___ */