blob: 50f315caa2ff982014b2cbaf4a7294531ec92619 [file] [log] [blame]
José Fonseca7e329022010-11-19 17:05:18 +00001/**************************************************************************
2 *
3 * Copyright 2010 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 **************************************************************************/
25
26#ifndef _TRACE_PARSER_HPP_
27#define _TRACE_PARSER_HPP_
28
29
30#include <cassert>
31
32#include <iostream>
33
34#include <zlib.h>
35
36#include "trace_format.hpp"
37#include "trace_model.hpp"
38
39
40namespace Trace {
41
42
43class Parser
44{
45protected:
46 gzFile file;
47public:
48 Parser() {
49 file = NULL;
50 }
51
52 bool parse(const char *filename) {
53 unsigned long long version;
54
55 file = gzopen(filename, "rb");
56 if (!file) {
57 return false;
58 }
59
60 version = read_uint();
61 if (version != TRACE_VERSION) {
62 std::cerr << "Unsupported format version" << version << "\n";
63 return false;
64 }
65
66 while (!gzeof(file)) {
67 parse_call();
68 }
69
70 return true;
71 }
72
73 void parse_call(void) {
74 Call call;
75 call.name = read_string();
76 int c;
77 do {
78 c = gzgetc(file);
79 if (c == Trace::CALL_END || c == -1) {
80 break;
81 }
82 switch(c) {
83 case Trace::CALL_END:
84 return;
85 case Trace::CALL_ARG:
86 call.args.push_back(parse_arg());
87 break;
88 case Trace::CALL_RET:
89 call.ret = parse_value();
90 break;
91 default:
92 assert(0);
93 std::cerr << "Unknown call detail " << c << "\n";
94 break;
95 }
96 } while(true);
97 handle_call(call);
98 }
99
100 virtual void handle_call(Call &call) {
101 std::cout << call;
102 }
103
104 Arg parse_arg(void) {
105 std::string name = read_string();
106 Value *value = parse_value();
107 return Arg(name, value);
108 }
109
110 Value *parse_value(void) {
111 int c;
112 c = gzgetc(file);
113 switch(c) {
114 case Trace::TYPE_BOOL:
115 return parse_bool();
116 case Trace::TYPE_SINT:
117 return parse_sint();
118 case Trace::TYPE_UINT:
119 return parse_uint();
120 case Trace::TYPE_FLOAT:
121 return parse_float();
122 case Trace::TYPE_DOUBLE:
123 return parse_double();
124 case Trace::TYPE_STRING:
125 return parse_string();
126 case Trace::TYPE_CONST:
127 return parse_const();
128 case Trace::TYPE_BITMASK:
129 return parse_bitmask();
130 case Trace::TYPE_ARRAY:
131 return parse_array();
132 case Trace::TYPE_POINTER:
133 return parse_pointer();
134 case Trace::TYPE_VOID:
135 return NULL;
136 default:
137 std::cerr << "Unknown type " << c << "\n";
138 assert(0);
139 return NULL;
140 }
141 }
142
143 Value *parse_bool() {
144 int c;
145 c = gzgetc(file);
146 return new Bool(c);
147 }
148
149 Value *parse_sint() {
150 return new SInt(-read_uint());
151 }
152
153 Value *parse_uint() {
154 return new UInt(read_uint());
155 }
156
157 Value *parse_float() {
158 float value;
159 gzread(file, &value, sizeof value);
160 return new Float(value);
161 }
162
163 Value *parse_double() {
164 double value;
165 gzread(file, &value, sizeof value);
166 return new Float(value);
167 }
168
169 Value *parse_string() {
170 return new String(read_string());
171 }
172
173 Value *parse_const() {
174 std::string name = read_string();
175 Value *value = parse_value();
176 return new Const(name, value);
177 }
178
179 Value *parse_bitmask() {
180 unsigned long long value = 0;
181 int c;
182 do {
183 c = gzgetc(file);
184 switch(c) {
185 case Trace::TYPE_SINT:
186 value |= -read_uint();
187 break;
188 case Trace::TYPE_UINT:
189 value |= read_uint();
190 break;
191 case Trace::TYPE_CONST:
192 read_string();
193 break;
194 case Trace::TYPE_VOID:
195 goto done;
196 default:
197 std::cerr << "Unexpected type " << c << "\n";
198 assert(0);
199 return NULL;
200 }
201 } while(true);
202done:
203 return new UInt(value);
204 }
205
206 Value *parse_array() {
207 size_t len = read_uint();
208 Array *array = new Array(len);
209 for (size_t i = 0; i < len; ++i) {
210 array->values[i] = parse_value();
211 }
212 return array;
213 }
214
215 Value *parse_pointer() {
216 unsigned long long addr;
217 Value *value;
218 addr = read_uint();
219 value = parse_value();
220 if (!value)
221 value = new UInt(addr);
222 return value;
223 }
224
225 std::string read_string(void) {
226 size_t len = read_uint();
227 char * buf = new char[len];
228 gzread(file, buf, len);
229 std::string value(buf, len);
230 delete [] buf;
231 return value;
232 }
233
234 unsigned long long read_uint(void) {
235 unsigned long long value = 0;
236 int c;
237 unsigned shift = 0;
238 do {
239 c = gzgetc(file);
240 if (c == -1) {
241 break;
242 }
243 value |= (unsigned long long)(c & 0x7f) << shift;
244 shift += 7;
245 } while(c & 0x80);
246 return value;
247 }
248};
249
250
251} /* namespace Trace */
252
253#endif /* _TRACE_PARSER_HPP_ */