(ves_icall_System_Enum_ToObject): and likewise for s1 > s2
[mono.git] / mono / metadata / icall.c
1 /*
2  * icall.c:
3  *
4  * Authors:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <stdarg.h>
13 #include <string.h>
14 #include <sys/time.h>
15 #include <unistd.h>
16
17 #include <mono/metadata/object.h>
18 #include <mono/metadata/threads.h>
19 #include <mono/metadata/reflection.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/tabledefs.h>
22 #include <mono/metadata/exception.h>
23 #include <mono/metadata/file-io.h>
24 #include <mono/metadata/socket-io.h>
25 #include <mono/metadata/mono-endian.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/unicode.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/io-layer/io-layer.h>
30 #include "decimal.h"
31
32 static MonoObject *
33 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
34 {
35         MonoClass *ac, *ic;
36         MonoArray *ao, *io;
37         gint32 i, pos, *ind, esize;
38         gpointer *ea;
39
40         io = (MonoArray *)idxs;
41         ic = (MonoClass *)io->obj.vtable->klass;
42         
43         ao = (MonoArray *)this;
44         ac = (MonoClass *)ao->obj.vtable->klass;
45
46         g_assert (ic->rank == 1);
47         g_assert (io->bounds [0].length == ac->rank);
48
49         ind = (guint32 *)io->vector;
50
51         pos = ind [0] - ao->bounds [0].lower_bound;
52         for (i = 1; i < ac->rank; i++)
53                 pos = pos*ao->bounds [i].length + ind [i] - 
54                         ao->bounds [i].lower_bound;
55
56         esize = mono_array_element_size (ac);
57         ea = (gpointer*)((char*)ao->vector + (pos * esize));
58
59         if (ac->element_class->valuetype)
60                 return mono_value_box (this->vtable->domain, ac->element_class, ea);
61         else {
62                 return *ea;
63         }
64 }
65
66 static void 
67 ves_icall_System_Array_SetValue (MonoObject *this, MonoObject *value,
68                                  MonoObject *idxs)
69 {
70         MonoArray *ao, *io, *vo;
71         MonoClass *ac, *ic, *vc;
72         gint32 i, pos, *ind, esize;
73         gpointer *ea;
74
75         vo = (MonoArray *)value;
76         vc = (MonoClass *)vo->obj.vtable->klass;
77
78         io = (MonoArray *)idxs;
79         ic = (MonoClass *)io->obj.vtable->klass;
80         
81         ao = (MonoArray *)this;
82         ac = (MonoClass *)ao->obj.vtable->klass;
83
84         g_assert (ic->rank == 1);
85         g_assert (io->bounds [0].length == ac->rank);
86         if (!mono_object_isinst (value, ac->element_class)) {
87                 g_error ("Array not compatible: %s <= %s", ac->element_class->name, vc->name);
88         }
89
90         ind = (guint32 *)io->vector;
91
92         pos = ind [0] - ao->bounds [0].lower_bound;
93         for (i = 1; i < ac->rank; i++)
94                 pos = pos*ao->bounds [i].length + ind [i] - 
95                         ao->bounds [i].lower_bound;
96
97         esize = mono_array_element_size (ac);
98         ea = (gpointer*)((char*)ao->vector + (pos * esize));
99
100         if (ac->element_class->valuetype) {
101                 g_assert (vc->valuetype);
102
103                 memcpy (ea, (char *)vo + sizeof (MonoObject), esize);
104         } else
105                 *ea = (gpointer)vo;
106
107 }
108
109 static void
110 ves_icall_System_Array_CreateInstance ()
111 {
112         g_warning ("not implemented");
113         g_assert_not_reached ();
114 }
115
116
117 static gint32 
118 ves_icall_System_Array_GetRank (MonoObject *this)
119 {
120         return this->vtable->klass->rank;
121 }
122
123 static gint32
124 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
125 {
126         return this->bounds [dimension].length;
127 }
128
129 static gint32
130 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
131 {
132         return this->bounds [dimension].lower_bound;
133 }
134
135 static void
136 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
137 {
138         int element_size = mono_array_element_size (source->obj.vtable->klass);
139         void * dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
140         void * source_addr = mono_array_addr_with_size (source, element_size, dest_idx);
141
142         memcpy (dest_addr, source_addr, element_size * length);
143 }
144
145 static void
146 ves_icall_InitializeArray (MonoArray *array, MonoClassField *field_handle)
147 {
148         MonoClass *klass = array->obj.vtable->klass;
149         guint32 size = mono_array_element_size (klass);
150         int i;
151
152         for (i = 0; i < klass->rank; ++i) 
153                 size *= array->bounds [i].length;
154
155         memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
156
157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
158 #define SWAP(n) {\
159         gint i; \
160         guint ## n tmp; \
161         guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
162 \
163         for (i = 0; i < size; i += n/8, data++) { \
164                 tmp = read ## n (data); \
165                 *data = tmp; \
166         } \
167 }
168
169         printf ("Initialize array with elements of %s type\n", klass->element_class->name);
170
171         switch (klass->element_class->byval_arg.type) {
172         case MONO_TYPE_CHAR:
173         case MONO_TYPE_I2:
174         case MONO_TYPE_U2:
175                 SWAP (16);
176                 break;
177         case MONO_TYPE_I4:
178         case MONO_TYPE_U4:
179                 SWAP (32);
180                 break;
181         case MONO_TYPE_I8:
182         case MONO_TYPE_U8:
183                 SWAP (64);
184                 break;
185         }
186                  
187 #endif
188 }
189
190 static MonoObject *
191 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
192 {
193         return mono_object_clone (this);
194 }
195
196 static void
197 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
198 {
199         mtype->type = &obj->vtable->klass->byval_arg;
200         g_assert (mtype->type->type);
201 }
202
203 static gint32
204 ves_icall_get_data_chunk (MonoReflectionAssemblyBuilder *assb, gint32 type, MonoArray *buf)
205 {
206         int count;
207
208         if (type == 0) { /* get the header */
209                 count = mono_image_get_header (assb, (char*)buf->vector, buf->bounds->length);
210                 if (count != -1)
211                         return count;
212         } else {
213                 MonoDynamicAssembly *ass = assb->dynamic_assembly;
214                 char *p = mono_array_addr (buf, char, 0);
215                 count = ass->code.index + ass->meta_size;
216                 if (count > buf->bounds->length)
217                         return 0;
218                 memcpy (p, ass->code.data, ass->code.index);
219                 memcpy (p + ass->code.index, ass->assembly.image->raw_metadata, ass->meta_size);
220                 return count;
221         }
222         
223         return 0;
224 }
225
226 static MonoReflectionType*
227 ves_icall_type_from_name (MonoString *name)
228 {
229         MonoDomain *domain = mono_domain_get (); 
230         MonoClass *klass;
231         MonoImage *image;
232         MonoTypeNameParse info;
233         gchar *str;
234         
235         str = mono_string_to_utf8 (name);
236         /*g_print ("requested type %s\n", str);*/
237         if (!mono_reflection_parse_type (str, &info)) {
238                 g_free (str);
239                 return NULL;
240         }
241
242         if (info.assembly) {
243                 image = mono_image_loaded (info.assembly);
244                 /* do we need to load if it's not already loaded? */
245                 if (!image) {
246                         g_free (str);
247                         return NULL;
248                 }
249         } else
250                 image = mono_defaults.corlib;
251         if (info.nest_name) {
252                 klass = mono_class_from_name (image, info.nest_name_space, info.nest_name);
253                 if (klass) {
254                         GList *nested;
255                         mono_class_init (klass);
256                         nested = klass->nested_classes;
257                         while (nested) {
258                                 klass = nested->data;
259                                 if (strcmp (klass->name, info.nest_name) == 0 &&
260                                                 strcmp (klass->name_space, info.nest_name_space) == 0)
261                                         break;
262                                 klass = NULL;
263                         }
264                 }
265         } else {
266                 klass = mono_class_from_name (image, info.name_space, info.name);
267         }
268         g_free (str);
269         if (!klass)
270                 return NULL;
271         mono_class_init (klass);
272         if (info.rank)
273                 klass = mono_array_class_get (klass, info.rank);
274         
275         if (info.isbyref || info.ispointer) /* hack */
276                 return mono_type_get_object (domain, &klass->this_arg);
277         else
278                 return mono_type_get_object (domain, &klass->byval_arg);
279 }
280
281 static MonoReflectionType*
282 ves_icall_type_from_handle (MonoType *handle)
283 {
284         MonoDomain *domain = mono_domain_get (); 
285
286         mono_class_init (handle->data.klass);
287         return mono_type_get_object (domain, handle);
288 }
289
290 static guint32
291 ves_icall_type_Equals (MonoReflectionType *type, MonoReflectionType *c)
292 {
293         if (type->type && c->type)
294                 return mono_metadata_type_equal (type->type, c->type);
295         g_print ("type equals\n");
296         return 0;
297 }
298
299 static guint32
300 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c)
301 {
302         MonoDomain *domain; 
303         MonoClass *klass;
304         MonoClass *klassc;
305
306         g_assert (type != NULL);
307         
308         domain = ((MonoObject *)type)->vtable->domain;
309
310         if (!c) /* FIXME: dont know what do do here */
311                 return 0;
312         
313         while (!type->type) { /* FIXME: hack for TypeBuilder */
314                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)type;
315                 type = tb->parent;
316         }
317
318         while (!c->type) { /* FIXME: hack for TypeBuilder */
319                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)c;
320                 c = tb->parent;
321         }
322
323         klass = mono_class_from_mono_type (type->type);
324         klassc = mono_class_from_mono_type (c->type);
325
326         /* cut&paste from mono_object_isinst (): keep in sync */
327         if (klassc->flags & TYPE_ATTRIBUTE_INTERFACE) {
328                 MonoVTable *klass_vt = mono_class_vtable (domain, klass);
329                 if ((klassc->interface_id <= klass->max_interface_id) &&
330                     klass_vt->interface_offsets [klassc->interface_id])
331                         return 1;
332         } else {
333                 if ((klass->baseval - klassc->baseval) <= klassc->diffval)
334                         return 1;
335         }
336         return 0;
337 }
338
339 static guint32
340 ves_icall_get_attributes (MonoReflectionType *type)
341 {
342         MonoClass *klass = mono_class_from_mono_type (type->type);
343
344         return klass->flags;
345 }
346
347 static void
348 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
349 {
350         MonoDomain *domain = mono_domain_get (); 
351
352         info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
353         info->ret = mono_type_get_object (domain, method->signature->ret);
354         info->name = mono_string_new (domain, method->name);
355         info->attrs = method->flags;
356         info->implattrs = method->iflags;
357 }
358
359 static MonoArray*
360 ves_icall_get_parameter_info (MonoMethod *method)
361 {
362         MonoDomain *domain = mono_domain_get (); 
363         MonoArray *res;
364         static MonoClass *System_Reflection_ParameterInfo;
365         MonoReflectionParameter** args;
366         int i;
367
368         args = mono_param_get_objects (domain, method);
369         if (!System_Reflection_ParameterInfo)
370                 System_Reflection_ParameterInfo = mono_class_from_name (
371                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
372         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
373         for (i = 0; i < method->signature->param_count; ++i) {
374                 mono_array_set (res, gpointer, i, args [i]);
375         }
376         return res;
377 }
378
379 static void
380 ves_icall_get_field_info (MonoReflectionField *field, MonoFieldInfo *info)
381 {
382         MonoDomain *domain = mono_domain_get (); 
383
384         info->parent = mono_type_get_object (domain, &field->klass->byval_arg);
385         info->type = mono_type_get_object (domain, field->field->type);
386         info->name = mono_string_new (domain, field->field->name);
387         info->attrs = field->field->type->attrs;
388 }
389
390 static void
391 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info)
392 {
393         MonoDomain *domain = mono_domain_get (); 
394
395         info->parent = mono_type_get_object (domain, &property->klass->byval_arg);
396         info->name = mono_string_new (domain, property->property->name);
397         info->attrs = property->property->attrs;
398         info->get = property->property->get ? mono_method_get_object (domain, property->property->get): NULL;
399         info->set = property->property->set ? mono_method_get_object (domain, property->property->set): NULL;
400         /* 
401          * There may be other methods defined for properties, though, it seems they are not exposed 
402          * in the reflection API 
403          */
404 }
405
406 static void
407 ves_icall_get_type_info (MonoType *type, MonoTypeInfo *info)
408 {
409         MonoDomain *domain = mono_domain_get (); 
410         MonoClass *class = mono_class_from_mono_type (type);
411         MonoClass *parent;
412         MonoArray *intf;
413         int ninterf, i;
414         
415         info->parent = class->parent ? mono_type_get_object (domain, &class->parent->byval_arg): NULL;
416         info->name = mono_string_new (domain, class->name);
417         info->name_space = mono_string_new (domain, class->name_space);
418         info->attrs = class->flags;
419         info->rank = class->rank;
420         info->assembly = NULL; /* FIXME */
421         if (class->enumtype)
422                 info->etype = mono_type_get_object (domain, class->enum_basetype);
423         else if (class->element_class)
424                 info->etype = mono_type_get_object (domain, &class->element_class->byval_arg);
425         else
426                 info->etype = NULL;
427
428         ninterf = 0;
429         for (parent = class; parent; parent = parent->parent) {
430                 ninterf += parent->interface_count;
431         }
432         intf = mono_array_new (domain, mono_defaults.monotype_class, ninterf);
433         ninterf = 0;
434         for (parent = class; parent; parent = parent->parent) {
435                 for (i = 0; i < parent->interface_count; ++i) {
436                         mono_array_set (intf, gpointer, ninterf, mono_type_get_object (domain, &parent->interfaces [i]->byval_arg));
437                         ++ninterf;
438                 }
439         }
440         info->interfaces = intf;
441 }
442
443 static MonoObject*
444 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params) {
445         MonoMethodSignature *sig = method->method->signature;
446
447         /*
448          * Do we need to copy the values so that the called method can't change them?
449          */
450
451         return NULL;
452 }
453
454 static MonoObject *
455 ves_icall_System_Enum_ToObject (MonoReflectionType *type, MonoObject *obj)
456 {
457         MonoDomain *domain = mono_domain_get (); 
458         MonoClass *enumc;
459         gint32 s1, s2;
460         MonoObject *res;
461         
462         MONO_CHECK_ARG_NULL (domain, type);
463         MONO_CHECK_ARG_NULL (domain, obj);
464
465         enumc = mono_class_from_mono_type (type->type);
466
467         MONO_CHECK_ARG (domain, obj, enumc->enumtype == TRUE);
468         MONO_CHECK_ARG (domain, obj, obj->vtable->klass->byval_arg.type >= MONO_TYPE_I1 &&  
469                         obj->vtable->klass->byval_arg.type <= MONO_TYPE_U8);
470
471         
472         s1 = mono_class_value_size (enumc, NULL);
473         s2 = mono_class_value_size (obj->vtable->klass, NULL);
474
475         res = mono_object_new (domain, enumc);
476
477 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
478         memcpy ((gpointer)res + sizeof (MonoObject), (gpointer)obj + sizeof (MonoObject), MIN (s1, s2));
479 #else
480         memcpy ((gpointer)res + sizeof (MonoObject) + (s1 > s2 ? s1 - s2 : 0),
481                 (gpointer)obj + sizeof (MonoObject) + (s2 > s1 ? s2 - s1 : 0),
482                 MIN (s1, s2));
483 #endif
484         return res;
485 }
486
487 static MonoObject *
488 ves_icall_System_Enum_get_value (MonoObject *this)
489 {
490         MonoDomain *domain = mono_domain_get (); 
491         MonoObject *res;
492         MonoClass *enumc;
493         gpointer dst;
494         gpointer src;
495         int size;
496
497         if (!this)
498                 return NULL;
499
500         g_assert (this->vtable->klass->enumtype);
501         
502         enumc = mono_class_from_mono_type (this->vtable->klass->enum_basetype);
503         res = mono_object_new (domain, enumc);
504         dst = (gpointer)res + sizeof (MonoObject);
505         src = (gpointer)this + sizeof (MonoObject);
506         size = mono_class_value_size (enumc, NULL);
507
508         memcpy (dst, src, size);
509
510         return res;
511 }
512
513 static void
514 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
515 {
516         MonoDomain *domain = mono_domain_get (); 
517         MonoClass *enumc = mono_class_from_mono_type (type->type);
518         guint i, j, nvalues, crow;
519         MonoClassField *field;
520         
521         info->utype = mono_type_get_object (domain, enumc->enum_basetype);
522         nvalues = enumc->field.count - 1;
523         info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
524         info->values = mono_array_new (domain, mono_class_from_mono_type (enumc->enum_basetype), nvalues);
525         
526         for (i = 0, j = 0; i < enumc->field.count; ++i) {
527                 field = &enumc->fields [i];
528                 if (strcmp ("value__", field->name) == 0)
529                         continue;
530                 mono_array_set (info->names, gpointer, j, mono_string_new (domain, field->name));
531                 if (!field->data) {
532                         crow = mono_metadata_get_constant_index (enumc->image, MONO_TOKEN_FIELD_DEF | (i+enumc->field.first+1));
533                         crow = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_VALUE);
534                         /* 1 is the length of the blob */
535                         field->data = 1 + mono_metadata_blob_heap (enumc->image, crow);
536                 }
537                 switch (enumc->enum_basetype->type) {
538                 case MONO_TYPE_U1:
539                 case MONO_TYPE_I1:
540                         mono_array_set (info->values, gchar, j, *field->data);
541                         break;
542                 case MONO_TYPE_CHAR:
543                 case MONO_TYPE_U2:
544                 case MONO_TYPE_I2:
545                         mono_array_set (info->values, gint16, j, read16 (field->data));
546                         break;
547                 case MONO_TYPE_U4:
548                 case MONO_TYPE_I4:
549                         mono_array_set (info->values, gint32, j, read32 (field->data));
550                         break;
551                 case MONO_TYPE_U8:
552                 case MONO_TYPE_I8:
553                         mono_array_set (info->values, gint64, j, read64 (field->data));
554                         break;
555                 default:
556                         g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
557                 }
558                 ++j;
559         }
560 }
561
562 static MonoMethod*
563 search_method (MonoReflectionType *type, char *name, guint32 flags, MonoArray *args)
564 {
565         MonoClass *klass;
566         MonoMethod *m;
567         MonoReflectionType *paramt;
568         int i, j;
569
570         klass = mono_class_from_mono_type (type->type);
571         while (klass) {
572                 for (i = 0; i < klass->method.count; ++i) {
573                         m = klass->methods [i];
574                         if (!((m->flags & flags) == flags))
575                                 continue;
576                         if (strcmp(m->name, name))
577                                 continue;
578                         if (m->signature->param_count != mono_array_length (args))
579                                 continue;
580                         for (j = 0; j < m->signature->param_count; ++j) {
581                                 paramt = mono_array_get (args, MonoReflectionType*, j);
582                                 if (!mono_metadata_type_equal (paramt->type, m->signature->params [j]))
583                                         break;
584                         }
585                         if (j == m->signature->param_count)
586                                 return m;
587                 }
588                 klass = klass->parent;
589         }
590         g_print ("Method %s::%s (%d) not found\n", klass->name, name, mono_array_length (args));
591         return NULL;
592 }
593
594 static MonoReflectionMethod*
595 ves_icall_get_constructor (MonoReflectionType *type, MonoArray *args)
596 {
597         MonoDomain *domain = mono_domain_get (); 
598         MonoMethod *m;
599
600         m = search_method (type, ".ctor", METHOD_ATTRIBUTE_RT_SPECIAL_NAME, args);
601         if (m)
602                 return mono_method_get_object (domain, m);
603         return NULL;
604 }
605
606 static MonoReflectionMethod*
607 ves_icall_get_method (MonoReflectionType *type, MonoString *name, MonoArray *args)
608 {
609         MonoDomain *domain = mono_domain_get (); 
610         MonoMethod *m;
611         char *n = mono_string_to_utf8 (name);
612
613         m = search_method (type, n, 0, args);
614         g_free (n);
615         if (m)
616                 return mono_method_get_object (domain, m);
617         return NULL;
618 }
619
620 static MonoProperty*
621 search_property (MonoClass *klass, char* name, MonoArray *args) {
622         int i;
623         MonoProperty *p;
624
625         /* FIXME: handle args */
626         for (i = 0; i < klass->property.count; ++i) {
627                 p = &klass->properties [i];
628                 if (strcmp (p->name, name) == 0)
629                         return p;
630         }
631         return NULL;
632 }
633
634 static MonoReflectionProperty*
635 ves_icall_get_property (MonoReflectionType *type, MonoString *name, MonoArray *args)
636 {
637         MonoDomain *domain = mono_domain_get (); 
638         MonoProperty *p;
639         MonoClass *class = mono_class_from_mono_type (type->type);
640         char *n = mono_string_to_utf8 (name);
641
642         p = search_property (class, n, args);
643         g_free (n);
644         if (p)
645                 return mono_property_get_object (domain, class, p);
646         return NULL;
647 }
648
649 enum {
650         BFLAGS_IgnoreCase = 1,
651         BFLAGS_DeclaredOnly = 2,
652         BFLAGS_Instance = 4,
653         BFLAGS_Static = 8,
654         BFLAGS_Public = 0x10,
655         BFLAGS_NonPublic = 0x20,
656         BFLAGS_InvokeMethod = 0x100,
657         BFLAGS_CreateInstance = 0x200,
658         BFLAGS_GetField = 0x400,
659         BFLAGS_SetField = 0x800,
660         BFLAGS_GetProperty = 0x1000,
661         BFLAGS_SetProperty = 0x2000,
662         BFLAGS_ExactBinding = 0x10000,
663         BFLAGS_SuppressChangeType = 0x20000,
664         BFLAGS_OptionalParamBinding = 0x40000
665 };
666
667
668 /*
669  * Note: the filter is applied from within corlib.
670  */
671 static MonoArray*
672 ves_icall_type_find_members (MonoReflectionType *type, guint32 membertypes, guint32 bflags)
673 {
674         MonoDomain *domain; 
675         GSList *l = NULL, *tmp;
676         static MonoClass *System_Reflection_MemberInfo;
677         MonoClass *startklass, *klass;
678         MonoArray *res;
679         MonoMethod *method;
680         MonoObject *member;
681         int i, is_ctor, len, match;
682
683         domain = ((MonoObject *)type)->vtable->domain;
684         klass = startklass = mono_class_from_mono_type (type->type);
685
686         /* FIXME: check the bindingflags */
687 handle_parent:  
688         if (membertypes & (1|8)) { /* constructors and methods */
689                 for (i = 0; i < klass->method.count; ++i) {
690                         match = 0;
691                         method = klass->methods [i];
692                         if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
693                                 if (bflags & BFLAGS_Public)
694                                         match++;
695                         } else {
696                                 if (bflags & BFLAGS_NonPublic)
697                                         match++;
698                         }
699                         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
700                                 if (bflags & BFLAGS_Static)
701                                         match++;
702                         } else {
703                                 if (bflags & BFLAGS_Instance)
704                                         match++;
705                         }
706
707                         if (!match)
708                                 continue;
709                         member = (MonoObject*)mono_method_get_object (domain, method);
710                         
711                         is_ctor = strcmp (method->name, ".ctor") == 0 ||
712                                         strcmp (method->name, ".cctor") == 0;
713                         if (is_ctor && (membertypes & 1)) {
714                                 l = g_slist_prepend (l, member);
715                                 continue;
716                         }
717                         if (!is_ctor && (membertypes & 8)) {
718                                 l = g_slist_prepend (l, member);
719                         }
720                 }
721         }
722         if (membertypes & 4) { /* fields */
723                 MonoClassField *field;
724                 for (i = 0; i < klass->field.count; ++i) {
725                         match = 0;
726                         field = &klass->fields [i];
727                         if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
728                                 if (bflags & BFLAGS_Public)
729                                         match++;
730                         } else {
731                                 if (bflags & BFLAGS_NonPublic)
732                                         match++;
733                         }
734                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
735                                 if (bflags & BFLAGS_Static)
736                                         match++;
737                         } else {
738                                 if (bflags & BFLAGS_Instance)
739                                         match++;
740                         }
741
742                         if (!match)
743                                 continue;
744                         member = (MonoObject*)mono_field_get_object (domain, klass, field);
745                         l = g_slist_prepend (l, member);
746                 }
747         }
748         if (membertypes & 16) { /* properties */
749                 MonoProperty *prop;
750                 for (i = 0; i < klass->property.count; ++i) {
751                         match = 0;
752                         prop = &klass->properties [i];
753                         /* FIXME: handle bflags */
754                         l = g_slist_prepend (l, mono_property_get_object (domain, klass, prop));
755                 }
756         }
757         if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
758                 goto handle_parent;
759         len = g_slist_length (l);
760         if (!System_Reflection_MemberInfo)
761                 System_Reflection_MemberInfo = mono_class_from_name (
762                         mono_defaults.corlib, "System.Reflection", "MemberInfo");
763         res = mono_array_new (domain, System_Reflection_MemberInfo, len);
764         i = 0;
765         tmp = l;
766         for (; tmp; tmp = tmp->next, ++i)
767                 mono_array_set (res, gpointer, i, tmp->data);
768         g_slist_free (l);
769         return res;
770 }
771
772 static gpointer
773 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr)
774 {
775         return (gpointer)(*(int *)ptr);
776 }
777
778 static MonoString*
779 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
780 {
781         MonoDomain *domain = mono_domain_get (); 
782
783         return mono_string_new (domain, (char *)ptr);
784 }
785
786 static guint32 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error(void)
787 {
788         return(GetLastError());
789 }
790
791 static MonoReflectionType*
792 ves_icall_System_Reflection_Assembly_GetType (MonoReflectionAssembly *assembly, MonoString *type, MonoBoolean throwOnError, MonoBoolean ignoreCase)
793 {
794         MonoDomain *domain = mono_domain_get (); 
795         /* FIXME : use ignoreCase */
796         gchar *name, *namespace, *str;
797         char *byref, *isarray, *ispointer;
798         guint rank;
799         MonoClass *klass;
800
801         str = namespace = mono_string_to_utf8 (type);
802         /*g_print ("requested type %s in %s\n", str, assembly->assembly->name);*/
803
804         name = strrchr (str, '.');
805         byref = strrchr (str, '&');
806         ispointer = strrchr (str, '*');
807         if (byref)
808                 *byref = 0;
809         if (ispointer)
810                 *ispointer = 0;
811         isarray = strrchr (str, '[');
812         if (isarray) {
813                 rank = 1;
814                 *isarray = 0;
815                 while (*isarray) {
816                         if (*isarray == ',')
817                                 rank++;
818                         if (*isarray == ']')
819                                 break;
820                         ++isarray;
821                 }
822         }
823
824         if (name) {
825                 *name = 0;
826                 ++name;
827         } else {
828                 namespace = "";
829                 name = str;
830         }
831
832         klass = mono_class_from_name (assembly->assembly->image, namespace, name);
833         g_free (str);
834         if (!klass) {
835                 if (throwOnError)
836                         mono_raise_exception (mono_get_exception_type_load ());
837                 return NULL;
838         }
839         if (!klass->inited)
840                 mono_class_init (klass);
841
842         if (isarray) {
843                 klass = mono_array_class_get (klass, rank);
844                 mono_class_init (klass);
845                 /*g_print ("got array class %s [%d] (0x%x)\n", klass->element_class->name, klass->rank, klass->this_arg.type);*/
846         }
847
848         if (byref || ispointer)
849                 return mono_type_get_object (domain, &klass->this_arg);
850         else
851                 return mono_type_get_object (domain, &klass->byval_arg);
852 }
853
854 static MonoString *
855 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly)
856 {
857         MonoDomain *domain = mono_domain_get (); 
858         MonoString *res;
859         char *name = g_strconcat (
860                 "file://", assembly->assembly->image->name, NULL);
861         
862         res = mono_string_new (domain, name);
863         g_free (name);
864         return res;
865 }
866
867 static MonoString *
868 ves_icall_System_MonoType_assQualifiedName (MonoReflectionType *object)
869 {
870         MonoDomain *domain = mono_domain_get (); 
871         /* FIXME : real rules are more complicated (internal classes,
872           reference types, array types, etc. */
873         MonoString *res;
874         gchar *fullname;
875         MonoClass *klass;
876         char *append = NULL;
877
878         switch (object->type->type) {
879         case MONO_TYPE_SZARRAY:
880                 klass = object->type->data.type->data.klass;
881                 append = "[]";
882                 break;
883         default:
884                 klass = object->type->data.klass;
885                 break;
886         }
887
888         fullname = g_strconcat (klass->name_space, ".",
889                                    klass->name, ",",
890                                    klass->image->assembly_name, append, NULL);
891         res = mono_string_new (domain, fullname);
892         g_free (fullname);
893
894         return res;
895 }
896
897 static MonoString *
898 ves_icall_System_PAL_GetCurrentDirectory (MonoObject *object)
899 {
900         MonoDomain *domain = mono_domain_get (); 
901         MonoString *res;
902         gchar *path = g_get_current_dir ();
903         res = mono_string_new (domain, path);
904         g_free (path);
905         return res;
906 }
907
908 /*
909  * Magic number to convert a time which is relative to
910  * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
911  */
912 #define EPOCH_ADJUST    ((gint64)62135596800L)
913
914 static gint64
915 ves_icall_System_DateTime_GetNow ()
916 {
917         struct timeval tv;
918         gint64 res;
919
920         if (gettimeofday (&tv, NULL) == 0) {
921                 res = (((gint64)tv.tv_sec + EPOCH_ADJUST)* 1000000 + tv.tv_usec)*10;
922                 return res;
923         }
924
925         /* fixme: raise exception */
926         return 0;
927 }
928
929 static gpointer icall_map [] = {
930         /*
931          * System.Array
932          */
933         "System.Array::GetValue",         ves_icall_System_Array_GetValue,
934         "System.Array::SetValue",         ves_icall_System_Array_SetValue,
935         "System.Array::GetRank",          ves_icall_System_Array_GetRank,
936         "System.Array::GetLength",        ves_icall_System_Array_GetLength,
937         "System.Array::GetLowerBound",    ves_icall_System_Array_GetLowerBound,
938         "System.Array::CreateInstance",   ves_icall_System_Array_CreateInstance,
939         "System.Array::FastCopy",         ves_icall_System_Array_FastCopy,
940         "System.Array::Clone",            mono_array_clone,
941
942         /*
943          * System.Object
944          */
945         "System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
946
947         /*
948          * System.String
949          */
950         "System.String::IsInterned", mono_string_is_interned,
951         "System.String::Intern", mono_string_intern,
952
953         /*
954          * System.AppDomain
955          */
956         "System.AppDomain::createDomain", ves_icall_System_AppDomain_createDomain,
957         "System.AppDomain::getCurDomain", ves_icall_System_AppDomain_getCurDomain,
958         "System.AppDomain::GetData", ves_icall_System_AppDomain_GetData,
959         "System.AppDomain::SetData", ves_icall_System_AppDomain_SetData,
960         "System.AppDomain::getSetup", ves_icall_System_AppDomain_getSetup,
961         "System.AppDomain::getFriendlyName", ves_icall_System_AppDomain_getFriendlyName,
962         "System.AppDomain::GetAssemblies", ves_icall_System_AppDomain_GetAssemblies,
963         "System.AppDomain::LoadAssembly", ves_icall_System_AppDomain_LoadAssembly,
964         "System.AppDomain::Unload", ves_icall_System_AppDomain_Unload,
965         "System.AppDomain::ExecuteAssembly", ves_icall_System_AppDomain_ExecuteAssembly,
966
967         /*
968          * System.AppDomainSetup
969          */
970         "System.AppDomainSetup::InitAppDomainSetup", ves_icall_System_AppDomainSetup_InitAppDomainSetup,
971
972         /*
973          * System.Decimal
974          */
975         "System.Decimal::decimal2UInt64", mono_decimal2UInt64,
976         "System.Decimal::decimal2Int64", mono_decimal2Int64,
977         "System.Decimal::double2decimal", mono_double2decimal, /* FIXME: wrong signature. */
978         "System.Decimal::decimalIncr", mono_decimalIncr,
979         "System.Decimal::decimalSetExponent", mono_decimalSetExponent,
980         "System.Decimal::decimal2double", mono_decimal2double,
981         "System.Decimal::decimalFloorAndTrunc", mono_decimalFloorAndTrunc,
982         "System.Decimal::decimalRound", mono_decimalRound,
983         "System.Decimal::decimalMult", mono_decimalMult,
984         "System.Decimal::decimalDiv", mono_decimalDiv,
985         "System.Decimal::decimalIntDiv", mono_decimalIntDiv,
986         "System.Decimal::decimalCompare", mono_decimalCompare,
987         "System.Decimal::string2decimal", mono_string2decimal,
988         "System.Decimal::decimal2string", mono_decimal2string,
989
990         /*
991          * ModuleBuilder
992          */
993         
994         /*
995          * AssemblyBuilder
996          */
997         "System.Reflection.Emit.AssemblyBuilder::getDataChunk", ves_icall_get_data_chunk,
998         "System.Reflection.Emit.AssemblyBuilder::getUSIndex", mono_image_insert_string,
999         "System.Reflection.Emit.AssemblyBuilder::getToken", mono_image_create_token,
1000
1001         /*
1002          * Reflection stuff.
1003          */
1004         "System.Reflection.MonoMethodInfo::get_method_info", ves_icall_get_method_info,
1005         "System.Reflection.MonoMethodInfo::get_parameter_info", ves_icall_get_parameter_info,
1006         "System.Reflection.MonoFieldInfo::get_field_info", ves_icall_get_field_info,
1007         "System.Reflection.MonoPropertyInfo::get_property_info", ves_icall_get_property_info,
1008         "System.Reflection.MonoMethod::InternalInvoke", ves_icall_InternalInvoke,
1009         
1010         /* System.Enum */
1011
1012         "System.MonoEnumInfo::get_enum_info", ves_icall_get_enum_info,
1013         "System.Enum::get_value", ves_icall_System_Enum_get_value,
1014         "System.Enum::ToObject", ves_icall_System_Enum_ToObject,
1015
1016         /*
1017          * TypeBuilder
1018          */
1019         
1020         /*
1021          * MethodBuilder
1022          */
1023         
1024         /*
1025          * System.Type
1026          */
1027         "System.Type::internal_from_name", ves_icall_type_from_name,
1028         "System.Type::internal_from_handle", ves_icall_type_from_handle,
1029         "System.Type::get_constructor", ves_icall_get_constructor,
1030         "System.Type::get_property", ves_icall_get_property,
1031         "System.Type::get_method", ves_icall_get_method,
1032         "System.MonoType::get_attributes", ves_icall_get_attributes,
1033         "System.Type::type_is_subtype_of", ves_icall_type_is_subtype_of,
1034         "System.Type::Equals", ves_icall_type_Equals,
1035         "System.Type::FindMembers", ves_icall_type_find_members,
1036
1037         /*
1038          * System.Runtime.CompilerServices.RuntimeHelpers
1039          */
1040         "System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray", ves_icall_InitializeArray,
1041         
1042         /*
1043          * System.Threading
1044          */
1045         "System.Threading.Thread::Thread_internal", ves_icall_System_Threading_Thread_Thread_internal,
1046         "System.Threading.Thread::Start_internal", ves_icall_System_Threading_Thread_Start_internal,
1047         "System.Threading.Thread::Sleep_internal", ves_icall_System_Threading_Thread_Sleep_internal,
1048         "System.Threading.Thread::CurrentThread_internal", ves_icall_System_Threading_Thread_CurrentThread_internal,
1049         "System.Threading.Thread::Join_internal", ves_icall_System_Threading_Thread_Join_internal,
1050         "System.Threading.Thread::SlotHash_lookup", ves_icall_System_Threading_Thread_SlotHash_lookup,
1051         "System.Threading.Thread::SlotHash_store", ves_icall_System_Threading_Thread_SlotHash_store,
1052         "System.Threading.Monitor::Monitor_exit", ves_icall_System_Threading_Monitor_Monitor_exit,
1053         "System.Threading.Monitor::Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_test_owner,
1054         "System.Threading.Monitor::Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised,
1055         "System.Threading.Monitor::Monitor_pulse", ves_icall_System_Threading_Monitor_Monitor_pulse,
1056         "System.Threading.Monitor::Monitor_pulse_all", ves_icall_System_Threading_Monitor_Monitor_pulse_all,
1057         "System.Threading.Monitor::Monitor_try_enter", ves_icall_System_Threading_Monitor_Monitor_try_enter,
1058         "System.Threading.Monitor::Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait,
1059         "System.Threading.Mutex::CreateMutex_internal", ves_icall_System_Threading_Mutex_CreateMutex_internal,
1060         "System.Threading.Mutex::ReleaseMutex_internal", ves_icall_System_Threading_Mutex_ReleaseMutex_internal,
1061         "System.Threading.NativeEventCalls::CreateEvent_internal", ves_icall_System_Threading_Events_CreateEvent_internal,
1062         "System.Threading.NativeEventCalls::SetEvent_internal",    ves_icall_System_Threading_Events_SetEvent_internal,
1063         "System.Threading.NativeEventCalls::ResetEvent_internal",  ves_icall_System_Threading_Events_ResetEvent_internal,
1064
1065         /*
1066          * System.Threading.WaitHandle
1067          */
1068         "System.Threading.WaitHandle::WaitAll_internal", ves_icall_System_Threading_WaitHandle_WaitAll_internal,
1069         "System.Threading.WaitHandle::WaitAny_internal", ves_icall_System_Threading_WaitHandle_WaitAny_internal,
1070         "System.Threading.WaitHandle::WaitOne_internal", ves_icall_System_Threading_WaitHandle_WaitOne_internal,
1071
1072         "System.Runtime.InteropServices.Marshal::ReadIntPtr", ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr,
1073         "System.Runtime.InteropServices.Marshal::PtrToStringAuto", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto,
1074         "System.Runtime.InteropServices.Marshal::GetLastWin32Error", ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error,
1075
1076         "System.Reflection.Assembly::GetType", ves_icall_System_Reflection_Assembly_GetType,
1077         "System.Reflection.Assembly::get_code_base", ves_icall_System_Reflection_Assembly_get_code_base,
1078
1079         /*
1080          * System.MonoType.
1081          */
1082         "System.MonoType::assQualifiedName", ves_icall_System_MonoType_assQualifiedName,
1083         "System.MonoType::type_from_obj", mono_type_type_from_obj,
1084         "System.MonoType::get_type_info", ves_icall_get_type_info,
1085
1086         "System.PAL.OpSys::GetCurrentDirectory", ves_icall_System_PAL_GetCurrentDirectory,
1087
1088         /*
1089          * System.PAL.OpSys I/O Services
1090          */
1091         "System.PAL.OpSys::GetStdHandle", ves_icall_System_PAL_OpSys_GetStdHandle,
1092         "System.PAL.OpSys::ReadFile", ves_icall_System_PAL_OpSys_ReadFile,
1093         "System.PAL.OpSys::WriteFile", ves_icall_System_PAL_OpSys_WriteFile,
1094         "System.PAL.OpSys::SetLengthFile", ves_icall_System_PAL_OpSys_SetLengthFile,
1095         "System.PAL.OpSys::OpenFile", ves_icall_System_PAL_OpSys_OpenFile,
1096         "System.PAL.OpSys::CloseFile", ves_icall_System_PAL_OpSys_CloseFile,
1097         "System.PAL.OpSys::SeekFile", ves_icall_System_PAL_OpSys_SeekFile,
1098         "System.PAL.OpSys::DeleteFile", ves_icall_System_PAL_OpSys_DeleteFile,
1099         "System.PAL.OpSys::ExistsFile", ves_icall_System_PAL_OpSys_ExistsFile,
1100         "System.PAL.OpSys::GetFileTime", ves_icall_System_PAL_OpSys_GetFileTime,
1101         "System.PAL.OpSys::SetFileTime", ves_icall_System_PAL_OpSys_SetFileTime,
1102
1103         /*
1104          * System.Net.Sockets I/O Services
1105          */
1106         "System.Net.Sockets.Socket::Socket_internal", ves_icall_System_Net_Sockets_Socket_Socket_internal,
1107         "System.Net.Sockets.Socket::Close_internal", ves_icall_System_Net_Sockets_Socket_Close_internal,
1108         "System.Net.Sockets.SocketException::WSAGetLastError_internal", ves_icall_System_Net_Sockets_SocketException_WSAGetLastError_internal,
1109         "System.Net.Sockets.Socket::Available_internal", ves_icall_System_Net_Sockets_Socket_Available_internal,
1110         "System.Net.Sockets.Socket::Blocking_internal", ves_icall_System_Net_Sockets_Socket_Blocking_internal,
1111         "System.Net.Sockets.Socket::Accept_internal", ves_icall_System_Net_Sockets_Socket_Accept_internal,
1112         "System.Net.Sockets.Socket::Listen_internal", ves_icall_System_Net_Sockets_Socket_Listen_internal,
1113         "System.Net.Sockets.Socket::LocalEndPoint_internal", ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal,
1114         "System.Net.Sockets.Socket::RemoteEndPoint_internal", ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal,
1115         "System.Net.Sockets.Socket::Bind_internal", ves_icall_System_Net_Sockets_Socket_Bind_internal,
1116         "System.Net.Sockets.Socket::Connect_internal", ves_icall_System_Net_Sockets_Socket_Connect_internal,
1117         "System.Net.Sockets.Socket::Receive_internal", ves_icall_System_Net_Sockets_Socket_Receive_internal,
1118         "System.Net.Sockets.Socket::RecvFrom_internal", ves_icall_System_Net_Sockets_Socket_RecvFrom_internal,
1119         "System.Net.Sockets.Socket::Send_internal", ves_icall_System_Net_Sockets_Socket_Send_internal,
1120         "System.Net.Sockets.Socket::SendTo_internal", ves_icall_System_Net_Sockets_Socket_SendTo_internal,
1121         "System.Net.Sockets.Socket::Select_internal", ves_icall_System_Net_Sockets_Socket_Select_internal,
1122         "System.Net.Sockets.Socket::Shutdown_internal", ves_icall_System_Net_Sockets_Socket_Shutdown_internal,
1123         "System.Net.Sockets.Socket::GetSocketOption_obj_internal", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal,
1124         "System.Net.Sockets.Socket::GetSocketOption_arr_internal", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal,
1125         "System.Net.Sockets.Socket::SetSocketOption_internal", ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal,
1126         "System.Net.Dns::GetHostByName_internal", ves_icall_System_Net_Dns_GetHostByName_internal,
1127         "System.Net.Dns::GetHostByAddr_internal", ves_icall_System_Net_Dns_GetHostByAddr_internal,
1128
1129         /*
1130          * System.Char
1131          */
1132         "System.Char::GetNumericValue", ves_icall_System_Char_GetNumericValue,
1133         "System.Char::GetUnicodeCategory", ves_icall_System_Char_GetUnicodeCategory,
1134         "System.Char::IsControl", ves_icall_System_Char_IsControl,
1135         "System.Char::IsDigit", ves_icall_System_Char_IsDigit,
1136         "System.Char::IsLetter", ves_icall_System_Char_IsLetter,
1137         "System.Char::IsLower", ves_icall_System_Char_IsLower,
1138         "System.Char::IsUpper", ves_icall_System_Char_IsUpper,
1139         "System.Char::IsNumber", ves_icall_System_Char_IsNumber,
1140         "System.Char::IsPunctuation", ves_icall_System_Char_IsPunctuation,
1141         "System.Char::IsSeparator", ves_icall_System_Char_IsSeparator,
1142         "System.Char::IsSurrogate", ves_icall_System_Char_IsSurrogate,
1143         "System.Char::IsSymbol", ves_icall_System_Char_IsSymbol,
1144         "System.Char::IsWhiteSpace", ves_icall_System_Char_IsWhiteSpace,
1145         "System.Char::ToLower", ves_icall_System_Char_ToLower,
1146         "System.Char::ToUpper", ves_icall_System_Char_ToUpper,
1147
1148         "System.Text.Encoding::IConvNewEncoder", ves_icall_iconv_new_encoder,
1149         "System.Text.Encoding::IConvNewDecoder", ves_icall_iconv_new_decoder,
1150         "System.Text.Encoding::IConvReset", ves_icall_iconv_reset,
1151         "System.Text.Encoding::IConvGetByteCount", ves_icall_iconv_get_byte_count,
1152         "System.Text.Encoding::IConvGetBytes", ves_icall_iconv_get_bytes,
1153         "System.Text.Encoding::IConvGetCharCount", ves_icall_iconv_get_char_count,
1154         "System.Text.Encoding::IConvGetChars", ves_icall_iconv_get_chars,
1155
1156         "System.DateTime::GetNow", ves_icall_System_DateTime_GetNow,
1157         /*
1158          * add other internal calls here
1159          */
1160         NULL, NULL
1161 };
1162
1163 void
1164 mono_init_icall ()
1165 {
1166         char *n;
1167         int i = 0;
1168
1169         while ((n = icall_map [i])) {
1170                 mono_add_internal_call (n, icall_map [i+1]);
1171                 i += 2;
1172         }
1173        
1174 }
1175
1176