From 838decf2821aba49d2256f4d27a35b09394336fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Sun, 11 Sep 2011 14:44:41 +0100 Subject: [PATCH] Interleave parse_xxx and scan_xxx methods. Makes much easier to read/maintain. --- trace_parser.cpp | 609 ++++++++++++++++++++++++++++--------------------------- trace_parser.hpp | 57 ++---- 2 files changed, 326 insertions(+), 340 deletions(-) diff --git a/trace_parser.cpp b/trace_parser.cpp index 2ca32a5..e19d31f 100644 --- a/trace_parser.cpp +++ b/trace_parser.cpp @@ -130,6 +130,31 @@ Call *Parser::parse_call(void) { } +Call * Parser::scan_call() +{ + assert(m_supportsSeeking); + do { + int c = read_byte(); + switch(c) { + case Trace::EVENT_ENTER: + scan_enter(); + break; + case Trace::EVENT_LEAVE: + return scan_leave(); + default: + std::cerr << "error: unknown event " << c << "\n"; + exit(1); + case -1: + for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) { + std::cerr << "warning: incomplete call " << (*it)->name() << "\n"; + std::cerr << **it << "\n"; + } + return NULL; + } + } while (true); +} + + /** * Helper function to lookup an ID in a vector, resizing the vector if it doesn't fit. */ @@ -175,6 +200,100 @@ FunctionSig *Parser::parse_function_sig(void) { return sig; } + +StructSig *Parser::parse_struct_sig() { + size_t id = read_uint(); + + StructSigState *sig = lookup(structs, id); + + if (!sig) { + /* parse the signature */ + sig = new StructSigState; + sig->id = id; + sig->name = read_string(); + sig->num_members = read_uint(); + const char **member_names = new const char *[sig->num_members]; + for (unsigned i = 0; i < sig->num_members; ++i) { + member_names[i] = read_string(); + } + sig->member_names = member_names; + sig->offset = file->currentOffset(); + structs[id] = sig; + } else if (file->currentOffset() < sig->offset) { + /* skip over the signature */ + skip_string(); /* name */ + unsigned num_members = read_uint(); + for (unsigned i = 0; i < num_members; ++i) { + skip_string(); /* member_name */ + } + } + + assert(sig); + return sig; +} + + +EnumSig *Parser::parse_enum_sig() { + size_t id = read_uint(); + + EnumSigState *sig = lookup(enums, id); + + if (!sig) { + /* parse the signature */ + sig = new EnumSigState; + sig->id = id; + sig->name = read_string(); + Value *value = parse_value(); + sig->value = value->toSInt(); + delete value; + sig->offset = file->currentOffset(); + enums[id] = sig; + } else if (file->currentOffset() < sig->offset) { + /* skip over the signature */ + skip_string(); /*name*/ + scan_value(); + } + + assert(sig); + return sig; +} + + +BitmaskSig *Parser::parse_bitmask_sig() { + size_t id = read_uint(); + + BitmaskSigState *sig = lookup(bitmasks, id); + + if (!sig) { + /* parse the signature */ + sig = new BitmaskSigState; + sig->id = id; + sig->num_flags = read_uint(); + BitmaskFlag *flags = new BitmaskFlag[sig->num_flags]; + for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) { + it->name = read_string(); + it->value = read_uint(); + if (it->value == 0 && it != flags) { + std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n"; + } + } + sig->flags = flags; + sig->offset = file->currentOffset(); + bitmasks[id] = sig; + } else if (file->currentOffset() < sig->offset) { + /* skip over the signature */ + int num_flags = read_uint(); + for (int i = 0; i < num_flags; ++i) { + skip_string(); /*name */ + skip_uint(); /* value */ + } + } + + assert(sig); + return sig; +} + + void Parser::parse_enter(void) { FunctionSig *sig = parse_function_sig(); @@ -190,6 +309,20 @@ void Parser::parse_enter(void) { } +void Parser::scan_enter(void) { + FunctionSig *sig = parse_function_sig(); + + Call *call = new Call(sig); + call->no = next_call_no++; + + if (scan_call_details(call)) { + calls.push_back(call); + } else { + delete call; + } +} + + Call *Parser::parse_leave(void) { unsigned call_no = read_uint(); Call *call = NULL; @@ -213,6 +346,29 @@ Call *Parser::parse_leave(void) { } +Call *Parser::scan_leave(void) { + unsigned call_no = read_uint(); + Call *call = NULL; + for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) { + if ((*it)->no == call_no) { + call = *it; + calls.erase(it); + break; + } + } + if (!call) { + return NULL; + } + + if (scan_call_details(call)) { + return call; + } else { + delete call; + return NULL; + } +} + + bool Parser::parse_call_details(Call *call) { do { int c = read_byte(); @@ -236,6 +392,29 @@ bool Parser::parse_call_details(Call *call) { } +bool Parser::scan_call_details(Call *call) { + do { + int c = read_byte(); + switch(c) { + case Trace::CALL_END: + return true; + case Trace::CALL_ARG: + scan_arg(call); + break; + case Trace::CALL_RET: + scan_value(); + break; + default: + std::cerr << "error: ("<name()<< ") unknown call detail " + << c << "\n"; + exit(1); + case -1: + return false; + } + } while(true); +} + + void Parser::parse_arg(Call *call) { unsigned index = read_uint(); Value *value = parse_value(); @@ -246,6 +425,12 @@ void Parser::parse_arg(Call *call) { } +void Parser::scan_arg(Call *call) { + skip_uint(); /* index */ + scan_value(); /* value */ +} + + Value *Parser::parse_value(void) { int c; Value *value; @@ -309,16 +494,75 @@ Value *Parser::parse_value(void) { } +void Parser::scan_value(void) { + int c = read_byte(); + switch(c) { + case Trace::TYPE_NULL: + case Trace::TYPE_FALSE: + case Trace::TYPE_TRUE: + break; + case Trace::TYPE_SINT: + scan_sint(); + break; + case Trace::TYPE_UINT: + scan_uint(); + break; + case Trace::TYPE_FLOAT: + scan_float(); + break; + case Trace::TYPE_DOUBLE: + scan_double(); + break; + case Trace::TYPE_STRING: + scan_string(); + break; + case Trace::TYPE_ENUM: + scan_enum(); + break; + case Trace::TYPE_BITMASK: + scan_bitmask(); + break; + case Trace::TYPE_ARRAY: + scan_array(); + break; + case Trace::TYPE_STRUCT: + scan_struct(); + break; + case Trace::TYPE_BLOB: + scan_blob(); + break; + case Trace::TYPE_OPAQUE: + scan_opaque(); + break; + default: + std::cerr << "error: unknown type " << c << "\n"; + exit(1); + case -1: + break; + } +} + + Value *Parser::parse_sint() { return new SInt(-(signed long long)read_uint()); } +void Parser::scan_sint() { + skip_uint(); +} + + Value *Parser::parse_uint() { return new UInt(read_uint()); } +void Parser::scan_uint() { + skip_uint(); +} + + Value *Parser::parse_float() { float value; file->read(&value, sizeof value); @@ -326,6 +570,11 @@ Value *Parser::parse_float() { } +void Parser::scan_float() { + file->skip(sizeof(float)); +} + + Value *Parser::parse_double() { double value; file->read(&value, sizeof value); @@ -333,74 +582,29 @@ Value *Parser::parse_double() { } +void Parser::scan_double() { + file->skip(sizeof(double)); +} + + Value *Parser::parse_string() { return new String(read_string()); } -EnumSig *Parser::parse_enum_sig() { - size_t id = read_uint(); - - EnumSigState *sig = lookup(enums, id); - - if (!sig) { - /* parse the signature */ - sig = new EnumSigState; - sig->id = id; - sig->name = read_string(); - Value *value = parse_value(); - sig->value = value->toSInt(); - delete value; - sig->offset = file->currentOffset(); - enums[id] = sig; - } else if (file->currentOffset() < sig->offset) { - /* skip over the signature */ - skip_string(); /*name*/ - scan_value(); - } - - assert(sig); - return sig; +void Parser::scan_string() { + skip_string(); } + Value *Parser::parse_enum() { EnumSig *sig = parse_enum_sig(); return new Enum(sig); } -BitmaskSig *Parser::parse_bitmask_sig() { - size_t id = read_uint(); - - BitmaskSigState *sig = lookup(bitmasks, id); - - if (!sig) { - /* parse the signature */ - sig = new BitmaskSigState; - sig->id = id; - sig->num_flags = read_uint(); - BitmaskFlag *flags = new BitmaskFlag[sig->num_flags]; - for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) { - it->name = read_string(); - it->value = read_uint(); - if (it->value == 0 && it != flags) { - std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n"; - } - } - sig->flags = flags; - sig->offset = file->currentOffset(); - bitmasks[id] = sig; - } else if (file->currentOffset() < sig->offset) { - /* skip over the signature */ - int num_flags = read_uint(); - for (int i = 0; i < num_flags; ++i) { - skip_string(); /*name */ - skip_uint(); /* value */ - } - } - - assert(sig); - return sig; +void Parser::scan_enum() { + parse_enum_sig(); } @@ -413,6 +617,12 @@ Value *Parser::parse_bitmask() { } +void Parser::scan_bitmask() { + parse_bitmask_sig(); + skip_uint(); /* value */ +} + + Value *Parser::parse_array(void) { size_t len = read_uint(); Array *array = new Array(len); @@ -423,6 +633,14 @@ Value *Parser::parse_array(void) { } +void Parser::scan_array(void) { + size_t len = read_uint(); + for (size_t i = 0; i < len; ++i) { + scan_value(); + } +} + + Value *Parser::parse_blob(void) { size_t size = read_uint(); Blob *blob = new Blob(size); @@ -433,37 +651,14 @@ Value *Parser::parse_blob(void) { } -StructSig *Parser::parse_struct_sig() { - size_t id = read_uint(); - - StructSigState *sig = lookup(structs, id); - - if (!sig) { - /* parse the signature */ - sig = new StructSigState; - sig->id = id; - sig->name = read_string(); - sig->num_members = read_uint(); - const char **member_names = new const char *[sig->num_members]; - for (unsigned i = 0; i < sig->num_members; ++i) { - member_names[i] = read_string(); - } - sig->member_names = member_names; - sig->offset = file->currentOffset(); - structs[id] = sig; - } else if (file->currentOffset() < sig->offset) { - /* skip over the signature */ - skip_string(); /* name */ - unsigned num_members = read_uint(); - for (unsigned i = 0; i < num_members; ++i) { - skip_string(); /* member_name */ - } +void Parser::scan_blob(void) { + size_t size = read_uint(); + if (size) { + file->skip(size); } - - assert(sig); - return sig; } + Value *Parser::parse_struct() { StructSig *sig = parse_struct_sig(); Struct *value = new Struct(sig); @@ -476,6 +671,14 @@ Value *Parser::parse_struct() { } +void Parser::scan_struct() { + StructSig *sig = parse_struct_sig(); + for (size_t i = 0; i < sig->num_members; ++i) { + scan_value(); + } +} + + Value *Parser::parse_opaque() { unsigned long long addr; addr = read_uint(); @@ -483,6 +686,11 @@ Value *Parser::parse_opaque() { } +void Parser::scan_opaque() { + skip_uint(); +} + + const char * Parser::read_string(void) { size_t len = read_uint(); char * value = new char[len + 1]; @@ -497,6 +705,12 @@ const char * Parser::read_string(void) { } +void Parser::skip_string(void) { + size_t len = read_uint(); + file->skip(len); +} + + unsigned long long Parser::read_uint(void) { unsigned long long value = 0; int c; @@ -516,6 +730,17 @@ unsigned long long Parser::read_uint(void) { } +void Parser::skip_uint(void) { + int c; + do { + c = file->getc(); + if (c == -1) { + break; + } + } while(c & 0x80); +} + + inline int Parser::read_byte(void) { int c = file->getc(); #if TRACE_VERBOSE @@ -528,224 +753,6 @@ inline int Parser::read_byte(void) { } -Call * Parser::scan_call() -{ - assert(m_supportsSeeking); - do { - int c = read_byte(); - switch(c) { - case Trace::EVENT_ENTER: - scan_enter(); - break; - case Trace::EVENT_LEAVE: - return scan_leave(); - default: - std::cerr << "error: unknown event " << c << "\n"; - exit(1); - case -1: - for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) { - std::cerr << "warning: incomplete call " << (*it)->name() << "\n"; - std::cerr << **it << "\n"; - } - return NULL; - } - } while (true); -} - -void Parser::scan_enter(void) { - FunctionSig *sig = parse_function_sig(); - - Call *call = new Call(sig); - call->no = next_call_no++; - - if (scan_call_details(call)) { - calls.push_back(call); - } else { - delete call; - } -} - -Call *Parser::scan_leave(void) { - unsigned call_no = read_uint(); - Call *call = NULL; - for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) { - if ((*it)->no == call_no) { - call = *it; - calls.erase(it); - break; - } - } - if (!call) { - return NULL; - } - - if (scan_call_details(call)) { - return call; - } else { - delete call; - return NULL; - } -} - -bool Parser::scan_call_details(Call *call) { - do { - int c = read_byte(); - switch(c) { - case Trace::CALL_END: - return true; - case Trace::CALL_ARG: - scan_arg(call); - break; - case Trace::CALL_RET: - scan_value(); - break; - default: - std::cerr << "error: ("<name()<< ") unknown call detail " - << c << "\n"; - exit(1); - case -1: - return false; - } - } while(true); -} - -void Parser::scan_arg(Call *call) { - skip_uint(); /* index */ - scan_value(); /* value */ -} - - -void Parser::scan_value(void) { - int c = read_byte(); - switch(c) { - case Trace::TYPE_NULL: - case Trace::TYPE_FALSE: - case Trace::TYPE_TRUE: - break; - case Trace::TYPE_SINT: - scan_sint(); - break; - case Trace::TYPE_UINT: - scan_uint(); - break; - case Trace::TYPE_FLOAT: - scan_float(); - break; - case Trace::TYPE_DOUBLE: - scan_double(); - break; - case Trace::TYPE_STRING: - scan_string(); - break; - case Trace::TYPE_ENUM: - scan_enum(); - break; - case Trace::TYPE_BITMASK: - scan_bitmask(); - break; - case Trace::TYPE_ARRAY: - scan_array(); - break; - case Trace::TYPE_STRUCT: - scan_struct(); - break; - case Trace::TYPE_BLOB: - scan_blob(); - break; - case Trace::TYPE_OPAQUE: - scan_opaque(); - break; - default: - std::cerr << "error: unknown type " << c << "\n"; - exit(1); - case -1: - break; - } -} - - -void Parser::scan_sint() { - skip_uint(); -} - - -void Parser::scan_uint() { - skip_uint(); -} - - -void Parser::scan_float() { - file->skip(sizeof(float)); -} - - -void Parser::scan_double() { - file->skip(sizeof(double)); -} - - -void Parser::scan_string() { - skip_string(); -} - - -void Parser::scan_enum() { - parse_enum_sig(); -} - - -void Parser::scan_bitmask() { - parse_bitmask_sig(); - skip_uint(); /* value */ -} - - -void Parser::scan_array(void) { - size_t len = read_uint(); - for (size_t i = 0; i < len; ++i) { - scan_value(); - } -} - - -void Parser::scan_blob(void) { - size_t size = read_uint(); - if (size) { - file->skip(size); - } -} - - -void Parser::scan_struct() { - StructSig *sig = parse_struct_sig(); - for (size_t i = 0; i < sig->num_members; ++i) { - scan_value(); - } -} - - -void Parser::scan_opaque() { - skip_uint(); -} - - -void Parser::skip_string(void) { - size_t len = read_uint(); - file->skip(len); -} - - -void Parser::skip_uint(void) { - int c; - do { - c = file->getc(); - if (c == -1) { - break; - } - } while(c & 0x80); -} - - inline void Parser::skip_byte(void) { file->skip(1); } diff --git a/trace_parser.hpp b/trace_parser.hpp index 1a2f9e1..962c323 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -29,7 +29,6 @@ #include #include -#include #include "trace_file.hpp" #include "trace_format.hpp" @@ -127,80 +126,60 @@ protected: BitmaskSig *parse_bitmask_sig(); void parse_enter(void); - - Call *parse_leave(void); - - bool parse_call_details(Call *call); - - void parse_arg(Call *call); - - Value *parse_value(void); - - Value *parse_sint(); - - Value *parse_uint(); - - Value *parse_float(); - - Value *parse_double(); - - Value *parse_string(); - - Value *parse_enum(); - - Value *parse_bitmask(); - - Value *parse_array(void); - - Value *parse_blob(void); - - Value *parse_struct(); - - Value *parse_opaque(); - - const char * read_string(void); - - unsigned long long read_uint(void); - - inline int read_byte(void); - -protected: void scan_enter(void); + Call *parse_leave(void); Call *scan_leave(void); + bool parse_call_details(Call *call); bool scan_call_details(Call *call); + void parse_arg(Call *call); void scan_arg(Call *call); + Value *parse_value(void); void scan_value(void); + Value *parse_sint(); void scan_sint(); + Value *parse_uint(); void scan_uint(); + Value *parse_float(); void scan_float(); + Value *parse_double(); void scan_double(); + Value *parse_string(); void scan_string(); + Value *parse_enum(); void scan_enum(); + Value *parse_bitmask(); void scan_bitmask(); + Value *parse_array(void); void scan_array(void); + Value *parse_blob(void); void scan_blob(void); + Value *parse_struct(); void scan_struct(); + Value *parse_opaque(); void scan_opaque(); + const char * read_string(void); void skip_string(void); + unsigned long long read_uint(void); void skip_uint(void); + inline int read_byte(void); inline void skip_byte(void); }; -- 2.7.4