diff options
author | fche <fche> | 2005-07-26 22:40:14 +0000 |
---|---|---|
committer | fche <fche> | 2005-07-26 22:40:14 +0000 |
commit | 54dfabe9e604ec06cdb5550f58420c60d0cbdbd9 (patch) | |
tree | 2dc021fd5534f57a51235a9598cec6cec9ed2342 | |
parent | f05bc729c752cee5eb11fde9193eea12a21b0d12 (diff) | |
download | systemtap-steved-54dfabe9e604ec06cdb5550f58420c60d0cbdbd9.tar.gz systemtap-steved-54dfabe9e604ec06cdb5550f58420c60d0cbdbd9.tar.xz systemtap-steved-54dfabe9e604ec06cdb5550f58420c60d0cbdbd9.zip |
2005-07-26 Frank Ch. Eigler <fche@redhat.com>
Support %{ embedded-c %}
* staptree.h (embeddedcode): New statement subtype. Stub support in
visitors.
* staptree.cxx: Ditto.
* parse.cxx: Parse %{ / %}. Accept "_" as identifier leading char.
(parse_probe): Simplify calling convention.
* elaborate.h: Store embedded code.
* elaborate.cxx: Pass it.
* translate.cxx: Transcribe it. Return some dropped module init/exit
code.
* Makefile.am: Add buildok/buildko tests.
* Makefile.in: Regenerated.
* main.cxx: Return EXIT_SUCCESS/FAILURE even for weird rc.
* testsuite/parseok/nine.stp: Test _identifiers.
* testsuite/transko/*.stp: Tweak to force -p3 rather than -p2 errors.
* testsuite/semok/transko.stp: ... and keep it that way in the future.
* testsuite/parse*/*: Some new tests for %{ %}.
* testsuite/build*/*: New tests for -p4.
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | Makefile.in | 7 | ||||
-rw-r--r-- | elaborate.cxx | 9 | ||||
-rw-r--r-- | elaborate.h | 38 | ||||
-rw-r--r-- | main.cxx | 2 | ||||
-rw-r--r-- | parse.cxx | 96 | ||||
-rw-r--r-- | parse.h | 8 | ||||
-rw-r--r-- | staptree.cxx | 136 | ||||
-rw-r--r-- | staptree.h | 24 | ||||
-rwxr-xr-x | testsuite/buildko/one.stp | 17 | ||||
-rwxr-xr-x | testsuite/buildok/one.stp | 16 | ||||
-rwxr-xr-x | testsuite/buildok/two.stp | 16 | ||||
-rwxr-xr-x | testsuite/parseko/ten.stp | 5 | ||||
-rwxr-xr-x | testsuite/parseok/nine.stp | 4 | ||||
-rwxr-xr-x | testsuite/parseok/twelve.stp | 9 | ||||
-rwxr-xr-x | testsuite/semok/transko.stp | 10 | ||||
-rwxr-xr-x | testsuite/transko/one.stp | 2 | ||||
-rwxr-xr-x | testsuite/transko/two.stp | 3 | ||||
-rwxr-xr-x | testsuite/transok/nine.stp | 12 | ||||
-rw-r--r-- | translate.cxx | 74 | ||||
-rw-r--r-- | translate.h | 2 |
22 files changed, 384 insertions, 134 deletions
@@ -1,3 +1,24 @@ +2005-07-26 Frank Ch. Eigler <fche@redhat.com> + + Support %{ embedded-c %} + * staptree.h (embeddedcode): New statement subtype. Stub support in + visitors. + * staptree.cxx: Ditto. + * parse.cxx: Parse %{ / %}. Accept "_" as identifier leading char. + (parse_probe): Simplify calling convention. + * elaborate.h: Store embedded code. + * elaborate.cxx: Pass it. + * translate.cxx: Transcribe it. Return some dropped module init/exit + code. + * Makefile.am: Add buildok/buildko tests. + * Makefile.in: Regenerated. + * main.cxx: Return EXIT_SUCCESS/FAILURE even for weird rc. + * testsuite/parseok/nine.stp: Test _identifiers. + * testsuite/transko/*.stp: Tweak to force -p3 rather than -p2 errors. + * testsuite/semok/transko.stp: ... and keep it that way in the future. + * testsuite/parse*/*: Some new tests for %{ %}. + * testsuite/build*/*: New tests for -p4. + 2005-07-26 Martin Hunt <hunt@redhat.com> * Makefile.am (AM_CPPFLAGS): Set PKGLIBDIR correctly. diff --git a/Makefile.am b/Makefile.am index a689999d..de152e92 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,12 +38,15 @@ install-data-local: p=$(srcdir)/testsuite/parse s=$(srcdir)/testsuite/sem t=$(srcdir)/testsuite/trans +b=$(srcdir)/testsuite/build TESTS = $(wildcard $(p)ok/*.stp) $(wildcard $(p)ko/*.stp) \ $(wildcard $(s)ok/*.stp) $(wildcard $(s)ko/*.stp) \ - $(wildcard $(t)ok/*.stp) $(wildcard $(t)ko/*.stp) + $(wildcard $(t)ok/*.stp) $(wildcard $(t)ko/*.stp) \ + $(wildcard $(b)ok/*.stp) $(wildcard $(b)ko/*.stp) XFAIL_TESTS = $(wildcard $(p)ko/*.stp) \ $(wildcard $(s)ko/*.stp) \ - $(wildcard $(t)ko/*.stp) + $(wildcard $(t)ko/*.stp) \ + $(wildcard $(b)ko/*.stp) TESTS_ENVIRONMENT = $(srcdir)/runtest.sh diff --git a/Makefile.in b/Makefile.in index 730161e1..4ca59a02 100644 --- a/Makefile.in +++ b/Makefile.in @@ -198,13 +198,16 @@ EXTRA_DIST = testsuite runtime $(wildcard $(srcdir)/*.h) systemtap.spec p = $(srcdir)/testsuite/parse s = $(srcdir)/testsuite/sem t = $(srcdir)/testsuite/trans +b = $(srcdir)/testsuite/build TESTS = $(wildcard $(p)ok/*.stp) $(wildcard $(p)ko/*.stp) \ $(wildcard $(s)ok/*.stp) $(wildcard $(s)ko/*.stp) \ - $(wildcard $(t)ok/*.stp) $(wildcard $(t)ko/*.stp) + $(wildcard $(t)ok/*.stp) $(wildcard $(t)ko/*.stp) \ + $(wildcard $(b)ok/*.stp) $(wildcard $(b)ko/*.stp) XFAIL_TESTS = $(wildcard $(p)ko/*.stp) \ $(wildcard $(s)ko/*.stp) \ - $(wildcard $(t)ko/*.stp) + $(wildcard $(t)ko/*.stp) \ + $(wildcard $(b)ko/*.stp) TESTS_ENVIRONMENT = $(srcdir)/runtest.sh all: config.h diff --git a/elaborate.cxx b/elaborate.cxx index 8980895f..e7d9f967 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -580,6 +580,9 @@ semantic_pass_symbols (systemtap_session& s) for (unsigned i=0; i<dome->functions.size(); i++) s.functions.push_back (dome->functions[i]); + for (unsigned i=0; i<dome->embeds.size(); i++) + s.embeds.push_back (dome->embeds[i]); + // Pass 2: process functions for (unsigned i=0; i<dome->functions.size(); i++) @@ -1385,6 +1388,12 @@ typeresolution_info::visit_block (block* e) void +typeresolution_info::visit_embeddedcode (embeddedcode* e) +{ +} + + +void typeresolution_info::visit_if_statement (if_statement* e) { t = pe_long; diff --git a/elaborate.h b/elaborate.h index a4c9f2cf..599bc230 100644 --- a/elaborate.h +++ b/elaborate.h @@ -65,9 +65,10 @@ struct typeresolution_info: public visitor exp_type t; // implicit parameter for nested visit call; may clobber - void visit_block (block *s); - void visit_null_statement (null_statement *s); - void visit_expr_statement (expr_statement *s); + void visit_block (block* s); + void visit_embeddedcode (embeddedcode* s); + void visit_null_statement (null_statement* s); + void visit_expr_statement (expr_statement* s); void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); @@ -140,11 +141,11 @@ struct derived_probe_builder { virtual void build(systemtap_session & sess, - probe * base, - probe_point * location, - std::map<std::string, literal *> const & parameters, - std::vector<probe *> & results_to_expand_further, - std::vector<derived_probe *> & finished_results) = 0; + probe* base, + probe_point* location, + std::map<std::string, literal*> const & parameters, + std::vector<probe*> & results_to_expand_further, + std::vector<derived_probe*> & finished_results) = 0; virtual ~derived_probe_builder() {} }; @@ -169,20 +170,20 @@ match_key class match_node { - std::map<match_key, match_node *> sub; - derived_probe_builder * end; + std::map<match_key, match_node*> sub; + derived_probe_builder* end; public: match_node(); - derived_probe_builder * find_builder(std::vector<probe_point::component *> const & components, + derived_probe_builder* find_builder(std::vector<probe_point::component*> const & components, unsigned pos, - std::vector< std::pair<std::string, literal *> > & parameters); + std::vector< std::pair<std::string, literal*> > & parameters); - match_node * bind(match_key const & k); - match_node * bind(std::string const & k); - match_node * bind_str(std::string const & k); - match_node * bind_num(std::string const & k); - void bind(derived_probe_builder * e); + match_node* bind(match_key const & k); + match_node* bind(std::string const & k); + match_node* bind_str(std::string const & k); + match_node* bind_num(std::string const & k); + void bind(derived_probe_builder* e); }; // ------------------------------------------------------------------------ @@ -211,7 +212,7 @@ struct systemtap_session std::string tmpdir; std::string translated_source; // C source code - match_node * pattern_root; + match_node* pattern_root; void register_library_aliases(); // parse trees for the various script files @@ -223,6 +224,7 @@ struct systemtap_session std::vector<vardecl*> globals; std::vector<functiondecl*> functions; std::vector<derived_probe*> probes; + std::vector<embeddedcode*> embeds; // unparser data translator_output* op; @@ -381,5 +381,5 @@ main (int argc, char * const argv []) } } - return rc; + return rc ? EXIT_FAILURE : EXIT_SUCCESS; } @@ -63,8 +63,10 @@ operator << (ostream& o, const token& t) t.type == tok_operator ? "operator" : t.type == tok_string ? "string" : t.type == tok_number ? "number" : + t.type == tok_embedded ? "embedded-code" : "unknown token"); + // XXX: filter out embedded-code contents? o << " '"; for (unsigned i=0; i<t.content.length(); i++) { @@ -194,7 +196,7 @@ lexer::scan () if (isspace (c)) goto skip; - else if (isalpha (c) || c == '$') + else if (isalpha (c) || c == '$' || c == '_') { n->type = tok_identifier; n->content = (char) c; @@ -300,6 +302,31 @@ lexer::scan () } goto skip; } + else if (c == '%' && c2 == '{') // embedded code + { + n->type = tok_embedded; + (void) input_get (); // swallow '{' already in c2 + while (true) + { + c = input_get (); + if (c == 0) // EOF + { + n->type = tok_junk; + break; + } + if (c == '%') + { + c2 = input_peek (); + if (c2 == '}') + { + (void) input_get (); // swallow '}' too + break; + } + } + n->content += c; + } + return n; + } // We're committed to recognizing at least the first character // as an operator. @@ -373,21 +400,15 @@ parser::parse () empty = false; if (t->type == tok_identifier && t->content == "probe") - { - probe * p; - probe_alias * a; - parse_probe (p, a); - if (a) - f->aliases.push_back(a); - else - f->probes.push_back (p); - } + parse_probe (f->probes, f->aliases); else if (t->type == tok_identifier && t->content == "global") parse_global (f->globals); else if (t->type == tok_identifier && t->content == "function") f->functions.push_back (parse_functiondecl ()); + else if (t->type == tok_embedded) + f->embeds.push_back (parse_embeddedcode ()); else - throw parse_error ("expected 'probe', 'global', or 'function'"); + throw parse_error ("expected 'probe', 'global', 'function', or embedded code"); } catch (parse_error& pe) { @@ -423,16 +444,13 @@ parser::parse () void -parser::parse_probe (probe * & probe_ret, - probe_alias * & alias_ret) +parser::parse_probe (std::vector<probe *> & probe_ret, + std::vector<probe_alias *> & alias_ret) { const token* t0 = next (); if (! (t0->type == tok_identifier && t0->content == "probe")) throw parse_error ("expected 'probe'"); - probe_ret = NULL; - alias_ret = NULL; - vector<probe_point *> aliases; vector<probe_point *> locations; @@ -473,21 +491,36 @@ parser::parse_probe (probe * & probe_ret, throw parse_error ("expected probe point specifier"); } - probe *p; if (aliases.empty()) { - probe_ret = new probe; - p = probe_ret; + probe* p = new probe; + p->tok = t0; + p->locations = locations; + p->body = parse_stmt_block (); + probe_ret.push_back (p); } else { - alias_ret = new probe_alias(aliases);; - p = alias_ret; + probe_alias* p = new probe_alias (aliases); + p->tok = t0; + p->locations = locations; + p->body = parse_stmt_block (); + alias_ret.push_back (p); } +} - p->tok = t0; - p->locations = locations; - p->body = parse_stmt_block (); + +embeddedcode* +parser::parse_embeddedcode () +{ + embeddedcode* e = new embeddedcode; + const token* t = next (); + if (t->type != tok_embedded) + throw parse_error ("expected embedded code"); + + e->tok = t; + e->code = t->content; + return e; } @@ -518,15 +551,15 @@ parser::parse_stmt_block () catch (parse_error& pe) { print_error (pe); + // Quietly swallow all tokens until the next ';' or '}'. while (1) { const token* t = peek (); - if (! t) - return 0; + if (! t) return 0; next (); - if (t->type == tok_operator && (t->content == "}" - || t->content == ";")) + if (t->type == tok_operator + && (t->content == "}" || t->content == ";")) break; } } @@ -572,6 +605,7 @@ parser::parse_statement () t->type == tok_number || t->type == tok_string)) return parse_expr_statement (); + // XXX: consider generally accepting tok_embedded here too else throw parse_error ("expected statement"); } @@ -657,7 +691,11 @@ parser::parse_functiondecl () throw parse_error ("expected ',' or ')'"); } - fd->body = parse_stmt_block (); + t = peek (); + if (t && t->type == tok_embedded) + fd->body = parse_embeddedcode (); + else + fd->body = parse_stmt_block (); return fd; } @@ -27,7 +27,8 @@ struct source_loc enum token_type { - tok_junk, tok_identifier, tok_operator, tok_string, tok_number + tok_junk, tok_identifier, tok_operator, tok_string, tok_number, + tok_embedded // XXX: add tok_keyword throughout }; @@ -95,10 +96,11 @@ private: unsigned num_errors; private: // nonterminals - void parse_probe (probe *&, probe_alias *&); + void parse_probe (std::vector<probe*>&, std::vector<probe_alias*>&); + void parse_global (std::vector<vardecl*>&); + embeddedcode* parse_embeddedcode (); probe_point* parse_probe_point (); literal* parse_literal (); - void parse_global (std::vector<vardecl*>&); functiondecl* parse_functiondecl (); block* parse_stmt_block (); statement* parse_statement (); diff --git a/staptree.cxx b/staptree.cxx index 9a6d72bd..fb7c56aa 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -288,6 +288,13 @@ ostream& operator << (ostream& o, statement& k) } +void embeddedcode::print (ostream &o) +{ + o << "%{"; + o << code; + o << "%}"; +} + void block::print (ostream& o) { o << "{" << endl; @@ -374,6 +381,9 @@ void stapfile::print (ostream& o) { o << "# file " << name << endl; + for (unsigned i=0; i<embeds.size(); i++) + embeds[i]->print (o); + for (unsigned i=0; i<globals.size(); i++) { o << "global "; @@ -477,6 +487,14 @@ block::visit (visitor* u) u->visit_block (this); } + +void +embeddedcode::visit (visitor* u) +{ + u->visit_embeddedcode (this); +} + + void for_loop::visit (visitor* u) { @@ -637,19 +655,24 @@ functioncall::visit (visitor* u) // ------------------------------------------------------------------------ void -traversing_visitor::visit_block (block *s) +traversing_visitor::visit_block (block* s) { for (unsigned i=0; i<s->statements.size(); i++) s->statements[i]->visit (this); } void -traversing_visitor::visit_null_statement (null_statement *s) +traversing_visitor::visit_embeddedcode (embeddedcode* s) +{ +} + +void +traversing_visitor::visit_null_statement (null_statement* s) { } void -traversing_visitor::visit_expr_statement (expr_statement *s) +traversing_visitor::visit_expr_statement (expr_statement* s) { s->value->visit (this); } @@ -826,19 +849,25 @@ throwing_visitor::throwone (const token* t) } void -throwing_visitor::visit_block (block *s) +throwing_visitor::visit_block (block* s) +{ + throwone (s->tok); +} + +void +throwing_visitor::visit_embeddedcode (embeddedcode* s) { throwone (s->tok); } void -throwing_visitor::visit_null_statement (null_statement *s) +throwing_visitor::visit_null_statement (null_statement* s) { throwone (s->tok); } void -throwing_visitor::visit_expr_statement (expr_statement *s) +throwing_visitor::visit_expr_statement (expr_statement* s) { throwone (s->tok); } @@ -992,12 +1021,12 @@ throwing_visitor::visit_functioncall (functioncall* e) // ------------------------------------------------------------------------ template <typename T> static void -require (deep_copy_visitor *v, T *dst, T src) +require (deep_copy_visitor* v, T* dst, T src) { *dst = NULL; if (src != NULL) { - v->targets.push(static_cast<void *>(dst)); + v->targets.push(static_cast<void* >(dst)); src->visit(v); v->targets.pop(); assert(*dst); @@ -1005,20 +1034,20 @@ require (deep_copy_visitor *v, T *dst, T src) } template <typename T> static void -provide (deep_copy_visitor *v, T src) +provide (deep_copy_visitor* v, T src) { assert(!v->targets.empty()); *(static_cast<T*>(v->targets.top())) = src; } void -deep_copy_visitor::visit_block (block *s) +deep_copy_visitor::visit_block (block* s) { - block *n = new block; + block* n = new block; n->tok = s->tok; for (unsigned i = 0; i < s->statements.size(); ++i) { - statement *ns; + statement* ns; require <statement*> (this, &ns, s->statements[i]); n->statements.push_back(ns); } @@ -1026,17 +1055,26 @@ deep_copy_visitor::visit_block (block *s) } void -deep_copy_visitor::visit_null_statement (null_statement *s) +deep_copy_visitor::visit_embeddedcode (embeddedcode* s) +{ + embeddedcode* n = new embeddedcode; + n->tok = s->tok; + n->code = s->code; + provide <embeddedcode*> (this, n); +} + +void +deep_copy_visitor::visit_null_statement (null_statement* s) { - null_statement *n = new null_statement; + null_statement* n = new null_statement; n->tok = s->tok; provide <null_statement*> (this, n); } void -deep_copy_visitor::visit_expr_statement (expr_statement *s) +deep_copy_visitor::visit_expr_statement (expr_statement* s) { - expr_statement *n = new expr_statement; + expr_statement* n = new expr_statement; n->tok = s->tok; require <expression*> (this, &(n->value), s->value); provide <expr_statement*> (this, n); @@ -1045,7 +1083,7 @@ deep_copy_visitor::visit_expr_statement (expr_statement *s) void deep_copy_visitor::visit_if_statement (if_statement* s) { - if_statement *n = new if_statement; + if_statement* n = new if_statement; n->tok = s->tok; require <expression*> (this, &(n->condition), s->condition); require <statement*> (this, &(n->thenblock), s->thenblock); @@ -1056,7 +1094,7 @@ deep_copy_visitor::visit_if_statement (if_statement* s) void deep_copy_visitor::visit_for_loop (for_loop* s) { - for_loop *n = new for_loop; + for_loop* n = new for_loop; n->tok = s->tok; require <expr_statement*> (this, &(n->init), s->init); require <expression*> (this, &(n->cond), s->cond); @@ -1068,11 +1106,11 @@ deep_copy_visitor::visit_for_loop (for_loop* s) void deep_copy_visitor::visit_foreach_loop (foreach_loop* s) { - foreach_loop *n = new foreach_loop; + foreach_loop* n = new foreach_loop; n->tok = s->tok; for (unsigned i = 0; i < s->indexes.size(); ++i) { - symbol *sym; + symbol* sym; require <symbol*> (this, &sym, s->indexes[i]); n->indexes.push_back(sym); } @@ -1085,7 +1123,7 @@ deep_copy_visitor::visit_foreach_loop (foreach_loop* s) void deep_copy_visitor::visit_return_statement (return_statement* s) { - return_statement *n = new return_statement; + return_statement* n = new return_statement; n->tok = s->tok; require <expression*> (this, &(n->value), s->value); provide <return_statement*> (this, n); @@ -1094,7 +1132,7 @@ deep_copy_visitor::visit_return_statement (return_statement* s) void deep_copy_visitor::visit_delete_statement (delete_statement* s) { - delete_statement *n = new delete_statement; + delete_statement* n = new delete_statement; n->tok = s->tok; require <expression*> (this, &(n->value), s->value); provide <delete_statement*> (this, n); @@ -1103,7 +1141,7 @@ deep_copy_visitor::visit_delete_statement (delete_statement* s) void deep_copy_visitor::visit_next_statement (next_statement* s) { - next_statement *n = new next_statement; + next_statement* n = new next_statement; n->tok = s->tok; provide <next_statement*> (this, n); } @@ -1111,7 +1149,7 @@ deep_copy_visitor::visit_next_statement (next_statement* s) void deep_copy_visitor::visit_break_statement (break_statement* s) { - break_statement *n = new break_statement; + break_statement* n = new break_statement; n->tok = s->tok; provide <break_statement*> (this, n); } @@ -1119,7 +1157,7 @@ deep_copy_visitor::visit_break_statement (break_statement* s) void deep_copy_visitor::visit_continue_statement (continue_statement* s) { - continue_statement *n = new continue_statement; + continue_statement* n = new continue_statement; n->tok = s->tok; provide <continue_statement*> (this, n); } @@ -1127,7 +1165,7 @@ deep_copy_visitor::visit_continue_statement (continue_statement* s) void deep_copy_visitor::visit_literal_string (literal_string* e) { - literal_string *n = new literal_string(e->value); + literal_string* n = new literal_string(e->value); n->tok = e->tok; provide <literal_string*> (this, n); } @@ -1135,7 +1173,7 @@ deep_copy_visitor::visit_literal_string (literal_string* e) void deep_copy_visitor::visit_literal_number (literal_number* e) { - literal_number *n = new literal_number(e->value); + literal_number* n = new literal_number(e->value); n->tok = e->tok; provide <literal_number*> (this, n); } @@ -1143,7 +1181,7 @@ deep_copy_visitor::visit_literal_number (literal_number* e) void deep_copy_visitor::visit_binary_expression (binary_expression* e) { - binary_expression *n = new binary_expression; + binary_expression* n = new binary_expression; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->left), e->left); @@ -1154,7 +1192,7 @@ deep_copy_visitor::visit_binary_expression (binary_expression* e) void deep_copy_visitor::visit_unary_expression (unary_expression* e) { - unary_expression *n = new unary_expression; + unary_expression* n = new unary_expression; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->operand), e->operand); @@ -1164,7 +1202,7 @@ deep_copy_visitor::visit_unary_expression (unary_expression* e) void deep_copy_visitor::visit_pre_crement (pre_crement* e) { - pre_crement *n = new pre_crement; + pre_crement* n = new pre_crement; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->operand), e->operand); @@ -1174,7 +1212,7 @@ deep_copy_visitor::visit_pre_crement (pre_crement* e) void deep_copy_visitor::visit_post_crement (post_crement* e) { - post_crement *n = new post_crement; + post_crement* n = new post_crement; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->operand), e->operand); @@ -1185,7 +1223,7 @@ deep_copy_visitor::visit_post_crement (post_crement* e) void deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e) { - logical_or_expr *n = new logical_or_expr; + logical_or_expr* n = new logical_or_expr; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->left), e->left); @@ -1196,7 +1234,7 @@ deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e) void deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e) { - logical_and_expr *n = new logical_and_expr; + logical_and_expr* n = new logical_and_expr; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->left), e->left); @@ -1207,7 +1245,7 @@ deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e) void deep_copy_visitor::visit_array_in (array_in* e) { - array_in *n = new array_in; + array_in* n = new array_in; n->tok = e->tok; require <arrayindex*> (this, &(n->operand), e->operand); provide <array_in*> (this, n); @@ -1216,7 +1254,7 @@ deep_copy_visitor::visit_array_in (array_in* e) void deep_copy_visitor::visit_comparison (comparison* e) { - comparison *n = new comparison; + comparison* n = new comparison; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->left), e->left); @@ -1227,7 +1265,7 @@ deep_copy_visitor::visit_comparison (comparison* e) void deep_copy_visitor::visit_concatenation (concatenation* e) { - concatenation *n = new concatenation; + concatenation* n = new concatenation; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->left), e->left); @@ -1238,7 +1276,7 @@ deep_copy_visitor::visit_concatenation (concatenation* e) void deep_copy_visitor::visit_ternary_expression (ternary_expression* e) { - ternary_expression *n = new ternary_expression; + ternary_expression* n = new ternary_expression; n->tok = e->tok; require <expression*> (this, &(n->cond), e->cond); require <expression*> (this, &(n->truevalue), e->truevalue); @@ -1249,7 +1287,7 @@ deep_copy_visitor::visit_ternary_expression (ternary_expression* e) void deep_copy_visitor::visit_assignment (assignment* e) { - assignment *n = new assignment; + assignment* n = new assignment; n->op = e->op; n->tok = e->tok; require <expression*> (this, &(n->left), e->left); @@ -1260,7 +1298,7 @@ deep_copy_visitor::visit_assignment (assignment* e) void deep_copy_visitor::visit_symbol (symbol* e) { - symbol *n = new symbol; + symbol* n = new symbol; n->tok = e->tok; n->name = e->name; n->referent = NULL; @@ -1270,13 +1308,13 @@ deep_copy_visitor::visit_symbol (symbol* e) void deep_copy_visitor::visit_arrayindex (arrayindex* e) { - arrayindex *n = new arrayindex; + arrayindex* n = new arrayindex; n->tok = e->tok; n->base = e->base; n->referent = NULL; for (unsigned i = 0; i < e->indexes.size(); ++i) { - expression *ne; + expression* ne; require <expression*> (this, &ne, e->indexes[i]); n->indexes.push_back(ne); } @@ -1286,32 +1324,32 @@ deep_copy_visitor::visit_arrayindex (arrayindex* e) void deep_copy_visitor::visit_functioncall (functioncall* e) { - functioncall *n = new functioncall; + functioncall* n = new functioncall; n->tok = e->tok; n->function = e->function; n->referent = NULL; for (unsigned i = 0; i < e->args.size(); ++i) { - expression *na; + expression* na; require <expression*> (this, &na, e->args[i]); n->args.push_back(na); } provide <functioncall*> (this, n); } -block * -deep_copy_visitor::deep_copy (block *b) +block* +deep_copy_visitor::deep_copy (block* b) { - block *n; + block* n; deep_copy_visitor v; require <block*> (&v, &n, b); return n; } -statement * -deep_copy_visitor::deep_copy (statement *s) +statement* +deep_copy_visitor::deep_copy (statement* s) { - statement *n; + statement* n; deep_copy_visitor v; require <statement*> (&v, &n, s); return n; @@ -236,12 +236,12 @@ struct vardecl_builtin: public vardecl }; -struct block; +struct statement; struct functiondecl: public symboldecl { std::vector<vardecl*> formal_args; std::vector<vardecl*> locals; - block* body; + statement* body; functiondecl (); void print (std::ostream& o); void printsig (std::ostream& o); @@ -263,6 +263,14 @@ struct statement std::ostream& operator << (std::ostream& o, statement& k); +struct embeddedcode: public statement +{ + std::string code; + void print (std::ostream& o); + void visit (visitor* u); +}; + + struct block: public statement { std::vector<statement*> statements; @@ -358,6 +366,7 @@ struct next_statement: public statement struct probe; struct probe_alias; +struct embeddedcode; struct stapfile { std::string name; @@ -365,10 +374,13 @@ struct stapfile std::vector<probe_alias*> aliases; std::vector<functiondecl*> functions; std::vector<vardecl*> globals; + std::vector<embeddedcode*> embeds; void print (std::ostream& o); }; + + struct probe_point { struct component // XXX: sort of a restricted functioncall @@ -398,13 +410,11 @@ struct probe virtual ~probe() {} }; -struct probe_alias - : public probe +struct probe_alias: public probe { probe_alias(std::vector<probe_point*> const & aliases); std::vector<probe_point*> alias_names; virtual void printsig (std::ostream &o); - virtual ~probe_alias() {} }; @@ -414,6 +424,7 @@ struct visitor { virtual ~visitor () {} virtual void visit_block (block *s) = 0; + virtual void visit_embeddedcode (embeddedcode *s) = 0; virtual void visit_null_statement (null_statement *s) = 0; virtual void visit_expr_statement (expr_statement *s) = 0; virtual void visit_if_statement (if_statement* s) = 0; @@ -449,6 +460,7 @@ struct visitor struct traversing_visitor: public visitor { void visit_block (block *s); + void visit_embeddedcode (embeddedcode *s); void visit_null_statement (null_statement *s); void visit_expr_statement (expr_statement *s); void visit_if_statement (if_statement* s); @@ -489,6 +501,7 @@ struct throwing_visitor: public visitor virtual void throwone (const token* t); void visit_block (block *s); + void visit_embeddedcode (embeddedcode *s); void visit_null_statement (null_statement *s); void visit_expr_statement (expr_statement *s); void visit_if_statement (if_statement* s); @@ -531,6 +544,7 @@ struct deep_copy_visitor: public visitor static block *deep_copy (block *s); void visit_block (block *s); + void visit_embeddedcode (embeddedcode *s); void visit_null_statement (null_statement *s); void visit_expr_statement (expr_statement *s); void visit_if_statement (if_statement* s); diff --git a/testsuite/buildko/one.stp b/testsuite/buildko/one.stp new file mode 100755 index 00000000..b8d54c51 --- /dev/null +++ b/testsuite/buildko/one.stp @@ -0,0 +1,17 @@ +#! stap -p4 + +%{ +#include <linux/version.h> +%} + +function get_release () %{ +/* this is a type error, detected by gcc */ +THIS->__retvalue = 5; +%} + +probe begin +{ + printk("hello from systemtap, kernel version " . get_release()) +} + + diff --git a/testsuite/buildok/one.stp b/testsuite/buildok/one.stp new file mode 100755 index 00000000..1f4f8f9b --- /dev/null +++ b/testsuite/buildok/one.stp @@ -0,0 +1,16 @@ +#! stap -p4 + +global foo, bar + +probe begin +{ + x = 10 + foo["hello"] = 25 + foo["hello"]++ + ++foo["hello"] + x = foo["hello"] + foo["yo"] *= bar[x, foo["hello"], "goodbye"]++; + printk("hello from systemtap") +} + + diff --git a/testsuite/buildok/two.stp b/testsuite/buildok/two.stp new file mode 100755 index 00000000..83a4705c --- /dev/null +++ b/testsuite/buildok/two.stp @@ -0,0 +1,16 @@ +#! stap -p4 + +%{ +#include <linux/version.h> +%} + +function get_release () %{ +strncpy(THIS->__retvalue, UTS_RELEASE, MAXSTRINGLEN); +%} + +probe begin +{ + printk("hello from systemtap, kernel version " . get_release()) +} + + diff --git a/testsuite/parseko/ten.stp b/testsuite/parseko/ten.stp new file mode 100755 index 00000000..a268db4e --- /dev/null +++ b/testsuite/parseko/ten.stp @@ -0,0 +1,5 @@ +#! stap -p1 + +probe foo { + %{ /* not a valid place for embedded code */ %} +} diff --git a/testsuite/parseok/nine.stp b/testsuite/parseok/nine.stp index 13e40cbf..3582907a 100755 --- a/testsuite/parseok/nine.stp +++ b/testsuite/parseok/nine.stp @@ -9,7 +9,7 @@ probe two { a = b c = d - e = f(); - g = h; + _e = $f(); + _g = h_; ; } diff --git a/testsuite/parseok/twelve.stp b/testsuite/parseok/twelve.stp new file mode 100755 index 00000000..5b8a3932 --- /dev/null +++ b/testsuite/parseok/twelve.stp @@ -0,0 +1,9 @@ +#! stap -p1 + +%{ +/* hello world */ +%} + +function foo (p1, p2) %{ + /* goodbye world */ +%} diff --git a/testsuite/semok/transko.stp b/testsuite/semok/transko.stp new file mode 100755 index 00000000..9c78c6ef --- /dev/null +++ b/testsuite/semok/transko.stp @@ -0,0 +1,10 @@ +#! /bin/sh + +# make sure that we can *semcheck* all transko test files, to ensure +# that it is translation-time checks that fail, not earlier ones errors + +set -e +for file in ${SRCDIR}/testsuite/transko/*.stp +do + ./stap -p2 $file +done diff --git a/testsuite/transko/one.stp b/testsuite/transko/one.stp index b6bb3e89..3c69161d 100755 --- a/testsuite/transko/one.stp +++ b/testsuite/transko/one.stp @@ -1,6 +1,6 @@ #! stap -p3 -probe foo { +probe begin { 1 = a a+1 = 4 } diff --git a/testsuite/transko/two.stp b/testsuite/transko/two.stp index 77e1f6d0..5185281a 100755 --- a/testsuite/transko/two.stp +++ b/testsuite/transko/two.stp @@ -2,9 +2,10 @@ function bar () { next + return 0 } -probe foo { +probe end { break for (a=0; a<10; a=a+1) for (b=0; b<10; b=b+1) ; continue diff --git a/testsuite/transok/nine.stp b/testsuite/transok/nine.stp new file mode 100755 index 00000000..a75fad5e --- /dev/null +++ b/testsuite/transok/nine.stp @@ -0,0 +1,12 @@ +#! stap -p3 + +%{ +void just_some_declaration () {} +%} + +function bar(foo) %{ just_some_declaration(); THIS->__retvalue = THIS->foo + 5; %} + +probe begin +{ + bar (5) + 0 +} diff --git a/translate.cxx b/translate.cxx index d794c6be..e4bf28b9 100644 --- a/translate.cxx +++ b/translate.cxx @@ -46,7 +46,7 @@ struct c_unparser: public unparser, public visitor unsigned tmpvar_counter; unsigned label_counter; - c_unparser (systemtap_session *ss): + c_unparser (systemtap_session* ss): session (ss), o (ss->op), current_probe(0), current_function (0), tmpvar_counter (0), label_counter (0) {} ~c_unparser () {} @@ -68,7 +68,7 @@ struct c_unparser: public unparser, public visitor string c_typename (exp_type e); string c_varname (const string& e); - void c_assign (var& lvalue, const string& rvalue, const token *tok); + void c_assign (var& lvalue, const string& rvalue, const token* tok); void c_assign (const string& lvalue, expression* rvalue, const string& msg); void c_assign (const string& lvalue, const string& rvalue, exp_type type, const string& msg, const token* tok); @@ -82,23 +82,24 @@ struct c_unparser: public unparser, public visitor void c_strcpy (const string& lvalue, const string& rvalue); void c_strcpy (const string& lvalue, expression* rvalue); - bool is_local (vardecl const *r, token const *tok); + bool is_local (vardecl const* r, token const* tok); tmpvar gensym(exp_type ty); - var getvar(vardecl *v, token const *tok = NULL); - itervar getiter(foreach_loop *f); - mapvar getmap(vardecl *v, token const *tok = NULL); + var getvar(vardecl* v, token const* tok = NULL); + itervar getiter(foreach_loop* f); + mapvar getmap(vardecl* v, token const* tok = NULL); - void load_map_indices(arrayindex *e, + void load_map_indices(arrayindex* e, vector<tmpvar> & idx); - void collect_map_index_types(vector<vardecl *> const & vars, + void collect_map_index_types(vector<vardecl* > const & vars, set< exp_type > & value_types, set< vector<exp_type> > & index_types); - void visit_block (block *s); - void visit_null_statement (null_statement *s); - void visit_expr_statement (expr_statement *s); + void visit_block (block* s); + void visit_embeddedcode (embeddedcode* s); + void visit_null_statement (null_statement* s); + void visit_expr_statement (expr_statement* s); void visit_if_statement (if_statement* s); void visit_for_loop (for_loop* s); void visit_foreach_loop (foreach_loop* s); @@ -174,16 +175,16 @@ struct c_unparser_assignment: void prepare_rvalue (string const & op, tmpvar const & rval, - token const * tok); + token const* tok); void c_assignop(tmpvar & res, var const & lvar, tmpvar const & tmp, - token const * tok); + token const* tok); // only symbols and arrayindex nodes are possible lvalues - void visit_symbol (symbol *e); - void visit_arrayindex (arrayindex *e); + void visit_symbol (symbol* e); + void visit_arrayindex (arrayindex* e); }; @@ -198,8 +199,8 @@ struct c_tmpcounter_assignment: parent (p), op (o), rvalue (e) {} // only symbols and arrayindex nodes are possible lvalues - void visit_symbol (symbol *e); - void visit_arrayindex (arrayindex *e); + void visit_symbol (symbol* e); + void visit_arrayindex (arrayindex* e); }; @@ -390,7 +391,7 @@ class itervar public: - itervar (foreach_loop *e, unsigned & counter) + itervar (foreach_loop* e, unsigned & counter) : referent_ty(e->base_referent->type), name("__tmp" + stringify(counter++)) { @@ -742,6 +743,8 @@ c_unparser::emit_function (functiondecl* v) << "& c->locals[c->nesting].function_" << c_varname (v->name) << ";"; o->newline(-1) << "(void) l;"; // make sure "l" is marked used + o->newline() << "#define THIS l"; + o->newline() << "if (0) goto out;"; // make sure out: is marked used // initialize locals for (unsigned i=0; i<v->locals.size(); i++) @@ -762,6 +765,7 @@ c_unparser::emit_function (functiondecl* v) o->newline(-1) << "out:"; o->newline(1) << ";"; + o->newline() << "#undef THIS"; o->newline(-1) << "}" << endl; } @@ -1266,6 +1270,13 @@ c_unparser::visit_block (block *s) void +c_unparser::visit_embeddedcode (embeddedcode *s) +{ + o->newline() << s->code; +} + + +void c_unparser::visit_null_statement (null_statement *s) { o->newline() << "/* null */;"; @@ -2073,10 +2084,18 @@ translate_pass (systemtap_session& s) s.op->newline() << "#else"; s.op->newline() << "#include \"runtime.h\""; s.op->newline() << "#include <linux/string.h>"; + // XXX + s.op->newline() << "#define KALLSYMS_LOOKUP_NAME \"\""; + s.op->newline() << "#define KALLSYMS_LOOKUP 0"; s.op->newline() << "#endif"; s.up->emit_common_header (); + for (unsigned i=0; i<s.embeds.size(); i++) + { + s.op->newline() << s.embeds[i]->code << endl; + } + for (unsigned i=0; i<s.globals.size(); i++) { s.op->newline(); @@ -2113,13 +2132,28 @@ translate_pass (systemtap_session& s) s.op->newline() << "/* test mode mainline */"; s.op->newline() << "int main () {"; - s.op->newline(1) << "int rc = probe_start ();"; - s.op->newline() << "if (!rc) probe_exit ();"; + s.op->newline(1) << "int rc = systemtap_module_init ();"; + s.op->newline() << "if (!rc) systemtap_module_exit ();"; s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; s.op->newline() << "#else"; + + s.op->newline(); + // XXX + s.op->newline() << "int probe_start () {"; + s.op->newline(1) << "return systemtap_module_init ();"; + s.op->newline(-1) << "}"; + s.op->newline(); + s.op->newline() << "void probe_exit () {"; + // XXX: need to reference these static functions for -Werror avoidance + s.op->newline(1) << "if (0) next_fmt ((void *) 0, (void *) 0);"; + s.op->newline() << "if (0) _stp_dbug(\"\", 0, \"\");"; + s.op->newline() << "systemtap_module_exit ();"; + s.op->newline(-1) << "}"; + s.op->newline() << "MODULE_DESCRIPTION(\"systemtap probe\");"; + s.op->newline() << "MODULE_LICENSE(\"GPL\");"; // XXX s.op->newline() << "#endif"; s.op->line() << endl; diff --git a/translate.h b/translate.h index 0627994b..2a012273 100644 --- a/translate.h +++ b/translate.h @@ -53,9 +53,9 @@ struct unparser // starting, begin, running, suspended, errored, ending, ended // }; // static atomic_t session_state; - // static atomic_t errorcount; /* subcategorize? */ // // struct context { + // unsigned errorcount; // unsigned busy; // unsigned actioncount; // unsigned nesting; |