--- 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 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 + * parse.cxx, parse.h: Allows the use of $x and @x identifier + during the preprocessing. + +2007-04-03 Pierre Peiffer + * parse.cxx: Add $# and @# identifiers to access the number of arguments passed as 'number' or as 'string'.