]> sourceware.org Git - systemtap.git/commitdiff
PR5792: wildcard support for %( kernel/arch %) preprocessor operands
authorfche <fche>
Tue, 26 Feb 2008 00:28:42 +0000 (00:28 +0000)
committerfche <fche>
Tue, 26 Feb 2008 00:28:42 +0000 (00:28 +0000)
2008-02-25  Frank Ch. Eigler  <fche@elastic.org>

PR5792.
* parse.cxx (eval_pp_conditional): Support wildcards in
%( kernel_v/kernel_vr/arch ==/!= "*foo?" %) operands.
* NEWS, stap.1.in: Document this.

2008-02-25  Frank Ch. Eigler  <fche@elastic.org>

PR5792.
* systemtap.base/preprocessor.exp: New test.

ChangeLog
NEWS
parse.cxx
stap.1.in
testsuite/ChangeLog
testsuite/systemtap.base/preprocessor.exp [new file with mode: 0644]

index fad79819eb5c010d8f1fee38d16f96ea35f9a21c..e453cd8f36dfd5c0499b29665d82039aa4f00745 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-02-25  Frank Ch. Eigler  <fche@elastic.org>
+
+       PR5792.
+       * parse.cxx (eval_pp_conditional): Support wildcards in 
+       %( kernel_v/kernel_vr/arch ==/!= "*foo?" %) operands.
+       * NEWS, stap.1.in: Document this.
+
 2008-02-22  Frank Ch. Eigler  <fche@elastic.org>
 
        PR5787, PR2608, .statement()
diff --git a/NEWS b/NEWS
index 073945e1498d95382c154cb0417bc64111774e46..df7e27b4692ad24e22b1a45a6d7511e4d15174dd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
 * What's new in version 0.6 / 0.6.1
 
+- Preprocessor conditional expressions can now include wildcard style
+  matches on kernel versions. 
+  %( kernel_vr != "*xen" %? foo %: bar %)
+
 - Prototype support for user-space probing is showing some progress.
   No symbolic notations are supported yet (so no probing by function names,
   file names, process names, and no access to $context variables), but at
index a829fa10b737c269f0551be229c9eea99d292065..ea22f36da46b9b9e8cf5e5364c685fc2ad616f5e 100644 (file)
--- a/parse.cxx
+++ b/parse.cxx
@@ -24,6 +24,9 @@
 #include <sstream>
 #include <cstring>
 #include <cctype>
+extern "C" {
+#include <fnmatch.h>
+}
 
 using namespace std;
 
@@ -173,10 +176,16 @@ bool eval_pp_conditional (systemtap_session& s,
       
       if (! (r->type == tok_string))
         throw parse_error ("expected string literal", r);
-      string query_kernel_vr = r->content;
-      
+
+      string target = (l->content == "kernel_vr" ? 
+                       target_kernel_vr.c_str() :
+                       target_kernel_v.c_str());
+      string query = r->content;
+      bool rhs_wildcard = (strpbrk (query.c_str(), "*?[") != 0);
+
       // collect acceptable strverscmp results.
       int rvc_ok1, rvc_ok2;
+      bool wc_ok = false;
       if (op->type == tok_operator && op->content == "<=")
         { rvc_ok1 = -1; rvc_ok2 = 0; }
       else if (op->type == tok_operator && op->content == ">=")
@@ -186,21 +195,30 @@ bool eval_pp_conditional (systemtap_session& s,
       else if (op->type == tok_operator && op->content == ">")
         { rvc_ok1 = 1; rvc_ok2 = 1; }
       else if (op->type == tok_operator && op->content == "==")
-        { rvc_ok1 = 0; rvc_ok2 = 0; }
+        { rvc_ok1 = 0; rvc_ok2 = 0; wc_ok = true; }
       else if (op->type == tok_operator && op->content == "!=")
-        { rvc_ok1 = -1; rvc_ok2 = 1; }
+        { rvc_ok1 = -1; rvc_ok2 = 1; wc_ok = true; }
       else
         throw parse_error ("expected comparison operator", op);
-      
-      int rvc_result = strverscmp ((l->content == "kernel_vr" ? 
-                                    target_kernel_vr.c_str() :
-                                    target_kernel_v.c_str()),
-                                   query_kernel_vr.c_str());
-      // normalize rvc_result
-      if (rvc_result < 0) rvc_result = -1;
-      if (rvc_result > 0) rvc_result = 1;
-      
-      return (rvc_result == rvc_ok1 || rvc_result == rvc_ok2);
+
+      if ((!wc_ok) && rhs_wildcard)
+        throw parse_error ("wildcard not allowed with order comparison operators", op);
+
+      if (rhs_wildcard)
+        {
+          int rvc_result = fnmatch (query.c_str(), target.c_str(),
+                                    FNM_NOESCAPE); // spooky
+          bool badness = (rvc_result == 0) ^ (op->content == "==");
+          return !badness;
+        }
+      else
+        {
+          int rvc_result = strverscmp (target.c_str(), query.c_str());
+          // normalize rvc_result
+          if (rvc_result < 0) rvc_result = -1;
+          if (rvc_result > 0) rvc_result = 1;
+          return (rvc_result == rvc_ok1 || rvc_result == rvc_ok2);
+        }
     }
   else if (l->type == tok_identifier && l->content == "arch")
     {
@@ -209,11 +227,15 @@ bool eval_pp_conditional (systemtap_session& s,
         throw parse_error ("expected string literal", r);
       string query_architecture = r->content;
       
+      int nomatch = fnmatch (query_architecture.c_str(),
+                             target_architecture.c_str(),
+                             FNM_NOESCAPE); // still spooky
+
       bool result;
       if (op->type == tok_operator && op->content == "==")
-        result = target_architecture == query_architecture;
+        result = !nomatch;
       else if (op->type == tok_operator && op->content == "!=")
-        result = target_architecture != query_architecture;
+        result = nomatch;
       else
         throw parse_error ("expected '==' or '!='", op);
       
@@ -245,6 +267,8 @@ bool eval_pp_conditional (systemtap_session& s,
       if (rvc_result < 0) rvc_result = -1;
       if (rvc_result > 0) rvc_result = 1;
 
+      // NB: no wildcarding option here
+
       return (rvc_result == rvc_ok1 || rvc_result == rvc_ok2);
     }
   else if (l->type == tok_string && r->type == tok_number
index 05eecda2fef6fc4b76e0ac81d6bc719dff87616b..51ba6380f3b55e7b079079192945dde7292beb65 100644 (file)
--- a/stap.1.in
+++ b/stap.1.in
@@ -224,6 +224,15 @@ version of the target kernel (as optionally overridden by the
 option) compares to the given version string.  The comparison is
 performed by the glibc function
 .BR strverscmp .
+As a special case, if the operator is for simple equality 
+.RB ( == ),
+or inequality
+.RB ( != ),
+and the third part contains any wildcard characters
+.RB ( * " or " ? " or " [ "),"
+then the expression is treated as a wildcard (mis)match as evaluated
+by
+.BR fnmatch .
 .PP
 If, on the other hand, the first part is the identifier
 .BR arch
@@ -231,7 +240,7 @@ to refer to the processor architecture, then the second part
 then the second part is one of the two string comparison operators
 .BR == " or " != ,
 and the third part is a string literal for matching it.  This
-comparison is simple string (in)equality.
+comparison is a wildcard (mis)match.
 .PP
 Otherwise, the CONDITION is expected to be a comparison between two string
 literals or two numeric literals.  In this case, the arguments are the only
index c6f7ced8a9fb078c15f3b14753d0a3d44b8896b4..addab7198fbd0f3b0314f138929e69d67ede3ad8 100644 (file)
@@ -1,3 +1,8 @@
+2008-02-25  Frank Ch. Eigler  <fche@elastic.org>
+
+       PR5792.
+       * systemtap.base/preprocessor.exp: New test.
+
 2008-02-23  Frank Ch. Eigler  <fche@elastic.org>
 
        * systemtap.printf/*.exp: Canonicalize pass/fail messages.
diff --git a/testsuite/systemtap.base/preprocessor.exp b/testsuite/systemtap.base/preprocessor.exp
new file mode 100644 (file)
index 0000000..4e0c7fc
--- /dev/null
@@ -0,0 +1,52 @@
+
+set kvr [exec uname -r]
+set kv [exec uname -r | cut -f1 -d-]
+# a pattern bound to match
+set kr {2?[0-9]*}
+# a pattern bound to mismatch
+set krx {?noSuchKernel*}
+
+set arch [exec uname -m]
+set ar "?[string range $arch 1 end-1]?"
+set arx {?noSuchArch?}
+
+# This test works so that if all the preprocessor conditionals
+# work as expected, stap will indicate no error.
+
+set test "preprocessor basic ops"
+spawn stap -p2 -e "probe never {}
+%( kernel_v == \"$kv\"   %? %: ERROR %)
+%( kernel_v == \"$kr\"   %? %: ERROR %)
+%( kernel_v == \"$krx\"   %? ERROR %: %)
+%( kernel_v != \"$kv\"   %? ERROR %: %)
+%( kernel_v != \"$kr\"   %? ERROR %: %)
+%( kernel_v != \"$krx\"   %? %: ERROR %)
+%( kernel_v < \"9.9999\"  %? %: ERROR %)
+%( kernel_v <= \"9.9999\" %? %: ERROR %)
+%( kernel_v > \"9.9999\"  %? ERROR %: %)
+%( kernel_v >= \"9.9999\" %? ERROR %: %)
+%( kernel_vr == \"$kvr\"  %? %: ERROR %)
+%( kernel_vr == \"$kr\"  %? %: ERROR %)
+%( kernel_vr == \"$krx\"  %? ERROR %: %)
+%( kernel_vr != \"$kvr\"  %? ERROR %: %)
+%( kernel_vr != \"$kr\"   %? ERROR %: %)
+%( kernel_vr != \"$krx\"   %? %: ERROR %)
+%( kernel_vr < \"9.9999\"  %? %: ERROR %)
+%( kernel_vr <= \"9.9999\" %? %: ERROR %)
+%( kernel_vr > \"9.9999\"  %? ERROR %: %)
+%( kernel_vr >= \"9.9999\" %? ERROR %: %)
+%( arch == \"$arch\"      %? %: ERROR %)
+%( arch == \"$ar\"        %? %: ERROR %)
+%( arch == \"$arx\"        %? ERROR %: %)
+%( arch != \"$arch\"      %? ERROR %: %)
+%( arch != \"$ar\"        %? ERROR %: %)
+%( arch != \"$arx\"        %? %: ERROR %)
+"
+set ok 0
+expect {
+    "never" { incr ok }
+    eof { }
+    timeout { }
+}
+catch {close; wait}
+if {$ok == 1} { pass $test } { fail $test }
This page took 0.050033 seconds and 5 git commands to generate.