for (EnumMap::iterator it = enums.begin(); it != enums.end(); ++it) {
EnumSigState *sig = *it;
if (sig) {
- delete [] sig->name;
+ for (unsigned value = 0; value < sig->num_values; ++value) {
+ delete [] sig->values[value].name;
+ }
+ delete [] sig->values;
delete sig;
}
}
}
-EnumSig *Parser::parse_enum_sig() {
+/*
+ * Old enum signatures would cover a single name/value only:
+ *
+ * enum_sig = id name value
+ * | id
+ */
+EnumSig *Parser::parse_old_enum_sig() {
size_t id = read_uint();
EnumSigState *sig = lookup(enums, id);
/* parse the signature */
sig = new EnumSigState;
sig->id = id;
- sig->name = read_string();
- Value *value = parse_value();
- sig->value = value->toSInt();
- delete value;
+ sig->num_values = 1;
+ EnumValue *values = new EnumValue[sig->num_values];
+ values->name = read_string();
+ values->value = read_sint();
+ sig->values = values;
sig->offset = file->currentOffset();
enums[id] = sig;
} else if (file->currentOffset() < sig->offset) {
}
+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->num_values = read_uint();
+ EnumValue *values = new EnumValue[sig->num_values];
+ for (EnumValue *it = values; it != values + sig->num_values; ++it) {
+ it->name = read_string();
+ it->value = read_sint();
+ }
+ sig->values = values;
+ sig->offset = file->currentOffset();
+ enums[id] = sig;
+ } else if (file->currentOffset() < sig->offset) {
+ /* skip over the signature */
+ int num_values = read_uint();
+ for (int i = 0; i < num_values; ++i) {
+ skip_string(); /*name */
+ skip_sint(); /* value */
+ }
+ }
+
+ assert(sig);
+ return sig;
+}
+
+
BitmaskSig *Parser::parse_bitmask_sig() {
size_t id = read_uint();
void Parser::parse_enter(Mode mode) {
+ unsigned thread_id;
+
+ if (version >= 4) {
+ thread_id = read_uint();
+ } else {
+ thread_id = 0;
+ }
+
FunctionSigFlags *sig = parse_function_sig();
- Call *call = new Call(sig, sig->flags);
+ Call *call = new Call(sig, sig->flags, thread_id);
call->no = next_call_no++;
if (index >= call->args.size()) {
call->args.resize(index + 1);
}
- call->args[index] = value;
+ call->args[index].value = value;
}
}
Value *Parser::parse_enum() {
- EnumSig *sig = parse_enum_sig();
- return new Enum(sig);
+ EnumSig *sig;
+ signed long long value;
+ if (version >= 3) {
+ sig = parse_enum_sig();
+ value = read_sint();
+ } else {
+ sig = parse_old_enum_sig();
+ assert(sig->num_values == 1);
+ value = sig->values->value;
+ }
+ return new Enum(sig, value);
}
void Parser::scan_enum() {
- parse_enum_sig();
+ if (version >= 3) {
+ parse_enum_sig();
+ skip_sint();
+ } else {
+ parse_old_enum_sig();
+ }
}
}
+/*
+ * For the time being, a signed int is encoded as any other value, but we here parse
+ * it without the extra baggage of the Value class.
+ */
+signed long long
+Parser::read_sint(void) {
+ int c;
+ c = read_byte();
+ switch (c) {
+ case trace::TYPE_SINT:
+ return -read_uint();
+ case trace::TYPE_UINT:
+ return read_uint();
+ default:
+ std::cerr << "error: unexpected type " << c << "\n";
+ exit(1);
+ case -1:
+ return 0;
+ }
+}
+
+void
+Parser::skip_sint(void) {
+ skip_byte();
+ skip_uint();
+}
+
unsigned long long Parser::read_uint(void) {
unsigned long long value = 0;
int c;