summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--parse.cxx37
-rw-r--r--parse.h2
-rw-r--r--staptree.cxx86
-rw-r--r--staptree.h9
-rwxr-xr-xtestsuite/parseko/four.stp5
-rwxr-xr-xtestsuite/parseok/three.stp7
-rwxr-xr-xtestsuite/semok/six.stp7
8 files changed, 141 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index a03c482b..d87b69dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2005-03-04 Frank Ch. Eigler <fche@redhat.com>
+
+ * parse.cxx (scan): Support '$' characters in identifiers.
+ (parse_symbol): Support thread-> / process-> shorthand.
+ * staptree.cxx (symresolution_info::find): Split up into
+ find_scalar, find_array, find_function.
+ (resolve_symbols): Call the above for symbol/arrayindex/functioncall.
+ (find_scalar): Add stub support for synthetic builtin variables.
+ * staptree.h: Corresponding changes.
+ * testsuite/*: Some new tests.
+
2005-03-03 Frank Ch. Eigler <fche@redhat.com>
* parse.cxx (parse_assignment): Assert lvalueness of left
diff --git a/parse.cxx b/parse.cxx
index 41ec6fef..640c3715 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -157,7 +157,7 @@ lexer::scan ()
if (isspace (c))
goto skip;
- else if (isalpha (c))
+ else if (isalpha (c) || c == '$')
{
n->type = tok_identifier;
n->content = (char) c;
@@ -166,7 +166,7 @@ lexer::scan ()
int c2 = input.peek ();
if (! input)
break;
- if ((isalnum(c2) || c2 == '_'))
+ if ((isalnum(c2) || c2 == '_' || c2 == '$'))
{
n->content.push_back(c2);
input_get ();
@@ -247,6 +247,7 @@ lexer::scan ()
(c == '+' && c2 == '=') ||
(c == '-' && c2 == '=') ||
(c == ':' && c2 == ':') ||
+ (c == '-' && c2 == '>') ||
false) // XXX: etc.
n->content.push_back((char) input_get ());
@@ -947,8 +948,9 @@ parser::parse_value ()
}
+// var, var[index], func(parms), thread->var, process->var
expression*
-parser::parse_symbol () // var, var[index], func(parms)
+parser::parse_symbol ()
{
const token* t = next ();
if (t->type != tok_identifier)
@@ -957,7 +959,34 @@ parser::parse_symbol () // var, var[index], func(parms)
string name = t->content;
t = peek ();
- if (t && t->type == tok_operator && t->content == "[") // array
+ if (t && t->type == tok_operator && t->content == "->")
+ {
+ // shorthand for process- or thread-specific array element
+ // map "thread->VAR" to "VAR[$tid]",
+ // and "process->VAR" to "VAR[$pid]"
+ symbol* sym = new symbol;
+ if (name == "thread")
+ sym->name = "$tid";
+ else if (name == "process")
+ sym->name = "$pid";
+ else
+ throw parse_error ("expected 'thread->' or 'process->'");
+ struct token* t2prime = new token (*t2);
+ t2prime->content = sym->name;
+ sym->tok = t2prime;
+
+ next (); // swallow "->"
+ t = next ();
+ if (! (t->type == tok_identifier))
+ throw parse_error ("expected identifier");
+
+ struct arrayindex* ai = new arrayindex;
+ ai->tok = t;
+ ai->base = t->content;
+ ai->indexes.push_back (sym);
+ return ai;
+ }
+ else if (t && t->type == tok_operator && t->content == "[") // array
{
next ();
struct arrayindex* ai = new arrayindex;
diff --git a/parse.h b/parse.h
index ddfb19c1..c8008bc7 100644
--- a/parse.h
+++ b/parse.h
@@ -22,6 +22,7 @@ enum token_type
tok_junk, tok_identifier, tok_operator, tok_string, tok_number
};
+
struct token
{
source_loc location;
@@ -29,6 +30,7 @@ struct token
std::string content;
};
+
std::ostream& operator << (std::ostream& o, const token& t);
diff --git a/staptree.cxx b/staptree.cxx
index 8a4fc148..2bbdea9f 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -387,7 +387,7 @@ symbol::resolve_symbols (symresolution_info& r)
if (referent)
return;
- vardecl* d = r.find (name);
+ vardecl* d = r.find_scalar (name);
if (d)
referent = d;
else
@@ -398,7 +398,6 @@ symbol::resolve_symbols (symresolution_info& r)
v->tok = tok;
r.locals.push_back (v);
referent = v;
- // XXX: check for conflicting function name
}
}
@@ -412,7 +411,7 @@ arrayindex::resolve_symbols (symresolution_info& r)
if (referent)
return;
- vardecl* d = r.find (base);
+ vardecl* d = r.find_array (base, indexes);
if (d)
referent = d;
else
@@ -423,7 +422,6 @@ arrayindex::resolve_symbols (symresolution_info& r)
v->tok = tok;
r.locals.push_back (v);
referent = v;
- // XXX: check for conflicting function name
}
}
@@ -437,19 +435,7 @@ functioncall::resolve_symbols (symresolution_info& r)
if (referent)
return;
- // find global functiondecl
- functiondecl* d = 0;
- for (unsigned j = 0; j < r.current_file->functions.size(); j++)
- {
- functiondecl* fd = r.current_file->functions[j];
- if (fd->name == function)
- {
- d = fd;
- break;
- }
- }
- // XXX: check for conflicting variable name
-
+ functiondecl* d = r.find_function (function, args);
if (d)
referent = d;
else
@@ -492,13 +478,32 @@ expr_statement::resolve_symbols (symresolution_info& r)
vardecl*
-symresolution_info::find (const string& name)
+symresolution_info::find_scalar (const string& name)
{
// search locals
for (unsigned i=0; i<locals.size(); i++)
if (locals[i]->name == name)
return locals[i];
+ // search builtins that become locals
+ // XXX: need to invent a proper formalism for this
+ if (name == "$pid" || name == "$tid")
+ {
+ vardecl_builtin* vb = new vardecl_builtin;
+ vb->name = name;
+ vb->type = pe_long;
+
+ // XXX: need a better way to synthesize tokens
+ token* t = new token;
+ t->type = tok_identifier;
+ t->content = name;
+ t->location.file = "<builtin>";
+ vb->tok = t;
+
+ locals.push_back (vb);
+ return vb;
+ }
+
// search function formal parameters (if any)
if (current_function)
{
@@ -513,9 +518,54 @@ symresolution_info::find (const string& name)
return globals[i];
return 0;
+ // XXX: add checking for conflicting array or function
}
+vardecl*
+symresolution_info::find_array (const string& name,
+ const vector<expression*>& indexes)
+{
+ // search locals
+ for (unsigned i=0; i<locals.size(); i++)
+ if (locals[i]->name == name)
+ return locals[i];
+
+ // search function formal parameters (if any)
+ if (current_function)
+ {
+ for (unsigned i=0; i<current_function->formal_args.size(); i++)
+ if (current_function->formal_args [i]->name == name)
+ return current_function->formal_args [i];
+ }
+
+ // search globals
+ for (unsigned i=0; i<globals.size(); i++)
+ if (globals[i]->name == name)
+ return globals[i];
+
+ return 0;
+ // XXX: add checking for conflicting scalar or function
+}
+
+
+functiondecl*
+symresolution_info::find_function (const string& name,
+ const vector<expression*>& args)
+{
+ for (unsigned j = 0; j < current_file->functions.size(); j++)
+ {
+ functiondecl* fd = current_file->functions[j];
+ if (fd->name == name)
+ return fd;
+ }
+
+ return 0;
+ // XXX: add checking for conflicting variables
+}
+
+
+
void
symresolution_info::unresolved (const token* tok)
{
diff --git a/staptree.h b/staptree.h
index a95d9f05..b38221bc 100644
--- a/staptree.h
+++ b/staptree.h
@@ -209,7 +209,9 @@ struct symresolution_info
vector<stapfile*>& f,
stapfile* cfil);
- vardecl* find (const string& name);
+ vardecl* find_scalar (const string& name);
+ vardecl* find_array (const string& name, const vector<expression*>&);
+ functiondecl* find_function (const string& name, const vector<expression*>&);
void unresolved (const token* tok);
unsigned num_unresolved;
@@ -257,6 +259,11 @@ struct vardecl: public symboldecl
};
+struct vardecl_builtin: public vardecl
+{
+};
+
+
struct block;
struct functiondecl: public symboldecl
{
diff --git a/testsuite/parseko/four.stp b/testsuite/parseko/four.stp
new file mode 100755
index 00000000..ad77239b
--- /dev/null
+++ b/testsuite/parseko/four.stp
@@ -0,0 +1,5 @@
+#! semtest
+
+probe foo {
+ somethingawful->foo = 1;
+}
diff --git a/testsuite/parseok/three.stp b/testsuite/parseok/three.stp
new file mode 100755
index 00000000..b2628d4d
--- /dev/null
+++ b/testsuite/parseok/three.stp
@@ -0,0 +1,7 @@
+#! parsetest
+
+probe kernel:systemcall("foo")
+{
+ $a = a$a = a$a$ = 0;
+}
+
diff --git a/testsuite/semok/six.stp b/testsuite/semok/six.stp
new file mode 100755
index 00000000..53d69503
--- /dev/null
+++ b/testsuite/semok/six.stp
@@ -0,0 +1,7 @@
+#! parsetest
+
+probe foo
+{
+ thread->bar = 4;
+ process->baz = "5";
+}