bug-gawk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: evaluating "&&" order with div by zero in subsequent part.


From: arnold
Subject: Re: evaluating "&&" order with div by zero in subsequent part.
Date: Sun, 14 Aug 2022 09:07:37 -0600
User-agent: Heirloom mailx 12.5 7/5/10

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:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]