4 * Runtime and assembly configuration file support routines.
6 * Author: Paolo Molaro (lupus@ximian.com)
8 * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
16 #include "mono/metadata/assembly.h"
17 #include "mono/metadata/loader.h"
18 #include "mono/metadata/loader-internals.h"
19 #include "mono/metadata/mono-config.h"
20 #include "mono/metadata/mono-config-internals.h"
21 #include "mono/metadata/metadata-internals.h"
22 #include "mono/metadata/object-internals.h"
23 #include "mono/utils/mono-logger-internals.h"
25 #if defined(TARGET_PS3)
26 #define CONFIG_OS "CellOS"
27 #elif defined(__linux__)
28 #define CONFIG_OS "linux"
29 #elif defined(__APPLE__)
30 #define CONFIG_OS "osx"
32 #define CONFIG_OS "solaris"
33 #elif defined(__FreeBSD__)
34 #define CONFIG_OS "freebsd"
35 #elif defined(__NetBSD__)
36 #define CONFIG_OS "netbsd"
37 #elif defined(__OpenBSD__)
38 #define CONFIG_OS "openbsd"
39 #elif defined(__WIN32__) || defined(TARGET_WIN32)
40 #define CONFIG_OS "windows"
42 #define CONFIG_OS "aix"
44 #define CONFIG_OS "hpux"
45 #elif defined(__HAIKU__)
46 #define CONFIG_OS "haiku"
47 #elif defined (TARGET_WASM)
48 #define CONFIG_OS "wasm"
50 #warning Unknown operating system
51 #define CONFIG_OS "unknownOS"
55 #if defined(__i386__) || defined(TARGET_X86)
56 #define CONFIG_CPU "x86"
57 #define CONFIG_WORDSIZE "32"
58 #elif defined(__x86_64__) || defined(TARGET_AMD64)
59 #define CONFIG_CPU "x86-64"
60 #define CONFIG_WORDSIZE "64"
61 #elif defined(sparc) || defined(__sparc__)
62 #define CONFIG_CPU "sparc"
63 #define CONFIG_WORDSIZE "32"
64 #elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_64) || defined(TARGET_POWERPC)
65 #define CONFIG_WORDSIZE "64"
66 #ifdef __mono_ppc_ilp32__
67 # define CONFIG_CPU "ppc64ilp32"
69 # define CONFIG_CPU "ppc64"
71 #elif defined(__ppc__) || defined(__powerpc__)
72 #define CONFIG_CPU "ppc"
73 #define CONFIG_WORDSIZE "32"
74 #elif defined(__s390x__)
75 #define CONFIG_CPU "s390x"
76 #define CONFIG_WORDSIZE "64"
77 #elif defined(__s390__)
78 #define CONFIG_CPU "s390"
79 #define CONFIG_WORDSIZE "32"
80 #elif defined(__arm__)
81 #define CONFIG_CPU "arm"
82 #define CONFIG_WORDSIZE "32"
83 #elif defined(__aarch64__)
84 #define CONFIG_CPU "armv8"
85 #define CONFIG_WORDSIZE "64"
86 #elif defined(mips) || defined(__mips) || defined(_mips)
87 #define CONFIG_CPU "mips"
88 #define CONFIG_WORDSIZE "32"
89 #elif defined (TARGET_RISCV32)
90 #define CONFIG_CPU "riscv32"
91 #define CONFIG_WORDSIZE "32"
92 #elif defined (TARGET_RISCV64)
93 #define CONFIG_CPU "riscv64"
94 #define CONFIG_WORDSIZE "64"
95 #elif defined(TARGET_WASM)
96 #define CONFIG_CPU "wasm"
97 #define CONFIG_WORDSIZE "32"
100 #define CONFIG_CPU "unknownCPU"
105 * mono_config_get_os:
107 * Returns the operating system that Mono is running on, as used for dllmap entries.
110 mono_config_get_os (void)
116 * mono_config_get_cpu:
118 * Returns the architecture that Mono is running on, as used for dllmap entries.
121 mono_config_get_cpu (void)
127 * mono_config_get_wordsize:
129 * Returns the word size that Mono is running on, as used for dllmap entries.
132 mono_config_get_wordsize (void)
134 return CONFIG_WORDSIZE
;
137 static void start_element (GMarkupParseContext
*context
,
138 const gchar
*element_name
,
139 const gchar
**attribute_names
,
140 const gchar
**attribute_values
,
144 static void end_element (GMarkupParseContext
*context
,
145 const gchar
*element_name
,
149 static void parse_text (GMarkupParseContext
*context
,
155 static void passthrough (GMarkupParseContext
*context
,
161 static void parse_error (GMarkupParseContext
*context
,
165 static const GMarkupParser
174 static GHashTable
*config_handlers
;
176 static char *mono_cfg_dir
= NULL
;
178 /* when this interface is stable, export it. */
179 typedef struct MonoParseHandler MonoParseHandler
;
181 struct MonoParseHandler
{
182 const char *element_name
;
183 void*(*init
) (MonoImage
*assembly
);
184 void (*start
) (gpointer user_data
, const gchar
*name
,
185 const gchar
**attributes
,
186 const gchar
**values
);
187 void (*text
) (gpointer user_data
, const char *text
, gsize test_len
);
188 void (*end
) (gpointer user_data
, const char *name
);
189 void (*finish
) (gpointer user_data
);
193 MonoAssemblyBindingInfo
*info
;
194 void (*info_parsed
)(MonoAssemblyBindingInfo
*info
, void *user_data
);
199 MonoParseHandler
*current
;
203 } MonoConfigParseState
;
205 static void start_element (GMarkupParseContext
*context
,
206 const gchar
*element_name
,
207 const gchar
**attribute_names
,
208 const gchar
**attribute_values
,
212 MonoConfigParseState
*state
= (MonoConfigParseState
*)user_data
;
213 if (!state
->current
) {
214 state
->current
= (MonoParseHandler
*)g_hash_table_lookup (config_handlers
, element_name
);
215 if (state
->current
&& state
->current
->init
)
216 state
->user_data
= state
->current
->init (state
->assembly
);
218 if (state
->current
&& state
->current
->start
)
219 state
->current
->start (state
->user_data
, element_name
, attribute_names
, attribute_values
);
222 static void end_element (GMarkupParseContext
*context
,
223 const gchar
*element_name
,
227 MonoConfigParseState
*state
= (MonoConfigParseState
*)user_data
;
228 if (state
->current
) {
229 if (state
->current
->end
)
230 state
->current
->end (state
->user_data
, element_name
);
231 if (strcmp (state
->current
->element_name
, element_name
) == 0) {
232 if (state
->current
->finish
)
233 state
->current
->finish (state
->user_data
);
234 state
->current
= NULL
;
235 state
->user_data
= NULL
;
240 static void parse_text (GMarkupParseContext
*context
,
246 MonoConfigParseState
*state
= (MonoConfigParseState
*)user_data
;
247 if (state
->current
&& state
->current
->text
)
248 state
->current
->text (state
->user_data
, text
, text_len
);
251 static void passthrough (GMarkupParseContext
*context
,
260 static void parse_error (GMarkupParseContext
*context
,
264 MonoConfigParseState
*state
= (MonoConfigParseState
*)user_data
;
266 const gchar
*filename
;
268 filename
= state
&& state
->user_data
? (gchar
*) state
->user_data
: "<unknown>";
269 msg
= gerror
&& gerror
->message
? gerror
->message
: "";
270 g_warning ("Error parsing %s: %s", filename
, msg
);
274 arch_matches (const char* arch
, const char *value
)
276 char **splitted
, **p
;
278 if (value
[0] == '!')
279 return !arch_matches (arch
, value
+ 1);
280 p
= splitted
= g_strsplit (value
, ",", 0);
282 if (strcmp (arch
, *p
) == 0) {
288 g_strfreev (splitted
);
300 dllmap_init (MonoImage
*assembly
) {
301 DllInfo
*info
= g_new0 (DllInfo
, 1);
302 info
->assembly
= assembly
;
307 dllmap_start (gpointer user_data
,
308 const gchar
*element_name
,
309 const gchar
**attribute_names
,
310 const gchar
**attribute_values
)
313 DllInfo
*info
= (DllInfo
*)user_data
;
315 if (strcmp (element_name
, "dllmap") == 0) {
317 g_free (info
->target
);
318 info
->dll
= info
->target
= NULL
;
319 info
->ignore
= FALSE
;
320 for (i
= 0; attribute_names
[i
]; ++i
) {
321 if (strcmp (attribute_names
[i
], "dll") == 0)
322 info
->dll
= g_strdup (attribute_values
[i
]);
323 else if (strcmp (attribute_names
[i
], "target") == 0){
324 const char* p
= strstr (attribute_values
[i
], "$mono_libdir");
326 char *libdir
= mono_native_getrootdir ();
327 size_t libdir_len
= strlen (libdir
);
330 result
= (char *)g_malloc (libdir_len
-strlen("$mono_libdir")+strlen(attribute_values
[i
])+1);
331 strncpy (result
, attribute_values
[i
], p
-attribute_values
[i
]);
332 strcpy (result
+(p
-attribute_values
[i
]), libdir
);
334 strcat (result
, p
+strlen("$mono_libdir"));
335 info
->target
= result
;
337 info
->target
= g_strdup (attribute_values
[i
]);
338 } else if (strcmp (attribute_names
[i
], "os") == 0 && !arch_matches (CONFIG_OS
, attribute_values
[i
]))
340 else if (strcmp (attribute_names
[i
], "cpu") == 0 && !arch_matches (CONFIG_CPU
, attribute_values
[i
]))
342 else if (strcmp (attribute_names
[i
], "wordsize") == 0 && !arch_matches (CONFIG_WORDSIZE
, attribute_values
[i
]))
346 mono_dllmap_insert_internal (info
->assembly
, info
->dll
, NULL
, info
->target
, NULL
);
347 } else if (strcmp (element_name
, "dllentry") == 0) {
348 const char *name
= NULL
, *target
= NULL
, *dll
= NULL
;
350 for (i
= 0; attribute_names
[i
]; ++i
) {
351 if (strcmp (attribute_names
[i
], "dll") == 0)
352 dll
= attribute_values
[i
];
353 else if (strcmp (attribute_names
[i
], "target") == 0)
354 target
= attribute_values
[i
];
355 else if (strcmp (attribute_names
[i
], "name") == 0)
356 name
= attribute_values
[i
];
357 else if (strcmp (attribute_names
[i
], "os") == 0 && !arch_matches (CONFIG_OS
, attribute_values
[i
]))
359 else if (strcmp (attribute_names
[i
], "cpu") == 0 && !arch_matches (CONFIG_CPU
, attribute_values
[i
]))
361 else if (strcmp (attribute_names
[i
], "wordsize") == 0 && !arch_matches (CONFIG_WORDSIZE
, attribute_values
[i
]))
366 if (!info
->ignore
&& !ignore
)
367 mono_dllmap_insert_internal (info
->assembly
, info
->dll
, name
, dll
, target
);
372 dllmap_finish (gpointer user_data
)
374 DllInfo
*info
= (DllInfo
*)user_data
;
377 g_free (info
->target
);
381 static const MonoParseHandler
392 legacyUEP_start (gpointer user_data
,
393 const gchar
*element_name
,
394 const gchar
**attribute_names
,
395 const gchar
**attribute_values
) {
396 if ((strcmp (element_name
, "legacyUnhandledExceptionPolicy") == 0) &&
397 (attribute_names
[0] != NULL
) &&
398 (strcmp (attribute_names
[0], "enabled") == 0)) {
399 if ((strcmp (attribute_values
[0], "1") == 0) ||
400 (g_ascii_strcasecmp (attribute_values
[0], "true") == 0)) {
401 mono_runtime_unhandled_exception_policy_set (MONO_UNHANDLED_POLICY_LEGACY
);
406 static const MonoParseHandler
407 legacyUEP_handler
= {
408 "legacyUnhandledExceptionPolicy",
417 aot_cache_start (gpointer user_data
,
418 const gchar
*element_name
,
419 const gchar
**attribute_names
,
420 const gchar
**attribute_values
)
423 MonoAotCacheConfig
*config
;
425 if (strcmp (element_name
, "aotcache") != 0)
428 config
= mono_get_aot_cache_config ();
430 /* Per-app configuration */
431 for (i
= 0; attribute_names
[i
]; ++i
) {
432 if (!strcmp (attribute_names
[i
], "app")) {
433 config
->apps
= g_slist_prepend (config
->apps
, g_strdup (attribute_values
[i
]));
437 /* Global configuration */
438 for (i
= 0; attribute_names
[i
]; ++i
) {
439 if (!strcmp (attribute_names
[i
], "assemblies")) {
443 parts
= g_strsplit (attribute_values
[i
], " ", -1);
444 for (ptr
= parts
; ptr
&& *ptr
; ptr
++) {
446 config
->assemblies
= g_slist_prepend (config
->assemblies
, g_strdup (part
));
449 } else if (!strcmp (attribute_names
[i
], "options")) {
450 config
->aot_options
= g_strdup (attribute_values
[i
]);
455 static const MonoParseHandler
456 aot_cache_handler
= {
465 static int inited
= 0;
468 mono_config_init (void)
471 config_handlers
= g_hash_table_new (g_str_hash
, g_str_equal
);
472 g_hash_table_insert (config_handlers
, (gpointer
) dllmap_handler
.element_name
, (gpointer
) &dllmap_handler
);
473 g_hash_table_insert (config_handlers
, (gpointer
) legacyUEP_handler
.element_name
, (gpointer
) &legacyUEP_handler
);
474 g_hash_table_insert (config_handlers
, (gpointer
) aot_cache_handler
.element_name
, (gpointer
) &aot_cache_handler
);
478 * mono_config_cleanup:
481 mono_config_cleanup (void)
484 g_hash_table_destroy (config_handlers
);
485 g_free (mono_cfg_dir
);
488 /* FIXME: error handling */
491 mono_config_parse_xml_with_context (MonoConfigParseState
*state
, const char *text
, gsize len
)
493 GMarkupParseContext
*context
;
498 context
= g_markup_parse_context_new (&mono_parser
, (GMarkupParseFlags
)0, state
, NULL
);
499 if (g_markup_parse_context_parse (context
, text
, len
, NULL
)) {
500 g_markup_parse_context_end_parse (context
, NULL
);
502 g_markup_parse_context_free (context
);
505 /* If assembly is NULL, parse in the global context */
507 mono_config_parse_file_with_context (MonoConfigParseState
*state
, const char *filename
)
513 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_CONFIG
,
514 "Config attempting to parse: '%s'.", filename
);
516 if (!g_file_get_contents (filename
, &text
, &len
, NULL
))
520 if (len
> 3 && text
[0] == '\xef' && text
[1] == (gchar
) '\xbb' && text
[2] == '\xbf')
521 offset
= 3; /* Skip UTF-8 BOM */
522 if (state
->user_data
== NULL
)
523 state
->user_data
= (gpointer
) filename
;
524 mono_config_parse_xml_with_context (state
, text
+ offset
, len
- offset
);
530 * mono_config_parse_memory:
531 * \param buffer a pointer to an string XML representation of the configuration
532 * Parses the configuration from a buffer
535 mono_config_parse_memory (const char *buffer
)
537 MonoConfigParseState state
= {NULL
};
539 state
.user_data
= (gpointer
) "<buffer>";
540 mono_config_parse_xml_with_context (&state
, buffer
, strlen (buffer
));
544 mono_config_parse_file (const char *filename
)
546 MonoConfigParseState state
= {NULL
};
547 state
.user_data
= (gpointer
) filename
;
548 mono_config_parse_file_with_context (&state
, filename
);
552 * use the equivalent lookup code from the GAC when available.
553 * Depending on state, this should give something like:
554 * aname/version-pubtoken/
559 get_assembly_filename (MonoImage
*image
, int state
)
563 return g_strdup (mono_image_get_name (image
));
569 typedef struct _BundledConfig BundledConfig
;
571 struct _BundledConfig
{
574 const char* config_xml
;
577 static BundledConfig
*bundled_configs
= NULL
;
579 static const char *bundled_machine_config
= NULL
;
582 * mono_register_config_for_assembly:
585 mono_register_config_for_assembly (const char* assembly_name
, const char* config_xml
)
587 BundledConfig
*bconfig
;
589 bconfig
= g_new0 (BundledConfig
, 1);
590 bconfig
->aname
= assembly_name
;
591 bconfig
->config_xml
= config_xml
;
592 bconfig
->next
= bundled_configs
;
593 bundled_configs
= bconfig
;
597 * mono_config_string_for_assembly_file:
600 mono_config_string_for_assembly_file (const char *filename
)
602 BundledConfig
*bconfig
;
604 for (bconfig
= bundled_configs
; bconfig
; bconfig
= bconfig
->next
) {
605 if (bconfig
->aname
&& strcmp (bconfig
->aname
, filename
) == 0)
606 return bconfig
->config_xml
;
612 mono_config_for_assembly_internal (MonoImage
*assembly
)
614 MONO_REQ_GC_UNSAFE_MODE
;
616 MonoConfigParseState state
= {NULL
};
618 char *aname
, *cfg
, *cfg_name
;
619 const char *bundled_config
;
621 state
.assembly
= assembly
;
623 bundled_config
= mono_config_string_for_assembly_file (assembly
->module_name
);
624 if (bundled_config
) {
625 state
.user_data
= (gpointer
) "<bundled>";
626 mono_config_parse_xml_with_context (&state
, bundled_config
, strlen (bundled_config
));
629 cfg_name
= g_strdup_printf ("%s.config", mono_image_get_filename (assembly
));
630 mono_config_parse_file_with_context (&state
, cfg_name
);
633 cfg_name
= g_strdup_printf ("%s.config", mono_image_get_name (assembly
));
634 const char *cfg_dir
= mono_get_config_dir ();
640 for (i
= 0; (aname
= get_assembly_filename (assembly
, i
)) != NULL
; ++i
) {
641 cfg
= g_build_filename (cfg_dir
, "mono", "assemblies", aname
, cfg_name
, (const char*)NULL
);
642 got_it
+= mono_config_parse_file_with_context (&state
, cfg
);
646 const char *home
= g_get_home_dir ();
647 cfg
= g_build_filename (home
, ".mono", "assemblies", aname
, cfg_name
, (const char*)NULL
);
648 got_it
+= mono_config_parse_file_with_context (&state
, cfg
);
660 * \param filename the filename to load the configuration variables from.
661 * Pass a NULL filename to parse the default config files
662 * (or the file in the \c MONO_CONFIG env var).
665 mono_config_parse (const char *filename
)
668 mono_config_parse_file (filename
);
672 const char *home
= g_getenv ("MONO_CONFIG");
674 mono_config_parse_file (home
);
678 const char *cfg_dir
= mono_get_config_dir ();
680 char *mono_cfg
= g_build_filename (cfg_dir
, "mono", "config", (const char*)NULL
);
681 mono_config_parse_file (mono_cfg
);
685 #if !defined(TARGET_WIN32)
686 home
= g_get_home_dir ();
687 char *user_cfg
= g_strconcat (home
, G_DIR_SEPARATOR_S
, ".mono/config", (const char*)NULL
);
688 mono_config_parse_file (user_cfg
);
694 * mono_set_config_dir:
695 * Invoked during startup
698 mono_set_config_dir (const char *dir
)
700 /* If this environment variable is set, overrides the directory computed */
701 char *env_mono_cfg_dir
= g_getenv ("MONO_CFG_DIR");
702 if (env_mono_cfg_dir
== NULL
&& dir
!= NULL
)
703 env_mono_cfg_dir
= g_strdup (dir
);
706 g_free (mono_cfg_dir
);
707 mono_cfg_dir
= env_mono_cfg_dir
;
711 * mono_get_config_dir:
714 mono_get_config_dir (void)
716 if (mono_cfg_dir
== NULL
)
717 mono_set_dirs (NULL
, NULL
);
723 * mono_register_machine_config:
726 mono_register_machine_config (const char *config_xml
)
728 bundled_machine_config
= config_xml
;
732 * mono_get_machine_config:
735 mono_get_machine_config (void)
737 return bundled_machine_config
;
741 assembly_binding_end (gpointer user_data
, const char *element_name
)
743 ParserUserData
*pud
= (ParserUserData
*)user_data
;
745 if (!strcmp (element_name
, "dependentAssembly")) {
746 if (pud
->info_parsed
&& pud
->info
) {
747 pud
->info_parsed (pud
->info
, pud
->user_data
);
748 g_free (pud
->info
->name
);
749 g_free (pud
->info
->culture
);
755 publisher_policy_start (gpointer user_data
,
756 const gchar
*element_name
,
757 const gchar
**attribute_names
,
758 const gchar
**attribute_values
)
761 MonoAssemblyBindingInfo
*info
;
764 pud
= (ParserUserData
*)user_data
;
766 if (!strcmp (element_name
, "dependentAssembly")) {
768 info
->culture
= NULL
;
769 info
->has_old_version_bottom
= FALSE
;
770 info
->has_old_version_top
= FALSE
;
771 info
->has_new_version
= FALSE
;
772 info
->is_valid
= FALSE
;
773 memset (&info
->old_version_bottom
, 0, sizeof (info
->old_version_bottom
));
774 memset (&info
->old_version_top
, 0, sizeof (info
->old_version_top
));
775 memset (&info
->new_version
, 0, sizeof (info
->new_version
));
776 } else if (!strcmp (element_name
, "assemblyIdentity")) {
777 for (n
= 0; attribute_names
[n
]; n
++) {
778 const gchar
*attribute_name
= attribute_names
[n
];
780 if (!strcmp (attribute_name
, "name"))
781 info
->name
= g_strdup (attribute_values
[n
]);
782 else if (!strcmp (attribute_name
, "publicKeyToken")) {
783 if (strlen (attribute_values
[n
]) == MONO_PUBLIC_KEY_TOKEN_LENGTH
- 1)
784 g_strlcpy ((char *) info
->public_key_token
, attribute_values
[n
], MONO_PUBLIC_KEY_TOKEN_LENGTH
);
785 } else if (!strcmp (attribute_name
, "culture")) {
786 if (!strcmp (attribute_values
[n
], "neutral"))
787 info
->culture
= g_strdup ("");
789 info
->culture
= g_strdup (attribute_values
[n
]);
792 } else if (!strcmp (element_name
, "bindingRedirect")) {
793 for (n
= 0; attribute_names
[n
]; n
++) {
794 const gchar
*attribute_name
= attribute_names
[n
];
796 if (!strcmp (attribute_name
, "oldVersion")) {
797 gchar
**numbers
, **version
, **versions
;
798 gint major
, minor
, build
, revision
;
801 if (!strcmp (attribute_values
[n
], ""))
804 versions
= g_strsplit (attribute_values
[n
], "-", 2);
805 version
= g_strsplit (*versions
, ".", 4);
807 /* We assign the values to gint vars to do the checks */
809 major
= *numbers
? atoi (*numbers
++) : -1;
810 minor
= *numbers
? atoi (*numbers
++) : -1;
811 build
= *numbers
? atoi (*numbers
++) : -1;
812 revision
= *numbers
? atoi (*numbers
) : -1;
813 g_strfreev (version
);
814 if (major
< 0 || minor
< 0 || build
< 0 || revision
< 0) {
815 g_strfreev (versions
);
819 info
->old_version_bottom
.major
= major
;
820 info
->old_version_bottom
.minor
= minor
;
821 info
->old_version_bottom
.build
= build
;
822 info
->old_version_bottom
.revision
= revision
;
823 info
->has_old_version_bottom
= TRUE
;
825 if (!*(versions
+ 1)) {
826 g_strfreev (versions
);
830 numbers
= version
= g_strsplit (*(versions
+ 1), ".", 4);
831 major
= *numbers
? atoi (*numbers
++) : -1;
832 minor
= *numbers
? atoi (*numbers
++) : -1;
833 build
= *numbers
? atoi (*numbers
++) : -1;
834 revision
= *numbers
? atoi (*numbers
) : 1;
835 g_strfreev (version
);
836 if (major
< 0 || minor
< 0 || build
< 0 || revision
< 0) {
837 g_strfreev (versions
);
841 info
->old_version_top
.major
= major
;
842 info
->old_version_top
.minor
= minor
;
843 info
->old_version_top
.build
= build
;
844 info
->old_version_top
.revision
= revision
;
845 info
->has_old_version_top
= TRUE
;
847 g_strfreev (versions
);
848 } else if (!strcmp (attribute_name
, "newVersion")) {
849 gchar
**numbers
, **version
;
852 if (!strcmp (attribute_values
[n
], ""))
855 numbers
= version
= g_strsplit (attribute_values
[n
], ".", 4);
856 info
->new_version
.major
= *numbers
? atoi (*numbers
++) : -1;
857 info
->new_version
.minor
= *numbers
? atoi (*numbers
++) : -1;
858 info
->new_version
.build
= *numbers
? atoi (*numbers
++) : -1;
859 info
->new_version
.revision
= *numbers
? atoi (*numbers
) : -1;
860 info
->has_new_version
= TRUE
;
861 g_strfreev (version
);
867 static MonoParseHandler
868 publisher_policy_parser
= {
869 "", /* We don't need to use declare an xml element */
871 publisher_policy_start
,
878 mono_config_parse_publisher_policy (const gchar
*filename
, MonoAssemblyBindingInfo
*info
)
880 ParserUserData user_data
= {
885 MonoConfigParseState state
= {
886 &publisher_policy_parser
, /* MonoParseHandler */
887 &user_data
, /* user_data */
888 NULL
, /* MonoImage (we don't need it right now)*/
889 TRUE
/* We are already inited */
892 mono_config_parse_file_with_context (&state
, filename
);
895 static MonoParseHandler
896 config_assemblybinding_parser
= {
897 "", /* We don't need to use declare an xml element */
899 publisher_policy_start
,
901 assembly_binding_end
,
906 mono_config_parse_assembly_bindings (const char *filename
, int amajor
, int aminor
, void *user_data
, void (*infocb
)(MonoAssemblyBindingInfo
*info
, void *user_data
))
908 MonoAssemblyBindingInfo info
;
910 MonoConfigParseState state
;
916 pud
.info_parsed
= infocb
;
917 pud
.user_data
= user_data
;
919 state
.current
= &config_assemblybinding_parser
; /* MonoParseHandler */
920 state
.user_data
= &pud
;
921 state
.assembly
= NULL
; /* MonoImage (we don't need it right now)*/
922 state
.inited
= TRUE
; /* We are already inited */
924 mono_config_parse_file_with_context (&state
, filename
);
927 static mono_bool mono_server_mode
= FALSE
;
930 * mono_config_set_server_mode:
933 mono_config_set_server_mode (mono_bool server_mode
)
935 mono_server_mode
= server_mode
;
939 * mono_config_is_server_mode:
942 mono_config_is_server_mode (void)
944 return mono_server_mode
;