X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=cli%2Fcli_pickle.cpp;h=3a9129f8782d0f4a1dc7b2d81616c37c0654e273;hb=48c661ea6c0f2bd9b76a3385cd946b7d07bc9b5f;hp=460a3c3c516dac018bbac8893cd41ed7060e4048;hpb=299a1b3adc806ef33234683bae4b9477ba5cc378;p=apitrace diff --git a/cli/cli_pickle.cpp b/cli/cli_pickle.cpp index 460a3c3..3a9129f 100644 --- a/cli/cli_pickle.cpp +++ b/cli/cli_pickle.cpp @@ -25,9 +25,13 @@ #include +#include // for CHAR_MAX +#include #include "pickle.hpp" +#include "os_binary.hpp" + #include "cli.hpp" #include "cli_pager.hpp" @@ -43,10 +47,12 @@ class PickleVisitor : public trace::Visitor { protected: PickleWriter &writer; + bool symbolic; public: - PickleVisitor(PickleWriter &_writer) : - writer(_writer) { + PickleVisitor(PickleWriter &_writer, bool _symbolic) : + writer(_writer), + symbolic(_symbolic) { } void visit(Null *node) { @@ -78,23 +84,56 @@ public: } void visit(Enum *node) { - // TODO: keep symbolic name + if (symbolic) { + const EnumValue *it = node->lookup(); + if (it) { + writer.writeString(it->name); + return; + } + } writer.writeInt(node->value); } void visit(Bitmask *node) { - // TODO: keep symbolic name - writer.writeInt(node->value); + if (symbolic) { + unsigned long long value = node->value; + const BitmaskSig *sig = node->sig; + writer.beginList(); + for (const BitmaskFlag *it = sig->flags; it != sig->flags + sig->num_flags; ++it) { + if ((it->value && (value & it->value) == it->value) || + (!it->value && value == 0)) { + writer.writeString(it->name); + value &= ~it->value; + } + if (value == 0) { + break; + } + } + if (value) { + writer.writeInt(value); + } + writer.endList(); + } else { + writer.writeInt(node->value); + } } void visit(Struct *node) { - writer.beginDict(); - for (unsigned i = 0; i < node->sig->num_members; ++i) { - writer.beginItem(node->sig->member_names[i]); - _visit(node->members[i]); - writer.endItem(); + if (false) { + writer.beginDict(); + for (unsigned i = 0; i < node->sig->num_members; ++i) { + writer.beginItem(node->sig->member_names[i]); + _visit(node->members[i]); + writer.endItem(); + } + writer.endDict(); + } else { + writer.beginTuple(); + for (unsigned i = 0; i < node->sig->num_members; ++i) { + _visit(node->members[i]); + } + writer.endTuple(); } - writer.endDict(); } void visit(Array *node) { @@ -106,13 +145,21 @@ public: } void visit(Blob *node) { - writer.writeString((const char *)node->buf, node->size); + writer.writeByteArray(node->buf, node->size); } void visit(Pointer *node) { writer.writeInt(node->value); } + void visit(Repr *r) { + if (symbolic) { + _visit(r->humanValue); + } else { + _visit(r->machineValue); + } + } + void visit(Call *call) { writer.beginTuple(); @@ -122,8 +169,8 @@ public: writer.beginList(); for (unsigned i = 0; i < call->args.size(); ++i) { - if (call->args[i]) { - _visit(call->args[i]); + if (call->args[i].value) { + _visit(call->args[i].value); } else { writer.writeNone(); } @@ -149,57 +196,74 @@ static void usage(void) { std::cout - << "usage: apitrace pickle [OPTIONS] ...\n" + << "usage: apitrace pickle [OPTIONS] TRACE_FILE...\n" << synopsis << "\n" "\n" - " --calls Only pickle specified calls\n" + " -h, --help show this help message and exit\n" + " -s, --symbolic dump symbolic names\n" + " --calls=CALLSET only dump specified calls\n" ; } -static int -command(int argc, char *argv[]) -{ - int i; +enum { + CALLS_OPT = CHAR_MAX + 1, +}; - for (i = 0; i < argc;) { - const char *arg = argv[i]; +const static char * +shortOptions = "hs"; - if (arg[0] != '-') { - break; - } +const static struct option +longOptions[] = { + {"help", no_argument, 0, 'h'}, + {"symbolic", no_argument, 0, 's'}, + {"calls", required_argument, 0, CALLS_OPT}, + {0, 0, 0, 0} +}; - ++i; +static int +command(int argc, char *argv[]) +{ + bool symbolic; - if (!strcmp(arg, "--")) { - break; - } else if (!strcmp(arg, "--help")) { + int opt; + while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) { + switch (opt) { + case 'h': usage(); return 0; - } else if (!strcmp(arg, "--calls")) { - calls = trace::CallSet(argv[i++]); - } else { - std::cerr << "error: unknown option " << arg << "\n"; + case 's': + symbolic = true; + break; + case CALLS_OPT: + calls = trace::CallSet(optarg); + break; + default: + std::cerr << "error: unexpected option `" << opt << "`\n"; usage(); return 1; } } - - for (; i < argc; ++i) { + os::setBinaryMode(stdout); + + std::cout.sync_with_stdio(false); + + PickleWriter writer(std::cout); + PickleVisitor visitor(writer, symbolic); + + for (int i = optind; i < argc; ++i) { trace::Parser parser; if (!parser.open(argv[i])) { - std::cerr << "error: failed to open " << argv[i] << "\n"; return 1; } trace::Call *call; while ((call = parser.parse_call())) { if (calls.contains(*call)) { - PickleWriter writer(std::cout); - PickleVisitor visitor(writer); - + writer.begin(); visitor.visit(call); + writer.end(); } delete call; }