Commit b834cd3b authored by Alastair Robertson's avatar Alastair Robertson

Parser: Pass through includes and structs as strings

parent 4cc2e864
......@@ -68,10 +68,6 @@ void Probe::accept(Visitor &v) {
v.visit(*this);
}
void Include::accept(Visitor &v) {
v.visit(*this);
}
void Program::accept(Visitor &v) {
v.visit(*this);
}
......
......@@ -199,22 +199,11 @@ public:
};
using ProbeList = std::vector<Probe *>;
class Include : public Node {
public:
explicit Include(const std::string &file, bool system_header)
: file(file), system_header(system_header) { }
std::string file;
bool system_header;
void accept(Visitor &v) override;
};
using IncludeList = std::vector<Include *>;
class Program : public Node {
public:
Program(IncludeList *includes, ProbeList *probes)
: includes(includes), probes(probes) { }
IncludeList *includes;
Program(const std::string &c_definitions, ProbeList *probes)
: c_definitions(c_definitions), probes(probes) { }
std::string c_definitions;
ProbeList *probes;
void accept(Visitor &v) override;
......@@ -239,7 +228,6 @@ public:
virtual void visit(Predicate &pred) = 0;
virtual void visit(AttachPoint &ap) = 0;
virtual void visit(Probe &probe) = 0;
virtual void visit(Include &include) = 0;
virtual void visit(Program &program) = 0;
};
......
......@@ -410,14 +410,8 @@ void CodegenLLVM::visit(Probe &probe)
b_.CreateRet(ConstantInt::get(module_->getContext(), APInt(64, 0)));
}
void CodegenLLVM::visit(Include &include)
{
}
void CodegenLLVM::visit(Program &program)
{
for (Include *include : *program.includes)
include->accept(*this);
for (Probe *probe : *program.probes)
probe->accept(*this);
}
......
......@@ -43,7 +43,6 @@ public:
void visit(Predicate &pred) override;
void visit(AttachPoint &ap) override;
void visit(Probe &probe) override;
void visit(Include &include) override;
void visit(Program &program) override;
AllocaInst *getMapKey(Map &map);
AllocaInst *getQuantizeMapKey(Map &map, Value *log2);
......
......@@ -167,23 +167,15 @@ void Printer::visit(Probe &probe)
--depth_;
}
void Printer::visit(Include &include)
{
std::string indent(depth_, ' ');
if (include.system_header)
out_ << indent << "#include <" << include.file << ">" << std::endl;
else
out_ << indent << "#include \"" << include.file << "\"" << std::endl;
}
void Printer::visit(Program &program)
{
if (program.c_definitions.size() > 0)
out_ << program.c_definitions << std::endl;
std::string indent(depth_, ' ');
out_ << indent << "Program" << std::endl;
++depth_;
for (Include *include : *program.includes)
include->accept(*this);
for (Probe *probe : *program.probes)
probe->accept(*this);
--depth_;
......
......@@ -26,7 +26,6 @@ public:
void visit(Predicate &pred) override;
void visit(AttachPoint &ap) override;
void visit(Probe &probe) override;
void visit(Include &include) override;
void visit(Program &program) override;
int depth_ = 0;
......
......@@ -479,14 +479,8 @@ void SemanticAnalyser::visit(Probe &probe)
}
}
void SemanticAnalyser::visit(Include &include)
{
}
void SemanticAnalyser::visit(Program &program)
{
for (Include *include : *program.includes)
include->accept(*this);
for (Probe *probe : *program.probes)
probe->accept(*this);
}
......
......@@ -34,7 +34,6 @@ public:
void visit(Predicate &pred) override;
void visit(AttachPoint &ap) override;
void visit(Probe &probe) override;
void visit(Include &include) override;
void visit(Program &program) override;
int analyse();
......
......@@ -9,7 +9,8 @@
#define yywrap(x) 1
static bpftrace::location loc;
static std::string string_buffer;
static std::string buffer;
static int open_brackets;
#define YY_USER_ACTION loc.columns(yyleng);
#define yyterminate() return bpftrace::Parser::make_END(loc)
......@@ -25,8 +26,8 @@ hspace [ \t]
vspace [\n\r]
space {hspace}|{vspace}
path :(\\.|[_\-\./a-zA-Z0-9])*:
header <(\\.|[_\-\./a-zA-Z0-9])*>
%x STR
%x STRUCT
%%
......@@ -40,9 +41,7 @@ header <(\\.|[_\-\./a-zA-Z0-9])*>
pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func {
return Parser::make_BUILTIN(yytext, loc); }
{ident} { return Parser::make_IDENT(yytext, loc); }
{path} { return Parser::make_PATH(yytext, loc); }
{header} { return Parser::make_HEADER(yytext, loc); }
{map} { return Parser::make_MAP(yytext, loc); }
{var} { return Parser::make_VAR(yytext, loc); }
{int} { return Parser::make_INT(strtoul(yytext, NULL, 0), loc); }
......@@ -75,17 +74,17 @@ pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func {
"^" { return Parser::make_BXOR(loc); }
"!" { return Parser::make_LNOT(loc); }
"~" { return Parser::make_BNOT(loc); }
"#include" { return Parser::make_INCLUDE(loc); }
"." { return Parser::make_DOT(loc); }
"->" { return Parser::make_PTR(loc); }
"#".* { return Parser::make_CPREPROC(yytext, loc); }
\" { BEGIN(STR); string_buffer.clear(); }
<STR>\" { BEGIN(INITIAL); return Parser::make_STRING(string_buffer, loc); }
<STR>[^\\\n\"]+ { string_buffer += std::string(yytext); }
<STR>\\n { string_buffer += std::string("\n"); }
<STR>\\t { string_buffer += std::string("\t"); }
<STR>\\\" { string_buffer += std::string("\""); }
<STR>\\\\ { string_buffer += std::string("\\"); }
\" { BEGIN(STR); buffer.clear(); }
<STR>\" { BEGIN(INITIAL); return Parser::make_STRING(buffer, loc); }
<STR>[^\\\n\"]+ { buffer += std::string(yytext); }
<STR>\\n { buffer += std::string("\n"); }
<STR>\\t { buffer += std::string("\t"); }
<STR>\\\" { buffer += std::string("\""); }
<STR>\\\\ { buffer += std::string("\\"); }
<STR>\n { driver.error(loc, std::string("unterminated string")); }
<STR><<EOF>> { driver.error(loc, std::string("unterminated string")); }
<STR>\\. { driver.error(loc, std::string("invalid escape character '") +
......@@ -93,6 +92,22 @@ pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func {
<STR>. { driver.error(loc, std::string("invalid character '") +
std::string(yytext) + std::string("'")); }
struct { BEGIN(STRUCT); buffer = std::string(yytext); open_brackets = 0; }
<STRUCT>"{" { BEGIN(STRUCT); buffer += std::string(yytext); open_brackets++; }
<STRUCT>"}" { buffer += std::string(yytext);
if (open_brackets == 1)
{
BEGIN(INITIAL); return Parser::make_STRUCT(buffer, loc);
}
else
{
open_brackets--;
}
}
<STRUCT>\n { buffer += std::string(yytext); }
<STRUCT>. { buffer += std::string(yytext); }
{ident} { return Parser::make_IDENT(yytext, loc); }
. { driver.error(loc, std::string("invalid character '") +
std::string(yytext) + std::string("'")); }
......
......@@ -65,7 +65,6 @@ void yyerror(bpftrace::Driver &driver, const char *s);
BXOR "^"
LNOT "!"
BNOT "~"
INCLUDE "#include"
DOT "."
PTR "->"
;
......@@ -73,14 +72,14 @@ void yyerror(bpftrace::Driver &driver, const char *s);
%token <std::string> BUILTIN "builtin"
%token <std::string> IDENT "identifier"
%token <std::string> PATH "path"
%token <std::string> HEADER "header"
%token <std::string> CPREPROC "preprocessor directive"
%token <std::string> STRUCT "struct"
%token <std::string> STRING "string"
%token <std::string> MAP "map"
%token <std::string> VAR "variable"
%token <int> INT "integer"
%type <ast::IncludeList *> includes
%type <ast::Include *> include
%type <std::string> c_definitions
%type <ast::ProbeList *> probes
%type <ast::Probe *> probe
%type <ast::Predicate *> pred
......@@ -114,15 +113,12 @@ void yyerror(bpftrace::Driver &driver, const char *s);
%%
program : includes probes { driver.root_ = new ast::Program($1, $2); }
program : c_definitions probes { driver.root_ = new ast::Program($1, $2); }
;
includes : includes include { $$ = $1; $1->push_back($2); }
| { $$ = new ast::IncludeList; }
;
include : INCLUDE STRING { $$ = new ast::Include($2, false); }
| INCLUDE HEADER { $$ = new ast::Include($2.substr(1, $2.size()-2), true); }
c_definitions : CPREPROC c_definitions { $$ = $1 + "\n" + $2; }
| STRUCT c_definitions { $$ = $1 + "\n" + $2; }
| { $$ = std::string(); }
;
probes : probes probe { $$ = $1; $1->push_back($2); }
......
......@@ -326,9 +326,10 @@ TEST(Parser, short_map_name)
TEST(Parser, include)
{
test("#include <stdio.h> kprobe:sys_read { @x = 1 }",
test("#include <stdio.h>\nkprobe:sys_read { @x = 1 }",
"#include <stdio.h>\n"
"\n"
"Program\n"
" #include <stdio.h>\n"
" kprobe:sys_read\n"
" =\n"
" map: @x\n"
......@@ -337,9 +338,10 @@ TEST(Parser, include)
TEST(Parser, include_quote)
{
test("#include \"stdio.h\" kprobe:sys_read { @x = 1 }",
test("#include \"stdio.h\"\nkprobe:sys_read { @x = 1 }",
"#include \"stdio.h\"\n"
"\n"
"Program\n"
" #include \"stdio.h\"\n"
" kprobe:sys_read\n"
" =\n"
" map: @x\n"
......@@ -348,11 +350,12 @@ TEST(Parser, include_quote)
TEST(Parser, include_multiple)
{
test("#include <stdio.h> #include \"blah\" #include <foo.h> kprobe:sys_read { @x = 1 }",
test("#include <stdio.h>\n#include \"blah\"\n#include <foo.h>\nkprobe:sys_read { @x = 1 }",
"#include <stdio.h>\n"
"#include \"blah\"\n"
"#include <foo.h>\n"
"\n"
"Program\n"
" #include <stdio.h>\n"
" #include \"blah\"\n"
" #include <foo.h>\n"
" kprobe:sys_read\n"
" =\n"
" map: @x\n"
......@@ -507,6 +510,26 @@ TEST(Parser, field_access_builtin)
" count\n");
}
TEST(Parser, cstruct)
{
test("struct Foo { int x, y; char *str; } kprobe:sys_read { 1; }",
"struct Foo { int x, y; char *str; }\n"
"\n"
"Program\n"
" kprobe:sys_read\n"
" int: 1\n");
}
TEST(Parser, cstruct_nested)
{
test("struct Foo { struct { int x; } bar; } kprobe:sys_read { 1; }",
"struct Foo { struct { int x; } bar; }\n"
"\n"
"Program\n"
" kprobe:sys_read\n"
" int: 1\n");
}
} // namespace parser
} // namespace test
} // namespace bpftrace
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment