]> git.cworth.org Git - apitrace/blob - common/trace_parser.cpp
WGL: Support float-based attrib_list parameters.
[apitrace] / common / trace_parser.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 <assert.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "trace_file.hpp"
33 #include "trace_dump.hpp"
34 #include "trace_parser.hpp"
35
36
37 #define TRACE_VERBOSE 0
38
39
40 namespace trace {
41
42
43 Parser::Parser() {
44     file = NULL;
45     next_call_no = 0;
46     version = 0;
47     api = API_UNKNOWN;
48
49     glGetErrorSig = NULL;
50 }
51
52
53 Parser::~Parser() {
54     close();
55 }
56
57
58 bool Parser::open(const char *filename) {
59     assert(!file);
60     file = File::createForRead(filename);
61     if (!file) {
62         return false;
63     }
64
65     version = read_uint();
66     if (version > TRACE_VERSION) {
67         std::cerr << "error: unsupported trace format version " << version << "\n";
68         return false;
69     }
70     api = API_UNKNOWN;
71
72     return true;
73 }
74
75 template <typename Iter>
76 inline void
77 deleteAll(Iter begin, Iter end)
78 {
79     while (begin != end) {
80         delete *begin;
81         ++begin;
82     }
83 }
84
85 template <typename Container>
86 inline void
87 deleteAll(Container &c)
88 {
89     deleteAll(c.begin(), c.end());
90     c.clear();
91 }
92
93 void Parser::close(void) {
94     if (file) {
95         file->close();
96         delete file;
97         file = NULL;
98     }
99
100     deleteAll(calls);
101
102     // Delete all signature data.  Signatures are mere structures which don't
103     // own their own memory, so we need to destroy all data we created here.
104
105     for (FunctionMap::iterator it = functions.begin(); it != functions.end(); ++it) {
106         FunctionSigState *sig = *it;
107         if (sig) {
108             delete [] sig->name;
109             for (unsigned arg = 0; arg < sig->num_args; ++arg) {
110                 delete [] sig->arg_names[arg];
111             }
112             delete [] sig->arg_names;
113             delete sig;
114         }
115     }
116     functions.clear();
117
118     for (StructMap::iterator it = structs.begin(); it != structs.end(); ++it) {
119         StructSigState *sig = *it;
120         if (sig) {
121             delete [] sig->name;
122             for (unsigned member = 0; member < sig->num_members; ++member) {
123                 delete [] sig->member_names[member];
124             }
125             delete [] sig->member_names;
126             delete sig;
127         }
128     }
129     structs.clear();
130
131     for (EnumMap::iterator it = enums.begin(); it != enums.end(); ++it) {
132         EnumSigState *sig = *it;
133         if (sig) {
134             for (unsigned value = 0; value < sig->num_values; ++value) {
135                 delete [] sig->values[value].name;
136             }
137             delete [] sig->values;
138             delete sig;
139         }
140     }
141     enums.clear();
142     
143     for (BitmaskMap::iterator it = bitmasks.begin(); it != bitmasks.end(); ++it) {
144         BitmaskSigState *sig = *it;
145         if (sig) {
146             for (unsigned flag = 0; flag < sig->num_flags; ++flag) {
147                 delete [] sig->flags[flag].name;
148             }
149             delete [] sig->flags;
150             delete sig;
151         }
152     }
153     bitmasks.clear();
154
155     next_call_no = 0;
156 }
157
158
159 void Parser::getBookmark(ParseBookmark &bookmark) {
160     bookmark.offset = file->currentOffset();
161     bookmark.next_call_no = next_call_no;
162 }
163
164
165 void Parser::setBookmark(const ParseBookmark &bookmark) {
166     file->setCurrentOffset(bookmark.offset);
167     next_call_no = bookmark.next_call_no;
168     
169     // Simply ignore all pending calls
170     deleteAll(calls);
171 }
172
173
174 Call *Parser::parse_call(Mode mode) {
175     do {
176         Call *call;
177         int c = read_byte();
178         switch (c) {
179         case trace::EVENT_ENTER:
180 #if TRACE_VERBOSE
181             std::cerr << "\tENTER\n";
182 #endif
183             parse_enter(mode);
184             break;
185         case trace::EVENT_LEAVE:
186 #if TRACE_VERBOSE
187             std::cerr << "\tLEAVE\n";
188 #endif
189             call = parse_leave(mode);
190             if (call) {
191                 adjust_call_flags(call);
192                 return call;
193             }
194             break;
195         default:
196             std::cerr << "error: unknown event " << c << "\n";
197             exit(1);
198         case -1:
199             if (!calls.empty()) {
200                 call = calls.front();
201                 call->flags |= CALL_FLAG_INCOMPLETE;
202                 calls.pop_front();
203                 adjust_call_flags(call);
204                 return call;
205             }
206             return NULL;
207         }
208     } while(true);
209 }
210
211
212 /**
213  * Helper function to lookup an ID in a vector, resizing the vector if it doesn't fit.
214  */
215 template<class T>
216 T *lookup(std::vector<T *> &map, size_t index) {
217     if (index >= map.size()) {
218         map.resize(index + 1);
219         return NULL;
220     } else {
221         return map[index];
222     }
223 }
224
225
226 Parser::FunctionSigFlags *
227 Parser::parse_function_sig(void) {
228     size_t id = read_uint();
229
230     FunctionSigState *sig = lookup(functions, id);
231
232     if (!sig) {
233         /* parse the signature */
234         sig = new FunctionSigState;
235         sig->id = id;
236         sig->name = read_string();
237         sig->num_args = read_uint();
238         const char **arg_names = new const char *[sig->num_args];
239         for (unsigned i = 0; i < sig->num_args; ++i) {
240             arg_names[i] = read_string();
241         }
242         sig->arg_names = arg_names;
243         sig->flags = lookupCallFlags(sig->name);
244         sig->fileOffset = file->currentOffset();
245         functions[id] = sig;
246
247         /**
248          * Try to autodetect the API.
249          *
250          * XXX: Ideally we would allow to mix multiple APIs in a single trace,
251          * but as it stands today, retrace is done separately for each API.
252          */
253         if (api == API_UNKNOWN) {
254             const char *n = sig->name;
255             if ((n[0] == 'g' && n[1] == 'l' && n[2] == 'X') || // glX*
256                 (n[0] == 'w' && n[1] == 'g' && n[2] == 'l' && n[3] >= 'A' && n[3] <= 'Z') || // wgl[A-Z]*
257                 (n[0] == 'C' && n[1] == 'G' && n[2] == 'L')) { // CGL*
258                 api = trace::API_GL;
259             } else if (n[0] == 'e' && n[1] == 'g' && n[2] == 'l' && n[3] >= 'A' && n[3] <= 'Z') { // egl[A-Z]*
260                 api = trace::API_EGL;
261             } else if ((n[0] == 'D' &&
262                         ((n[1] == 'i' && n[2] == 'r' && n[3] == 'e' && n[4] == 'c' && n[5] == 't') || // Direct*
263                          (n[1] == '3' && n[2] == 'D'))) || // D3D*
264                        (n[0] == 'C' && n[1] == 'r' && n[2] == 'e' && n[3] == 'a' && n[4] == 't' && n[5] == 'e')) { // Create*
265                 api = trace::API_DX;
266             } else {
267                 /* TODO */
268             }
269         }
270
271         /**
272          * Note down the signature of special functions for future reference.
273          *
274          * NOTE: If the number of comparisons increases we should move this to a
275          * separate function and use bisection.
276          */
277         if (sig->num_args == 0 &&
278             strcmp(sig->name, "glGetError") == 0) {
279             glGetErrorSig = sig;
280         }
281
282     } else if (file->currentOffset() < sig->fileOffset) {
283         /* skip over the signature */
284         skip_string(); /* name */
285         unsigned num_args = read_uint();
286         for (unsigned i = 0; i < num_args; ++i) {
287              skip_string(); /*arg_name*/
288         }
289     }
290
291     assert(sig);
292     return sig;
293 }
294
295
296 StructSig *Parser::parse_struct_sig() {
297     size_t id = read_uint();
298
299     StructSigState *sig = lookup(structs, id);
300
301     if (!sig) {
302         /* parse the signature */
303         sig = new StructSigState;
304         sig->id = id;
305         sig->name = read_string();
306         sig->num_members = read_uint();
307         const char **member_names = new const char *[sig->num_members];
308         for (unsigned i = 0; i < sig->num_members; ++i) {
309             member_names[i] = read_string();
310         }
311         sig->member_names = member_names;
312         sig->fileOffset = file->currentOffset();
313         structs[id] = sig;
314     } else if (file->currentOffset() < sig->fileOffset) {
315         /* skip over the signature */
316         skip_string(); /* name */
317         unsigned num_members = read_uint();
318         for (unsigned i = 0; i < num_members; ++i) {
319             skip_string(); /* member_name */
320         }
321     }
322
323     assert(sig);
324     return sig;
325 }
326
327
328 /*
329  * Old enum signatures would cover a single name/value only:
330  *
331  *   enum_sig = id name value
332  *            | id
333  */
334 EnumSig *Parser::parse_old_enum_sig() {
335     size_t id = read_uint();
336
337     EnumSigState *sig = lookup(enums, id);
338
339     if (!sig) {
340         /* parse the signature */
341         sig = new EnumSigState;
342         sig->id = id;
343         sig->num_values = 1;
344         EnumValue *values = new EnumValue[sig->num_values];
345         values->name = read_string();
346         values->value = read_sint();
347         sig->values = values;
348         sig->fileOffset = file->currentOffset();
349         enums[id] = sig;
350     } else if (file->currentOffset() < sig->fileOffset) {
351         /* skip over the signature */
352         skip_string(); /*name*/
353         scan_value();
354     }
355
356     assert(sig);
357     return sig;
358 }
359
360
361 EnumSig *Parser::parse_enum_sig() {
362     size_t id = read_uint();
363
364     EnumSigState *sig = lookup(enums, id);
365
366     if (!sig) {
367         /* parse the signature */
368         sig = new EnumSigState;
369         sig->id = id;
370         sig->num_values = read_uint();
371         EnumValue *values = new EnumValue[sig->num_values];
372         for (EnumValue *it = values; it != values + sig->num_values; ++it) {
373             it->name = read_string();
374             it->value = read_sint();
375         }
376         sig->values = values;
377         sig->fileOffset = file->currentOffset();
378         enums[id] = sig;
379     } else if (file->currentOffset() < sig->fileOffset) {
380         /* skip over the signature */
381         int num_values = read_uint();
382         for (int i = 0; i < num_values; ++i) {
383             skip_string(); /*name */
384             skip_sint(); /* value */
385         }
386     }
387
388     assert(sig);
389     return sig;
390 }
391
392
393 BitmaskSig *Parser::parse_bitmask_sig() {
394     size_t id = read_uint();
395
396     BitmaskSigState *sig = lookup(bitmasks, id);
397
398     if (!sig) {
399         /* parse the signature */
400         sig = new BitmaskSigState;
401         sig->id = id;
402         sig->num_flags = read_uint();
403         BitmaskFlag *flags = new BitmaskFlag[sig->num_flags];
404         for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) {
405             it->name = read_string();
406             it->value = read_uint();
407             if (it->value == 0 && it != flags) {
408                 std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n";
409             }
410         }
411         sig->flags = flags;
412         sig->fileOffset = file->currentOffset();
413         bitmasks[id] = sig;
414     } else if (file->currentOffset() < sig->fileOffset) {
415         /* skip over the signature */
416         int num_flags = read_uint();
417         for (int i = 0; i < num_flags; ++i) {
418             skip_string(); /*name */
419             skip_uint(); /* value */
420         }
421     }
422
423     assert(sig);
424     return sig;
425 }
426
427
428 void Parser::parse_enter(Mode mode) {
429     unsigned thread_id;
430
431     if (version >= 4) {
432         thread_id = read_uint();
433     } else {
434         thread_id = 0;
435     }
436
437     FunctionSigFlags *sig = parse_function_sig();
438
439     Call *call = new Call(sig, sig->flags, thread_id);
440
441     call->no = next_call_no++;
442
443     if (parse_call_details(call, mode)) {
444         calls.push_back(call);
445     } else {
446         delete call;
447     }
448 }
449
450
451 Call *Parser::parse_leave(Mode mode) {
452     unsigned call_no = read_uint();
453     Call *call = NULL;
454     for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
455         if ((*it)->no == call_no) {
456             call = *it;
457             calls.erase(it);
458             break;
459         }
460     }
461     if (!call) {
462         /* This might happen on random access, when an asynchronous call is stranded
463          * between two frames.  We won't return this call, but we still need to skip 
464          * over its data.
465          */
466         const FunctionSig sig = {0, NULL, 0, NULL};
467         call = new Call(&sig, 0, 0);
468         parse_call_details(call, SCAN);
469         delete call;
470         return NULL;
471     }
472
473     if (parse_call_details(call, mode)) {
474         return call;
475     } else {
476         delete call;
477         return NULL;
478     }
479 }
480
481
482 bool Parser::parse_call_details(Call *call, Mode mode) {
483     do {
484         int c = read_byte();
485         switch (c) {
486         case trace::CALL_END:
487 #if TRACE_VERBOSE
488             std::cerr << "\tCALL_END\n";
489 #endif
490             return true;
491         case trace::CALL_ARG:
492 #if TRACE_VERBOSE
493             std::cerr << "\tCALL_ARG\n";
494 #endif
495             parse_arg(call, mode);
496             break;
497         case trace::CALL_RET:
498 #if TRACE_VERBOSE
499             std::cerr << "\tCALL_RET\n";
500 #endif
501             call->ret = parse_value(mode);
502             break;
503         case trace::CALL_BACKTRACE:
504 #if TRACE_VERBOSE
505             std::cerr << "\tCALL_BACKTRACE\n";
506 #endif
507             parse_call_backtrace(call, mode);
508             break;
509         default:
510             std::cerr << "error: ("<<call->name()<< ") unknown call detail "
511                       << c << "\n";
512             exit(1);
513         case -1:
514             return false;
515         }
516     } while(true);
517 }
518
519 bool Parser::parse_call_backtrace(Call *call, Mode mode) {
520     unsigned num_frames = read_uint();
521     Backtrace* backtrace = new Backtrace(num_frames);
522     for (unsigned i = 0; i < num_frames; ++i) {
523         (*backtrace)[i] = parse_backtrace_frame(mode);
524     }
525     call->backtrace = backtrace;
526     return true;
527 }
528
529 StackFrame * Parser::parse_backtrace_frame(Mode mode) {
530     size_t id = read_uint();
531
532     StackFrameState *frame = lookup(frames, id);
533
534     if (!frame) {
535         frame = new StackFrameState;
536         int c = read_byte();
537         while (c != trace::BACKTRACE_END &&
538                c != -1) {
539             switch (c) {
540             case trace::BACKTRACE_MODULE:
541                 frame->module = read_string();
542                 break;
543             case trace::BACKTRACE_FUNCTION:
544                 frame->function = read_string();
545                 break;
546             case trace::BACKTRACE_FILENAME:
547                 frame->filename = read_string();
548                 break;
549             case trace::BACKTRACE_LINENUMBER:
550                 frame->linenumber = read_uint();
551                 break;
552             case trace::BACKTRACE_OFFSET:
553                 frame->offset = read_uint();
554                 break;
555             default:
556                 std::cerr << "error: unknown backtrace detail "
557                           << c << "\n";
558                 exit(1);
559             }
560             c = read_byte();
561         }
562
563         frame->fileOffset = file->currentOffset();
564         frames[id] = frame;
565     } else if (file->currentOffset() < frame->fileOffset) {
566         int c = read_byte();
567         while (c != trace::BACKTRACE_END &&
568                c != -1) {
569             switch (c) {
570             case trace::BACKTRACE_MODULE:
571                 scan_string();
572                 break;
573             case trace::BACKTRACE_FUNCTION:
574                 scan_string();
575                 break;
576             case trace::BACKTRACE_FILENAME:
577                 scan_string();
578                 break;
579             case trace::BACKTRACE_LINENUMBER:
580                 scan_uint();
581                 break;
582             case trace::BACKTRACE_OFFSET:
583                 scan_uint();
584                 break;
585             default:
586                 std::cerr << "error: unknown backtrace detail "
587                           << c << "\n";
588                 exit(1);
589             }
590             c = read_byte();
591         }
592     }
593
594     return frame;
595 }
596
597 /**
598  * Make adjustments to this particular call flags.
599  *
600  * NOTE: This is called per-call so no string comparisons should be done here.
601  * All name comparisons should be done when the signature is parsed instead.
602  */
603 void Parser::adjust_call_flags(Call *call) {
604     // Mark glGetError() = GL_NO_ERROR as verbose
605     if (call->sig == glGetErrorSig &&
606         call->ret &&
607         call->ret->toSInt() == 0) {
608         call->flags |= CALL_FLAG_VERBOSE;
609     }
610 }
611
612 void Parser::parse_arg(Call *call, Mode mode) {
613     unsigned index = read_uint();
614     Value *value = parse_value(mode);
615     if (value) {
616         if (index >= call->args.size()) {
617             call->args.resize(index + 1);
618         }
619         call->args[index].value = value;
620     }
621 }
622
623
624 Value *Parser::parse_value(void) {
625     int c;
626     Value *value;
627     c = read_byte();
628     switch (c) {
629     case trace::TYPE_NULL:
630         value = new Null;
631         break;
632     case trace::TYPE_FALSE:
633         value = new Bool(false);
634         break;
635     case trace::TYPE_TRUE:
636         value = new Bool(true);
637         break;
638     case trace::TYPE_SINT:
639         value = parse_sint();
640         break;
641     case trace::TYPE_UINT:
642         value = parse_uint();
643         break;
644     case trace::TYPE_FLOAT:
645         value = parse_float();
646         break;
647     case trace::TYPE_DOUBLE:
648         value = parse_double();
649         break;
650     case trace::TYPE_STRING:
651         value = parse_string();
652         break;
653     case trace::TYPE_ENUM:
654         value = parse_enum();
655         break;
656     case trace::TYPE_BITMASK:
657         value = parse_bitmask();
658         break;
659     case trace::TYPE_ARRAY:
660         value = parse_array();
661         break;
662     case trace::TYPE_STRUCT:
663         value = parse_struct();
664         break;
665     case trace::TYPE_BLOB:
666         value = parse_blob();
667         break;
668     case trace::TYPE_OPAQUE:
669         value = parse_opaque();
670         break;
671     case trace::TYPE_REPR:
672         value = parse_repr();
673         break;
674     default:
675         std::cerr << "error: unknown type " << c << "\n";
676         exit(1);
677     case -1:
678         value = NULL;
679         break;
680     }
681 #if TRACE_VERBOSE
682     if (value) {
683         std::cerr << "\tVALUE ";
684         trace::dump(value, std::cerr);
685         std::cerr << "\n";
686     }
687 #endif
688     return value;
689 }
690
691
692 void Parser::scan_value(void) {
693     int c = read_byte();
694     switch (c) {
695     case trace::TYPE_NULL:
696     case trace::TYPE_FALSE:
697     case trace::TYPE_TRUE:
698         break;
699     case trace::TYPE_SINT:
700         scan_sint();
701         break;
702     case trace::TYPE_UINT:
703         scan_uint();
704         break;
705     case trace::TYPE_FLOAT:
706         scan_float();
707         break;
708     case trace::TYPE_DOUBLE:
709         scan_double();
710         break;
711     case trace::TYPE_STRING:
712         scan_string();
713         break;
714     case trace::TYPE_ENUM:
715         scan_enum();
716         break;
717     case trace::TYPE_BITMASK:
718         scan_bitmask();
719         break;
720     case trace::TYPE_ARRAY:
721         scan_array();
722         break;
723     case trace::TYPE_STRUCT:
724         scan_struct();
725         break;
726     case trace::TYPE_BLOB:
727         scan_blob();
728         break;
729     case trace::TYPE_OPAQUE:
730         scan_opaque();
731         break;
732     case trace::TYPE_REPR:
733         scan_repr();
734         break;
735     default:
736         std::cerr << "error: unknown type " << c << "\n";
737         exit(1);
738     case -1:
739         break;
740     }
741 }
742
743
744 Value *Parser::parse_sint() {
745     return new SInt(-(signed long long)read_uint());
746 }
747
748
749 void Parser::scan_sint() {
750     skip_uint();
751 }
752
753
754 Value *Parser::parse_uint() {
755     return new UInt(read_uint());
756 }
757
758
759 void Parser::scan_uint() {
760     skip_uint();
761 }
762
763
764 Value *Parser::parse_float() {
765     float value;
766     file->read(&value, sizeof value);
767     return new Float(value);
768 }
769
770
771 void Parser::scan_float() {
772     file->skip(sizeof(float));
773 }
774
775
776 Value *Parser::parse_double() {
777     double value;
778     file->read(&value, sizeof value);
779     return new Double(value);
780 }
781
782
783 void Parser::scan_double() {
784     file->skip(sizeof(double));
785 }
786
787
788 Value *Parser::parse_string() {
789     return new String(read_string());
790 }
791
792
793 void Parser::scan_string() {
794     skip_string();
795 }
796
797
798 Value *Parser::parse_enum() {
799     EnumSig *sig;
800     signed long long value;
801     if (version >= 3) {
802         sig = parse_enum_sig();
803         value = read_sint();
804     } else {
805         sig = parse_old_enum_sig();
806         assert(sig->num_values == 1);
807         value = sig->values->value;
808     }
809     return new Enum(sig, value);
810 }
811
812
813 void Parser::scan_enum() {
814     if (version >= 3) {
815         parse_enum_sig();
816         skip_sint();
817     } else {
818         parse_old_enum_sig();
819     }
820 }
821
822
823 Value *Parser::parse_bitmask() {
824     BitmaskSig *sig = parse_bitmask_sig();
825
826     unsigned long long value = read_uint();
827
828     return new Bitmask(sig, value);
829 }
830
831
832 void Parser::scan_bitmask() {
833     parse_bitmask_sig();
834     skip_uint(); /* value */
835 }
836
837
838 Value *Parser::parse_array(void) {
839     size_t len = read_uint();
840     Array *array = new Array(len);
841     for (size_t i = 0; i < len; ++i) {
842         array->values[i] = parse_value();
843     }
844     return array;
845 }
846
847
848 void Parser::scan_array(void) {
849     size_t len = read_uint();
850     for (size_t i = 0; i < len; ++i) {
851         scan_value();
852     }
853 }
854
855
856 Value *Parser::parse_blob(void) {
857     size_t size = read_uint();
858     Blob *blob = new Blob(size);
859     if (size) {
860         file->read(blob->buf, size);
861     }
862     return blob;
863 }
864
865
866 void Parser::scan_blob(void) {
867     size_t size = read_uint();
868     if (size) {
869         file->skip(size);
870     }
871 }
872
873
874 Value *Parser::parse_struct() {
875     StructSig *sig = parse_struct_sig();
876     Struct *value = new Struct(sig);
877
878     for (size_t i = 0; i < sig->num_members; ++i) {
879         value->members[i] = parse_value();
880     }
881
882     return value;
883 }
884
885
886 void Parser::scan_struct() {
887     StructSig *sig = parse_struct_sig();
888     for (size_t i = 0; i < sig->num_members; ++i) {
889         scan_value();
890     }
891 }
892
893
894 Value *Parser::parse_opaque() {
895     unsigned long long addr;
896     addr = read_uint();
897     return new Pointer(addr);
898 }
899
900
901 void Parser::scan_opaque() {
902     skip_uint();
903 }
904
905
906 Value *Parser::parse_repr() {
907     Value *humanValue = parse_value();
908     Value *machineValue = parse_value();
909     return new Repr(humanValue, machineValue);
910 }
911
912
913 void Parser::scan_repr() {
914     scan_value();
915     scan_value();
916 }
917
918
919 const char * Parser::read_string(void) {
920     size_t len = read_uint();
921     char * value = new char[len + 1];
922     if (len) {
923         file->read(value, len);
924     }
925     value[len] = 0;
926 #if TRACE_VERBOSE
927     std::cerr << "\tSTRING \"" << value << "\"\n";
928 #endif
929     return value;
930 }
931
932
933 void Parser::skip_string(void) {
934     size_t len = read_uint();
935     file->skip(len);
936 }
937
938
939 /*
940  * For the time being, a signed int is encoded as any other value, but we here parse
941  * it without the extra baggage of the Value class.
942  */
943 signed long long
944 Parser::read_sint(void) {
945     int c;
946     c = read_byte();
947     switch (c) {
948     case trace::TYPE_SINT:
949         return -(signed long long)read_uint();
950     case trace::TYPE_UINT:
951         return read_uint();
952     default:
953         std::cerr << "error: unexpected type " << c << "\n";
954         exit(1);
955     case -1:
956         return 0;
957     }
958 }
959
960 void
961 Parser::skip_sint(void) {
962     skip_byte();
963     skip_uint();
964 }
965
966 unsigned long long Parser::read_uint(void) {
967     unsigned long long value = 0;
968     int c;
969     unsigned shift = 0;
970     do {
971         c = file->getc();
972         if (c == -1) {
973             break;
974         }
975         value |= (unsigned long long)(c & 0x7f) << shift;
976         shift += 7;
977     } while(c & 0x80);
978 #if TRACE_VERBOSE
979     std::cerr << "\tUINT " << value << "\n";
980 #endif
981     return value;
982 }
983
984
985 void Parser::skip_uint(void) {
986     int c;
987     do {
988         c = file->getc();
989         if (c == -1) {
990             break;
991         }
992     } while(c & 0x80);
993 }
994
995
996 inline int Parser::read_byte(void) {
997     int c = file->getc();
998 #if TRACE_VERBOSE
999     if (c < 0)
1000         std::cerr << "\tEOF" << "\n";
1001     else
1002         std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n";
1003 #endif
1004     return c;
1005 }
1006
1007
1008 inline void Parser::skip_byte(void) {
1009     file->skip(1);
1010 }
1011
1012
1013 } /* namespace trace */