public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Make the 3rd operand of ternary '?:' bind tighter than binary '='
@ 2018-08-27 23:05 Yichun Zhang (agentzh)
  2018-08-28 17:26 ` [PATCH v2] " Yichun Zhang (agentzh)
  0 siblings, 1 reply; 3+ messages in thread
From: Yichun Zhang (agentzh) @ 2018-08-27 23:05 UTC (permalink / raw)
  To: systemtap; +Cc: Yichun Zhang (agentzh)

In the C language, the 3rd operand of the ternary operator binds tighter
than the binary assignment operators. It is better for the stap language
to be consistent with C in operator precedence.

Added several tests to check the precedence of the ternary operator.
I've verified the results with similar C programs with gcc myself.
---
 parse.cxx                                 |   2 +-
 testsuite/systemtap.base/ternary_op.exp   | 135 ++++++++++++++++++++++++++++++
 testsuite/systemtap.base/ternary_op_1.stp |   5 ++
 testsuite/systemtap.base/ternary_op_2.stp |   5 ++
 testsuite/systemtap.base/ternary_op_3.stp |   5 ++
 5 files changed, 151 insertions(+), 1 deletion(-)
 create mode 100644 testsuite/systemtap.base/ternary_op.exp
 create mode 100644 testsuite/systemtap.base/ternary_op_1.stp
 create mode 100644 testsuite/systemtap.base/ternary_op_2.stp
 create mode 100644 testsuite/systemtap.base/ternary_op_3.stp

diff --git a/parse.cxx b/parse.cxx
index 751f56add..169486d8d 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -3286,7 +3286,7 @@ parser::parse_ternary ()
         throw PARSE_ERROR (_("expected ':'"));
       swallow ();
 
-      e->falsevalue = parse_expression (); // XXX
+      e->falsevalue = parse_ternary (); // XXX
       return e;
     }
   else
diff --git a/testsuite/systemtap.base/ternary_op.exp b/testsuite/systemtap.base/ternary_op.exp
new file mode 100644
index 000000000..4f9eabf21
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op.exp
@@ -0,0 +1,135 @@
+set test "ternary_op"
+set testpath "$srcdir/$subdir"
+
+if {! [installtest_p]} { untested "$test"; return }
+
+# --- TEST 1 ---
+
+set subtest1 "TEST 1: ternary operator should be tighter than ,"
+foreach runtime [get_runtime_list] {
+    if {$runtime eq ""} {
+        set runtime "kernel"
+    }
+    set test_name "$test: $subtest1 ($runtime)"
+
+    set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_1.stp'"
+    send_log "executing: $cmd\n"
+    set pipe [open "| sh -c {$cmd}" r]
+    set out [read $pipe]
+    set failed 0
+    if {[catch {close $pipe} stderr] != 0} {
+        if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+            append stderr "\n"
+        }
+        global errorCode
+        if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+            set failed [lindex $errorCode 2]
+        }
+    }
+
+    set exp_out "positive 3\n"
+    regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+    if {$out eq $exp_out} {
+        pass "${test_name}: stdout matches \"$escaped_exp_out\""
+    } else {
+        fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+    }
+
+    if {$failed} {
+        fail "${test_name}: exit code should be zero but is $failed"
+    } else {
+        pass "${test_name}: exit code is zero"
+    }
+    if {$stderr ne ""} {
+        send_log "stderr:\n$stderr"
+    }
+}
+
+# --- TEST 2 ---
+
+set subtest2 "TEST 2: ternary operator should be tighter than = (bad case)"
+set test_name "$test: $subtest2"
+
+set cmd "stap '$srcdir/$subdir/${test}_2.stp'"
+send_log "executing: $cmd\n"
+set pipe [open "| sh -c {$cmd}" r]
+set out [read $pipe]
+set failed 0
+if {[catch {close $pipe} stderr] != 0} {
+    if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+        append stderr "\n"
+    }
+    global errorCode
+    if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+        set failed [lindex $errorCode 2]
+    }
+}
+
+set exp_out ""
+regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+if {$out eq $exp_out} {
+    pass "${test_name}: stdout matches \"$escaped_exp_out\""
+} else {
+    fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+}
+
+if {$failed} {
+    pass "${test_name}: exit code should be non-zero"
+} else {
+    fail "${test_name}: exit code should be non-zero but is zero"
+}
+
+set stderr_pat "^semantic error: Expecting lvalue for assignment: operator '=' at :3:38\\n        source:     printf\\(\"%d\\\\n\", a > 0 \\? b = 3 : c = 4\\);\\n                                                     \\^\\n"
+regsub -all -- {\n} $stderr_pat {\n} escaped_stderr_pat
+if {[regexp -linestop -lineanchor -- $stderr_pat $stderr]} {
+    pass "${test_name}: stderr matches \"$escaped_stderr_pat\""
+} else {
+    fail "${test_name}: stderr fails to match \"$escaped_stderr_pat\": got \"$stderr\""
+}
+
+# --- TEST 3 ---
+
+set subtest3 "TEST 3: ternary operator should be tighter than = (good case, with parens)"
+foreach runtime [get_runtime_list] {
+    if {$runtime eq ""} {
+        set runtime "kernel"
+    }
+    set test_name "$test: $subtest3 ($runtime)"
+
+    set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_3.stp'"
+    send_log "executing: $cmd\n"
+    set pipe [open "| sh -c {$cmd}" r]
+    set out [read $pipe]
+    set failed 0
+    if {[catch {close $pipe} stderr] != 0} {
+        if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+            append stderr "\n"
+        }
+        global errorCode
+        if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+            set failed [lindex $errorCode 2]
+        }
+    }
+
+    set exp_out "3\n"
+    regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+    if {$out eq $exp_out} {
+        pass "${test_name}: stdout matches \"$escaped_exp_out\""
+    } else {
+        fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+    }
+
+    set stderr_pat "^WARNING: Eliding assignment to 'b': operator '=' at \[^\\n\]*?\\.stp:3:30\n.*?\nWARNING: Eliding assignment to 'c': operator '=' at :3:39\n"
+    regsub -all -- {\n} $stderr_pat {\n} escaped_stderr_pat
+    if {[regexp -lineanchor -- $stderr_pat $stderr]} {
+        pass "${test_name}: stderr matches \"$escaped_stderr_pat\""
+    } else {
+        fail "${test_name}: stderr fails to match \"$escaped_stderr_pat\": got \"$stderr\""
+    }
+
+    if {$failed} {
+        fail "${test_name}: exit code should be zero but is $failed"
+    } else {
+        pass "${test_name}: exit code is zero"
+    }
+}
diff --git a/testsuite/systemtap.base/ternary_op_1.stp b/testsuite/systemtap.base/ternary_op_1.stp
new file mode 100644
index 000000000..d4be95987
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_1.stp
@@ -0,0 +1,5 @@
+probe begin {
+    a = 3;
+    printf("%s %d\n", a > 0 ? "positive" : "negative", a);
+    exit();
+}
diff --git a/testsuite/systemtap.base/ternary_op_2.stp b/testsuite/systemtap.base/ternary_op_2.stp
new file mode 100644
index 000000000..ca4426812
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_2.stp
@@ -0,0 +1,5 @@
+probe begin {
+    a = 3;
+    printf("%d\n", a > 0 ? b = 3 : c = 4);
+    exit();
+}
diff --git a/testsuite/systemtap.base/ternary_op_3.stp b/testsuite/systemtap.base/ternary_op_3.stp
new file mode 100644
index 000000000..8e6593b28
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_3.stp
@@ -0,0 +1,5 @@
+probe begin {
+    a = 3;
+    printf("%d\n", a > 0 ? b = 3 : (c = 4));
+    exit();
+}
-- 
2.11.0.295.gd7dffce

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2] Make the 3rd operand of ternary '?:' bind tighter than binary '='
  2018-08-27 23:05 [PATCH] Make the 3rd operand of ternary '?:' bind tighter than binary '=' Yichun Zhang (agentzh)
@ 2018-08-28 17:26 ` Yichun Zhang (agentzh)
  2018-08-28 17:41   ` Yichun Zhang (agentzh)
  0 siblings, 1 reply; 3+ messages in thread
From: Yichun Zhang (agentzh) @ 2018-08-28 17:26 UTC (permalink / raw)
  To: systemtap; +Cc: Yichun Zhang (agentzh)

In the C language, the 3rd operand of the ternary operator binds tighter
than the binary assignment operators. It is better for the stap language
to be consistent with C in operator precedence.

Added several tests to check the precedence of the ternary operator,
including nested ternary operator expressions. I've verified the results
with similar C programs with gcc myself.

Fixed an existing test case under systemtap.examples/, ansi_colors2.stp,
which incorrectly assumed that `+=` binds tighter than the 3rd operand
of the ternary operator.

The original behavior can be restored by the --compatible 3.3 option.

Updated NEWS to reflect this backward-incompatible change in the parser.
---
 NEWS                                               |   5 +
 parse.cxx                                          |   5 +-
 testsuite/systemtap.base/ternary_op.exp            | 303 +++++++++++++++++++++
 testsuite/systemtap.base/ternary_op_1.stp          |   4 +
 testsuite/systemtap.base/ternary_op_2.stp          |   5 +
 testsuite/systemtap.base/ternary_op_3.stp          |   5 +
 testsuite/systemtap.base/ternary_op_6.stp          |   4 +
 testsuite/systemtap.base/ternary_op_7.stp          |  10 +
 .../systemtap.examples/general/ansi_colors2.stp    |   2 +-
 9 files changed, 341 insertions(+), 2 deletions(-)
 create mode 100644 testsuite/systemtap.base/ternary_op.exp
 create mode 100644 testsuite/systemtap.base/ternary_op_1.stp
 create mode 100644 testsuite/systemtap.base/ternary_op_2.stp
 create mode 100644 testsuite/systemtap.base/ternary_op_3.stp
 create mode 100644 testsuite/systemtap.base/ternary_op_6.stp
 create mode 100644 testsuite/systemtap.base/ternary_op_7.stp

diff --git a/NEWS b/NEWS
index 7ed02a99f..ab20986bf 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,11 @@
   can now be stored in variables, passed as function arguments,
   and stored as array keys and values.
 
+- The 3rd operand of the ternary operator '?:' in the script language
+  now binds tighter than the binary assignment operators like '=' and
+  '+=', just like the C language. The original operator precedence can
+  be restored by the '--compatible 3.3' option.
+
 * What's new in version 3.3, 2018-06-08
 
 - A new "stap --example FOO.stp" mode searches the example scripts
diff --git a/parse.cxx b/parse.cxx
index 751f56add..902feb64e 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -3286,7 +3286,10 @@ parser::parse_ternary ()
         throw PARSE_ERROR (_("expected ':'"));
       swallow ();
 
-      e->falsevalue = parse_expression (); // XXX
+      if (input.has_version("4.0"))
+        e->falsevalue = parse_ternary ();
+      else
+        e->falsevalue = parse_assignment ();
       return e;
     }
   else
diff --git a/testsuite/systemtap.base/ternary_op.exp b/testsuite/systemtap.base/ternary_op.exp
new file mode 100644
index 000000000..55262289e
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op.exp
@@ -0,0 +1,303 @@
+set test "ternary_op"
+set testpath "$srcdir/$subdir"
+
+if {! [installtest_p]} { untested "$test"; return }
+
+# --- TEST 1 ---
+
+set subtest1 "TEST 1: ternary operator should be tighter than ,"
+foreach runtime [get_runtime_list] {
+    if {$runtime eq ""} {
+        set runtime "kernel"
+    }
+    set test_name "$test: $subtest1 ($runtime)"
+
+    set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_1.stp'"
+    send_log "executing: $cmd\n"
+    set pipe [open "| sh -c {$cmd}" r]
+    set out [read $pipe]
+    set failed 0
+    if {[catch {close $pipe} stderr] != 0} {
+        if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+            append stderr "\n"
+        }
+        global errorCode
+        if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+            set failed [lindex $errorCode 2]
+        }
+    }
+
+    set exp_out "positive 3\n"
+    regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+    if {$out eq $exp_out} {
+        pass "${test_name}: stdout matches \"$escaped_exp_out\""
+    } else {
+        fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+    }
+
+    if {$failed} {
+        fail "${test_name}: exit code should be zero but is $failed"
+    } else {
+        pass "${test_name}: exit code is zero"
+    }
+    if {$stderr ne ""} {
+        send_log "stderr:\n$stderr"
+    }
+}
+
+# --- TEST 2 ---
+
+set subtest2 "TEST 2: ternary operator should be tighter than = (bad case)"
+set test_name "$test: $subtest2"
+
+set cmd "stap '$srcdir/$subdir/${test}_2.stp'"
+send_log "executing: $cmd\n"
+set pipe [open "| sh -c {$cmd}" r]
+set out [read $pipe]
+set failed 0
+if {[catch {close $pipe} stderr] != 0} {
+    if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+        append stderr "\n"
+    }
+    global errorCode
+    if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+        set failed [lindex $errorCode 2]
+    }
+}
+
+set exp_out ""
+regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+if {$out eq $exp_out} {
+    pass "${test_name}: stdout matches \"$escaped_exp_out\""
+} else {
+    fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+}
+
+if {$failed} {
+    pass "${test_name}: exit code should be non-zero"
+} else {
+    fail "${test_name}: exit code should be non-zero but is zero"
+}
+
+set stderr_pat "^semantic error: Expecting lvalue for assignment: operator '=' at \[^\\n\]*?\\.stp:4:58\\n        source:     printf\\(\"a = %d, b = %d, c = %d\\\\n\", a > 0 \\? b = 4 : c = 5, b, c\\);\\n                                                                         \\^\\n"
+regsub -all -- {\n} $stderr_pat {\n} escaped_stderr_pat
+if {[regexp -linestop -lineanchor -- $stderr_pat $stderr]} {
+    pass "${test_name}: stderr matches \"$escaped_stderr_pat\""
+} else {
+    fail "${test_name}: stderr fails to match \"$escaped_stderr_pat\": got \"$stderr\""
+}
+
+# --- TEST 3 ---
+
+set subtest3 "TEST 3: ternary operator should be tighter than = (bad case, compatible 4.0)"
+set test_name "$test: $subtest3"
+
+set cmd "stap --compatible 4.0 '$srcdir/$subdir/${test}_2.stp'"
+send_log "executing: $cmd\n"
+set pipe [open "| sh -c {$cmd}" r]
+set out [read $pipe]
+set failed 0
+if {[catch {close $pipe} stderr] != 0} {
+    if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+        append stderr "\n"
+    }
+    global errorCode
+    if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+        set failed [lindex $errorCode 2]
+    }
+}
+
+set exp_out ""
+regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+if {$out eq $exp_out} {
+    pass "${test_name}: stdout matches \"$escaped_exp_out\""
+} else {
+    fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+}
+
+if {$failed} {
+    pass "${test_name}: exit code should be non-zero"
+} else {
+    fail "${test_name}: exit code should be non-zero but is zero"
+}
+
+set stderr_pat "^semantic error: Expecting lvalue for assignment: operator '=' at \[^\\n\]*?\\.stp:4:58\\n        source:     printf\\(\"a = %d, b = %d, c = %d\\\\n\", a > 0 \\? b = 4 : c = 5, b, c\\);\\n                                                                         \\^\\n"
+regsub -all -- {\n} $stderr_pat {\n} escaped_stderr_pat
+if {[regexp -linestop -lineanchor -- $stderr_pat $stderr]} {
+    pass "${test_name}: stderr matches \"$escaped_stderr_pat\""
+} else {
+    fail "${test_name}: stderr fails to match \"$escaped_stderr_pat\": got \"$stderr\""
+}
+
+# --- TEST 4 ---
+
+set subtest4 "TEST 4: ternary operator should be tighter than = (bad case, compatible 3.3)"
+foreach runtime [get_runtime_list] {
+    if {$runtime eq ""} {
+        set runtime "kernel"
+    }
+    set test_name "$test: $subtest4 ($runtime)"
+
+    set cmd "stap --compatible 3.3 --runtime=$runtime '$srcdir/$subdir/${test}_2.stp'"
+    send_log "executing: $cmd\n"
+    set pipe [open "| sh -c {$cmd}" r]
+    set out [read $pipe]
+    set failed 0
+    if {[catch {close $pipe} stderr] != 0} {
+        if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+            append stderr "\n"
+        }
+        global errorCode
+        if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+            set failed [lindex $errorCode 2]
+        }
+    }
+
+    set exp_out "a = 4, b = 4, c = 0\n"
+    regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+    if {$out eq $exp_out} {
+        pass "${test_name}: stdout matches \"$escaped_exp_out\""
+    } else {
+        fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+    }
+
+    if {$failed} {
+        fail "${test_name}: exit code should be zero but is $failed"
+    } else {
+        pass "${test_name}: exit code is zero"
+    }
+    if {$stderr ne ""} {
+        send_log "stderr:\n$stderr"
+    }
+}
+
+# --- TEST 5 ---
+
+set subtest5 "TEST 5: ternary operator should be tighter than = (bad case, compatible 3.2)"
+foreach runtime [get_runtime_list] {
+    if {$runtime eq ""} {
+        set runtime "kernel"
+    }
+    set test_name "$test: $subtest5 ($runtime)"
+
+    set cmd "stap --compatible 3.2 --runtime=$runtime '$srcdir/$subdir/${test}_2.stp'"
+    send_log "executing: $cmd\n"
+    set pipe [open "| sh -c {$cmd}" r]
+    set out [read $pipe]
+    set failed 0
+    if {[catch {close $pipe} stderr] != 0} {
+        if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+            append stderr "\n"
+        }
+        global errorCode
+        if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+            set failed [lindex $errorCode 2]
+        }
+    }
+
+    set exp_out "a = 4, b = 4, c = 0\n"
+    regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+    if {$out eq $exp_out} {
+        pass "${test_name}: stdout matches \"$escaped_exp_out\""
+    } else {
+        fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+    }
+
+    if {$failed} {
+        fail "${test_name}: exit code should be zero but is $failed"
+    } else {
+        pass "${test_name}: exit code is zero"
+    }
+    if {$stderr ne ""} {
+        send_log "stderr:\n$stderr"
+    }
+}
+
+# --- TEST 6 ---
+
+set subtest6 "TEST 6: ternary operator should be tighter than = (good case, with parens)"
+foreach runtime [get_runtime_list] {
+    if {$runtime eq ""} {
+        set runtime "kernel"
+    }
+    set test_name "$test: $subtest6 ($runtime)"
+
+    set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_6.stp'"
+    send_log "executing: $cmd\n"
+    set pipe [open "| sh -c {$cmd}" r]
+    set out [read $pipe]
+    set failed 0
+    if {[catch {close $pipe} stderr] != 0} {
+        if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+            append stderr "\n"
+        }
+        global errorCode
+        if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+            set failed [lindex $errorCode 2]
+        }
+    }
+
+    set exp_out "3\n"
+    regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+    if {$out eq $exp_out} {
+        pass "${test_name}: stdout matches \"$escaped_exp_out\""
+    } else {
+        fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+    }
+
+    set stderr_pat "^WARNING: Eliding assignment to 'b': operator '=' at \[^\\n\]*?\\.stp:3:30\n.*?\nWARNING: Eliding assignment to 'c': operator '=' at :3:39\n"
+    regsub -all -- {\n} $stderr_pat {\n} escaped_stderr_pat
+    if {[regexp -lineanchor -- $stderr_pat $stderr]} {
+        pass "${test_name}: stderr matches \"$escaped_stderr_pat\""
+    } else {
+        fail "${test_name}: stderr fails to match \"$escaped_stderr_pat\": got \"$stderr\""
+    }
+
+    if {$failed} {
+        fail "${test_name}: exit code should be zero but is $failed"
+    } else {
+        pass "${test_name}: exit code is zero"
+    }
+}
+
+# --- TEST 7 ---
+
+set subtest7 "TEST 7: nested ternary operators"
+foreach runtime [get_runtime_list] {
+    if {$runtime eq ""} {
+        set runtime "kernel"
+    }
+    set test_name "$test: $subtest7 ($runtime)"
+
+    set cmd "stap --runtime=$runtime '$srcdir/$subdir/${test}_7.stp'"
+    send_log "executing: $cmd\n"
+    set pipe [open "| sh -c {$cmd}" r]
+    set out [read $pipe]
+    set failed 0
+    if {[catch {close $pipe} stderr] != 0} {
+        if {$stderr ne "" && [string index $stderr end] ne "\n"} {
+            append stderr "\n"
+        }
+        global errorCode
+        if {"CHILDSTATUS" == [lindex $errorCode 0]} {
+            set failed [lindex $errorCode 2]
+        }
+    }
+
+    set exp_out "3\n4\n6\n5\n"
+    regsub -all -- {\n} $exp_out {\n} escaped_exp_out
+    if {$out eq $exp_out} {
+        pass "${test_name}: stdout matches \"$escaped_exp_out\""
+    } else {
+        fail "${test_name}: stdout fails to match \"$escaped_exp_out\": got \"$out\""
+    }
+
+    if {$failed} {
+        fail "${test_name}: exit code should be zero but is $failed"
+    } else {
+        pass "${test_name}: exit code is zero"
+    }
+    if {$stderr ne ""} {
+        send_log "stderr:\n$stderr"
+    }
+}
diff --git a/testsuite/systemtap.base/ternary_op_1.stp b/testsuite/systemtap.base/ternary_op_1.stp
new file mode 100644
index 000000000..ec9b697b4
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_1.stp
@@ -0,0 +1,4 @@
+probe oneshot {
+    a = 3;
+    printf("%s %d\n", a > 0 ? "positive" : "negative", a);
+}
diff --git a/testsuite/systemtap.base/ternary_op_2.stp b/testsuite/systemtap.base/ternary_op_2.stp
new file mode 100644
index 000000000..374803003
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_2.stp
@@ -0,0 +1,5 @@
+probe oneshot {
+    a = 3;
+    c = 0;
+    printf("a = %d, b = %d, c = %d\n", a > 0 ? b = 4 : c = 5, b, c);
+}
diff --git a/testsuite/systemtap.base/ternary_op_3.stp b/testsuite/systemtap.base/ternary_op_3.stp
new file mode 100644
index 000000000..8e6593b28
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_3.stp
@@ -0,0 +1,5 @@
+probe begin {
+    a = 3;
+    printf("%d\n", a > 0 ? b = 3 : (c = 4));
+    exit();
+}
diff --git a/testsuite/systemtap.base/ternary_op_6.stp b/testsuite/systemtap.base/ternary_op_6.stp
new file mode 100644
index 000000000..c2a6bcd47
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_6.stp
@@ -0,0 +1,4 @@
+probe oneshot {
+    a = 3;
+    printf("%d\n", a > 0 ? b = 3 : (c = 4));
+}
diff --git a/testsuite/systemtap.base/ternary_op_7.stp b/testsuite/systemtap.base/ternary_op_7.stp
new file mode 100644
index 000000000..248803703
--- /dev/null
+++ b/testsuite/systemtap.base/ternary_op_7.stp
@@ -0,0 +1,10 @@
+function test(a) {
+    printf("%d\n", a > 0 ? a > 1 ? 3 : 4 : a < -1 ? 5 : 6);
+}
+
+probe oneshot {
+    test(2);
+    test(1);
+    test(-1);
+    test(-2);
+}
diff --git a/testsuite/systemtap.examples/general/ansi_colors2.stp b/testsuite/systemtap.examples/general/ansi_colors2.stp
index 3ff3a16cd..64434e30c 100755
--- a/testsuite/systemtap.examples/general/ansi_colors2.stp
+++ b/testsuite/systemtap.examples/general/ansi_colors2.stp
@@ -18,7 +18,7 @@ probe begin {
 
 	for (r = 30; r < 38; r++)
 		# this displays more attributes
-		for (t = 0; t < 8; !t ? ++t : t+=3) {
+		for (t = 0; t < 8; !t ? ++t : (t+=3)) {
 			printf("   %2d,%1d   |", r, t);
 			for (c = 40; c < 48; c++) {
 				ansi_set_color(r, c, t)
-- 
2.11.0.295.gd7dffce

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] Make the 3rd operand of ternary '?:' bind tighter than binary '='
  2018-08-28 17:26 ` [PATCH v2] " Yichun Zhang (agentzh)
@ 2018-08-28 17:41   ` Yichun Zhang (agentzh)
  0 siblings, 0 replies; 3+ messages in thread
From: Yichun Zhang (agentzh) @ 2018-08-28 17:41 UTC (permalink / raw)
  To: systemtap

Hello!

On Tue, Aug 28, 2018 at 10:26 AM Yichun Zhang (agentzh) wrote:
> In the C language, the 3rd operand of the ternary operator binds tighter
> than the binary assignment operators. It is better for the stap language
> to be consistent with C in operator precedence.
>

Just for the record, I've just changed `parse_assignment ()` back to
`parse_expression ()` as per fche's suggestion and committed it to
master with his green light on IRC.

Best,
Yichun

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-08-28 17:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-27 23:05 [PATCH] Make the 3rd operand of ternary '?:' bind tighter than binary '=' Yichun Zhang (agentzh)
2018-08-28 17:26 ` [PATCH v2] " Yichun Zhang (agentzh)
2018-08-28 17:41   ` Yichun Zhang (agentzh)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).