Tue Jun 4 16:06:19 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / mono-config.c
1 /*
2  * mono-config.c
3  *
4  * Runtime and assembly configuration file support routines.
5  *
6  * Author: Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  */
10 #include "config.h"
11 #include <glib.h>
12 #include <string.h>
13 #include "mono/metadata/loader.h"
14 #include "mono/metadata/mono-config.h"
15
16 static void start_element (GMarkupParseContext *context, 
17                            const gchar         *element_name,
18                            const gchar        **attribute_names,
19                            const gchar        **attribute_values,
20                            gpointer             user_data,
21                            GError             **error);
22
23 static void end_element   (GMarkupParseContext *context,
24                            const gchar         *element_name,
25                            gpointer             user_data,
26                            GError             **error);
27
28 static void parse_text    (GMarkupParseContext *context,
29                            const gchar         *text,
30                            gsize                text_len,
31                            gpointer             user_data,
32                            GError             **error);
33
34 static void passthrough   (GMarkupParseContext *context,
35                            const gchar         *text,
36                            gsize                text_len,
37                            gpointer             user_data,
38                            GError             **error);
39
40 static void parse_error   (GMarkupParseContext *context,
41                            GError              *error,
42                            gpointer             user_data);
43
44 static const GMarkupParser 
45 mono_parser = {
46         start_element,
47         end_element,
48         parse_text,
49         passthrough,
50         parse_error
51 };
52
53 static GHashTable *config_handlers;
54
55 /* when this interface is stable, export it. */
56 typedef struct MonoParseHandler MonoParseHandler;
57
58 struct MonoParseHandler {
59         const char *element_name;
60         void*(*init)   (void);
61         void (*start)  (gpointer user_data, const gchar *name,
62                         const gchar **attributes,
63                         const gchar **values);
64         void (*text)   (gpointer user_data, const char *text, gsize test_len);
65         void (*end)    (gpointer user_data, const char *name);
66         void (*finish) (gpointer user_data);
67 };
68
69 typedef struct {
70         MonoParseHandler *current;
71         void *user_data;
72         int inited;
73 } ParseState;
74
75 static void start_element (GMarkupParseContext *context, 
76                            const gchar         *element_name,
77                            const gchar        **attribute_names,
78                            const gchar        **attribute_values,
79                            gpointer             user_data,
80                            GError             **error)
81 {
82         ParseState *state = user_data;
83         if (!state->current) {
84                 state->current = g_hash_table_lookup (config_handlers, element_name);
85                 if (state->current && state->current->init)
86                         state->user_data = state->current->init ();
87         }
88         if (state->current && state->current->start)
89                 state->current->start (state->user_data, element_name, attribute_names, attribute_values);
90 }
91
92 static void end_element   (GMarkupParseContext *context,
93                            const gchar         *element_name,
94                            gpointer             user_data,
95                            GError             **error)
96 {
97         ParseState *state = user_data;
98         if (state->current) {
99                 if (state->current->end)
100                         state->current->end (state->user_data, element_name);
101                 if (strcmp (state->current->element_name, element_name) == 0) {
102                         if (state->current->finish)
103                                 state->current->finish (state->user_data);
104                         state->current = NULL;
105                         state->user_data = NULL;
106                 }
107         }
108 }
109
110 static void parse_text    (GMarkupParseContext *context,
111                            const gchar         *text,
112                            gsize                text_len,
113                            gpointer             user_data,
114                            GError             **error)
115 {
116         ParseState *state = user_data;
117         if (state->current && state->current->text)
118                 state->current->text (state->user_data, text, text_len);
119 }
120
121 static void passthrough   (GMarkupParseContext *context,
122                            const gchar         *text,
123                            gsize                text_len,
124                            gpointer             user_data,
125                            GError             **error)
126 {
127         /* do nothing */
128 }
129
130 static void parse_error   (GMarkupParseContext *context,
131                            GError              *error,
132                            gpointer             user_data)
133 {
134 }
135
136 typedef struct {
137         char *dll;
138         char *target;
139 } DllInfo;
140
141 static void*
142 dllmap_init (void) {
143         DllInfo *info = g_new0 (DllInfo, 1);
144         return info;
145 }
146
147 static void
148 dllmap_start (gpointer user_data, 
149               const gchar         *element_name,
150               const gchar        **attribute_names,
151               const gchar        **attribute_values)
152 {
153         int i;
154         DllInfo *info = user_data;
155         
156         if (strcmp (element_name, "dllmap") == 0) {
157                 g_free (info->dll);
158                 g_free (info->target);
159                 info->dll = info->target = NULL;
160                 for (i = 0; attribute_names [i]; ++i) {
161                         if (strcmp (attribute_names [i], "dll") == 0)
162                                 info->dll = g_strdup (attribute_values [i]);
163                         else if (strcmp (attribute_names [i], "target") == 0)
164                                 info->target = g_strdup (attribute_values [i]);
165                 }
166                 mono_dllmap_insert (info->dll, NULL, info->target, NULL);
167         } else if (strcmp (element_name, "dllentry") == 0) {
168                 const char *name = NULL, *target = NULL, *dll = NULL;
169                 for (i = 0; attribute_names [i]; ++i) {
170                         if (strcmp (attribute_names [i], "dll") == 0)
171                                 dll = attribute_values [i];
172                         else if (strcmp (attribute_names [i], "target") == 0)
173                                 target = attribute_values [i];
174                         else if (strcmp (attribute_names [i], "name") == 0)
175                                 name = attribute_values [i];
176                 }
177                 if (!dll)
178                         dll = info->dll;
179                 mono_dllmap_insert (info->dll, name, dll, target);
180         }
181 }
182
183 static void
184 dllmap_finish (gpointer user_data)
185 {
186         DllInfo *info = user_data;
187
188         g_free (info->dll);
189         g_free (info->target);
190         g_free (info);
191 }
192
193 static const MonoParseHandler
194 dllmap_handler = {
195         "dllmap",
196         dllmap_init,
197         dllmap_start,
198         NULL, /* text */
199         NULL, /* end */
200         dllmap_finish
201 };
202
203
204 static int inited = 0;
205
206 static void
207 mono_config_init (void)
208 {
209         inited = 1;
210         config_handlers = g_hash_table_new (g_str_hash, g_str_equal);
211         g_hash_table_insert (config_handlers, dllmap_handler.element_name, &dllmap_handler);
212 }
213
214 /* FIXME: error handling */
215
216 static void
217 mono_config_parse_file (const char *filename)
218 {
219         GMarkupParseContext *context;
220         ParseState state = {NULL};
221         char *text;
222         gsize len;
223
224         if (!inited)
225                 mono_config_init ();
226
227         if (!g_file_get_contents (filename, &text, &len, NULL))
228                 return;
229         context = g_markup_parse_context_new (&mono_parser, 0, &state, NULL);
230         if (g_markup_parse_context_parse (context, text, len, NULL)) {
231                 g_markup_parse_context_end_parse (context, NULL);
232         }
233         g_markup_parse_context_free (context);
234 }
235
236 /*
237  * Pass a NULL filename to parse the default config files
238  * (or the file in the MONO_CONFIG env var).
239  */
240 void
241 mono_config_parse (const char *filename) {
242         const char *home;
243         char *user_cfg;
244         
245         if (filename) {
246                 mono_config_parse_file (filename);
247                 return;
248         }
249
250         home = g_getenv ("MONO_CONFIG");
251         if (home) {
252                 mono_config_parse_file (home);
253                 return;
254         }
255 #if defined (PLATFORM_WIN32)
256         /* maybe it's better to use a registry key or the install root from the binary */
257         mono_config_parse_file (MONO_CFG_DIR "\\mono\\config");
258 #else
259         mono_config_parse_file (MONO_CFG_DIR "/mono/config");
260         home = g_get_home_dir ();
261         user_cfg = g_strconcat (home, G_DIR_SEPARATOR_S, ".mono/config", NULL);
262         mono_config_parse_file (user_cfg);
263         g_free (user_cfg);
264 #endif
265         
266 }
267