X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=cli%2Fcli_dump.cpp;h=e30f6cc2b49574a00d58a111b38c82b59ca0982f;hb=3801952b80cd7a7160f6410518f6e3740d461b60;hp=4a7338285b26aafd0e1a0d86f2dbc7c9c986f431;hpb=340f569e669055e7fb095ba5ff38b34e2a64880f;p=apitrace diff --git a/cli/cli_dump.cpp b/cli/cli_dump.cpp index 4a73382..e30f6cc 100644 --- a/cli/cli_dump.cpp +++ b/cli/cli_dump.cpp @@ -1,5 +1,6 @@ /************************************************************************** * + * Copyright 2011 Jose Fonseca * Copyright 2010 VMware, Inc. * All Rights Reserved. * @@ -23,11 +24,22 @@ * **************************************************************************/ + #include +#include // for CHAR_MAX +#include +#ifndef _WIN32 +#include // for isatty() +#endif #include "cli.hpp" +#include "cli_pager.hpp" #include "trace_parser.hpp" +#include "trace_dump.hpp" +#include "trace_callset.hpp" +#include "trace_option.hpp" + enum ColorOption { COLOR_OPTION_NEVER = 0, @@ -39,56 +51,104 @@ static ColorOption color = COLOR_OPTION_AUTO; static bool verbose = false; +static trace::CallSet calls(trace::FREQUENCY_ALL); + static const char *synopsis = "Dump given trace(s) to standard output."; static void usage(void) { std::cout - << "usage: apitrace dump [OPTIONS] ...\n" + << "usage: apitrace dump [OPTIONS] TRACE_FILE...\n" << synopsis << "\n" "\n" - " -v, --verbose verbose output\n" - " --color=\n" - " --colour= Colored syntax highlighting\n" - " WHEN is 'auto', 'always', or 'never'\n"; + " -h, --help show this help message and exit\n" + " -v, --verbose verbose output\n" + " --calls=CALLSET only dump specified calls\n" + " --color[=WHEN]\n" + " --colour[=WHEN] colored syntax highlighting\n" + " WHEN is 'auto', 'always', or 'never'\n" + " --thread-ids=[=BOOL] dump thread ids [default: no]\n" + " --call-nos[=BOOL] dump call numbers[default: yes]\n" + " --arg-names[=BOOL] dump argument names [default: yes]\n" + "\n" + ; } +enum { + CALLS_OPT = CHAR_MAX + 1, + COLOR_OPT, + THREAD_IDS_OPT, + CALL_NOS_OPT, + ARG_NAMES_OPT, +}; + +const static char * +shortOptions = "hv"; + +const static struct option +longOptions[] = { + {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, + {"calls", required_argument, 0, CALLS_OPT}, + {"colour", optional_argument, 0, COLOR_OPT}, + {"color", optional_argument, 0, COLOR_OPT}, + {"thread-ids", optional_argument, 0, THREAD_IDS_OPT}, + {"call-nos", optional_argument, 0, CALL_NOS_OPT}, + {"arg-names", optional_argument, 0, ARG_NAMES_OPT}, + {0, 0, 0, 0} +}; + static int command(int argc, char *argv[]) { - int i; - - for (i = 0; i < argc; ++i) { - const char *arg = argv[i]; - - if (arg[0] != '-') { - break; - } - - if (!strcmp(arg, "--")) { - break; - } else if (!strcmp(arg, "--help")) { + trace::DumpFlags dumpFlags = 0; + bool dumpThreadIds = false; + + int opt; + while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) { + switch (opt) { + case 'h': usage(); return 0; - } else if (strcmp(arg, "-v") == 0 || - strcmp(arg, "--verbose") == 0) { + case 'v': verbose = true; - } else if (!strcmp(arg, "--color=auto") || - !strcmp(arg, "--colour=auto")) { - color = COLOR_OPTION_AUTO; - } else if (!strcmp(arg, "--color") || - !strcmp(arg, "--colour") || - !strcmp(arg, "--color=always") || - !strcmp(arg, "--colour=always")) { - color = COLOR_OPTION_ALWAYS; - } else if (!strcmp(arg, "--color=never") || - !strcmp(arg, "--colour=never") || - !strcmp(arg, "--no-color") || - !strcmp(arg, "--no-colour")) { - color = COLOR_OPTION_NEVER; - } else { - std::cerr << "error: unknown option " << arg << "\n"; + break; + case CALLS_OPT: + calls = trace::CallSet(optarg); + break; + case COLOR_OPT: + if (!optarg || + !strcmp(optarg, "always")) { + color = COLOR_OPTION_ALWAYS; + } else if (!strcmp(optarg, "auto")) { + color = COLOR_OPTION_AUTO; + } else if (!strcmp(optarg, "never")) { + color = COLOR_OPTION_NEVER; + } else { + std::cerr << "error: unknown color argument " << optarg << "\n"; + return 1; + } + break; + case THREAD_IDS_OPT: + dumpThreadIds = trace::boolOption(optarg); + break; + case CALL_NOS_OPT: + if (trace::boolOption(optarg)) { + dumpFlags &= ~trace::DUMP_FLAG_NO_CALL_NO; + } else { + dumpFlags |= trace::DUMP_FLAG_NO_CALL_NO; + } + break; + case ARG_NAMES_OPT: + if (trace::boolOption(optarg)) { + dumpFlags &= ~trace::DUMP_FLAG_NO_ARG_NAMES; + } else { + dumpFlags |= trace::DUMP_FLAG_NO_ARG_NAMES; + } + break; + default: + std::cerr << "error: unexpected option `" << opt << "`\n"; usage(); return 1; } @@ -99,22 +159,31 @@ command(int argc, char *argv[]) color = COLOR_OPTION_ALWAYS; #else color = isatty(1) ? COLOR_OPTION_ALWAYS : COLOR_OPTION_NEVER; + pipepager(); #endif } - for (; i < argc; ++i) { + if (color == COLOR_OPTION_NEVER) { + dumpFlags |= trace::DUMP_FLAG_NO_COLOR; + } + + for (int i = optind; i < argc; ++i) { trace::Parser p; if (!p.open(argv[i])) { - std::cerr << "error: failed to open " << argv[i] << "\n"; return 1; } trace::Call *call; while ((call = p.parse_call())) { - if (verbose || - !(call->flags & trace::CALL_FLAG_VERBOSE)) { - call->dump(std::cout, color); + if (calls.contains(*call)) { + if (verbose || + !(call->flags & trace::CALL_FLAG_VERBOSE)) { + if (dumpThreadIds) { + std::cout << std::hex << call->thread_id << std::dec << " "; + } + trace::dump(*call, std::cout, dumpFlags); + } } delete call; }