This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch proposal 2/2: allow use of $x and @x identifiers during preprocessing



Hi again,


Here is a second proposal to complete the previous one: this patch allows the use of $x or @x identifiers ($1 ... $n and $#, etc) during the preprocessing (in addition of kernel_v pattern, etc).
Again, I originally have written this for a colleague and found this useful.
So again:
That's why I send it to this list, but just forget this mail if you don't like it ;-)

Thanks


--
Pierre Peiffer
---
 ChangeLog |    5 +++++
 parse.cxx |   51 +++++++++++++++++++++++++++++++++++++++++++++------
 parse.h   |    4 ++--
 3 files changed, 52 insertions(+), 8 deletions(-)

Index: b/parse.cxx
===================================================================
--- a/parse.cxx
+++ b/parse.cxx
@@ -146,6 +146,8 @@ parser::last ()
 // The basic form is %( CONDITION %? THEN-TOKENS %: ELSE-TOKENS %)
 // where CONDITION is: kernel_v[r] COMPARISON-OP "version-string"
 //                 or: arch COMPARISON-OP "arch-string"
+//                 or: "string1" COMPARISON-OP "string2"
+//                 or: number1 COMPARISON-OP number2
 // The %: ELSE-TOKENS part is optional.
 //
 // e.g. %( kernel_v > "2.5" %? "foo" %: "baz" %)
@@ -212,14 +214,49 @@ bool eval_pp_conditional (systemtap_sess
       
       return result;
     }  
+  else if ((l->type == tok_string && r->type == tok_string)
+	   || (l->type == tok_number && r->type == tok_number))
+    {
+      // collect acceptable strverscmp results.
+      int rvc_ok1, rvc_ok2;
+      if (op->type == tok_operator && op->content == "<=")
+        { rvc_ok1 = -1; rvc_ok2 = 0; }
+      else if (op->type == tok_operator && op->content == ">=")
+        { rvc_ok1 = 1; rvc_ok2 = 0; }
+      else if (op->type == tok_operator && op->content == "<")
+        { rvc_ok1 = -1; rvc_ok2 = -1; }
+      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; }
+      else if (op->type == tok_operator && op->content == "!=")
+        { rvc_ok1 = -1; rvc_ok2 = 1; }
+      else
+        throw parse_error ("expected comparison operator", op);
+
+      int rvc_result = l->content.compare(r->content);
+
+      // 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_string && r->type == tok_number
+	    && op->type == tok_operator)
+    throw parse_error ("expected string literal as right value", r);
+  else if (l->type == tok_number && r->type == tok_string
+	    && op->type == tok_operator)
+    throw parse_error ("expected number as right value", r);
   // XXX: support other forms?  "CONFIG_SMP" ?
   else
-    throw parse_error ("expected 'arch' or 'kernel_v' or 'kernel_vr'", l);
+    throw parse_error ("expected 'arch' or 'kernel_v' or 'kernel_vr'\n"
+		       "             or comparison between strings or integers", l);
 }
 
 
 const token*
-parser::scan_pp ()
+parser::scan_pp (bool expand_args)
 {
   while (true)
     {
@@ -230,7 +267,7 @@ parser::scan_pp ()
           return t;
         }
 
-      const token* t = input.scan (); // NB: not recursive!
+      const token* t = input.scan (expand_args); // NB: not recursive!
       if (t == 0) // EOF
         return t;
       
@@ -262,7 +299,7 @@ parser::scan_pp ()
       
       while (true) // consume THEN tokens
         {
-          m = scan_pp (); // NB: recursive
+          m = scan_pp (result); // NB: recursive
           if (m == 0)
             throw parse_error ("missing THEN tokens for conditional", t);
           
@@ -282,7 +319,7 @@ parser::scan_pp ()
           delete m; // "%:"
           while (true)
             {
-              m = scan_pp (); // NB: recursive
+              m = scan_pp (!result); // NB: recursive
               if (m == 0)
                 throw parse_error ("missing ELSE tokens for conditional", t);
               
@@ -473,7 +510,7 @@ lexer::input_get ()
 
 
 token*
-lexer::scan ()
+lexer::scan (bool expand_args)
 {
   token* n = new token;
   n->location.file = input_name;
@@ -514,6 +551,8 @@ lexer::scan ()
       // numbers and @1 .. @999 as strings.
       if (n->content[0] == '@' || n->content[0] == '$')
         {
+	  if (!expand_args)
+	    return n;
 	  if (n->content[1] == '#')
 	    {
 	      stringstream converter;
Index: b/parse.h
===================================================================
--- a/parse.h
+++ b/parse.h
@@ -64,7 +64,7 @@ struct systemtap_session;
 class lexer
 {
 public:
-  token* scan ();
+  token* scan (bool expand_args=true);
   lexer (std::istream&, const std::string&, systemtap_session&);
 
 private:
@@ -124,7 +124,7 @@ private:
 
   // preprocessing subordinate
   std::vector<const token*> enqueued_pp;
-  const token* scan_pp ();
+  const token* scan_pp (bool expand_args=true);
 
   // scanning state
   const token* last ();
Index: b/ChangeLog
===================================================================
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2007-04-03  Pierre Peiffer  <pierre.peiffer@bull.net>
 
+	* parse.cxx, parse.h: Allows the use of $x and @x identifier
+	during the preprocessing.
+
+2007-04-03  Pierre Peiffer  <pierre.peiffer@bull.net>
+
 	* parse.cxx: Add $# and @# identifiers to access the number
 	of arguments passed as 'number' or as 'string'.
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]