}
 
 
-Call *Parser::parse_call(void) {
+Call *Parser::parse_call(Mode mode) {
     do {
         int c = read_byte();
         switch(c) {
         case Trace::EVENT_ENTER:
-            parse_enter();
+            parse_enter(mode);
             break;
         case Trace::EVENT_LEAVE:
-            return parse_leave();
+            return parse_leave(mode);
         default:
             std::cerr << "error: unknown event " << c << "\n";
             exit(1);
 }
 
 
-Call * Parser::scan_call()
-{
-    do {
-        int c = read_byte();
-        switch(c) {
-        case Trace::EVENT_ENTER:
-            scan_enter();
-            break;
-        case Trace::EVENT_LEAVE:
-            return scan_leave();
-        default:
-            std::cerr << "error: unknown event " << c << "\n";
-            exit(1);
-        case -1:
-            for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
-                std::cerr << "warning: incomplete call " << (*it)->name() << "\n";
-                std::cerr << **it << "\n";
-            }
-            return NULL;
-        }
-    } while (true);
-}
-
-
 /**
  * Helper function to lookup an ID in a vector, resizing the vector if it doesn't fit.
  */
 }
 
 
-void Parser::parse_enter(void) {
+void Parser::parse_enter(Mode mode) {
     FunctionSig *sig = parse_function_sig();
 
     Call *call = new Call(sig);
 
     call->no = next_call_no++;
 
-    if (parse_call_details(call)) {
+    if (parse_call_details(call, mode)) {
         calls.push_back(call);
     } else {
         delete call;
 }
 
 
-void Parser::scan_enter(void) {
-    FunctionSig *sig = parse_function_sig();
-
-    Call *call = new Call(sig);
-    call->no = next_call_no++;
-
-    if (scan_call_details(call)) {
-        calls.push_back(call);
-    } else {
-        delete call;
-    }
-}
-
-
-Call *Parser::parse_leave(void) {
-    unsigned call_no = read_uint();
-    Call *call = NULL;
-    for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
-        if ((*it)->no == call_no) {
-            call = *it;
-            calls.erase(it);
-            break;
-        }
-    }
-    if (!call) {
-        return NULL;
-    }
-
-    if (parse_call_details(call)) {
-        return call;
-    } else {
-        delete call;
-        return NULL;
-    }
-}
-
-
-Call *Parser::scan_leave(void) {
+Call *Parser::parse_leave(Mode mode) {
     unsigned call_no = read_uint();
     Call *call = NULL;
     for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
         return NULL;
     }
 
-    if (scan_call_details(call)) {
+    if (parse_call_details(call, mode)) {
         return call;
     } else {
         delete call;
 }
 
 
-bool Parser::parse_call_details(Call *call) {
+bool Parser::parse_call_details(Call *call, Mode mode) {
     do {
         int c = read_byte();
         switch(c) {
         case Trace::CALL_END:
             return true;
         case Trace::CALL_ARG:
-            parse_arg(call);
+            parse_arg(call, mode);
             break;
         case Trace::CALL_RET:
-            call->ret = parse_value();
+            call->ret = parse_value(mode);
             break;
         default:
             std::cerr << "error: ("<<call->name()<< ") unknown call detail "
 }
 
 
-bool Parser::scan_call_details(Call *call) {
-    do {
-        int c = read_byte();
-        switch(c) {
-        case Trace::CALL_END:
-            return true;
-        case Trace::CALL_ARG:
-            scan_arg(call);
-            break;
-        case Trace::CALL_RET:
-            scan_value();
-            break;
-        default:
-            std::cerr << "error: ("<<call->name()<< ") unknown call detail "
-                      << c << "\n";
-            exit(1);
-        case -1:
-            return false;
-        }
-    } while(true);
-}
-
-
-void Parser::parse_arg(Call *call) {
+void Parser::parse_arg(Call *call, Mode mode) {
     unsigned index = read_uint();
-    Value *value = parse_value();
-    if (index >= call->args.size()) {
-        call->args.resize(index + 1);
+    Value *value = parse_value(mode);
+    if (value) {
+        if (index >= call->args.size()) {
+            call->args.resize(index + 1);
+        }
+        call->args[index] = value;
     }
-    call->args[index] = value;
-}
-
-
-void Parser::scan_arg(Call *call) {
-    skip_uint(); /* index */
-    scan_value(); /* value */
 }
 
 
 
 protected:
     File *file;
 
+    enum Mode {
+        FULL = 0,
+        SCAN,
+        SKIP
+    };
+
     typedef std::list<Call *> CallList;
     CallList calls;
 
 
     void close(void);
 
-    Call *parse_call(void);
+    Call *parse_call(void) {
+        return parse_call(FULL);
+    }
 
     bool supportsOffsets() const
     {
         return file->percentRead();
     }
 
-    Call *scan_call();
+    Call *scan_call() {
+        return parse_call(SCAN);
+    }
 
 protected:
+    Call *parse_call(Mode mode);
+
     FunctionSig *parse_function_sig(void);
     StructSig *parse_struct_sig();
     EnumSig *parse_enum_sig();
     BitmaskSig *parse_bitmask_sig();
+    
+    Call *parse_Call(Mode mode);
 
-    void parse_enter(void);
-    void scan_enter(void);
+    void parse_enter(Mode mode);
 
-    Call *parse_leave(void);
-    Call *scan_leave(void);
+    Call *parse_leave(Mode mode);
 
-    bool parse_call_details(Call *call);
-    bool scan_call_details(Call *call);
+    bool parse_call_details(Call *call, Mode mode);
 
-    void parse_arg(Call *call);
-    void scan_arg(Call *call);
+    void parse_arg(Call *call, Mode mode);
 
     Value *parse_value(void);
     void scan_value(void);
+    inline Value *parse_value(Mode mode) {
+        if (mode == FULL) {
+            return parse_value();
+        } else {
+            scan_value();
+            return NULL;
+        }
+    }
 
     Value *parse_sint();
     void scan_sint();