2004-11-12 Ben Maurer <bmaurer@ximian.com>
[mono.git] / mono / dis / get.c
1 /*
2  * get.c: Functions to get stringified values from the metadata tables.
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9 #include <config.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <glib.h>
15 #include "meta.h"
16 #include "util.h"
17 #include "get.h"
18 #include <mono/metadata/class.h>
19 #include <mono/metadata/marshal.h>
20
21 extern gboolean substitute_with_mscorlib_p;
22
23 static char *
24 get_memberref_parent (MonoImage *m, guint32 mrp_token);
25
26 GHashTable *key_table = NULL;
27 gboolean show_method_tokens = FALSE;
28 gboolean show_tokens = FALSE;
29
30 char *
31 get_typedef (MonoImage *m, int idx)
32 {
33         guint32 cols [MONO_TYPEDEF_SIZE];
34         const char *ns;
35         char *tstring, *result, *ename;
36         guint32 token;
37         
38         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEDEF], idx - 1, cols, MONO_TYPEDEF_SIZE);
39
40         ns = mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE]);
41
42         /* Check if this is a nested type */
43         token = MONO_TOKEN_TYPE_DEF | (idx);
44         token = mono_metadata_nested_in_typedef (m, token);
45         tstring = show_tokens ? g_strdup_printf ("/*%08x*/", token) : NULL;
46         if (token) {
47                 char *outer;
48                 
49                 outer = get_typedef (m, mono_metadata_token_index (token));
50                 result = g_strdup_printf (
51                         "%s%s%s/%s%s", ns, *ns?".":"", outer,
52                         mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]),
53                         tstring ? tstring : "");
54                 ename = get_escaped_name (result);
55                 g_free (result);
56                 g_free (outer);
57                 g_free (tstring);
58                 return ename;
59         }
60         
61         
62         result = g_strdup_printf (
63                 "%s%s%s%s", ns, *ns?".":"",
64                 mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME]),
65                 tstring ? tstring : "");
66         ename = get_escaped_name (result);
67         g_free (result);
68         g_free (tstring);
69
70         return ename;
71 }
72
73 char *
74 get_module (MonoImage *m, int idx)
75 {
76         guint32 cols [MONO_MODULE_SIZE];
77         
78         /*
79          * There MUST BE only one module in the Module table
80          */
81         g_assert (idx == 1);
82             
83         mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULE], idx - 1, cols, MONO_MODULE_SIZE);
84
85         return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULE_NAME]));
86 }
87
88 char *
89 get_moduleref (MonoImage *m, int idx)
90 {
91         guint32 cols [MONO_MODULEREF_SIZE];
92         
93         mono_metadata_decode_row (&m->tables [MONO_TABLE_MODULEREF], idx - 1, cols, MONO_MODULEREF_SIZE);
94
95         return g_strdup (mono_metadata_string_heap (m, cols [MONO_MODULEREF_NAME]));
96 }
97
98 char *
99 get_assemblyref (MonoImage *m, int idx)
100 {
101         guint32 cols [MONO_ASSEMBLYREF_SIZE];
102         
103         mono_metadata_decode_row (&m->tables [MONO_TABLE_ASSEMBLYREF], idx - 1, cols, MONO_ASSEMBLYREF_SIZE);
104
105         return g_strdup (mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME]));
106 }
107
108 /*
109  *
110  * Returns a string representing the ArrayShape (22.2.16).
111  */
112 static const char *
113 get_array_shape (MonoImage *m, const char *ptr, char **result)
114 {
115         GString *res = g_string_new ("[");
116         guint32 rank, num_sizes, num_lo_bounds;
117         guint32 *sizes = NULL, *lo_bounds = NULL;
118         int i, r;
119         char buffer [80];
120         
121         rank = mono_metadata_decode_value (ptr, &ptr);
122         num_sizes = mono_metadata_decode_value (ptr, &ptr);
123
124         if (num_sizes > 0)
125                 sizes = g_new (guint32, num_sizes);
126         
127         for (i = 0; i < num_sizes; i++)
128                 sizes [i] = mono_metadata_decode_value (ptr, &ptr);
129
130         num_lo_bounds = mono_metadata_decode_value (ptr, &ptr);
131         if (num_lo_bounds > 0)
132                 lo_bounds = g_new (guint32, num_lo_bounds);
133         
134         for (i = 0; i < num_lo_bounds; i++)
135                 lo_bounds [i] = mono_metadata_decode_value (ptr, &ptr);
136
137         for (r = 0; r < rank; r++){
138                 if (r < num_sizes){
139                         if (r < num_lo_bounds){
140                                 sprintf (buffer, "%d..%d", lo_bounds [r], lo_bounds [r] + sizes [r] - 1);
141                         } else {
142                                 sprintf (buffer, "0..%d", sizes [r] - 1);
143                         }
144                 } else
145                         buffer [0] = 0;
146                 
147                 g_string_append (res, buffer);
148                 if ((r + 1) != rank)
149                         g_string_append (res, ", ");
150         }
151         g_string_append (res, "]");
152         
153         if (sizes)
154                 g_free (sizes);
155
156         if (lo_bounds)
157                 g_free (lo_bounds);
158
159         *result = res->str;
160         g_string_free (res, FALSE);
161
162         return ptr;
163 }
164
165 /**
166  * get_typespec:
167  * @m: metadata context
168  * @blob_idx: index into the blob heap
169  *
170  * Returns the stringified representation of a TypeSpec signature (22.2.17)
171  */
172 char *
173 get_typespec (MonoImage *m, guint32 idx)
174 {
175         guint32 cols [MONO_TYPESPEC_SIZE];
176         const char *ptr;
177         char *s, *result;
178         GString *res = g_string_new ("");
179         int len;
180
181         MonoType *type;
182
183         type = mono_type_create_from_typespec (m, idx);
184                 
185         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPESPEC], idx-1, cols, MONO_TYPESPEC_SIZE);
186         ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]);
187         len = mono_metadata_decode_value (ptr, &ptr);
188         
189         switch (*ptr++){
190         case MONO_TYPE_PTR:
191                 ptr = get_custom_mod (m, ptr, &s);
192                 if (s){
193                         g_string_append (res, s);
194                         g_string_append_c (res, ' ');
195                         g_free (s);
196                 }
197                 
198                 if (*ptr == MONO_TYPE_VOID)
199                         g_string_append (res, "void");
200                 else {
201                         ptr = get_type (m, ptr, &s);
202                         if (s)
203                                 g_string_append (res, s);
204                 }
205                 g_string_append (res, "*");
206                 break;
207                 
208         case MONO_TYPE_FNPTR:
209                 s = dis_stringify_function_ptr (m, type->data.method);
210                 g_string_append (res, "method ");
211                 g_string_append (res, s);
212                 g_free (s);
213                 break;
214                         
215         case MONO_TYPE_ARRAY:
216                 ptr = get_type (m, ptr, &s);
217                 g_string_append (res, s);
218                 g_free (s);
219                 g_string_append_c (res, ' ');
220                 ptr = get_array_shape (m, ptr, &s);
221                 g_string_append (res, s);
222                 g_free (s);
223                 break;
224                 
225         case MONO_TYPE_SZARRAY:
226                 ptr = get_custom_mod (m, ptr, &s);
227                 if (s){
228                         g_string_append (res, s);
229                         g_string_append_c (res, ' ');
230                         g_free (s);
231                 }
232                 ptr = get_type (m, ptr, &s);
233                 g_string_append (res, s);
234                 g_string_append (res, "[]");
235                 g_free (s);
236                 break;
237
238         case MONO_TYPE_VAR:
239         case MONO_TYPE_MVAR:
240                 ptr = get_type (m, ptr-1, &s);
241                 g_string_append (res, s);
242                 g_free (s);
243                 break;
244                 
245         default:
246                 s = dis_stringify_type (m, type);
247                 g_string_append (res, s);
248                 g_free (s);
249                 break;
250         }
251
252         if (show_tokens) {
253                 int token = mono_metadata_make_token (MONO_TABLE_TYPESPEC, idx);
254                 result = g_strdup_printf ("%s/*%08x*/", res->str, token);
255         } else
256                 result = res->str;
257
258         g_string_free (res, FALSE);
259
260         return result;
261 }
262
263 char *
264 get_typeref (MonoImage *m, int idx)
265 {
266         guint32 cols [MONO_TYPEREF_SIZE];
267         const char *s, *t;
268         char *x, *ret;
269         guint32 rs_idx, table;
270         
271         mono_metadata_decode_row (&m->tables [MONO_TABLE_TYPEREF], idx - 1, cols, MONO_TYPEREF_SIZE);
272
273         t = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]);
274         s = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]);
275
276         rs_idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
277         table = cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK;
278         
279         switch (table){
280         case MONO_RESOLTION_SCOPE_MODULE: /* Module */
281                 x = get_module (m, rs_idx);
282                 ret = g_strdup_printf ("[%s] %s%s%s", x, s, *s?".":"", t);
283                 g_free (x);
284                 break;
285
286         case MONO_RESOLTION_SCOPE_MODULEREF: /* ModuleRef */
287                 x = get_moduleref (m, rs_idx);
288                 ret = g_strdup_printf ("[.module %s]%s%s%s", x, s, *s ? "." : "", t);
289                 break;
290                               
291         case MONO_RESOLTION_SCOPE_ASSEMBLYREF: /*
292                  * AssemblyRef (ECMA docs claim it is 3, but it looks to
293                  * me like it is 2 (tokens are prefixed with 0x23)
294                  */
295                 x = get_assemblyref (m, rs_idx);
296                 ret = g_strdup_printf ("[%s]%s%s%s", x, s, *s?".":"", t);
297                 g_free (x);
298                 break;
299                 
300         case MONO_RESOLTION_SCOPE_TYPEREF: /* TypeRef */
301                 x = get_typeref (m, rs_idx);
302                 ret =  g_strdup_printf ("%s/%s", x, t);
303                 g_free (x);
304                 break;
305                 
306         default:
307                 ret = g_strdup_printf ("Unknown table in TypeRef %d", table);
308         }
309
310         if (show_tokens) {
311                 int token = mono_metadata_make_token (MONO_TABLE_TYPEREF, idx);
312                 char *temp = g_strdup_printf ("%s/*%08x*/", ret, token);
313                 g_free (ret);
314                 ret = temp;
315         }
316
317         return ret;
318 }
319
320 /**
321  * get_typedef_or_ref:
322  * @m: metadata context
323  * @dor_token: def or ref encoded index
324  *
325  * Low two bits contain table to lookup from
326  * high bits contain the index into the def or ref table
327  *
328  * Returns: a stringified version of the MethodDef or MethodRef
329  * at (dor_token >> 2) 
330  */
331 char *
332 get_typedef_or_ref (MonoImage *m, guint32 dor_token)
333 {
334         char *temp = NULL, *s = NULL;
335         int table, idx;
336
337         /*
338          * low 2 bits contain encoding
339          */
340         table = dor_token & MONO_TYPEDEFORREF_MASK;
341         idx = dor_token >> MONO_TYPEDEFORREF_BITS;
342         
343         switch (table){
344         case 0: /* TypeDef */
345                 temp = get_typedef (m, idx);
346                 s = g_strdup_printf ("%s", temp);
347                 break;
348                 
349         case 1: /* TypeRef */
350                 temp = get_typeref (m, idx);
351                 s = g_strdup_printf ("%s", temp);
352                 break;
353                 
354         case 2: /* TypeSpec */
355                 s = get_typespec (m, idx);
356                 break;
357
358         default:
359                 g_error ("Unhandled encoding for typedef-or-ref coded index 0x%08x", dor_token);
360
361         }
362         
363         if (temp)
364                 g_free (temp);
365
366         return s;
367 }
368
369 /**
370  * get_type_or_methdef
371  * @m: metadata context
372  * @dor_token: type or method def encoded index
373  *
374  * Low bit contains the table to lookup from
375  * high bits contain the index into the type def or method def table
376  *
377  * Returns: a stringified version of the TypeOrMethodDef token
378  */
379 char *
380 get_type_or_methdef (MonoImage *m, guint32 dor_token)
381 {
382         if (dor_token & MONO_TYPEORMETHOD_METHOD) /* MethodDef */
383                 return get_methoddef (m, dor_token >> MONO_TYPEORMETHOD_BITS);
384         else  /* TypeDef */
385                 return get_typedef (m, dor_token >> MONO_TYPEORMETHOD_BITS);
386 }
387
388 /** 
389  * get_encoded_typedef_or_ref:
390  * @m: metadata context 
391  * @ptr: location to decode from.
392  * @result: pointer to string where resulting decoded string is stored
393  *
394  * result will point to a g_malloc()ed string.
395  *
396  * Returns: the new ptr to continue decoding
397  */
398 const char *
399 get_encoded_typedef_or_ref (MonoImage *m, const char *ptr, char **result)
400 {
401         guint32 token;
402         
403         token = mono_metadata_decode_value (ptr, &ptr);
404
405         *result = get_typedef_or_ref (m, token);
406
407         return ptr;
408 }
409
410 /**
411  * get_custom_mod:
412  *
413  * Decodes a CustomMod (22.2.7)
414  *
415  * Returns: updated pointer location
416  */
417 const char *
418 get_custom_mod (MonoImage *m, const char *ptr, char **return_value)
419 {
420         char *s;
421         const char *reqd;
422         
423         *return_value = NULL;
424         while ((*ptr == MONO_TYPE_CMOD_OPT) ||
425                    (*ptr == MONO_TYPE_CMOD_REQD)) {
426                 reqd = (*ptr == MONO_TYPE_CMOD_REQD) ? "reqd" : "opt";
427                 ptr++;
428                 ptr = get_encoded_typedef_or_ref (m, ptr, &s);
429
430                 if (*return_value == NULL)
431                         *return_value = g_strconcat (reqd, " ", s, NULL);
432                 else
433                         *return_value = g_strconcat (*return_value, " ", reqd, " ", s, NULL);
434                 g_free (s);
435         }
436         return ptr;
437 }
438
439
440 static dis_map_t element_type_map [] = {
441         { MONO_TYPE_END        , "end" },
442         { MONO_TYPE_VOID       , "void" },
443         { MONO_TYPE_BOOLEAN    , "bool" },
444         { MONO_TYPE_CHAR       , "char" }, 
445         { MONO_TYPE_I1         , "int8" },
446         { MONO_TYPE_U1         , "unsigned int8" }, 
447         { MONO_TYPE_I2         , "int16" },
448         { MONO_TYPE_U2         , "unsigned int16" },
449         { MONO_TYPE_I4         , "int32" },
450         { MONO_TYPE_U4         , "unsigned int32" },
451         { MONO_TYPE_I8         , "int64" },
452         { MONO_TYPE_U8         , "unsigned int64" },
453         { MONO_TYPE_R4         , "float32" },
454         { MONO_TYPE_R8         , "float64" },
455         { MONO_TYPE_STRING     , "string" },
456         { MONO_TYPE_TYPEDBYREF , "TypedByRef" },
457         { MONO_TYPE_I          , "native int" },
458         { MONO_TYPE_U          , "native unsigned int" },
459         { MONO_TYPE_OBJECT     , "object" },
460         { 0, NULL }
461 };
462
463 static dis_map_t call_conv_type_map [] = {
464         { MONO_CALL_DEFAULT     , "default" },
465         { MONO_CALL_C           , "unmanaged cdecl" },
466         { MONO_CALL_STDCALL     , "unmanaged stdcall" },
467         { MONO_CALL_THISCALL    , "unmanaged thiscall" },
468         { MONO_CALL_FASTCALL    , "unmanaged fastcall" },
469         { MONO_CALL_VARARG      , "vararg" },
470         { 0, NULL }
471 };
472
473 char*
474 dis_stringify_token (MonoImage *m, guint32 token)
475 {
476         guint idx = token & 0xffffff;
477         switch (token >> 24) {
478         case MONO_TABLE_TYPEDEF: return get_typedef (m, idx);
479         case MONO_TABLE_TYPEREF: return get_typeref (m, idx);
480         case MONO_TABLE_TYPESPEC: return get_typespec (m, idx);
481         default:
482                  break;
483         }
484         return g_strdup_printf("0x%08x", token);
485 }
486
487 char*
488 dis_stringify_array (MonoImage *m, MonoArrayType *array) 
489 {
490         char *type;
491         GString *s = g_string_new("");
492         int i;
493         
494         type = dis_stringify_type (m, &array->eklass->byval_arg);
495         g_string_append (s, type);
496         g_free (type);
497         g_string_append_c (s, '[');
498         for (i = 0; i < array->rank; ++i) {
499                 if (i)
500                         g_string_append_c (s, ',');
501                 if (i < array->numsizes) {
502                         if (i < array->numlobounds && array->lobounds[i] != 0)
503                                 g_string_sprintfa (s, "%d..%d", array->lobounds[i], array->sizes[i]);
504                         else
505                                 g_string_sprintfa (s, "%d", array->sizes[i]);
506                 }
507         }
508         g_string_append_c (s, ']');
509         type = s->str;
510         g_string_free (s, FALSE);
511         return type;
512 }
513
514 char*
515 dis_stringify_modifiers (MonoImage *m, int n, MonoCustomMod *mod)
516 {
517         GString *s = g_string_new("");
518         char *result;
519         int i;
520         for (i = 0; i < n; ++i) {
521                 char *tok = dis_stringify_token (m, mod[i].token);
522                 if (i > 0)
523                         g_string_sprintfa (s, " ");
524                 g_string_sprintfa (s, "%s (%s)", mod[i].required ? "modreq": "modopt", tok);
525                 g_free (tok);
526         }
527         g_string_append_c (s, ' ');
528         result = s->str;
529         g_string_free (s, FALSE);
530         return result;
531 }
532
533 char*
534 dis_stringify_param (MonoImage *m, MonoType *param) 
535 {
536         char *t;
537         char *result;
538         char *attribs;
539         const char *out = param->attrs & PARAM_ATTRIBUTE_OUT ? "[out]": "";
540         const char *opt = param->attrs & PARAM_ATTRIBUTE_OPTIONAL ? "[opt]": "";
541         attribs = g_strconcat(out, opt, NULL);
542         t = dis_stringify_type (m, param);
543         result = g_strjoin(attribs[0] ? " ":"", attribs, t, NULL);
544         g_free (t);
545         g_free (attribs);
546         return result;
547 }
548
549 /**
550  * get_generic_param
551  * @m: metadata context 
552  * @table_type: The type of table we are getting generics for (0 for typedef, 1 for method)
553  * @row: The row in the table
554  *
555  * Returns: Allocated stringified generic parameters
556  */
557 char*
558 get_generic_param (MonoImage *m, int table_type, guint32 row)
559 {
560         MonoTableInfo *t = &m->tables [MONO_TABLE_GENERICPARAM];
561         GString *result = g_string_new ("");
562         char *retval;
563         guint32 cols [MONO_GENERICPARAM_SIZE];
564         int i, own_tok, table, idx, found_count;
565
566         g_assert (table_type != MONO_TYPEORMETHOD_TYPE || table_type != MONO_TYPEORMETHOD_METHOD);
567         
568         found_count = 0;
569         for (i = 1; i <= t->rows; i++) {
570                 mono_metadata_decode_row (t, i-1, cols, MONO_GENERICPARAM_SIZE);
571                 own_tok = cols [MONO_GENERICPARAM_OWNER];
572                 table = own_tok & MONO_TYPEORMETHOD_MASK;
573                 idx = own_tok >> MONO_TYPEORMETHOD_BITS;
574                 
575                 if (table != table_type || idx != row)
576                         continue;
577
578                 if (found_count == 0)
579                         g_string_append_printf (result, "<%s",
580                                         mono_metadata_string_heap (m, cols [MONO_GENERICPARAM_NAME]));
581                 else
582                         g_string_append_printf (result, ", %s",
583                                         mono_metadata_string_heap (m, cols [MONO_GENERICPARAM_NAME]));
584                 found_count++;
585         }
586
587         if (found_count)
588                 g_string_append_c (result, '>');
589         retval = result->str;
590         g_string_free (result, FALSE);
591         return retval;
592 }
593
594 char*
595 dis_stringify_method_signature (MonoImage *m, MonoMethodSignature *method, int methoddef_row, gboolean fully_qualified)
596 {
597         guint32 cols [MONO_METHOD_SIZE];
598         guint32 pcols [MONO_PARAM_SIZE];
599         guint32 param_index = 0;
600         const char *name = "";
601         int free_method = 0;
602         char *retval, *esname;
603         char *type = NULL;
604         char *gen_param = NULL;
605         GString *result = g_string_new ("");
606         int i;
607         
608         g_assert (method || methoddef_row);
609
610         if (methoddef_row) {
611                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], methoddef_row -1, cols, MONO_METHOD_SIZE);
612                 if (fully_qualified)
613                         type = get_typedef (m, mono_metadata_typedef_from_method (m, methoddef_row));
614                 name = mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]);
615                 param_index = cols [MONO_METHOD_PARAMLIST];
616                 if (!method) {
617                         const char *sig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
618                         mono_metadata_decode_blob_size (sig, &sig);
619                         method = mono_metadata_parse_method_signature (m, methoddef_row, sig, &sig);
620                         free_method = 1;
621                 }      
622                 gen_param = get_generic_param (m, 1, methoddef_row);
623         }
624         
625         retval = dis_stringify_param (m, method->ret);
626         if (method->hasthis)
627                 g_string_append (result, "instance ");
628         g_string_append (result, map (method->call_convention, call_conv_type_map));
629         g_string_sprintfa (result, " %s ", retval);
630         if (type) {
631                 char *estype = get_escaped_name (type);
632                 g_string_sprintfa (result, "%s::", estype);
633                 g_free (estype);
634         }
635         esname = get_escaped_name (name);
636         g_string_append (result, esname);
637         g_free (esname);
638         if (gen_param) {
639                 g_string_append (result, gen_param);
640                 g_free (gen_param);
641         }
642         g_string_append (result, " (");
643         g_free (retval);
644         for (i = 0; i < method->param_count; ++i) {
645                 if (param_index && param_index <= m->tables [MONO_TABLE_PARAM].rows) {
646                         mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], param_index - 1, pcols, MONO_PARAM_SIZE);
647                         name = mono_metadata_string_heap (m, pcols [MONO_PARAM_NAME]);
648                         method->params [i]->attrs = pcols [MONO_PARAM_FLAGS];
649                         param_index++;
650                 } else {
651                         name = "";
652                 }
653                 if (i)
654                         g_string_append (result, ", ");
655                 retval = dis_stringify_param (m, method->params [i]);
656                 esname = get_escaped_name (name);
657                 g_string_append_printf (result, "%s %s", retval, esname);
658                 g_free (retval);
659                 g_free (esname);
660         }
661         g_string_append (result, ") ");
662
663         if (show_method_tokens && methoddef_row)
664                 g_string_append_printf (result, " /* 0x%X */ ",
665                                 (methoddef_row >> MONO_TYPEORMETHOD_BITS) | MONO_TOKEN_METHOD_DEF);
666
667         if (free_method)
668                 mono_metadata_free_method_signature (method);
669         retval = result->str;
670         g_string_free (result, FALSE);
671
672         return retval;
673 }
674
675 char*
676 dis_stringify_function_ptr (MonoImage *m, MonoMethodSignature *method)
677 {
678         char *retval;
679         GString *result = g_string_new ("");
680         int i;
681         
682         g_assert (method);
683
684         g_string_append (result, map (method->call_convention, call_conv_type_map));
685
686         retval = dis_stringify_param (m, method->ret);
687         g_string_sprintfa (result, " %s ", retval);
688         g_free (retval);
689
690         g_string_append (result, " *(");
691         for (i = 0; i < method->param_count; ++i) {
692                 if (i)
693                         g_string_append (result, ", ");
694                 retval = dis_stringify_param (m, method->params [i]);
695                 g_string_append (result, retval);
696                 g_free (retval);
697         }
698         g_string_append (result, ") ");
699
700         retval = result->str;
701         g_string_free (result, FALSE);
702
703         return retval;
704 }
705
706 char *
707 dis_stringify_object_with_class (MonoImage *m, MonoClass *c)
708 {
709         /* FIXME: handle MONO_TYPE_OBJECT ... */
710         const char *otype = c->byval_arg.type == MONO_TYPE_VALUETYPE ? "valuetype" : "class" ;
711         char *assemblyref = NULL, *result, *esname, *generic = NULL;
712         if (m != c->image) {
713                 if (c->image->assembly_name) {
714                         /* we cheat */
715                         if (substitute_with_mscorlib_p && !strcmp ("corlib", c->image->assembly_name))
716                                 assemblyref = g_strdup_printf ("[%s]", "mscorlib");
717                         else {
718                                 char *esc = get_escaped_name (c->image->assembly->aname.name);
719                                 
720                                 assemblyref = g_strdup_printf ("[%s]", esc);
721                                 g_free (esc);
722                         }
723                 } else {
724                         assemblyref = g_strdup_printf ("[.module %s]", c->image->module_name);
725                 }
726         }
727
728         if (c->nested_in) {
729                 result = g_strdup_printf ("%s%s%s/%s", c->nested_in->name_space, 
730                                 *c->nested_in->name_space?".":"", c->nested_in->name,
731                                 c->name);
732         } else {
733                 result = g_strdup_printf ("%s%s%s", c->name_space, 
734                                 *c->name_space?".":"", c->name);
735         }
736         
737         esname = get_escaped_name (result);
738         g_free (result);
739
740         if (c->generic_inst) {
741                 MonoGenericInst *ginst = c->generic_inst;
742                 GString *str = g_string_new ("");
743                 int i;
744
745                 for (i = 0; i < ginst->type_argc; i++){
746                         char *t = dis_stringify_type (m, ginst->type_argv [i]);
747
748                         g_string_append (str, t);
749                         if (i+1 != ginst->type_argc)
750                                 g_string_append (str, ", ");
751                         g_free (t);
752                 }
753                 generic = g_strdup_printf ("<%s>", str->str);
754                 g_string_free (str, TRUE);
755         }
756
757
758         result = g_strdup_printf ("%s %s%s%s", otype, assemblyref?assemblyref:"",
759                                   esname, generic?generic:"");
760         
761         g_free (generic);
762         g_free (assemblyref);
763         g_free (esname);
764         
765         return result;
766 }
767
768 static char *
769 dis_stringify_object (MonoImage *m, MonoType *type)
770 {
771         MonoClass *c = mono_class_from_mono_type (type);
772         return dis_stringify_object_with_class (m, c);
773 }
774
775 char*
776 dis_stringify_type (MonoImage *m, MonoType *type)
777 {
778         const char *pinned = "", *byref = "";
779         char *bare = NULL, *mods = NULL;
780         char *result;
781
782         if (type->num_mods)
783                 mods = dis_stringify_modifiers (m, type->num_mods, type->modifiers);
784
785         switch (type->type){
786         case MONO_TYPE_BOOLEAN:
787         case MONO_TYPE_CHAR:
788         case MONO_TYPE_I1:
789         case MONO_TYPE_U1:
790         case MONO_TYPE_I2:
791         case MONO_TYPE_U2:
792         case MONO_TYPE_I4:
793         case MONO_TYPE_U4:
794         case MONO_TYPE_I8:
795         case MONO_TYPE_U8:
796         case MONO_TYPE_R4:
797         case MONO_TYPE_R8:
798         case MONO_TYPE_I:
799         case MONO_TYPE_U:
800         case MONO_TYPE_STRING:
801         case MONO_TYPE_OBJECT:
802         case MONO_TYPE_TYPEDBYREF:
803                 bare = g_strdup (map (type->type, element_type_map));
804                 break;
805                 
806         case MONO_TYPE_VALUETYPE:
807         case MONO_TYPE_CLASS:
808                 bare = dis_stringify_object (m, type);
809                 break;
810         case MONO_TYPE_FNPTR: {
811                 char *child_type;
812                 child_type = dis_stringify_function_ptr (m, type->data.method);
813                 bare = g_strdup_printf ("method %s", child_type);
814                 g_free (child_type);
815                 break;
816         }
817         case MONO_TYPE_PTR: {
818                 char *child_type;
819                 child_type = dis_stringify_type (m, type->data.type);
820                 
821                 bare = g_strdup_printf ("%s*", child_type);
822                 g_free (child_type);
823                 break;
824         }
825         case MONO_TYPE_SZARRAY: {
826                 char *child_type;
827                 child_type = dis_stringify_type (m, &type->data.klass->byval_arg);
828                 
829                 bare = g_strdup_printf ("%s[]", child_type);
830                 g_free (child_type);
831                 break;
832         }
833         case MONO_TYPE_ARRAY:
834                 bare = dis_stringify_array (m, type->data.array);
835                 break;
836         case MONO_TYPE_VOID:
837                 bare = g_strdup ("void");
838                 break;
839         case MONO_TYPE_MVAR:
840                 bare = g_strdup_printf ("!!%d", type->data.generic_param->num);
841                 break;
842         case MONO_TYPE_VAR:
843                 bare = g_strdup_printf ("!%d", type->data.generic_param->num);
844                 break;
845         case MONO_TYPE_GENERICINST: {
846                 GString *str = g_string_new ("");
847                 int i;
848                 char *generic_type = dis_stringify_type (m, type->data.generic_inst->generic_type);
849
850                 for (i = 0; i < type->data.generic_inst->type_argc; i++){
851                         char *t = dis_stringify_type (m, type->data.generic_inst->type_argv [i]);
852
853                         g_string_append (str, t);
854                         if (i+1 != type->data.generic_inst->type_argc)
855                                 g_string_append (str, ", ");
856                         g_free (t);
857                 }
858                 bare = g_strdup_printf ("%s<%s>", generic_type, str->str);
859                 g_string_free (str, TRUE);
860                 break;
861         }
862                 
863         default:
864                 g_error ("Do not know how to stringify type 0x%x", type->type);
865         }
866         
867         if (type->pinned)
868                 pinned = " pinned";
869
870         if (type->byref)
871                 byref = "&";
872                 
873         result = g_strconcat (mods ? mods : "", bare, byref, pinned, NULL);
874
875         g_free (bare);
876
877         return result;
878 }
879
880 /**
881  * get_type:
882  * @m: metadata context 
883  * @ptr: location to decode from.
884  * @result: pointer to string where resulting decoded string is stored
885  *
886  * This routine returs in @result the stringified type pointed by @ptr.
887  * (22.2.12)
888  *
889  * Returns: the new ptr to continue decoding
890  */
891 const char *
892 get_type (MonoImage *m, const char *ptr, char **result)
893 {
894         const char *start = ptr;
895         guint32 type;
896         MonoType *t;
897
898         if (*ptr == MONO_TYPE_BYREF)
899                 ++ptr;
900
901         type = mono_metadata_decode_value (ptr, &ptr);
902
903         switch (type){
904         case MONO_TYPE_VALUETYPE:
905         case MONO_TYPE_CLASS: {
906                 guint32 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
907                 MonoClass *klass = mono_class_get (m, token);
908                 char *temp = dis_stringify_object_with_class (m, klass);
909
910                 if (show_tokens) {
911                         *result = g_strdup_printf ("%s/*%08x*/", temp, token);
912                         g_free (temp);
913                 } else
914                         *result = temp;
915                 break;
916         }
917
918         case MONO_TYPE_GENERICINST: {
919                 GString *str = g_string_new ("");
920                 int count, i;
921                 char *temp;
922
923                 ptr = get_type (m, ptr, &temp);
924                 g_string_append (str, temp);
925                 g_free (temp);
926
927                 count = mono_metadata_decode_value (ptr, &ptr);
928                 g_string_append (str, "<");
929
930                 for (i = 0; i < count; i++) {
931                         if (i)
932                                 g_string_append (str, ",");
933                         ptr = get_type (m, ptr, &temp);
934                         g_string_append (str, temp);
935                 }
936
937                 g_string_append (str, ">");
938                 *result = str->str;
939                 g_string_free (str, FALSE);
940                 break;
941         }
942
943         default:
944                 t = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, start, &ptr);
945                 *result = dis_stringify_type (m, t);
946                 mono_metadata_free_type (t);
947                 break;
948         }
949
950         return ptr;
951 }
952
953 /**
954  * 
955  * Returns a stringified representation of a FieldSig (22.2.4)
956  */
957 char *
958 get_field_signature (MonoImage *m, guint32 blob_signature)
959 {
960         char *allocated_modifier_string, *allocated_type_string;
961         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
962         const char *base;
963         char *res;
964         int len;
965         
966         len = mono_metadata_decode_value (ptr, &ptr);
967         base = ptr;
968         /* FIELD is 0x06 */
969         g_assert (*ptr == 0x06);
970 /*      hex_dump (ptr, 0, len); */
971         ptr++; len--;
972         
973         ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
974         ptr = get_type (m, ptr, &allocated_type_string);
975
976         res = g_strdup_printf (
977                 "%s %s",
978                 allocated_modifier_string ? allocated_modifier_string : "",
979                 allocated_type_string);
980         
981         if (allocated_modifier_string)
982                 g_free (allocated_modifier_string);
983         if (allocated_type_string)
984                 g_free (allocated_type_string);
985         
986         return res;
987 }
988
989 MonoTypeEnum
990 get_field_literal_type (MonoImage *m, guint32 blob_signature)
991 {
992         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
993         int len;
994         char *allocated_modifier_string;
995         
996         len = mono_metadata_decode_value (ptr, &ptr);
997
998         /* FIELD is 0x06 */
999         g_assert (*ptr == 0x06);
1000         ptr++; len--;
1001         
1002         ptr = get_custom_mod (m, ptr, &allocated_modifier_string);
1003         if (allocated_modifier_string)
1004                 g_free (allocated_modifier_string);
1005
1006         return (MonoTypeEnum) *ptr;
1007         
1008 }
1009
1010 /**
1011  * decode_literal:
1012  * @m: metadata context
1013  * @token: token to decode
1014  *
1015  * decodes the literal indexed by @token.
1016  */
1017 char *
1018 decode_literal (MonoImage *m, guint32 token)
1019 {
1020         return g_strdup ("LITERAL_VALUE");
1021 }
1022
1023 /**
1024  * get_ret_type:
1025  * @m: metadata context 
1026  * @ptr: location to decode from.
1027  * @result: pointer to string where resulting decoded string is stored
1028  *
1029  * This routine returns in @result the stringified RetType (22.2.11)
1030  *
1031  * Returns: the new ptr to continue decoding.
1032  */
1033 const char *
1034 get_ret_type (MonoImage *m, const char *ptr, char **ret_type)
1035 {
1036         GString *str = g_string_new ("");
1037         char *mod = NULL;
1038         char *allocated_type_string;
1039         
1040         ptr = get_custom_mod (m, ptr, &mod);
1041         if (mod){
1042                 g_string_append (str, mod);
1043                 g_string_append_c (str, ' ');
1044                 g_free (mod);
1045         }
1046
1047         if (*ptr == MONO_TYPE_TYPEDBYREF){
1048                 g_string_append (str, "typedbyref");
1049                 ptr++;
1050         } else if (*ptr == MONO_TYPE_VOID){
1051                  g_string_append (str, "void");
1052                  ptr++;
1053         } else {
1054                 if (*ptr == MONO_TYPE_BYREF){
1055                         g_string_append (str, "[out] ");
1056                         ptr++;
1057                 }
1058
1059                 ptr = get_type (m, ptr, &allocated_type_string);
1060                 g_string_append (str, allocated_type_string);
1061                 g_free (allocated_type_string);
1062         }
1063
1064         *ret_type = str->str;
1065         g_string_free (str, FALSE);
1066
1067         return ptr;
1068 }
1069
1070 /**
1071  * get_param:
1072  * @m: metadata context 
1073  * @ptr: location to decode from.
1074  * @result: pointer to string where resulting decoded string is stored
1075  *
1076  * This routine returns in @result the stringified Param (22.2.10)
1077  *
1078  * Returns: the new ptr to continue decoding.
1079  */
1080 const char *
1081 get_param (MonoImage *m, const char *ptr, char **retval)
1082 {
1083         GString *str = g_string_new ("");
1084         char *allocated_mod_string, *allocated_type_string;
1085         
1086         ptr = get_custom_mod (m, ptr, &allocated_mod_string);
1087         if (allocated_mod_string){
1088                 g_string_append (str, allocated_mod_string);
1089                 g_string_append_c (str, ' ');
1090                 g_free (allocated_mod_string);
1091         }
1092         
1093         if (*ptr == MONO_TYPE_TYPEDBYREF){
1094                 g_string_append (str, " typedbyref ");
1095                 ptr++;
1096         } else {
1097                 gboolean by_ref = 0;
1098                  if (*ptr == MONO_TYPE_BYREF){
1099                         g_string_append (str, "[out] ");
1100                         ptr++;
1101                         by_ref = 1;
1102                 }
1103                 ptr = get_type (m, ptr, &allocated_type_string);
1104                 g_string_append (str, allocated_type_string);
1105                 if (by_ref)
1106                         g_string_append_c (str, '&');
1107                 g_free (allocated_type_string);
1108         }
1109
1110         *retval = str->str;
1111         g_string_free (str, FALSE);
1112         return ptr;
1113 }
1114
1115 /**
1116  * get_escaped_name
1117  *
1118  * Returns: An allocated escaped name. A name needs to be escaped
1119  * because it might be an ilasm keyword.
1120  */
1121 char*
1122 get_escaped_name (const char *name)
1123 {
1124         const char *s;
1125
1126         g_assert (key_table);
1127
1128         if (strlen (name) == 0)
1129                 return g_strdup (name);
1130
1131         for (s = name; *s; s++) {
1132                 if (isalnum (*s) || *s == '_' || *s == '$' || *s == '@' || *s == '?' || *s == '.' || *s == 0)
1133                         continue;
1134                 return g_strdup_printf ("'%s'", name);
1135         }
1136         
1137         if (g_hash_table_lookup (key_table, name))
1138                 return g_strdup_printf ("'%s'", name);
1139                         
1140         return g_strdup (name);
1141 }
1142
1143 static dis_map_t param_map [] = {
1144         { PARAM_ATTRIBUTE_IN,                "[in] " },
1145         { PARAM_ATTRIBUTE_OUT,               "[out] " },
1146         { PARAM_ATTRIBUTE_OPTIONAL,          "optional " },
1147         { PARAM_ATTRIBUTE_HAS_DEFAULT,       "hasdefault " },
1148         { PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL, "fieldmarshal " },
1149         { 0, NULL }
1150 };
1151
1152 char *
1153 param_flags (guint32 f)
1154 {
1155         return g_strdup (flags (f, param_map));
1156 }
1157
1158 static dis_map_t field_access_map [] = {
1159         { FIELD_ATTRIBUTE_COMPILER_CONTROLLED, "compilercontrolled " },
1160         { FIELD_ATTRIBUTE_PRIVATE,             "private " },
1161         { FIELD_ATTRIBUTE_FAM_AND_ASSEM,       "famandassem " },
1162         { FIELD_ATTRIBUTE_ASSEMBLY,            "assembly " },
1163         { FIELD_ATTRIBUTE_FAMILY,              "family " },
1164         { FIELD_ATTRIBUTE_FAM_OR_ASSEM,        "famorassem " },
1165         { FIELD_ATTRIBUTE_PUBLIC,              "public " },
1166         { 0, NULL }
1167 };
1168
1169 static dis_map_t field_flags_map [] = {
1170         { FIELD_ATTRIBUTE_STATIC,              "static " },
1171         { FIELD_ATTRIBUTE_INIT_ONLY,           "initonly " },
1172         { FIELD_ATTRIBUTE_LITERAL,             "literal " },
1173         { FIELD_ATTRIBUTE_NOT_SERIALIZED,      "notserialized " },
1174         { FIELD_ATTRIBUTE_SPECIAL_NAME,        "specialname " },
1175         { FIELD_ATTRIBUTE_PINVOKE_IMPL,        "FIXME:pinvokeimpl " },
1176         { FIELD_ATTRIBUTE_RT_SPECIAL_NAME,        "rtspecialname " },
1177         { FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL,        "hasfieldmarshal " },
1178         { 0, NULL }
1179 };
1180
1181 /**
1182  * field_flags:
1183  *
1184  * Returns a stringified version of a Field's flags
1185  */
1186 char *
1187 field_flags (guint32 f)
1188 {
1189         char buffer [1024];
1190         int access = f & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
1191         
1192         buffer [0] = 0;
1193
1194         strcat (buffer, map (access, field_access_map));
1195         strcat (buffer, flags (f, field_flags_map));
1196         return g_strdup (buffer);
1197 }
1198
1199 /**
1200  * Returns a stringifed representation of a MethodRefSig (22.2.2)
1201  */
1202 char *
1203 get_methodref_signature (MonoImage *m, guint32 blob_signature, const char *fancy_name)
1204 {
1205         GString *res = g_string_new ("");
1206         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
1207         char *allocated_ret_type, *s;
1208         const char *cconv_str;
1209         gboolean seen_vararg = 0;
1210         int param_count, signature_len;
1211         int i, gen_count = 0;
1212         int cconv;
1213         
1214         signature_len = mono_metadata_decode_value (ptr, &ptr);
1215
1216         if (*ptr & 0x20){
1217                 if (*ptr & 0x40)
1218                         g_string_append (res, "explicit-this ");
1219                 else
1220                         g_string_append (res, "instance "); /* has-this */
1221         }
1222
1223         if (*ptr & 0x10)
1224                 gen_count = 1;
1225         cconv = *ptr & 0x0f;
1226         cconv_str = map (cconv, call_conv_type_map);
1227         if (strcmp (cconv_str, "default") != 0) {
1228                 g_string_append (res, cconv_str);
1229                 g_string_append (res, " ");
1230         }
1231
1232         ptr++;
1233         if (gen_count)
1234                 gen_count = mono_metadata_decode_value (ptr, &ptr);
1235         param_count = mono_metadata_decode_value (ptr, &ptr);
1236         if (cconv != 0xa) {
1237                 ptr = get_ret_type (m, ptr, &allocated_ret_type);
1238                 g_string_append (res, allocated_ret_type);
1239                 g_free (allocated_ret_type);
1240         }
1241
1242         if (fancy_name){
1243                 g_string_append_c (res, ' ');
1244                 g_string_append (res, fancy_name);
1245         }
1246         
1247         g_string_append (res, "(");
1248
1249         /*
1250          * param_count describes parameters *before* and *after*
1251          * the vararg sentinel
1252          */
1253         for (i = 0; i < param_count; i++){
1254                 char *param = NULL;
1255                 
1256                 /*
1257                  * If ptr is a SENTINEL
1258                  */
1259                 if (*ptr == 0x41){
1260                         if (!seen_vararg){
1261                                 g_string_append (res, "..., ");
1262                                 seen_vararg = 1;
1263                         }
1264
1265                         ptr++;
1266                 }
1267
1268                 ptr = get_param (m, ptr, &param);
1269                 g_string_append (res, param);
1270                 if (i+1 != param_count)
1271                         g_string_append (res, ", ");
1272                 g_free (param);
1273         }
1274         g_string_append (res, ")");
1275         
1276         /*
1277          * cleanup and return
1278          */
1279         s = res->str;
1280         g_string_free (res, FALSE);
1281         return s;
1282 }
1283
1284 /**
1285  * Returns a stringifed representation of a field ref
1286  */
1287 char *
1288 get_fieldref_signature (MonoImage *m, int idx)
1289 {
1290         guint32 cols [MONO_MEMBERREF_SIZE];
1291         char *sig;
1292         char *full_sig;
1293
1294         mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
1295                         idx - 1, cols, MONO_MEMBERREF_SIZE);
1296
1297         sig = get_field_signature (m, cols [MONO_MEMBERREF_SIGNATURE]);
1298         full_sig = g_strdup_printf ("%s %s::%s", sig,
1299                         get_memberref_parent (m, cols [MONO_MEMBERREF_CLASS]),
1300                         mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));
1301         g_free (sig);
1302         
1303         return full_sig;
1304 }
1305
1306 /**
1307  * get_field:
1308  * @m: metadata context
1309  * @token: a FIELD_DEF token
1310  *
1311  * This routine has to locate the TypeDef that "owns" this Field.
1312  * Since there is no backpointer in the Field table, we have to scan
1313  * the TypeDef table and locate the actual "owner" of the field
1314  */
1315 char *
1316 get_field (MonoImage *m, guint32 token)
1317 {
1318         int idx = mono_metadata_token_index (token);
1319         guint32 cols [MONO_FIELD_SIZE];
1320         char *sig, *res, *type, *estype, *esname;
1321         guint32 type_idx;
1322
1323         /*
1324          * We can get here also with a MenberRef token (for a field
1325          * defined in another module/assembly, just like in get_method ()
1326          */
1327         if (mono_metadata_token_code (token) == MONO_TOKEN_MEMBER_REF) {
1328                 return get_fieldref_signature (m, idx);
1329         }
1330         g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
1331
1332         mono_metadata_decode_row (&m->tables [MONO_TABLE_FIELD], idx - 1, cols, MONO_FIELD_SIZE);
1333         sig = get_field_signature (m, cols [MONO_FIELD_SIGNATURE]);
1334
1335         /*
1336          * To locate the actual "container" for this field, we have to scan
1337          * the TypeDef table.  LAME!
1338          */
1339         type_idx = mono_metadata_typedef_from_field (m, idx);
1340
1341         type = get_typedef (m, type_idx);
1342         estype = get_escaped_name (type);
1343         esname = get_escaped_name (mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]));
1344         res = g_strdup_printf ("%s %s::%s",
1345                         sig, estype, esname);
1346
1347         g_free (type);
1348         g_free (sig);
1349         g_free (estype);
1350         g_free (esname);
1351
1352         return res;
1353 }
1354
1355 static char *
1356 get_memberref_parent (MonoImage *m, guint32 mrp_token)
1357 {
1358         /*
1359          * mrp_index is a MemberRefParent coded index
1360          */
1361         guint32 table = mrp_token & 7;
1362         guint32 idx = mrp_token >> 3;
1363
1364         switch (table){
1365         case 0: /* TypeDef */
1366                 return get_typedef (m, idx);
1367                 
1368         case 1: /* TypeRef */
1369                 return get_typeref (m, idx);
1370                 
1371         case 2: /* ModuleRef */
1372                 return g_strdup_printf ("TODO:MemberRefParent-ModuleRef");
1373                 
1374         case 3: /* MethodDef */
1375                 return g_strdup ("TODO:MethodDef");
1376                 
1377         case 4: /* TypeSpec */
1378                 return get_typespec (m, idx);
1379         }
1380         g_assert_not_reached ();
1381         return NULL;
1382 }
1383
1384 /**
1385  * get_method:
1386  * @m: metadata context
1387  * @token: a METHOD_DEF or MEMBER_REF token
1388  *
1389  * This routine has to locate the TypeDef that "owns" this Field.
1390  * Since there is no backpointer in the Field table, we have to scan
1391  * the TypeDef table and locate the actual "owner" of the field
1392  */
1393 char *
1394 get_method (MonoImage *m, guint32 token)
1395 {
1396         int idx = mono_metadata_token_index (token);
1397         guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
1398         char *sig = NULL, *esname;
1399         const char *name;
1400
1401         MonoMethod *mh;
1402
1403         mh = mono_get_method (m, token, NULL);
1404         if (mh) {
1405                 esname = get_escaped_name (mh->name);
1406                 sig = dis_stringify_object_with_class (m, mh->klass);
1407                 if (show_tokens)
1408                         name = g_strdup_printf ("%s/*%08x*/::%s", sig, token, esname);
1409                 else
1410                         name = g_strdup_printf ("%s::%s", sig, esname);
1411                 g_free (sig);
1412                 g_free (esname);
1413         } else
1414                 name = NULL;
1415
1416         switch (mono_metadata_token_code (token)){
1417         case MONO_TOKEN_METHOD_DEF:
1418                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1419                                           idx - 1, method_cols, MONO_METHOD_SIZE);
1420
1421                 sig = get_methodref_signature (m, method_cols [MONO_METHOD_SIGNATURE], name);
1422                 break;
1423                 
1424         case MONO_TOKEN_MEMBER_REF: {
1425                 mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF],
1426                                           idx - 1, member_cols, MONO_MEMBERREF_SIZE);
1427                 if (!name)
1428                         name = g_strdup_printf ("%s::%s",
1429                                         get_memberref_parent (m, member_cols [MONO_MEMBERREF_CLASS]),
1430                                         mono_metadata_string_heap (m, member_cols [MONO_MEMBERREF_NAME]));
1431                 sig = get_methodref_signature (
1432                         m, member_cols [MONO_MEMBERREF_SIGNATURE], name);
1433                 break;
1434         }
1435         case MONO_TOKEN_METHOD_SPEC: {
1436                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC],
1437                                 idx - 1, member_cols, MONO_METHODSPEC_SIZE);
1438                 token = member_cols [MONO_METHODSPEC_METHOD];
1439                 sig = get_methodspec (m, idx, token, name);
1440                 break;
1441         }
1442
1443         default:
1444                 g_assert_not_reached ();
1445         }
1446
1447         if (show_tokens) {
1448                 char *retval = g_strdup_printf ("%s /* %08x */", sig, token);
1449                 g_free (sig);
1450                 return retval;
1451         } else
1452                 return sig;
1453 }
1454
1455 /**
1456  * get_methoddef
1457  * @m: metadata context
1458  * @idx: index into the method table
1459  *
1460  * Returns: A stringified version of the method signature.
1461  */
1462 char *
1463 get_methoddef (MonoImage *m, guint32 idx)
1464 {
1465         guint32 cols [MONO_METHOD_SIZE];
1466         char *sig;
1467         const char *name;
1468
1469         MonoMethod *mh;
1470
1471         mh = mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
1472         if (mh) {
1473                 sig = dis_stringify_object_with_class (m, mh->klass);
1474                 name = g_strdup_printf ("%s::%s", sig, mh->name);
1475                 g_free (sig);
1476         } else
1477                 name = NULL;
1478         mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1479                         idx - 1, cols, MONO_METHOD_SIZE);
1480         sig = get_methodref_signature (m, cols [MONO_METHOD_SIGNATURE], name);
1481         
1482         return sig;
1483 }
1484
1485 char *
1486 get_method_type_param (MonoImage *m, guint32 blob_signature)
1487 {
1488         GString *res = g_string_new ("");
1489         const char *ptr = mono_metadata_blob_heap (m, blob_signature);
1490         int param_count;
1491         int i = 0;
1492         char *s;
1493         
1494         mono_metadata_decode_value (ptr, &ptr);
1495         ptr++;
1496         param_count = mono_metadata_decode_value (ptr, &ptr);
1497         
1498         g_string_append_c (res, '<');
1499         
1500         for (i = 0; i < param_count; i++){
1501                 char *param = NULL;
1502                 
1503                 ptr = get_param (m, ptr, &param);
1504                 g_string_append (res, param);
1505                 if (i+1 != param_count)
1506                         g_string_append (res, ", ");
1507                 g_free (param);
1508         }
1509         g_string_append_c (res, '>');
1510         
1511         s = res->str;
1512         g_string_free (res, FALSE);
1513         return s;
1514 }
1515
1516 /**
1517  * get_methodspec
1518  *
1519  * Returns: An allocated stringified version of the methodspec signature.
1520  */
1521
1522 char *
1523 get_methodspec (MonoImage *m, int idx, guint32 token, const char *fancy_name)
1524 {
1525         GString *res = g_string_new ("");
1526         guint32 member_cols [MONO_MEMBERREF_SIZE], method_cols [MONO_METHOD_SIZE];
1527         char *s, *type_param;
1528         const char *ptr;
1529         guint32 sig = 0;
1530         int param_count, cconv, i, gen_count = 0;
1531
1532         switch (token & MONO_METHODDEFORREF_MASK) {
1533         case MONO_METHODDEFORREF_METHODDEF:
1534                 mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
1535                                           (token >> MONO_METHODDEFORREF_BITS) - 1,
1536                                           method_cols, MONO_METHOD_SIZE);
1537                 sig = method_cols [MONO_METHOD_SIGNATURE];
1538                 break;
1539         case MONO_METHODDEFORREF_METHODREF:
1540                 mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], 
1541                                           (token >> MONO_METHODDEFORREF_BITS) - 1,
1542                                           member_cols, MONO_MEMBERREF_SIZE);
1543                 sig = member_cols [MONO_MEMBERREF_SIGNATURE];
1544                 break;
1545         default:
1546                 g_assert_not_reached ();
1547         }
1548
1549         ptr = mono_metadata_blob_heap (m, sig);
1550         mono_metadata_decode_value (ptr, &ptr);
1551
1552         if (*ptr & 0x20){
1553                 if (*ptr & 0x40)
1554                         g_string_append (res, "explicit-this ");
1555                 else
1556                         g_string_append (res, "instance "); /* has-this */
1557         }
1558
1559         if (*ptr & 0x10)
1560                 gen_count = 1;
1561         cconv = *ptr & 0x0f;
1562         ptr++;
1563         if (gen_count)
1564                 gen_count = mono_metadata_decode_value (ptr, &ptr);
1565         param_count = mono_metadata_decode_value (ptr, &ptr);
1566         if (cconv != 0xa) {
1567                 char *allocated_ret_type;
1568                 ptr = get_ret_type (m, ptr, &allocated_ret_type);
1569                 g_string_append (res, allocated_ret_type);
1570                 g_free (allocated_ret_type);
1571         }
1572
1573         if (fancy_name){
1574                 g_string_append_c (res, ' ');
1575                 g_string_append (res, fancy_name);
1576         }
1577
1578         mono_metadata_decode_row (&m->tables [MONO_TABLE_METHODSPEC],
1579                         idx - 1, member_cols, MONO_METHODSPEC_SIZE);
1580         token = member_cols [MONO_METHODSPEC_SIGNATURE];
1581         type_param = get_method_type_param (m, token);
1582         g_string_append (res, type_param);
1583         g_string_append (res, " (");
1584
1585         /*
1586          * methodspecs can not be varargs so we don't need to worry about that here
1587          */
1588          
1589         for (i = 0; i < param_count; i++){
1590                 char *param = NULL;
1591                 
1592                 ptr = get_param (m, ptr, &param);
1593                 g_string_append (res, param);
1594                 if (i+1 != param_count)
1595                         g_string_append (res, ", ");
1596                 g_free (param);
1597         }
1598         g_string_append (res, ")");
1599         
1600         /*
1601          * cleanup and return
1602          */
1603         s = res->str;
1604         g_string_free (res, FALSE);
1605         return s;
1606 }
1607
1608
1609 /**
1610  * get_constant:
1611  * @m: metadata context
1612  * @blob_index: index into the blob where the constant is stored
1613  *
1614  * Returns: An allocated value representing a stringified version of the
1615  * constant.
1616  */
1617 char *
1618 get_constant (MonoImage *m, MonoTypeEnum t, guint32 blob_index)
1619 {
1620         const unsigned char *ptr = mono_metadata_blob_heap (m, blob_index);
1621         int len;
1622         
1623         len = mono_metadata_decode_value (ptr, (const char**)&ptr);
1624         
1625         switch (t){
1626         case MONO_TYPE_BOOLEAN:
1627                 return g_strdup_printf ("%s", *ptr ? "bool(true)" : "bool(false)");
1628                 
1629         case MONO_TYPE_CHAR:
1630                 return g_strdup_printf ("char(0x%04x)", read16(ptr)); 
1631                 
1632         case MONO_TYPE_U1:
1633         case MONO_TYPE_I1:
1634                 return g_strdup_printf ("int8(0x%02x)", (int) (*ptr));
1635                 break;
1636                 
1637         case MONO_TYPE_U2:
1638         case MONO_TYPE_I2:
1639                 return g_strdup_printf ("int16(0x%08x)", (int) read16 (ptr));
1640                 
1641         case MONO_TYPE_U4:
1642         case MONO_TYPE_I4:
1643                 return g_strdup_printf ("int32(%d)", read32 (ptr));
1644                 
1645         case MONO_TYPE_I8: {
1646                 guint32 low, high;
1647                 low = read32 (ptr);
1648                 high = read32 (ptr + 4);
1649                 return g_strdup_printf ("int64(0x%08x%08x)", high, low);
1650         }
1651         case MONO_TYPE_U8: {
1652                 guint32 low, high;
1653                 low = read32 (ptr);
1654                 high = read32 (ptr + 4);
1655                 return g_strdup_printf ("0x%08x%08x", high, low);
1656         }
1657         case MONO_TYPE_R4: {
1658                 float r;
1659                 readr4 (ptr, &r);
1660                 return g_strdup_printf ("float32(%g)", (double) r);
1661         }
1662         case MONO_TYPE_R8: {
1663                 double r;
1664                 readr8 (ptr, &r);
1665                 return g_strdup_printf ("float64(%g)", r);
1666         }
1667         case MONO_TYPE_STRING: {
1668                 gchar *str;
1669                 int i, j, tspaces = (len%16);
1670                 GString *res = g_string_new ("bytearray (\n\t");
1671
1672                 for(i = 1; i <= len; ++i) {
1673                         g_string_append_printf(res, "%02x ", ptr[i-1]);
1674
1675                         if(i%16 == 0) {
1676                                 if(i == len)
1677                                         g_string_append(res, ")// ");
1678                                 else
1679                                         g_string_append(res, " // ");
1680
1681                                 for(j = i-16; j < i; ++j) 
1682                                         g_string_append_printf(res, "%c", isprint(ptr[j]) ? ptr[j] : '.');
1683                                 g_string_append(res, "\n\t");
1684                         }
1685                 }
1686
1687                 if(tspaces) {
1688                         g_string_append(res, ")  ");
1689                         for(i = tspaces+1; i < 16; ++i)
1690                                 g_string_append_printf(res, "   ");
1691
1692                         g_string_append(res, " // ");
1693                         for(i = len-tspaces; i < len; ++i)
1694                                 g_string_append_printf(res, "%c", isprint(ptr[i]) ? ptr[i] : '.');
1695                         g_string_append(res, "\n\t");
1696                 } 
1697
1698                 str = res->str;
1699                 g_string_free(res, FALSE);
1700                 return str;
1701         }
1702                 
1703         case MONO_TYPE_CLASS:
1704                 return g_strdup ("nullref");
1705                 
1706         default:
1707                 g_error ("Unknown MONO_TYPE (%d) on constant at Blob index (0x%08x)\n",
1708                          (int) *ptr, blob_index);
1709                 return g_strdup_printf ("Unknown");
1710         }
1711
1712 }
1713
1714 /**
1715  * get_token:
1716  * @m: metadata context
1717  * @token: token that we want to decode.
1718  *
1719  * Returns: An allocated value representing a stringified version of the
1720  * constant.
1721  */
1722 char *
1723 get_token (MonoImage *m, guint32 token)
1724 {
1725         char *temp, *result;
1726         guint32 idx = mono_metadata_token_index (token);
1727
1728         switch (mono_metadata_token_code (token)){
1729         case MONO_TOKEN_FIELD_DEF:
1730                 temp = get_field (m, token);
1731                 result = g_strdup_printf ("field %s", temp);
1732                 g_free (temp);
1733                 return result;
1734         case MONO_TOKEN_TYPE_DEF:
1735                 return get_typedef (m, idx);
1736         case MONO_TOKEN_TYPE_REF:
1737                 return get_typeref (m, idx);
1738         case MONO_TOKEN_TYPE_SPEC:
1739                 return get_typespec (m, idx);
1740         case MONO_TOKEN_MEMBER_REF: {
1741                 guint32 cols [MONO_MEMBERREF_SIZE];
1742                 const char *sig;
1743                 mono_metadata_decode_row (&m->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
1744                 sig = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]);
1745                 mono_metadata_decode_blob_size (sig, &sig);
1746                 if (*sig == 0x6) { /* it's a field */
1747                         temp = get_field (m, token);
1748                         result = g_strdup_printf ("field %s", temp);
1749                         g_free (temp);
1750                         return result;
1751                 }
1752                 else {
1753                         g_error ("Do not know how to decode tokens of type 0x%08x", token);
1754                 }
1755                 break;
1756         }
1757         default:                
1758                 g_error ("Do not know how to decode tokens of type 0x%08x", token);
1759         }
1760
1761         g_assert_not_reached ();
1762         return g_strdup ("ERROR");
1763 }
1764
1765 /**
1766  * get_token_type:
1767  * @m: metadata context
1768  * @token: the token can belong to any of the following tables:
1769  * MONO_TOKEN_TYPE_REF, MONO_TOKEN_TYPE_DEF, MONO_TOKEN_TYPE_SPEC
1770  *
1771  * Returns: a stringified version of the MethodDef or MethodRef or TypeSpecn
1772  * at (token & 0xffffff) 
1773  */
1774 char *
1775 get_token_type (MonoImage *m, guint32 token)
1776 {
1777         char *temp = NULL, *s = NULL;
1778         int idx;
1779
1780         idx = mono_metadata_token_index (token);
1781         
1782         switch (mono_metadata_token_code (token)){
1783         case MONO_TOKEN_TYPE_DEF:
1784                 temp = get_typedef (m, idx);
1785                 s = g_strdup_printf ("%s", temp);
1786                 break;
1787                 
1788         case MONO_TOKEN_TYPE_REF: 
1789                 temp = get_typeref (m, idx);
1790                 s = g_strdup_printf ("%s", temp);
1791                 break;
1792                 
1793         case MONO_TOKEN_TYPE_SPEC:
1794                 s = get_typespec (m, idx);
1795                 break;
1796
1797         default:
1798                 g_error ("Unhandled encoding for token 0x%08x", token);
1799
1800         }
1801         
1802         if (temp)
1803                 g_free (temp);
1804
1805         return s;
1806 }
1807
1808 char *
1809 get_guid (MonoImage *m, guint32 guid_index)
1810 {
1811         const unsigned char *guid;
1812         char *result;
1813
1814         guid = mono_metadata_guid_heap (m, guid_index);
1815
1816         result = g_strdup_printf ("{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 
1817                         guid [3], guid [2], guid [1], guid [0], guid [5], guid [4], guid [7], guid [6],
1818                         guid [8], guid [9], guid [10], guid [11], guid [12], guid [13], guid [14], guid [15]);
1819         return result;
1820 }
1821
1822 GList *
1823 dis_get_custom_attrs (MonoImage *m, guint32 token)
1824 {
1825         GList *list = NULL;
1826         guint32 idx, i, len, mtoken;
1827         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1828         MonoTableInfo *ca;
1829         char *method;
1830         GString *attr;
1831         const char *val;
1832
1833         idx = mono_metadata_token_index (token);
1834         idx <<= MONO_CUSTOM_ATTR_BITS;
1835         
1836         switch (mono_metadata_token_table (token)) {
1837         case MONO_TABLE_TYPEDEF:
1838                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1839                 break;
1840         case MONO_TABLE_ASSEMBLY:
1841                 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1842                 break;
1843         case MONO_TABLE_MODULE:
1844                 idx |= MONO_CUSTOM_ATTR_MODULE;
1845                 break;
1846         case MONO_TABLE_PROPERTY:
1847                 idx |= MONO_CUSTOM_ATTR_PROPERTY;
1848                 break;
1849         case MONO_TABLE_EVENT:
1850                 idx |= MONO_CUSTOM_ATTR_EVENT;
1851                 break;
1852         case MONO_TABLE_FIELD:
1853                 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1854                 break;
1855         case MONO_TABLE_METHOD:
1856                 idx |= MONO_CUSTOM_ATTR_METHODDEF;
1857                 break;
1858         case MONO_TABLE_PARAM:
1859                 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1860                 break;
1861         default:
1862                 g_print ("Missing custom attr get support for token 0x%08x\n", token);
1863                 return NULL;
1864         }
1865
1866         ca = &m->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1867         /* the table is not sorted */
1868         for (i = 0; i < ca->rows; ++i) {
1869                 char *dump;
1870                 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
1871                 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
1872                         continue;
1873                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1874                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1875                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1876                         mtoken |= MONO_TOKEN_METHOD_DEF;
1877                         break;
1878                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1879                         mtoken |= MONO_TOKEN_MEMBER_REF;
1880                         break;
1881                 default:
1882                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1883                         break;
1884                 }
1885                 method = get_method (m, mtoken);
1886                 val = mono_metadata_blob_heap (m, cols [MONO_CUSTOM_ATTR_VALUE]);
1887                 len = mono_metadata_decode_value (val, &val);
1888                 attr = g_string_new (".custom ");
1889                 dump = data_dump (val, len, "\t\t");
1890                 g_string_sprintfa (attr, "%s = %s", method, dump);
1891                 g_free (dump);
1892                 list = g_list_append (list, attr->str);
1893                 g_string_free (attr, FALSE);
1894                 g_free (method);
1895         }
1896         return list;
1897 }
1898
1899 char*
1900 get_marshal_info (MonoImage *m, const char *blob) {
1901         int len, size = 0;
1902
1903         len = mono_metadata_decode_blob_size (blob, &blob);
1904
1905         switch (*blob) {
1906         case MONO_NATIVE_BOOLEAN:
1907                 return g_strdup ("bool");
1908         case MONO_NATIVE_I1:
1909                 return g_strdup ("int8");
1910         case MONO_NATIVE_U1:
1911                 return g_strdup ("unsigned int8");
1912         case MONO_NATIVE_I2:
1913                 return g_strdup ("int16");
1914         case MONO_NATIVE_U2:
1915                 return g_strdup ("unsigned int16");
1916         case MONO_NATIVE_I4:
1917                 return g_strdup ("int32");
1918         case MONO_NATIVE_U4:
1919                 return g_strdup ("unsigned int32");
1920         case MONO_NATIVE_I8:
1921                 return g_strdup ("int64");
1922         case MONO_NATIVE_U8:
1923                 return g_strdup ("unsigned int64");
1924         case MONO_NATIVE_R4:
1925                 return g_strdup ("float32");
1926         case MONO_NATIVE_R8:
1927                 return g_strdup ("float64");
1928         case MONO_NATIVE_CURRENCY:
1929                 return g_strdup ("currency");
1930         case MONO_NATIVE_BSTR:
1931                 return g_strdup ("bstr");
1932         case MONO_NATIVE_LPSTR:
1933                 return g_strdup ("lpstr");
1934         case MONO_NATIVE_LPWSTR:
1935                 return g_strdup ("lpwstr");
1936         case MONO_NATIVE_LPTSTR:
1937                 return g_strdup ("lptstr");
1938         case MONO_NATIVE_BYVALTSTR:
1939                 size = mono_metadata_decode_value (blob + 1, &blob);
1940                 return g_strdup_printf ("fixed sysstring [%d]", size);
1941         case MONO_NATIVE_IUNKNOWN:
1942                 return g_strdup ("iunknown");
1943         case MONO_NATIVE_IDISPATCH:
1944                 return g_strdup ("idispatch");
1945         case MONO_NATIVE_STRUCT:
1946                 return g_strdup ("struct");
1947         case MONO_NATIVE_INTERFACE:
1948                 return g_strdup ("interface");
1949         case MONO_NATIVE_SAFEARRAY:
1950                 return g_strdup ("safearray");
1951         case MONO_NATIVE_BYVALARRAY:
1952                 size = mono_metadata_decode_value (blob + 1, &blob);
1953                 return g_strdup_printf ("fixed array [%d]", size);
1954         case MONO_NATIVE_INT:
1955                 return g_strdup ("int");
1956         case MONO_NATIVE_UINT:
1957                 return g_strdup ("unsigned int");
1958         case MONO_NATIVE_VBBYREFSTR:
1959                 return g_strdup ("vbbyrefstr");
1960         case MONO_NATIVE_ANSIBSTR:
1961                 return g_strdup ("ansi bstr");
1962         case MONO_NATIVE_TBSTR:
1963                 return g_strdup ("tbstr");
1964         case MONO_NATIVE_VARIANTBOOL:
1965                 return g_strdup ("variant bool");
1966         case MONO_NATIVE_FUNC:
1967                 return g_strdup ("method");
1968         case MONO_NATIVE_ASANY:
1969                 return g_strdup ("as any");
1970         case MONO_NATIVE_LPARRAY:
1971                 return g_strdup ("[]");
1972         case MONO_NATIVE_LPSTRUCT:
1973                 return g_strdup ("lpstruct");
1974         case MONO_NATIVE_CUSTOM:
1975                 return g_strdup ("custom");
1976         case MONO_NATIVE_ERROR:
1977                 return g_strdup ("error");
1978         default:
1979                 return g_strdup ("unknown");
1980         }
1981 }
1982
1983 void
1984 init_key_table (void)
1985 {
1986         key_table = g_hash_table_new (g_str_hash, g_str_equal);
1987
1988         /* auto generated */
1989         g_hash_table_insert (key_table, (char *) "abstract", GINT_TO_POINTER (TRUE));
1990         g_hash_table_insert (key_table, (char *) "add", GINT_TO_POINTER (TRUE));
1991         g_hash_table_insert (key_table, (char *) "add.ovf", GINT_TO_POINTER (TRUE));
1992         g_hash_table_insert (key_table, (char *) "add.ovf.un", GINT_TO_POINTER (TRUE));
1993         g_hash_table_insert (key_table, (char *) "algorithm", GINT_TO_POINTER (TRUE));
1994         g_hash_table_insert (key_table, (char *) "alignment", GINT_TO_POINTER (TRUE));
1995         g_hash_table_insert (key_table, (char *) "and", GINT_TO_POINTER (TRUE));
1996         g_hash_table_insert (key_table, (char *) "ansi", GINT_TO_POINTER (TRUE));
1997         g_hash_table_insert (key_table, (char *) "any", GINT_TO_POINTER (TRUE));
1998         g_hash_table_insert (key_table, (char *) "arglist", GINT_TO_POINTER (TRUE));
1999         g_hash_table_insert (key_table, (char *) "array", GINT_TO_POINTER (TRUE));
2000         g_hash_table_insert (key_table, (char *) "as", GINT_TO_POINTER (TRUE));
2001         g_hash_table_insert (key_table, (char *) "assembly", GINT_TO_POINTER (TRUE));
2002         g_hash_table_insert (key_table, (char *) "assert", GINT_TO_POINTER (TRUE));
2003         g_hash_table_insert (key_table, (char *) "at", GINT_TO_POINTER (TRUE));
2004         g_hash_table_insert (key_table, (char *) "auto", GINT_TO_POINTER (TRUE));
2005         g_hash_table_insert (key_table, (char *) "autochar", GINT_TO_POINTER (TRUE));
2006         g_hash_table_insert (key_table, (char *) "beforefieldinit", GINT_TO_POINTER (TRUE));
2007         g_hash_table_insert (key_table, (char *) "beq", GINT_TO_POINTER (TRUE));
2008         g_hash_table_insert (key_table, (char *) "beq.s", GINT_TO_POINTER (TRUE));
2009         g_hash_table_insert (key_table, (char *) "bge", GINT_TO_POINTER (TRUE));
2010         g_hash_table_insert (key_table, (char *) "bge.s", GINT_TO_POINTER (TRUE));
2011         g_hash_table_insert (key_table, (char *) "bge.un", GINT_TO_POINTER (TRUE));
2012         g_hash_table_insert (key_table, (char *) "bge.un.s", GINT_TO_POINTER (TRUE));
2013         g_hash_table_insert (key_table, (char *) "bgt", GINT_TO_POINTER (TRUE));
2014         g_hash_table_insert (key_table, (char *) "bgt.s", GINT_TO_POINTER (TRUE));
2015         g_hash_table_insert (key_table, (char *) "bgt.un", GINT_TO_POINTER (TRUE));
2016         g_hash_table_insert (key_table, (char *) "9", GINT_TO_POINTER (TRUE));
2017         g_hash_table_insert (key_table, (char *) "bgt.un.s", GINT_TO_POINTER (TRUE));
2018         g_hash_table_insert (key_table, (char *) "ble", GINT_TO_POINTER (TRUE));
2019         g_hash_table_insert (key_table, (char *) "ble.s", GINT_TO_POINTER (TRUE));
2020         g_hash_table_insert (key_table, (char *) "ble.un", GINT_TO_POINTER (TRUE));
2021         g_hash_table_insert (key_table, (char *) "ble.un.s", GINT_TO_POINTER (TRUE));
2022         g_hash_table_insert (key_table, (char *) "blob", GINT_TO_POINTER (TRUE));
2023         g_hash_table_insert (key_table, (char *) "blob_object", GINT_TO_POINTER (TRUE));
2024         g_hash_table_insert (key_table, (char *) "blt", GINT_TO_POINTER (TRUE));
2025         g_hash_table_insert (key_table, (char *) "blt.s", GINT_TO_POINTER (TRUE));
2026         g_hash_table_insert (key_table, (char *) "blt.un", GINT_TO_POINTER (TRUE));
2027         g_hash_table_insert (key_table, (char *) "blt.un.s", GINT_TO_POINTER (TRUE));
2028         g_hash_table_insert (key_table, (char *) "bne.un", GINT_TO_POINTER (TRUE));
2029         g_hash_table_insert (key_table, (char *) "bne.un.s", GINT_TO_POINTER (TRUE));
2030         g_hash_table_insert (key_table, (char *) "bool", GINT_TO_POINTER (TRUE));
2031         g_hash_table_insert (key_table, (char *) "box", GINT_TO_POINTER (TRUE));
2032         g_hash_table_insert (key_table, (char *) "br", GINT_TO_POINTER (TRUE));
2033         g_hash_table_insert (key_table, (char *) "br.s", GINT_TO_POINTER (TRUE));
2034         g_hash_table_insert (key_table, (char *) "break", GINT_TO_POINTER (TRUE));
2035         g_hash_table_insert (key_table, (char *) "brfalse", GINT_TO_POINTER (TRUE));
2036         g_hash_table_insert (key_table, (char *) "brfalse.s", GINT_TO_POINTER (TRUE));
2037         g_hash_table_insert (key_table, (char *) "brinst", GINT_TO_POINTER (TRUE));
2038         g_hash_table_insert (key_table, (char *) "brinst.s", GINT_TO_POINTER (TRUE));
2039         g_hash_table_insert (key_table, (char *) "brnull", GINT_TO_POINTER (TRUE));
2040         g_hash_table_insert (key_table, (char *) "brnull.s", GINT_TO_POINTER (TRUE));
2041         g_hash_table_insert (key_table, (char *) "brtrue", GINT_TO_POINTER (TRUE));
2042         g_hash_table_insert (key_table, (char *) "brtrue.s", GINT_TO_POINTER (TRUE));
2043         g_hash_table_insert (key_table, (char *) "brzero", GINT_TO_POINTER (TRUE));
2044         g_hash_table_insert (key_table, (char *) "brzero.s", GINT_TO_POINTER (TRUE));
2045         g_hash_table_insert (key_table, (char *) "bstr", GINT_TO_POINTER (TRUE));
2046         g_hash_table_insert (key_table, (char *) "bytearray", GINT_TO_POINTER (TRUE));
2047         g_hash_table_insert (key_table, (char *) "byvalstr", GINT_TO_POINTER (TRUE));
2048         g_hash_table_insert (key_table, (char *) "call", GINT_TO_POINTER (TRUE));
2049         g_hash_table_insert (key_table, (char *) "calli", GINT_TO_POINTER (TRUE));
2050         g_hash_table_insert (key_table, (char *) "callmostderived", GINT_TO_POINTER (TRUE));
2051         g_hash_table_insert (key_table, (char *) "callvirt", GINT_TO_POINTER (TRUE));
2052         g_hash_table_insert (key_table, (char *) "carray", GINT_TO_POINTER (TRUE));
2053         g_hash_table_insert (key_table, (char *) "castclass", GINT_TO_POINTER (TRUE));
2054         g_hash_table_insert (key_table, (char *) "catch", GINT_TO_POINTER (TRUE));
2055         g_hash_table_insert (key_table, (char *) "cdecl", GINT_TO_POINTER (TRUE));
2056         g_hash_table_insert (key_table, (char *) "ceq", GINT_TO_POINTER (TRUE));
2057         g_hash_table_insert (key_table, (char *) "cf", GINT_TO_POINTER (TRUE));
2058         g_hash_table_insert (key_table, (char *) "cgt", GINT_TO_POINTER (TRUE));
2059         g_hash_table_insert (key_table, (char *) "cgt.un", GINT_TO_POINTER (TRUE));
2060         g_hash_table_insert (key_table, (char *) "char", GINT_TO_POINTER (TRUE));
2061         g_hash_table_insert (key_table, (char *) "cil", GINT_TO_POINTER (TRUE));
2062         g_hash_table_insert (key_table, (char *) "ckfinite", GINT_TO_POINTER (TRUE));
2063         g_hash_table_insert (key_table, (char *) "class", GINT_TO_POINTER (TRUE));
2064         g_hash_table_insert (key_table, (char *) "clsid", GINT_TO_POINTER (TRUE));
2065         g_hash_table_insert (key_table, (char *) "clt", GINT_TO_POINTER (TRUE));
2066         g_hash_table_insert (key_table, (char *) "clt.un", GINT_TO_POINTER (TRUE));
2067         g_hash_table_insert (key_table, (char *) "const", GINT_TO_POINTER (TRUE));
2068         g_hash_table_insert (key_table, (char *) "conv.i", GINT_TO_POINTER (TRUE));
2069         g_hash_table_insert (key_table, (char *) "conv.i1", GINT_TO_POINTER (TRUE));
2070         g_hash_table_insert (key_table, (char *) "conv.i2", GINT_TO_POINTER (TRUE));
2071         g_hash_table_insert (key_table, (char *) "conv.i4", GINT_TO_POINTER (TRUE));
2072         g_hash_table_insert (key_table, (char *) "conv.i8", GINT_TO_POINTER (TRUE));
2073         g_hash_table_insert (key_table, (char *) "conv.ovf.i", GINT_TO_POINTER (TRUE));
2074         g_hash_table_insert (key_table, (char *) "conv.ovf.i.un", GINT_TO_POINTER (TRUE));
2075         g_hash_table_insert (key_table, (char *) "conv.ovf.i1", GINT_TO_POINTER (TRUE));
2076         g_hash_table_insert (key_table, (char *) "conv.ovf.i1.un", GINT_TO_POINTER (TRUE));
2077         g_hash_table_insert (key_table, (char *) "conv.ovf.i2", GINT_TO_POINTER (TRUE));
2078         g_hash_table_insert (key_table, (char *) "conv.ovf.i2.un", GINT_TO_POINTER (TRUE));
2079         g_hash_table_insert (key_table, (char *) "conv.ovf.i4", GINT_TO_POINTER (TRUE));
2080         g_hash_table_insert (key_table, (char *) "conv.ovf.i4.un", GINT_TO_POINTER (TRUE));
2081         g_hash_table_insert (key_table, (char *) "conv.ovf.i8", GINT_TO_POINTER (TRUE));
2082         g_hash_table_insert (key_table, (char *) "conv.ovf.i8.un", GINT_TO_POINTER (TRUE));
2083         g_hash_table_insert (key_table, (char *) "conv.ovf.u", GINT_TO_POINTER (TRUE));
2084         g_hash_table_insert (key_table, (char *) "conv.ovf.u.un", GINT_TO_POINTER (TRUE));
2085         g_hash_table_insert (key_table, (char *) "conv.ovf.u1", GINT_TO_POINTER (TRUE));
2086         g_hash_table_insert (key_table, (char *) "conv.ovf.u1.un", GINT_TO_POINTER (TRUE));
2087         g_hash_table_insert (key_table, (char *) "conv.ovf.u2", GINT_TO_POINTER (TRUE));
2088         g_hash_table_insert (key_table, (char *) "conv.ovf.u2.un", GINT_TO_POINTER (TRUE));
2089         g_hash_table_insert (key_table, (char *) "conv.ovf.u4", GINT_TO_POINTER (TRUE));
2090         g_hash_table_insert (key_table, (char *) "conv.ovf.u4.un", GINT_TO_POINTER (TRUE));
2091         g_hash_table_insert (key_table, (char *) "conv.ovf.u8", GINT_TO_POINTER (TRUE));
2092         g_hash_table_insert (key_table, (char *) "conv.ovf.u8.un", GINT_TO_POINTER (TRUE));
2093         g_hash_table_insert (key_table, (char *) "conv.r.un", GINT_TO_POINTER (TRUE));
2094         g_hash_table_insert (key_table, (char *) "conv.r4", GINT_TO_POINTER (TRUE));
2095         g_hash_table_insert (key_table, (char *) "conv.r8", GINT_TO_POINTER (TRUE));
2096         g_hash_table_insert (key_table, (char *) "conv.u", GINT_TO_POINTER (TRUE));
2097         g_hash_table_insert (key_table, (char *) "conv.u1", GINT_TO_POINTER (TRUE));
2098         g_hash_table_insert (key_table, (char *) "conv.u2", GINT_TO_POINTER (TRUE));
2099         g_hash_table_insert (key_table, (char *) "conv.u4", GINT_TO_POINTER (TRUE));
2100         g_hash_table_insert (key_table, (char *) "conv.u8", GINT_TO_POINTER (TRUE));
2101         g_hash_table_insert (key_table, (char *) "cpblk", GINT_TO_POINTER (TRUE));
2102         g_hash_table_insert (key_table, (char *) "cpobj", GINT_TO_POINTER (TRUE));
2103         g_hash_table_insert (key_table, (char *) "currency", GINT_TO_POINTER (TRUE));
2104         g_hash_table_insert (key_table, (char *) "custom", GINT_TO_POINTER (TRUE));
2105         g_hash_table_insert (key_table, (char *) "date", GINT_TO_POINTER (TRUE));
2106         g_hash_table_insert (key_table, (char *) "decimal", GINT_TO_POINTER (TRUE));
2107         g_hash_table_insert (key_table, (char *) "default", GINT_TO_POINTER (TRUE));
2108         g_hash_table_insert (key_table, (char *) "default", GINT_TO_POINTER (TRUE));
2109         g_hash_table_insert (key_table, (char *) "demand", GINT_TO_POINTER (TRUE));
2110         g_hash_table_insert (key_table, (char *) "deny", GINT_TO_POINTER (TRUE));
2111         g_hash_table_insert (key_table, (char *) "div", GINT_TO_POINTER (TRUE));
2112         g_hash_table_insert (key_table, (char *) "div.un", GINT_TO_POINTER (TRUE));
2113         g_hash_table_insert (key_table, (char *) "dup", GINT_TO_POINTER (TRUE));
2114         g_hash_table_insert (key_table, (char *) "endfault", GINT_TO_POINTER (TRUE));
2115         g_hash_table_insert (key_table, (char *) "endfilter", GINT_TO_POINTER (TRUE));
2116         g_hash_table_insert (key_table, (char *) "endfinally", GINT_TO_POINTER (TRUE));
2117         g_hash_table_insert (key_table, (char *) "endmac", GINT_TO_POINTER (TRUE));
2118         g_hash_table_insert (key_table, (char *) "enum", GINT_TO_POINTER (TRUE));
2119         g_hash_table_insert (key_table, (char *) "error", GINT_TO_POINTER (TRUE));
2120         g_hash_table_insert (key_table, (char *) "explicit", GINT_TO_POINTER (TRUE));
2121         g_hash_table_insert (key_table, (char *) "extends", GINT_TO_POINTER (TRUE));
2122         g_hash_table_insert (key_table, (char *) "extern", GINT_TO_POINTER (TRUE));
2123         g_hash_table_insert (key_table, (char *) "false", GINT_TO_POINTER (TRUE));
2124         g_hash_table_insert (key_table, (char *) "famandassem", GINT_TO_POINTER (TRUE));
2125         g_hash_table_insert (key_table, (char *) "family", GINT_TO_POINTER (TRUE));
2126         g_hash_table_insert (key_table, (char *) "famorassem", GINT_TO_POINTER (TRUE));
2127         g_hash_table_insert (key_table, (char *) "fastcall", GINT_TO_POINTER (TRUE));
2128         g_hash_table_insert (key_table, (char *) "fastcall", GINT_TO_POINTER (TRUE));
2129         g_hash_table_insert (key_table, (char *) "fault", GINT_TO_POINTER (TRUE));
2130         g_hash_table_insert (key_table, (char *) "field", GINT_TO_POINTER (TRUE));
2131         g_hash_table_insert (key_table, (char *) "filetime", GINT_TO_POINTER (TRUE));
2132         g_hash_table_insert (key_table, (char *) "filter", GINT_TO_POINTER (TRUE));
2133         g_hash_table_insert (key_table, (char *) "final", GINT_TO_POINTER (TRUE));
2134         g_hash_table_insert (key_table, (char *) "finally", GINT_TO_POINTER (TRUE));
2135         g_hash_table_insert (key_table, (char *) "fixed", GINT_TO_POINTER (TRUE));
2136         g_hash_table_insert (key_table, (char *) "float", GINT_TO_POINTER (TRUE));
2137         g_hash_table_insert (key_table, (char *) "float32", GINT_TO_POINTER (TRUE));
2138         g_hash_table_insert (key_table, (char *) "float64", GINT_TO_POINTER (TRUE));
2139         g_hash_table_insert (key_table, (char *) "forwardref", GINT_TO_POINTER (TRUE));
2140         g_hash_table_insert (key_table, (char *) "fromunmanaged", GINT_TO_POINTER (TRUE));
2141         g_hash_table_insert (key_table, (char *) "handler", GINT_TO_POINTER (TRUE));
2142         g_hash_table_insert (key_table, (char *) "hidebysig", GINT_TO_POINTER (TRUE));
2143         g_hash_table_insert (key_table, (char *) "hresult", GINT_TO_POINTER (TRUE));
2144         g_hash_table_insert (key_table, (char *) "idispatch", GINT_TO_POINTER (TRUE));
2145         g_hash_table_insert (key_table, (char *) "il", GINT_TO_POINTER (TRUE));
2146         g_hash_table_insert (key_table, (char *) "illegal", GINT_TO_POINTER (TRUE));
2147         g_hash_table_insert (key_table, (char *) "implements", GINT_TO_POINTER (TRUE));
2148         g_hash_table_insert (key_table, (char *) "implicitcom", GINT_TO_POINTER (TRUE));
2149         g_hash_table_insert (key_table, (char *) "implicitres", GINT_TO_POINTER (TRUE));
2150         g_hash_table_insert (key_table, (char *) "import", GINT_TO_POINTER (TRUE));
2151         g_hash_table_insert (key_table, (char *) "in", GINT_TO_POINTER (TRUE));
2152         g_hash_table_insert (key_table, (char *) "inheritcheck", GINT_TO_POINTER (TRUE));
2153         g_hash_table_insert (key_table, (char *) "init", GINT_TO_POINTER (TRUE));
2154         g_hash_table_insert (key_table, (char *) "initblk", GINT_TO_POINTER (TRUE));
2155         g_hash_table_insert (key_table, (char *) "initobj", GINT_TO_POINTER (TRUE));
2156         g_hash_table_insert (key_table, (char *) "initonly", GINT_TO_POINTER (TRUE));
2157         g_hash_table_insert (key_table, (char *) "instance", GINT_TO_POINTER (TRUE));
2158         g_hash_table_insert (key_table, (char *) "int", GINT_TO_POINTER (TRUE));
2159         g_hash_table_insert (key_table, (char *) "int16", GINT_TO_POINTER (TRUE));
2160         g_hash_table_insert (key_table, (char *) "int32", GINT_TO_POINTER (TRUE));
2161         g_hash_table_insert (key_table, (char *) "int64", GINT_TO_POINTER (TRUE));
2162         g_hash_table_insert (key_table, (char *) "int8", GINT_TO_POINTER (TRUE));
2163         g_hash_table_insert (key_table, (char *) "interface", GINT_TO_POINTER (TRUE));
2164         g_hash_table_insert (key_table, (char *) "internalcall", GINT_TO_POINTER (TRUE));
2165         g_hash_table_insert (key_table, (char *) "isinst", GINT_TO_POINTER (TRUE));
2166         g_hash_table_insert (key_table, (char *) "iunknown", GINT_TO_POINTER (TRUE));
2167         g_hash_table_insert (key_table, (char *) "jmp", GINT_TO_POINTER (TRUE));
2168         g_hash_table_insert (key_table, (char *) "lasterr", GINT_TO_POINTER (TRUE));
2169         g_hash_table_insert (key_table, (char *) "lcid", GINT_TO_POINTER (TRUE));
2170         g_hash_table_insert (key_table, (char *) "ldarg", GINT_TO_POINTER (TRUE));
2171         g_hash_table_insert (key_table, (char *) "ldarg.0", GINT_TO_POINTER (TRUE));
2172         g_hash_table_insert (key_table, (char *) "ldarg.1", GINT_TO_POINTER (TRUE));
2173         g_hash_table_insert (key_table, (char *) "ldarg.2", GINT_TO_POINTER (TRUE));
2174         g_hash_table_insert (key_table, (char *) "ldarg.3", GINT_TO_POINTER (TRUE));
2175         g_hash_table_insert (key_table, (char *) "ldarg.s", GINT_TO_POINTER (TRUE));
2176         g_hash_table_insert (key_table, (char *) "ldarga", GINT_TO_POINTER (TRUE));
2177         g_hash_table_insert (key_table, (char *) "ldarga.s", GINT_TO_POINTER (TRUE));
2178         g_hash_table_insert (key_table, (char *) "ldc.i4", GINT_TO_POINTER (TRUE));
2179         g_hash_table_insert (key_table, (char *) "ldc.i4.0", GINT_TO_POINTER (TRUE));
2180         g_hash_table_insert (key_table, (char *) "ldc.i4.1", GINT_TO_POINTER (TRUE));
2181         g_hash_table_insert (key_table, (char *) "ldc.i4.2", GINT_TO_POINTER (TRUE));
2182         g_hash_table_insert (key_table, (char *) "ldc.i4.3", GINT_TO_POINTER (TRUE));
2183         g_hash_table_insert (key_table, (char *) "ldc.i4.4", GINT_TO_POINTER (TRUE));
2184         g_hash_table_insert (key_table, (char *) "ldc.i4.5", GINT_TO_POINTER (TRUE));
2185         g_hash_table_insert (key_table, (char *) "ldc.i4.6", GINT_TO_POINTER (TRUE));
2186         g_hash_table_insert (key_table, (char *) "ldc.i4.7", GINT_TO_POINTER (TRUE));
2187         g_hash_table_insert (key_table, (char *) "ldc.i4.8", GINT_TO_POINTER (TRUE));
2188         g_hash_table_insert (key_table, (char *) "ldc.i4.M1", GINT_TO_POINTER (TRUE));
2189         g_hash_table_insert (key_table, (char *) "ldc.i4.m1", GINT_TO_POINTER (TRUE));
2190         g_hash_table_insert (key_table, (char *) "ldc.i4.s", GINT_TO_POINTER (TRUE));
2191         g_hash_table_insert (key_table, (char *) "ldc.i8", GINT_TO_POINTER (TRUE));
2192         g_hash_table_insert (key_table, (char *) "ldc.r4", GINT_TO_POINTER (TRUE));
2193         g_hash_table_insert (key_table, (char *) "ldc.r8", GINT_TO_POINTER (TRUE));
2194         g_hash_table_insert (key_table, (char *) "ldelem.i", GINT_TO_POINTER (TRUE));
2195         g_hash_table_insert (key_table, (char *) "ldelem.i1", GINT_TO_POINTER (TRUE));
2196         g_hash_table_insert (key_table, (char *) "ldelem.i2", GINT_TO_POINTER (TRUE));
2197         g_hash_table_insert (key_table, (char *) "ldelem.i4", GINT_TO_POINTER (TRUE));
2198         g_hash_table_insert (key_table, (char *) "ldelem.i8", GINT_TO_POINTER (TRUE));
2199         g_hash_table_insert (key_table, (char *) "ldelem.r4", GINT_TO_POINTER (TRUE));
2200         g_hash_table_insert (key_table, (char *) "ldelem.r8", GINT_TO_POINTER (TRUE));
2201         g_hash_table_insert (key_table, (char *) "ldelem.ref", GINT_TO_POINTER (TRUE));
2202         g_hash_table_insert (key_table, (char *) "ldelem.u1", GINT_TO_POINTER (TRUE));
2203         g_hash_table_insert (key_table, (char *) "ldelem.u2", GINT_TO_POINTER (TRUE));
2204         g_hash_table_insert (key_table, (char *) "ldelem.u4", GINT_TO_POINTER (TRUE));
2205         g_hash_table_insert (key_table, (char *) "ldelem.u8", GINT_TO_POINTER (TRUE));
2206         g_hash_table_insert (key_table, (char *) "ldelema", GINT_TO_POINTER (TRUE));
2207         g_hash_table_insert (key_table, (char *) "ldfld", GINT_TO_POINTER (TRUE));
2208         g_hash_table_insert (key_table, (char *) "ldflda", GINT_TO_POINTER (TRUE));
2209         g_hash_table_insert (key_table, (char *) "ldftn", GINT_TO_POINTER (TRUE));
2210         g_hash_table_insert (key_table, (char *) "ldind.i", GINT_TO_POINTER (TRUE));
2211         g_hash_table_insert (key_table, (char *) "ldind.i1", GINT_TO_POINTER (TRUE));
2212         g_hash_table_insert (key_table, (char *) "ldind.i2", GINT_TO_POINTER (TRUE));
2213         g_hash_table_insert (key_table, (char *) "ldind.i4", GINT_TO_POINTER (TRUE));
2214         g_hash_table_insert (key_table, (char *) "ldind.i8", GINT_TO_POINTER (TRUE));
2215         g_hash_table_insert (key_table, (char *) "ldind.r4", GINT_TO_POINTER (TRUE));
2216         g_hash_table_insert (key_table, (char *) "ldind.r8", GINT_TO_POINTER (TRUE));
2217         g_hash_table_insert (key_table, (char *) "ldind.ref", GINT_TO_POINTER (TRUE));
2218         g_hash_table_insert (key_table, (char *) "ldind.u1", GINT_TO_POINTER (TRUE));
2219         g_hash_table_insert (key_table, (char *) "ldind.u2", GINT_TO_POINTER (TRUE));
2220         g_hash_table_insert (key_table, (char *) "ldind.u4", GINT_TO_POINTER (TRUE));
2221         g_hash_table_insert (key_table, (char *) "ldind.u8", GINT_TO_POINTER (TRUE));
2222         g_hash_table_insert (key_table, (char *) "ldlen", GINT_TO_POINTER (TRUE));
2223         g_hash_table_insert (key_table, (char *) "ldloc", GINT_TO_POINTER (TRUE));
2224         g_hash_table_insert (key_table, (char *) "ldloc.0", GINT_TO_POINTER (TRUE));
2225         g_hash_table_insert (key_table, (char *) "ldloc.1", GINT_TO_POINTER (TRUE));
2226         g_hash_table_insert (key_table, (char *) "ldloc.2", GINT_TO_POINTER (TRUE));
2227         g_hash_table_insert (key_table, (char *) "ldloc.3", GINT_TO_POINTER (TRUE));
2228         g_hash_table_insert (key_table, (char *) "ldloc.s", GINT_TO_POINTER (TRUE));
2229         g_hash_table_insert (key_table, (char *) "ldloca", GINT_TO_POINTER (TRUE));
2230         g_hash_table_insert (key_table, (char *) "ldloca.s", GINT_TO_POINTER (TRUE));
2231         g_hash_table_insert (key_table, (char *) "ldnull", GINT_TO_POINTER (TRUE));
2232         g_hash_table_insert (key_table, (char *) "ldobj", GINT_TO_POINTER (TRUE));
2233         g_hash_table_insert (key_table, (char *) "ldsfld", GINT_TO_POINTER (TRUE));
2234         g_hash_table_insert (key_table, (char *) "ldsflda", GINT_TO_POINTER (TRUE));
2235         g_hash_table_insert (key_table, (char *) "ldstr", GINT_TO_POINTER (TRUE));
2236         g_hash_table_insert (key_table, (char *) "ldtoken", GINT_TO_POINTER (TRUE));
2237         g_hash_table_insert (key_table, (char *) "ldvirtftn", GINT_TO_POINTER (TRUE));
2238         g_hash_table_insert (key_table, (char *) "leave", GINT_TO_POINTER (TRUE));
2239         g_hash_table_insert (key_table, (char *) "leave.s", GINT_TO_POINTER (TRUE));
2240         g_hash_table_insert (key_table, (char *) "linkcheck", GINT_TO_POINTER (TRUE));
2241         g_hash_table_insert (key_table, (char *) "literal", GINT_TO_POINTER (TRUE));
2242         g_hash_table_insert (key_table, (char *) "localloc", GINT_TO_POINTER (TRUE));
2243         g_hash_table_insert (key_table, (char *) "lpstr", GINT_TO_POINTER (TRUE));
2244         g_hash_table_insert (key_table, (char *) "lpstruct", GINT_TO_POINTER (TRUE));
2245         g_hash_table_insert (key_table, (char *) "lptstr", GINT_TO_POINTER (TRUE));
2246         g_hash_table_insert (key_table, (char *) "lpvoid", GINT_TO_POINTER (TRUE));
2247         g_hash_table_insert (key_table, (char *) "lpwstr", GINT_TO_POINTER (TRUE));
2248         g_hash_table_insert (key_table, (char *) "managed", GINT_TO_POINTER (TRUE));
2249         g_hash_table_insert (key_table, (char *) "marshal", GINT_TO_POINTER (TRUE));
2250         g_hash_table_insert (key_table, (char *) "method", GINT_TO_POINTER (TRUE));
2251         g_hash_table_insert (key_table, (char *) "mkrefany", GINT_TO_POINTER (TRUE));
2252         g_hash_table_insert (key_table, (char *) "modopt", GINT_TO_POINTER (TRUE));
2253         g_hash_table_insert (key_table, (char *) "modreq", GINT_TO_POINTER (TRUE));
2254         g_hash_table_insert (key_table, (char *) "mul", GINT_TO_POINTER (TRUE));
2255         g_hash_table_insert (key_table, (char *) "mul.ovf", GINT_TO_POINTER (TRUE));
2256         g_hash_table_insert (key_table, (char *) "mul.ovf.un", GINT_TO_POINTER (TRUE));
2257         g_hash_table_insert (key_table, (char *) "native", GINT_TO_POINTER (TRUE));
2258         g_hash_table_insert (key_table, (char *) "neg", GINT_TO_POINTER (TRUE));
2259         g_hash_table_insert (key_table, (char *) "nested", GINT_TO_POINTER (TRUE));
2260         g_hash_table_insert (key_table, (char *) "newarr", GINT_TO_POINTER (TRUE));
2261         g_hash_table_insert (key_table, (char *) "newobj", GINT_TO_POINTER (TRUE));
2262         g_hash_table_insert (key_table, (char *) "newslot", GINT_TO_POINTER (TRUE));
2263         g_hash_table_insert (key_table, (char *) "noappdomain", GINT_TO_POINTER (TRUE));
2264         g_hash_table_insert (key_table, (char *) "noinlining", GINT_TO_POINTER (TRUE));
2265         g_hash_table_insert (key_table, (char *) "nomachine", GINT_TO_POINTER (TRUE));
2266         g_hash_table_insert (key_table, (char *) "nomangle", GINT_TO_POINTER (TRUE));
2267         g_hash_table_insert (key_table, (char *) "nometadata", GINT_TO_POINTER (TRUE));
2268         g_hash_table_insert (key_table, (char *) "noncasdemand", GINT_TO_POINTER (TRUE));
2269         g_hash_table_insert (key_table, (char *) "noncasinheritance", GINT_TO_POINTER (TRUE));
2270         g_hash_table_insert (key_table, (char *) "noncaslinkdemand", GINT_TO_POINTER (TRUE));
2271         g_hash_table_insert (key_table, (char *) "nop", GINT_TO_POINTER (TRUE));
2272         g_hash_table_insert (key_table, (char *) "noprocess", GINT_TO_POINTER (TRUE));
2273         g_hash_table_insert (key_table, (char *) "not", GINT_TO_POINTER (TRUE));
2274         g_hash_table_insert (key_table, (char *) "not_in_gc_heap", GINT_TO_POINTER (TRUE));
2275         g_hash_table_insert (key_table, (char *) "notremotable", GINT_TO_POINTER (TRUE));
2276         g_hash_table_insert (key_table, (char *) "notserialized", GINT_TO_POINTER (TRUE));
2277         g_hash_table_insert (key_table, (char *) "null", GINT_TO_POINTER (TRUE));
2278         g_hash_table_insert (key_table, (char *) "nullref", GINT_TO_POINTER (TRUE));
2279         g_hash_table_insert (key_table, (char *) "object", GINT_TO_POINTER (TRUE));
2280         g_hash_table_insert (key_table, (char *) "objectref", GINT_TO_POINTER (TRUE));
2281         g_hash_table_insert (key_table, (char *) "opt", GINT_TO_POINTER (TRUE));
2282         g_hash_table_insert (key_table, (char *) "optil", GINT_TO_POINTER (TRUE));
2283         g_hash_table_insert (key_table, (char *) "or", GINT_TO_POINTER (TRUE));
2284         g_hash_table_insert (key_table, (char *) "out", GINT_TO_POINTER (TRUE));
2285         g_hash_table_insert (key_table, (char *) "permitonly", GINT_TO_POINTER (TRUE));
2286         g_hash_table_insert (key_table, (char *) "pinned", GINT_TO_POINTER (TRUE));
2287         g_hash_table_insert (key_table, (char *) "pinvokeimpl", GINT_TO_POINTER (TRUE));
2288         g_hash_table_insert (key_table, (char *) "pop", GINT_TO_POINTER (TRUE));
2289         g_hash_table_insert (key_table, (char *) "prefix1", GINT_TO_POINTER (TRUE));
2290         g_hash_table_insert (key_table, (char *) "prefix2", GINT_TO_POINTER (TRUE));
2291         g_hash_table_insert (key_table, (char *) "prefix3", GINT_TO_POINTER (TRUE));
2292         g_hash_table_insert (key_table, (char *) "prefix4", GINT_TO_POINTER (TRUE));
2293         g_hash_table_insert (key_table, (char *) "prefix5", GINT_TO_POINTER (TRUE));
2294         g_hash_table_insert (key_table, (char *) "prefix6", GINT_TO_POINTER (TRUE));
2295         g_hash_table_insert (key_table, (char *) "prefix7", GINT_TO_POINTER (TRUE));
2296         g_hash_table_insert (key_table, (char *) "prefixref", GINT_TO_POINTER (TRUE));
2297         g_hash_table_insert (key_table, (char *) "prejitdeny", GINT_TO_POINTER (TRUE));
2298         g_hash_table_insert (key_table, (char *) "prejitgrant", GINT_TO_POINTER (TRUE));
2299         g_hash_table_insert (key_table, (char *) "preservesig", GINT_TO_POINTER (TRUE));
2300         g_hash_table_insert (key_table, (char *) "private", GINT_TO_POINTER (TRUE));
2301         g_hash_table_insert (key_table, (char *) "Compilercontrolled", GINT_TO_POINTER (TRUE));
2302         g_hash_table_insert (key_table, (char *) "protected", GINT_TO_POINTER (TRUE));
2303         g_hash_table_insert (key_table, (char *) "public", GINT_TO_POINTER (TRUE));
2304         g_hash_table_insert (key_table, (char *) "readonly", GINT_TO_POINTER (TRUE));
2305         g_hash_table_insert (key_table, (char *) "record", GINT_TO_POINTER (TRUE));
2306         g_hash_table_insert (key_table, (char *) "refany", GINT_TO_POINTER (TRUE));
2307         g_hash_table_insert (key_table, (char *) "refanytype", GINT_TO_POINTER (TRUE));
2308         g_hash_table_insert (key_table, (char *) "refanyval", GINT_TO_POINTER (TRUE));
2309         g_hash_table_insert (key_table, (char *) "rem", GINT_TO_POINTER (TRUE));
2310         g_hash_table_insert (key_table, (char *) "rem.un", GINT_TO_POINTER (TRUE));
2311         g_hash_table_insert (key_table, (char *) "reqmin", GINT_TO_POINTER (TRUE));
2312         g_hash_table_insert (key_table, (char *) "reqopt", GINT_TO_POINTER (TRUE));
2313         g_hash_table_insert (key_table, (char *) "reqrefuse", GINT_TO_POINTER (TRUE));
2314         g_hash_table_insert (key_table, (char *) "reqsecobj", GINT_TO_POINTER (TRUE));
2315         g_hash_table_insert (key_table, (char *) "request", GINT_TO_POINTER (TRUE));
2316         g_hash_table_insert (key_table, (char *) "ret", GINT_TO_POINTER (TRUE));
2317         g_hash_table_insert (key_table, (char *) "rethrow", GINT_TO_POINTER (TRUE));
2318         g_hash_table_insert (key_table, (char *) "retval", GINT_TO_POINTER (TRUE));
2319         g_hash_table_insert (key_table, (char *) "rtspecialname", GINT_TO_POINTER (TRUE));
2320         g_hash_table_insert (key_table, (char *) "runtime", GINT_TO_POINTER (TRUE));
2321         g_hash_table_insert (key_table, (char *) "safearray", GINT_TO_POINTER (TRUE));
2322         g_hash_table_insert (key_table, (char *) "sealed", GINT_TO_POINTER (TRUE));
2323         g_hash_table_insert (key_table, (char *) "sequential", GINT_TO_POINTER (TRUE));
2324         g_hash_table_insert (key_table, (char *) "serializable", GINT_TO_POINTER (TRUE));
2325         g_hash_table_insert (key_table, (char *) "shl", GINT_TO_POINTER (TRUE));
2326         g_hash_table_insert (key_table, (char *) "shr", GINT_TO_POINTER (TRUE));
2327         g_hash_table_insert (key_table, (char *) "shr.un", GINT_TO_POINTER (TRUE));
2328         g_hash_table_insert (key_table, (char *) "sizeof", GINT_TO_POINTER (TRUE));
2329         g_hash_table_insert (key_table, (char *) "special", GINT_TO_POINTER (TRUE));
2330         g_hash_table_insert (key_table, (char *) "specialname", GINT_TO_POINTER (TRUE));
2331         g_hash_table_insert (key_table, (char *) "starg", GINT_TO_POINTER (TRUE));
2332         g_hash_table_insert (key_table, (char *) "starg.s", GINT_TO_POINTER (TRUE));
2333         g_hash_table_insert (key_table, (char *) "static", GINT_TO_POINTER (TRUE));
2334         g_hash_table_insert (key_table, (char *) "stdcall", GINT_TO_POINTER (TRUE));
2335         g_hash_table_insert (key_table, (char *) "stdcall", GINT_TO_POINTER (TRUE));
2336         g_hash_table_insert (key_table, (char *) "stelem.i", GINT_TO_POINTER (TRUE));
2337         g_hash_table_insert (key_table, (char *) "stelem.i1", GINT_TO_POINTER (TRUE));
2338         g_hash_table_insert (key_table, (char *) "stelem.i2", GINT_TO_POINTER (TRUE));
2339         g_hash_table_insert (key_table, (char *) "stelem.i4", GINT_TO_POINTER (TRUE));
2340         g_hash_table_insert (key_table, (char *) "stelem.i8", GINT_TO_POINTER (TRUE));
2341         g_hash_table_insert (key_table, (char *) "stelem.r4", GINT_TO_POINTER (TRUE));
2342         g_hash_table_insert (key_table, (char *) "stelem.r8", GINT_TO_POINTER (TRUE));
2343         g_hash_table_insert (key_table, (char *) "stelem.ref", GINT_TO_POINTER (TRUE));
2344         g_hash_table_insert (key_table, (char *) "stfld", GINT_TO_POINTER (TRUE));
2345         g_hash_table_insert (key_table, (char *) "stind.i", GINT_TO_POINTER (TRUE));
2346         g_hash_table_insert (key_table, (char *) "stind.i1", GINT_TO_POINTER (TRUE));
2347         g_hash_table_insert (key_table, (char *) "stind.i2", GINT_TO_POINTER (TRUE));
2348         g_hash_table_insert (key_table, (char *) "stind.i4", GINT_TO_POINTER (TRUE));
2349         g_hash_table_insert (key_table, (char *) "stind.i8", GINT_TO_POINTER (TRUE));
2350         g_hash_table_insert (key_table, (char *) "stind.r4", GINT_TO_POINTER (TRUE));
2351         g_hash_table_insert (key_table, (char *) "stind.r8", GINT_TO_POINTER (TRUE));
2352         g_hash_table_insert (key_table, (char *) "to", GINT_TO_POINTER (TRUE));
2353         g_hash_table_insert (key_table, (char *) "value", GINT_TO_POINTER (TRUE));
2354 }
2355
2356 guint32
2357 method_dor_to_token (guint32 idx) {
2358         switch (idx & MONO_METHODDEFORREF_MASK) {
2359         case MONO_METHODDEFORREF_METHODDEF:
2360                 return MONO_TOKEN_METHOD_DEF | (idx >> MONO_METHODDEFORREF_BITS);
2361         case MONO_METHODDEFORREF_METHODREF:
2362                 return MONO_TOKEN_MEMBER_REF | (idx >> MONO_METHODDEFORREF_BITS);
2363         }
2364         return -1;
2365 }
2366
2367 char *
2368 get_method_override (MonoImage *m, guint32 token)
2369 {
2370         MonoTableInfo *t = &m->tables [MONO_TABLE_METHODIMPL];
2371         int i;
2372
2373         for (i = 1; i <= t->rows; i++){
2374                 guint32 cols [MONO_METHODIMPL_SIZE];
2375                 guint32 decl, impl;
2376
2377                 mono_metadata_decode_row (t, i - 1, cols, MONO_METHODIMPL_SIZE);
2378
2379                 impl = method_dor_to_token (cols [MONO_METHODIMPL_BODY]);
2380                 decl = method_dor_to_token (cols [MONO_METHODIMPL_DECLARATION]);
2381
2382                 if (token == impl)
2383                         return get_method (m, decl);
2384         }
2385
2386         return NULL;
2387 }