Hi Ed.
Ed Morton<mortoneccc@comcast.net> wrote:
There's some inconsistency in the following division by zero treatment
(gawk 5.1.1 on cygwin):
...
but then if we swap denominator $0 which has value 0 with literal 0:
$ echo 0 | awk '{ print (0 && (4/0)) }'
awk: cmd. line:1: error: division by zero attempted
and if we then put parens around the numerator 4 and leave the
denominator 0:
$ echo 0 | awk '{ print (0 && ((4)/0)) }'
0
OK. This has do with gawk's "optimization" which involves VERY simple
constant folding. Gawk turns something like `x = 3 * 15' into `x = 15'
(except when pretty printing).
In the first case, both sides of the `/' are constant, and it checks
that the denominator of `/' is zero and produces an error.
In the second case, `(4)' is an expression, not a constant, and it
simply generated code to do the division, without checking for zero.
The patch below fixes that; now no matter what the numerator, if the
denominator of `/' or `%' is zero, it will produce an error.
As to the fact that `0 && ...' guards the division, gawk isn't that
smart. There are lots of optimization techniques known in the compiler
world that gawk doesn't implement, since they're complicated and not
worth the trouble, such as dead code elimination:
if (0)
stuff1
else
stuff2
Optmizing compilers would only generate code for `stuff2' in such
a case.
This fix will make it's way into Git shortly.
Thanks,
Arnold
-----------------------------------------------------
diff --git a/awkgram.y b/awkgram.y
index 36cac704..e2a3d21b 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -5533,9 +5533,21 @@ mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION
*op)
op->opcode = Op_times_i;
break;
case Op_quotient:
+ if (ip2->memory->numbr == 0.0) {
+ /* don't fatalize, allow parsing rest
of the input */
+ error_ln(op->source_line, _("division by
zero attempted"));
+ goto regular;
+ }
+
op->opcode = Op_quotient_i;
break;
case Op_mod:
+ if (ip2->memory->numbr == 0.0) {
+ /* don't fatalize, allow parsing rest
of the input */
+ error_ln(op->source_line, _("division by
zero attempted in `%%'"));
+ goto regular;
+ }
+
op->opcode = Op_mod_i;
break;
case Op_plus: