#define CSIZE(x) (sizeof (x) / 4)
+/*
+ * keeps track of loaded assemblies
+ */
+static GHashTable *assemblies;
+
+/**
+ * g_concat_dir_and_file:
+ * @dir: directory name
+ * @file: filename.
+ *
+ * returns a new allocated string that is the concatenation of dir and file,
+ * takes care of the exact details for concatenating them.
+ */
static char *
-default_assembly_name_resolver (const char *name)
+g_concat_dir_and_file (const char *dir, const char *file)
{
- if (strcmp (name, "mscorlib") == 0)
- return g_strdup (MONO_ASSEMBLIES "/" CORLIB_NAME);
+ g_return_val_if_fail (dir != NULL, NULL);
+ g_return_val_if_fail (file != NULL, NULL);
- return g_strconcat (MONO_ASSEMBLIES "/", name, ".dll", NULL);
+ /*
+ * If the directory name doesn't have a / on the end, we need
+ * to add one so we get a proper path to the file
+ */
+ if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
+ return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
+ else
+ return g_strconcat (dir, file, NULL);
+}
+
+static char *
+default_assembly_name_resolver (const char *base_dir, const char *name)
+{
+ char *file, *path;
+
+ if ((strcmp (name, "mscorlib") == 0) ||
+ (strcmp (name, "mscorlib.dll") == 0) ||
+ (strcmp (name, "corlib.dll") == 0) ||
+ (strcmp (name, "corlib") == 0))
+ return g_concat_dir_and_file (MONO_ASSEMBLIES, CORLIB_NAME);
+
+ path = g_concat_dir_and_file (base_dir, name);
+ if (g_file_test (name, G_FILE_TEST_EXISTS))
+ return path;
+
+ file = path;
+ path = g_strconcat (file, ".dll", NULL);
+ g_free (file);
+ if (g_file_test (path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free (path);
+
+ path = g_concat_dir_and_file (MONO_ASSEMBLIES, name);
+ if (g_file_test (path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free (path);
+
+ file = g_strconcat (name, ".dll", NULL);
+ path = g_concat_dir_and_file (MONO_ASSEMBLIES, file);
+ g_free (file);
+
+ return path;
}
/**
MonoAssembly *ass;
MonoImage *image;
MonoTableInfo *t;
- MonoMetadata *m;
int i;
- const char *basename = strrchr (filename, '/');
+ char *fullname, *base_dir;
+ const char *base_name = strrchr (filename, G_DIR_SEPARATOR);
static MonoAssembly *corlib;
- if (basename == NULL)
- basename = filename;
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ if (assemblies == NULL)
+ assemblies = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if ((ass = g_hash_table_lookup (assemblies, filename)) != NULL){
+ ass->ref_count++;
+ return ass;
+ }
+
+ if (base_name == NULL)
+ base_name = filename;
else
- basename++;
+ base_name++;
- /*
- * Temporary hack until we have a complete corlib.dll
- */
- if (!strcmp (basename, CORLIB_NAME) && corlib != NULL)
- return corlib;
-
- g_return_val_if_fail (filename != NULL, NULL);
+ if (resolver == NULL)
+ resolver = default_assembly_name_resolver;
+
+ base_dir = g_path_get_dirname (fullname);
+
+ fullname = resolver (base_dir, filename);
+ image = mono_image_open (fullname, status);
- image = mono_image_open (filename, status);
if (!image){
if (status)
*status = MONO_IMAGE_ERROR_ERRNO;
+ g_free (fullname);
+ g_free (base_dir);
return NULL;
}
- if (resolver == NULL)
- resolver = default_assembly_name_resolver;
-
- m = &image->metadata;
- t = &m->tables [MONO_TABLE_ASSEMBLYREF];
+ t = &image->tables [MONO_TABLE_ASSEMBLYREF];
image->references = g_new0 (MonoAssembly *, t->rows + 1);
+ /*
+ * Create assembly struct, and enter it into the assembly cache
+ */
ass = g_new (MonoAssembly, 1);
+ ass->name = fullname;
ass->image = image;
+
+ g_hash_table_insert (assemblies, image->name, ass);
+ g_hash_table_insert (assemblies, ass->name, ass);
/*
* Load any assemblies this image references
guint32 cols [MONO_ASSEMBLYREF_SIZE];
mono_metadata_decode_row (t, i, cols, CSIZE (cols));
- name = mono_metadata_string_heap (m, cols [MONO_ASSEMBLYREF_NAME]);
+ name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME]);
/*
* Special case until we have a passable corlib:
* ie, references to mscorlib from corlib.dll are ignored
* and we do not load corlib twice.
*/
- if (strcmp (basename, CORLIB_NAME) == 0){
+ if (strcmp (base_name, CORLIB_NAME) == 0){
if (corlib == NULL)
corlib = ass;
continue;
}
- assembly_ref = (*resolver) (name);
+ assembly_ref = (*resolver) (base_dir, name);
image->references [i] = mono_assembly_open (assembly_ref, resolver, status);
+
if (image->references [i] == NULL){
int j;
if (status)
*status = MONO_IMAGE_MISSING_ASSEMBLYREF;
g_free (ass);
+ g_free (base_dir);
return NULL;
}
g_free (assembly_ref);
}
image->references [i] = NULL;
+ g_free (base_dir);
return ass;
}
g_return_if_fail (assembly != NULL);
+ if (--assembly->ref_count != 0)
+ return;
+
+ image = assembly->image;
for (i = 0; image->references [i] != NULL; i++)
- mono_image_close (assembly->image);
+ mono_image_close (image->references [i]->image);
g_free (image->references);
mono_image_close (assembly->image);
+
+ g_hash_table_remove (assemblies, assembly->name);
+
+ g_free (assembly->name);
g_free (assembly);
}
+/*
+ * Temporary hack until we get AppDomains
+ */
+GHashTable *
+mono_get_assemblies ()
+{
+ return assemblies;
+}