Fix to UriTemplate.Match to properly handle query parameters without a value. No...
[mono.git] / tools / sgen / sgen-grep-binprot.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <glib.h>
5
6 #define SGEN_BINARY_PROTOCOL
7 #define MONO_INTERNAL
8
9 #include <mono/metadata/sgen-protocol.h>
10
11 #define SGEN_PROTOCOL_EOF       255
12
13 #define TYPE(t)         ((t) & 0x7f)
14 #define WORKER(t)       ((t) & 0x80)
15
16 static int
17 read_entry (FILE *in, void **data)
18 {
19         unsigned char type;
20         int size;
21
22         if (fread (&type, 1, 1, in) != 1)
23                 return SGEN_PROTOCOL_EOF;
24         switch (TYPE (type)) {
25
26 #define BEGIN_PROTOCOL_ENTRY0(method) \
27         case PROTOCOL_ID(method): size = 0; break;
28 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
29         case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
30 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
31         case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
32 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
33         case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
34 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
35         case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
36 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
37         case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
38 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
39         case PROTOCOL_ID(method): size = sizeof (PROTOCOL_STRUCT(method)); break;
40
41 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
42         BEGIN_PROTOCOL_ENTRY0 (method)
43 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
44         BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
45 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
46         BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
47 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
48         BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
49 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
50         BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
51 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
52         BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
53 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
54         BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
55
56 #define FLUSH()
57
58 #define DEFAULT_PRINT()
59 #define CUSTOM_PRINT(_)
60
61 #define IS_ALWAYS_MATCH(_)
62 #define MATCH_INDEX(_)
63 #define IS_VTABLE_MATCH(_)
64
65 #define END_PROTOCOL_ENTRY
66 #define END_PROTOCOL_ENTRY_HEAVY
67
68 #include <mono/metadata/sgen-protocol-def.h>
69
70         default: assert (0);
71         }
72
73         if (size) {
74                 *data = malloc (size);
75                 if (fread (*data, size, 1, in) != 1)
76                         assert (0);
77         } else {
78                 *data = NULL;
79         }
80
81         return (int)type;
82 }
83
84 static gboolean
85 is_always_match (int type)
86 {
87         switch (TYPE (type)) {
88 #define BEGIN_PROTOCOL_ENTRY0(method) \
89         case PROTOCOL_ID(method):
90 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
91         case PROTOCOL_ID(method):
92 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
93         case PROTOCOL_ID(method):
94 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
95         case PROTOCOL_ID(method):
96 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
97         case PROTOCOL_ID(method):
98 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
99         case PROTOCOL_ID(method):
100 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
101         case PROTOCOL_ID(method):
102
103 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
104         BEGIN_PROTOCOL_ENTRY0 (method)
105 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
106         BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
107 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
108         BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
109 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
110         BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
111 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
112         BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
113 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
114         BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
115 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
116         BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
117
118 #define FLUSH()
119
120 #define DEFAULT_PRINT()
121 #define CUSTOM_PRINT(_)
122
123 #define IS_ALWAYS_MATCH(is_always_match) \
124                 return is_always_match;
125 #define MATCH_INDEX(_)
126 #define IS_VTABLE_MATCH(_)
127
128 #define END_PROTOCOL_ENTRY
129 #define END_PROTOCOL_ENTRY_HEAVY
130
131 #include <mono/metadata/sgen-protocol-def.h>
132
133         default: assert (0);
134         }
135 }
136
137 #define WORKER_PREFIX(t)        (WORKER ((t)) ? "w" : " ")
138
139 enum { NO_COLOR = -1 };
140
141 typedef struct {
142         int type;
143         const char *name;
144         void *data;
145         /* The index of the ANSI color with which to highlight
146          * this entry, or NO_COLOR for no highlighting.
147          */
148         int color;
149 } PrintEntry;
150
151
152 #define TYPE_INT 0
153 #define TYPE_LONGLONG 1
154 #define TYPE_SIZE 2
155 #define TYPE_POINTER 3
156
157 static void
158 print_entry_content (int entries_size, PrintEntry *entries, gboolean color_output)
159 {
160         int i;
161         for (i = 0; i < entries_size; ++i) {
162                 printf ("%s%s ", i == 0 ? "" : " ", entries [i].name);
163                 if (color_output && entries [i].color != NO_COLOR)
164                         /* Set foreground color, excluding black & white. */
165                         printf ("\x1B[%dm", 31 + (entries [i].color % 6));
166                 switch (entries [i].type) {
167                 case TYPE_INT:
168                         printf ("%d", *(int*) entries [i].data);
169                         break;
170                 case TYPE_LONGLONG:
171                         printf ("%lld", *(long long*) entries [i].data);
172                         break;
173                 case TYPE_SIZE:
174                         printf ("%lu", *(size_t*) entries [i].data);
175                         break;
176                 case TYPE_POINTER:
177                         printf ("%p", *(gpointer*) entries [i].data);
178                         break;
179                 default:
180                         assert (0);
181                 }
182                 if (color_output && entries [i].color != NO_COLOR)
183                         /* Reset foreground color to default. */
184                         printf ("\x1B[0m");
185         }
186 }
187
188 static int
189 index_color (int index, int num_nums, int *match_indices)
190 {
191         int result;
192         for (result = 0; result < num_nums + 1; ++result)
193                 if (index == match_indices [result])
194                         return result;
195         return NO_COLOR;
196 }
197
198 static void
199 print_entry (int type, void *data, int num_nums, int *match_indices, gboolean color_output)
200 {
201         const char *always_prefix = is_always_match (type) ? "  " : "";
202         printf ("%s%s ", WORKER_PREFIX (type), always_prefix);
203
204         switch (TYPE (type)) {
205
206 #define BEGIN_PROTOCOL_ENTRY0(method) \
207         case PROTOCOL_ID(method): { \
208                 const int pes_size G_GNUC_UNUSED = 0; \
209                 PrintEntry pes [1] G_GNUC_UNUSED; \
210                 printf ("%s", #method + strlen ("binary_protocol_"));
211 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
212         case PROTOCOL_ID(method): { \
213                 PROTOCOL_STRUCT (method) *entry = data; \
214                 const int pes_size G_GNUC_UNUSED = 1; \
215                 PrintEntry pes [1] G_GNUC_UNUSED; \
216                 pes [0].type = t1; \
217                 pes [0].name = #f1; \
218                 pes [0].data = &entry->f1; \
219                 pes [0].color = index_color(0, num_nums, match_indices); \
220                 printf ("%s ", #method + strlen ("binary_protocol_"));
221 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
222         case PROTOCOL_ID(method): { \
223                 PROTOCOL_STRUCT (method) *entry = data; \
224                 const int pes_size G_GNUC_UNUSED = 2; \
225                 PrintEntry pes [2] G_GNUC_UNUSED; \
226                 pes [0].type = t1; \
227                 pes [0].name = #f1; \
228                 pes [0].data = &entry->f1; \
229                 pes [0].color = index_color(0, num_nums, match_indices); \
230                 pes [1].type = t2; \
231                 pes [1].name = #f2; \
232                 pes [1].data = &entry->f2; \
233                 pes [1].color = index_color(1, num_nums, match_indices); \
234                 printf ("%s ", #method + strlen ("binary_protocol_"));
235 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
236         case PROTOCOL_ID(method): { \
237                 PROTOCOL_STRUCT (method) *entry = data; \
238                 const int pes_size G_GNUC_UNUSED = 3; \
239                 PrintEntry pes [3] G_GNUC_UNUSED; \
240                 pes [0].type = t1; \
241                 pes [0].name = #f1; \
242                 pes [0].data = &entry->f1; \
243                 pes [0].color = index_color(0, num_nums, match_indices); \
244                 pes [1].type = t2; \
245                 pes [1].name = #f2; \
246                 pes [1].data = &entry->f2; \
247                 pes [1].color = index_color(1, num_nums, match_indices); \
248                 pes [2].type = t3; \
249                 pes [2].name = #f3; \
250                 pes [2].data = &entry->f3; \
251                 pes [2].color = index_color(2, num_nums, match_indices); \
252                 printf ("%s ", #method + strlen ("binary_protocol_"));
253 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
254         case PROTOCOL_ID(method): { \
255                 PROTOCOL_STRUCT (method) *entry = data; \
256                 const int pes_size G_GNUC_UNUSED = 4; \
257                 PrintEntry pes [4] G_GNUC_UNUSED; \
258                 pes [0].type = t1; \
259                 pes [0].name = #f1; \
260                 pes [0].data = &entry->f1; \
261                 pes [0].color = index_color(0, num_nums, match_indices); \
262                 pes [1].type = t2; \
263                 pes [1].name = #f2; \
264                 pes [1].data = &entry->f2; \
265                 pes [1].color = index_color(1, num_nums, match_indices); \
266                 pes [2].type = t3; \
267                 pes [2].name = #f3; \
268                 pes [2].data = &entry->f3; \
269                 pes [2].color = index_color(2, num_nums, match_indices); \
270                 pes [3].type = t4; \
271                 pes [3].name = #f4; \
272                 pes [3].data = &entry->f4; \
273                 pes [3].color = index_color(3, num_nums, match_indices); \
274                 printf ("%s ", #method + strlen ("binary_protocol_"));
275 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
276         case PROTOCOL_ID(method): { \
277                 PROTOCOL_STRUCT (method) *entry = data; \
278                 const int pes_size G_GNUC_UNUSED = 5; \
279                 PrintEntry pes [5] G_GNUC_UNUSED; \
280                 pes [0].type = t1; \
281                 pes [0].name = #f1; \
282                 pes [0].data = &entry->f1; \
283                 pes [0].color = index_color(0, num_nums, match_indices); \
284                 pes [1].type = t2; \
285                 pes [1].name = #f2; \
286                 pes [1].data = &entry->f2; \
287                 pes [1].color = index_color(1, num_nums, match_indices); \
288                 pes [2].type = t3; \
289                 pes [2].name = #f3; \
290                 pes [2].data = &entry->f3; \
291                 pes [2].color = index_color(2, num_nums, match_indices); \
292                 pes [3].type = t4; \
293                 pes [3].name = #f4; \
294                 pes [3].data = &entry->f4; \
295                 pes [3].color = index_color(3, num_nums, match_indices); \
296                 pes [4].type = t5; \
297                 pes [4].name = #f5; \
298                 pes [4].data = &entry->f5; \
299                 pes [4].color = index_color(4, num_nums, match_indices); \
300                 printf ("%s ", #method + strlen ("binary_protocol_"));
301 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
302         case PROTOCOL_ID(method): { \
303                 PROTOCOL_STRUCT (method) *entry = data; \
304                 const int pes_size G_GNUC_UNUSED = 6; \
305                 PrintEntry pes [6] G_GNUC_UNUSED; \
306                 pes [0].type = t1; \
307                 pes [0].name = #f1; \
308                 pes [0].data = &entry->f1; \
309                 pes [0].color = index_color(0, num_nums, match_indices); \
310                 pes [1].type = t2; \
311                 pes [1].name = #f2; \
312                 pes [1].data = &entry->f2; \
313                 pes [1].color = index_color(1, num_nums, match_indices); \
314                 pes [2].type = t3; \
315                 pes [2].name = #f3; \
316                 pes [2].data = &entry->f3; \
317                 pes [2].color = index_color(2, num_nums, match_indices); \
318                 pes [3].type = t4; \
319                 pes [3].name = #f4; \
320                 pes [3].data = &entry->f4; \
321                 pes [3].color = index_color(3, num_nums, match_indices); \
322                 pes [4].type = t5; \
323                 pes [4].name = #f5; \
324                 pes [4].data = &entry->f5; \
325                 pes [4].color = index_color(4, num_nums, match_indices); \
326                 pes [5].type = t6; \
327                 pes [5].name = #f6; \
328                 pes [5].data = &entry->f6; \
329                 pes [5].color = index_color(5, num_nums, match_indices); \
330                 printf ("%s ", #method + strlen ("binary_protocol_"));
331
332 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
333         BEGIN_PROTOCOL_ENTRY0 (method)
334 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
335         BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
336 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
337         BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
338 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
339         BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
340 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
341         BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
342 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
343         BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
344 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
345         BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
346
347 #define FLUSH()
348
349 #define DEFAULT_PRINT() \
350         print_entry_content (pes_size, pes, color_output);
351 #define CUSTOM_PRINT(print) \
352         print;
353
354 #define IS_ALWAYS_MATCH(_)
355 #define MATCH_INDEX(_)
356 #define IS_VTABLE_MATCH(_)
357
358 #define END_PROTOCOL_ENTRY \
359                 printf ("\n"); \
360                 break; \
361         }
362 #define END_PROTOCOL_ENTRY_HEAVY \
363         END_PROTOCOL_ENTRY
364
365 #include <mono/metadata/sgen-protocol-def.h>
366
367         default: assert (0);
368         }
369 }
370
371 #undef TYPE_INT
372 #undef TYPE_LONGLONG
373 #undef TYPE_SIZE
374 #undef TYPE_POINTER
375
376 #define TYPE_INT int
377 #define TYPE_LONGLONG long long
378 #define TYPE_SIZE size_t
379 #define TYPE_POINTER gpointer
380
381 static gboolean
382 matches_interval (gpointer ptr, gpointer start, int size)
383 {
384         return ptr >= start && (char*)ptr < (char*)start + size;
385 }
386
387 /* Returns the index of the field where a match was found,
388  * BINARY_PROTOCOL_NO_MATCH for no match, or
389  * BINARY_PROTOCOL_MATCH for a match with no index.
390  */
391 static int
392 match_index (gpointer ptr, int type, void *data)
393 {
394         switch (TYPE (type)) {
395
396 #define BEGIN_PROTOCOL_ENTRY0(method) \
397         case PROTOCOL_ID (method): {
398 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
399         case PROTOCOL_ID (method): { \
400                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
401 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
402         case PROTOCOL_ID (method): { \
403                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
404 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
405         case PROTOCOL_ID (method): { \
406                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
407 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
408         case PROTOCOL_ID (method): { \
409                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
410 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
411         case PROTOCOL_ID (method): { \
412                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
413 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
414         case PROTOCOL_ID (method): { \
415                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
416
417 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
418         BEGIN_PROTOCOL_ENTRY0 (method)
419 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
420         BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
421 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
422         BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
423 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
424         BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
425 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
426         BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
427 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
428         BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
429 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
430         BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
431
432 #define FLUSH()
433
434 #define DEFAULT_PRINT()
435 #define CUSTOM_PRINT(_)
436
437 #define IS_ALWAYS_MATCH(_)
438 #define MATCH_INDEX(block) \
439                 return (block);
440 #define IS_VTABLE_MATCH(_)
441
442 #define END_PROTOCOL_ENTRY \
443                 break; \
444         }
445 #define END_PROTOCOL_ENTRY_HEAVY \
446         END_PROTOCOL_ENTRY
447
448 #include <mono/metadata/sgen-protocol-def.h>
449
450         default: assert (0);
451         }
452 }
453
454 static gboolean
455 is_vtable_match (gpointer ptr, int type, void *data)
456 {
457         switch (TYPE (type)) {
458
459 #define BEGIN_PROTOCOL_ENTRY0(method) \
460         case PROTOCOL_ID (method): {
461 #define BEGIN_PROTOCOL_ENTRY1(method,t1,f1) \
462         case PROTOCOL_ID (method): { \
463                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
464 #define BEGIN_PROTOCOL_ENTRY2(method,t1,f1,t2,f2) \
465         case PROTOCOL_ID (method): { \
466                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
467 #define BEGIN_PROTOCOL_ENTRY3(method,t1,f1,t2,f2,t3,f3) \
468         case PROTOCOL_ID (method): { \
469                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
470 #define BEGIN_PROTOCOL_ENTRY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
471         case PROTOCOL_ID (method): { \
472                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
473 #define BEGIN_PROTOCOL_ENTRY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
474         case PROTOCOL_ID (method): { \
475                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
476 #define BEGIN_PROTOCOL_ENTRY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
477         case PROTOCOL_ID (method): { \
478                 PROTOCOL_STRUCT (method) *entry G_GNUC_UNUSED = data;
479
480 #define BEGIN_PROTOCOL_ENTRY_HEAVY0(method) \
481         BEGIN_PROTOCOL_ENTRY0 (method)
482 #define BEGIN_PROTOCOL_ENTRY_HEAVY1(method,t1,f1) \
483         BEGIN_PROTOCOL_ENTRY1 (method,t1,f1)
484 #define BEGIN_PROTOCOL_ENTRY_HEAVY2(method,t1,f1,t2,f2) \
485         BEGIN_PROTOCOL_ENTRY2 (method,t1,f1,t2,f2)
486 #define BEGIN_PROTOCOL_ENTRY_HEAVY3(method,t1,f1,t2,f2,t3,f3) \
487         BEGIN_PROTOCOL_ENTRY3 (method,t1,f1,t2,f2,t3,f3)
488 #define BEGIN_PROTOCOL_ENTRY_HEAVY4(method,t1,f1,t2,f2,t3,f3,t4,f4) \
489         BEGIN_PROTOCOL_ENTRY4 (method,t1,f1,t2,f2,t3,f3,t4,f4)
490 #define BEGIN_PROTOCOL_ENTRY_HEAVY5(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5) \
491         BEGIN_PROTOCOL_ENTRY5 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5)
492 #define BEGIN_PROTOCOL_ENTRY_HEAVY6(method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6) \
493         BEGIN_PROTOCOL_ENTRY6 (method,t1,f1,t2,f2,t3,f3,t4,f4,t5,f5,t6,f6)
494
495 #define FLUSH()
496
497 #define DEFAULT_PRINT()
498 #define CUSTOM_PRINT(_)
499
500 #define IS_ALWAYS_MATCH(_)
501 #define MATCH_INDEX(block) \
502                 return (block);
503 #define IS_VTABLE_MATCH(_)
504
505 #define END_PROTOCOL_ENTRY \
506                 break; \
507         }
508 #define END_PROTOCOL_ENTRY_HEAVY \
509         END_PROTOCOL_ENTRY
510
511 #include <mono/metadata/sgen-protocol-def.h>
512
513         default: assert (0);
514         }
515 }
516
517 #undef TYPE_INT
518 #undef TYPE_LONGLONG
519 #undef TYPE_SIZE
520 #undef TYPE_POINTER
521
522 int
523 main (int argc, char *argv[])
524 {
525         int type;
526         void *data;
527         int num_args = argc - 1;
528         int num_nums = 0;
529         int num_vtables = 0;
530         int i;
531         long nums [num_args];
532         long vtables [num_args];
533         gboolean dump_all = FALSE;
534         gboolean pause_times = FALSE;
535         gboolean pause_times_stopped = FALSE;
536         gboolean pause_times_concurrent = FALSE;
537         gboolean pause_times_finish = FALSE;
538         gboolean color_output = FALSE;
539         long long pause_times_ts = 0;
540
541         for (i = 0; i < num_args; ++i) {
542                 char *arg = argv [i + 1];
543                 char *next_arg = argv [i + 2];
544                 if (!strcmp (arg, "--all")) {
545                         dump_all = TRUE;
546                 } else if (!strcmp (arg, "--pause-times")) {
547                         pause_times = TRUE;
548                 } else if (!strcmp (arg, "-v") || !strcmp (arg, "--vtable")) {
549                         vtables [num_vtables++] = strtoul (next_arg, NULL, 16);
550                         ++i;
551                 } else if (!strcmp (arg, "-c") || !strcmp (arg, "--color")) {
552                         color_output = TRUE;
553                 } else {
554                         nums [num_nums++] = strtoul (arg, NULL, 16);
555                 }
556         }
557
558         if (dump_all)
559                 assert (!pause_times);
560         if (pause_times)
561                 assert (!dump_all);
562
563         while ((type = read_entry (stdin, &data)) != SGEN_PROTOCOL_EOF) {
564                 if (pause_times) {
565                         switch (type) {
566                         case PROTOCOL_ID (binary_protocol_world_stopping): {
567                                 PROTOCOL_STRUCT (binary_protocol_world_stopping) *entry = data;
568                                 assert (!pause_times_stopped);
569                                 pause_times_concurrent = FALSE;
570                                 pause_times_finish = FALSE;
571                                 pause_times_ts = entry->timestamp;
572                                 pause_times_stopped = TRUE;
573                                 break;
574                         }
575                         case PROTOCOL_ID (binary_protocol_concurrent_finish):
576                                 pause_times_finish = TRUE;
577                         case PROTOCOL_ID (binary_protocol_concurrent_start):
578                         case PROTOCOL_ID (binary_protocol_concurrent_update):
579                                 pause_times_concurrent = TRUE;
580                                 break;
581                         case PROTOCOL_ID (binary_protocol_world_restarted): {
582                                 PROTOCOL_STRUCT (binary_protocol_world_restarted) *entry = data;
583                                 assert (pause_times_stopped);
584                                 printf ("pause-time %d %d %d %lld %lld\n",
585                                                 entry->generation,
586                                                 pause_times_concurrent,
587                                                 pause_times_finish,
588                                                 entry->timestamp - pause_times_ts,
589                                                 pause_times_ts);
590                                 pause_times_stopped = FALSE;
591                                 break;
592                         }
593                         }
594                 } else {
595                         int match_indices [num_nums + 1];
596                         gboolean match = is_always_match (type);
597                         match_indices [num_nums] = num_nums == 0 ? match_index (NULL, type, data) : BINARY_PROTOCOL_NO_MATCH;
598                         match = match_indices [num_nums] != BINARY_PROTOCOL_NO_MATCH;
599                         for (i = 0; i < num_nums; ++i) {
600                                 match_indices [i] = match_index ((gpointer) nums [i], type, data);
601                                 match = match || match_indices [i] != BINARY_PROTOCOL_NO_MATCH;
602                         }
603                         if (!match) {
604                                 for (i = 0; i < num_vtables; ++i) {
605                                         if (is_vtable_match ((gpointer) vtables [i], type, data)) {
606                                                 match = TRUE;
607                                                 break;
608                                         }
609                                 }
610                         }
611                         if (dump_all)
612                                 printf (match ? "* " : "  ");
613                         if (match || dump_all)
614                                 print_entry (type, data, num_nums, match_indices, color_output);
615                 }
616                 free (data);
617         }
618
619         return 0;
620 }