]> git.cworth.org Git - apitrace/blob - cli/cli_dump.cpp
Merge branch 'master' into d3dretrace
[apitrace] / cli / cli_dump.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * Copyright 2010 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27
28 #include <string.h>
29 #include <limits.h> // for CHAR_MAX
30 #include <getopt.h>
31
32 #include "cli.hpp"
33 #include "cli_pager.hpp"
34
35 #include "trace_parser.hpp"
36 #include "trace_dump.hpp"
37 #include "trace_callset.hpp"
38
39
40 enum ColorOption {
41     COLOR_OPTION_NEVER = 0,
42     COLOR_OPTION_ALWAYS = 1,
43     COLOR_OPTION_AUTO = -1
44 };
45
46 static ColorOption color = COLOR_OPTION_AUTO;
47
48 static bool verbose = false;
49
50 static trace::CallSet calls(trace::FREQUENCY_ALL);
51
52 static const char *synopsis = "Dump given trace(s) to standard output.";
53
54 static void
55 usage(void)
56 {
57     std::cout
58         << "usage: apitrace dump [OPTIONS] TRACE_FILE...\n"
59         << synopsis << "\n"
60         "\n"
61         "    -h, --help           show this help message and exit\n"
62         "    -v, --verbose        verbose output\n"
63         "    --calls=CALLSET      only dump specified calls\n"
64         "    --color[=WHEN]\n"
65         "    --colour[=WHEN]      colored syntax highlighting\n"
66         "                         WHEN is 'auto', 'always', or 'never'\n"
67         "    --thread-ids=[=BOOL] dump thread ids [default: no]\n"
68         "    --call-nos[=BOOL]    dump call numbers[default: yes]\n"
69         "    --arg-names[=BOOL]   dump argument names [default: yes]\n"
70         "\n"
71     ;
72 }
73
74 enum {
75         CALLS_OPT = CHAR_MAX + 1,
76         COLOR_OPT,
77     THREAD_IDS_OPT,
78     CALL_NOS_OPT,
79     ARG_NAMES_OPT,
80 };
81
82 const static char *
83 shortOptions = "hv";
84
85 const static struct option
86 longOptions[] = {
87     {"help", no_argument, 0, 'h'},
88     {"verbose", no_argument, 0, 'v'},
89     {"calls", required_argument, 0, CALLS_OPT},
90     {"colour", optional_argument, 0, COLOR_OPT},
91     {"color", optional_argument, 0, COLOR_OPT},
92     {"thread-ids", optional_argument, 0, THREAD_IDS_OPT},
93     {"call-nos", optional_argument, 0, CALL_NOS_OPT},
94     {"arg-names", optional_argument, 0, ARG_NAMES_OPT},
95     {0, 0, 0, 0}
96 };
97
98 static bool
99 boolOption(const char *option, bool default_ = true) {
100     if (!option) {
101         return default_;
102     }
103     if (strcmp(option, "0") == 0 ||
104         strcmp(option, "no") == 0 ||
105         strcmp(option, "false") == 0) {
106         return false;
107     }
108     if (strcmp(option, "0") == 0 ||
109         strcmp(option, "yes") == 0 ||
110         strcmp(option, "true") == 0) {
111         return true;
112     }
113     std::cerr << "error: unexpected bool " << option << "\n";
114     return default_;
115 }
116
117 static int
118 command(int argc, char *argv[])
119 {
120     trace::DumpFlags dumpFlags = 0;
121     bool dumpThreadIds = false;
122     
123     int opt;
124     while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
125         switch (opt) {
126         case 'h':
127             usage();
128             return 0;
129         case 'v':
130             verbose = true;
131             break;
132         case CALLS_OPT:
133             calls = trace::CallSet(optarg);
134             break;
135         case COLOR_OPT:
136             if (!optarg ||
137                 !strcmp(optarg, "always")) {
138                 color = COLOR_OPTION_ALWAYS;
139             } else if (!strcmp(optarg, "auto")) {
140                 color = COLOR_OPTION_AUTO;
141             } else if (!strcmp(optarg, "never")) {
142                 color = COLOR_OPTION_NEVER;
143             } else {
144                 std::cerr << "error: unknown color argument " << optarg << "\n";
145                 return 1;
146             }
147             break;
148         case THREAD_IDS_OPT:
149             dumpThreadIds = boolOption(optarg);
150             break;
151         case CALL_NOS_OPT:
152             if (boolOption(optarg)) {
153                 dumpFlags &= ~trace::DUMP_FLAG_NO_CALL_NO;
154             } else {
155                 dumpFlags |= trace::DUMP_FLAG_NO_CALL_NO;
156             }
157             break;
158         case ARG_NAMES_OPT:
159             if (boolOption(optarg)) {
160                 dumpFlags &= ~trace::DUMP_FLAG_NO_ARG_NAMES;
161             } else {
162                 dumpFlags |= trace::DUMP_FLAG_NO_ARG_NAMES;
163             }
164             break;
165         default:
166             std::cerr << "error: unexpected option `" << opt << "`\n";
167             usage();
168             return 1;
169         }
170     }
171
172     if (color == COLOR_OPTION_AUTO) {
173 #ifdef _WIN32
174         color = COLOR_OPTION_ALWAYS;
175 #else
176         color = isatty(1) ? COLOR_OPTION_ALWAYS : COLOR_OPTION_NEVER;
177         pipepager();
178 #endif
179     }
180
181     if (color == COLOR_OPTION_NEVER) {
182         dumpFlags |= trace::DUMP_FLAG_NO_COLOR;
183     }
184
185     for (int i = optind; i < argc; ++i) {
186         trace::Parser p;
187
188         if (!p.open(argv[i])) {
189             std::cerr << "error: failed to open " << argv[i] << "\n";
190             return 1;
191         }
192
193         trace::Call *call;
194         while ((call = p.parse_call())) {
195             if (calls.contains(*call)) {
196                 if (verbose ||
197                     !(call->flags & trace::CALL_FLAG_VERBOSE)) {
198                     if (dumpThreadIds) {
199                         std::cout << std::hex << call->thread_id << std::dec << " ";
200                     }
201                     trace::dump(*call, std::cout, dumpFlags);
202                 }
203             }
204             delete call;
205         }
206     }
207
208     return 0;
209 }
210
211 const Command dump_command = {
212     "dump",
213     synopsis,
214     usage,
215     command
216 };