bug-gawk
[Top][All Lists]
Advanced

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

Re: [bug-gawk] pretty-print eats parentheses


From: Aharon Robbins
Subject: Re: [bug-gawk] pretty-print eats parentheses
Date: Thu, 30 Oct 2014 21:38:17 +0200
User-agent: Heirloom mailx 12.5 6/20/10

Hi.  Thanks for the reports. Fix below.  This was interesting.

First, our test file:

        $ cat x.awk
        BEGIN {
                x = 3
                print -(-x)
                Q = "|"
                print -3 Q (-4)
                print -3 Q (-4) (-5)
        }

Now a run with released gawk:

        $ gawk-4.1.1 -o/dev/stdout -f x.awk
        3
        -3|-4
        -3|-4-5
                # gawk profile, created Thu Oct 30 21:35:24 2014

                # BEGIN block(s)

                BEGIN {
                        x = 3
                        print --x
                        Q = "|"
                        print -3 Q -4
                        print -3 Q -4 -5
                }

Interestingly, 3.1.8 got it partially right:

        $ gawk-3.1.8 --profile=/dev/stdout -f x.awk
        3
        -3|-4
        -3|-4-5
                # gawk profile, created Thu Oct 30 21:36:10 2014

                # BEGIN block(s)

                BEGIN {
                        x = 3
                        print  -( -x)
                        Q = "|"
                        print (-3 Q -4)
                        print (-3 Q -4 -5)
                }

And now, after patching:

        $ ./gawk -o/dev/stdout -f x.awk
        3
        -3|-4
        -3|-4-5
                # gawk profile, created Thu Oct 30 21:36:30 2014

                # BEGIN rule(s)

                BEGIN {
                        x = 3
                        print -(-x)
                        Q = "|"
                        print -3 Q (-4)
                        print -3 Q (-4) (-5)
                }

Here is the fix. It will be in the git repo shortly.

Arnold
-------------------------
diff --git a/ChangeLog b/ChangeLog
index 8f4657a..a74dadd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,15 @@
 
        * configure: Regenerated after fix to m4/readline.m4.
 
+       Unrelated; fixes to profiling. Thanks to Hermann Peifer and
+       Manuel Collado for pointing out problems:
+
+       * profile.c (pprint): For Op_unary_minus, parenthesize -(-x)
+       correctly.
+       (prec_level): Get the levels right (checked the grammar).
+       (is_unary_minus): New function.
+       (pp_concat): Add checks for unary minus; needs to be parenthesized.
+
 2014-10-29         Arnold D. Robbins     <address@hidden>
 
        * dfa.c: Sync with GNU grep. Again, again.
diff --git a/profile.c b/profile.c
index a5ed381..ed17e62 100644
--- a/profile.c
+++ b/profile.c
@@ -395,7 +395,8 @@ cleanup:
                case Op_unary_minus:
                case Op_not:
                        t1 = pp_pop();
-                       if (is_binary(t1->type))
+                       if (is_binary(t1->type)
+                           || (((OPCODE) t1->type) == pc->opcode && pc->opcode 
== Op_unary_minus))
                                pp_parenthesize(t1);
 
                        /* optypes table (eval.c) includes space after ! */
@@ -1000,25 +1001,25 @@ prec_level(int type)
        case Op_func_call:
        case Op_K_delete_loop:
        case Op_builtin:
-               return 15;
+               return 16;
 
        case Op_field_spec:
        case Op_field_spec_lhs:
-               return 14;
-
-       case Op_exp:
-       case Op_exp_i:
-               return 13;
+               return 15;
 
        case Op_preincrement:
        case Op_predecrement:
        case Op_postincrement:
        case Op_postdecrement:
-               return 12;
+               return 14;
+
+       case Op_exp:
+       case Op_exp_i:
+               return 13;
 
        case Op_unary_minus:
        case Op_not:
-               return 11;
+               return 12;
 
        case Op_times:
        case Op_times_i:
@@ -1026,23 +1027,26 @@ prec_level(int type)
        case Op_quotient_i:
        case Op_mod:
        case Op_mod_i:
-               return 10;
+               return 11;
 
        case Op_plus:
        case Op_plus_i:
        case Op_minus:
        case Op_minus_i:
-               return 9;
+               return 10;
 
        case Op_concat:
        case Op_assign_concat:
-               return 8;
+               return 9;
 
        case Op_equal:
        case Op_notequal:
        case Op_greater:
+       case Op_less:
        case Op_leq:
        case Op_geq:
+               return 8;
+
        case Op_match:
        case Op_nomatch:
                return 7;
@@ -1051,7 +1055,6 @@ prec_level(int type)
        case Op_K_getline_redir:
                return 6;
 
-       case Op_less:
        case Op_in_array:
                return 5;
 
@@ -1360,6 +1363,14 @@ pp_list(int nargs, const char *paren, const char *delim)
        return str;                                     
 }
 
+/* is_unary_minus --- return true if string starts with unary minus */
+
+static bool
+is_unary_minus(const char *str)
+{
+       return str[0] == '-' && str[1] != '-';
+}
+
 /* pp_concat --- handle concatenation and correct parenthesizing of 
expressions */
 
 static char *
@@ -1401,7 +1412,12 @@ pp_concat(int nargs)
                pl_l = prec_level(pp_args[i]->type);
                pl_r = prec_level(pp_args[i+1]->type);
 
-               if (is_scalar(pp_args[i]->type) && 
is_scalar(pp_args[i+1]->type)) {
+               if (i >= 2 && is_unary_minus(r->pp_str)) {
+                       *s++ = '(';
+                       memcpy(s, r->pp_str, r->pp_len);
+                       s += r->pp_len;
+                       *s++ = ')';
+               } else if (is_scalar(pp_args[i]->type) && 
is_scalar(pp_args[i+1]->type)) {
                        memcpy(s, r->pp_str, r->pp_len);
                        s += r->pp_len;
                } else if (pl_l <= pl_r || is_scalar(pp_args[i+1]->type)) {
@@ -1423,7 +1439,7 @@ pp_concat(int nargs)
        pl_l = prec_level(pp_args[nargs-1]->type);
        pl_r = prec_level(pp_args[nargs]->type);
        r = pp_args[nargs];
-       if (pl_l >= pl_r && ! is_scalar(pp_args[nargs]->type)) {
+       if (is_unary_minus(r->pp_str) || ((pl_l >= pl_r && ! 
is_scalar(pp_args[nargs]->type)))) {
                *s++ = '(';
                memcpy(s, r->pp_str, r->pp_len);
                s += r->pp_len;



reply via email to

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