# HG changeset patch # User William Astle # Date 1359175681 25200 # Node ID 1f1a28b797e12f09b3f271f5b2a82f13574101dc # Parent 891bab942b5a457ec902c9f57e29a574fe713e64 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". diff -r 891bab942b5a -r 1f1a28b797e1 lwasm/lwasm.c --- 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; diff -r 891bab942b5a -r 1f1a28b797e1 lwasm/main.c --- 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(); diff -r 891bab942b5a -r 1f1a28b797e1 lwlib/lw_expr.c --- 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; diff -r 891bab942b5a -r 1f1a28b797e1 lwlib/lw_expr.h --- 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___ */