3 * Call specification facilities for the Mono Runtime.
6 * Paolo Molaro (lupus@ximian.com)
7 * Dietmar Maurer (dietmar@ximian.com)
9 * (C) 2002 Ximian, Inc.
10 * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full
12 * license information.
17 #include "class-internals.h"
18 #include "debug-helpers.h"
20 static MonoAssembly *prog_assembly;
23 mono_callspec_eval_exception (MonoClass *klass, MonoCallSpec *spec)
31 for (i = 0; i < spec->len; i++) {
32 MonoTraceOperation *op = &spec->ops [i];
36 case MONO_TRACEOP_EXCEPTION:
37 if (strcmp ("", op->data) == 0 &&
38 strcmp ("all", op->data2) == 0)
40 else if (strcmp ("", op->data) == 0 ||
41 strcmp (klass->name_space, op->data) == 0)
42 if (strcmp (klass->name, op->data2) == 0)
58 gboolean mono_callspec_eval (MonoMethod *method, const MonoCallSpec *spec)
63 for (i = 0; i < spec->len; i++) {
64 MonoTraceOperation *op = &spec->ops[i];
68 case MONO_TRACEOP_ALL:
71 case MONO_TRACEOP_PROGRAM:
73 (method->klass->image ==
74 mono_assembly_get_image (prog_assembly)))
77 case MONO_TRACEOP_WRAPPER:
78 if ((method->wrapper_type ==
79 MONO_WRAPPER_NATIVE_TO_MANAGED) ||
80 (method->wrapper_type ==
81 MONO_WRAPPER_MANAGED_TO_NATIVE))
84 case MONO_TRACEOP_METHOD:
85 if (mono_method_desc_full_match (
86 (MonoMethodDesc *)op->data, method))
89 case MONO_TRACEOP_CLASS:
90 if (strcmp (method->klass->name_space, op->data) == 0)
91 if (strcmp (method->klass->name, op->data2) ==
95 case MONO_TRACEOP_ASSEMBLY:
96 if (strcmp (mono_image_get_name (method->klass->image),
100 case MONO_TRACEOP_NAMESPACE:
101 if (strcmp (method->klass->name_space, op->data) == 0)
104 case MONO_TRACEOP_EXCEPTION:
117 static int is_filenamechar (char p)
119 if (p >= 'A' && p <= 'Z')
121 if (p >= 'a' && p <= 'z')
123 if (p >= '0' && p <= '9')
125 if (p == '.' || p == ':' || p == '_' || p == '-' || p == '`')
130 static char *get_string (char **in)
134 while (is_filenamechar (*p)) {
137 size_t len = p - start;
138 char *ret = (char *)g_malloc (len + 1);
139 memcpy (ret, start, len);
161 static int get_token (char **in, char **extra, char **errstr)
173 if (p[0] == 'M' && p[1] == ':') {
175 *extra = get_string (&p);
179 if (p[0] == 'N' && p[1] == ':') {
181 *extra = get_string (&p);
183 return TOKEN_NAMESPACE;
185 if (p[0] == 'T' && p[1] == ':') {
187 *extra = get_string (&p);
191 if (p[0] == 'E' && p[1] == ':') {
193 *extra = get_string (&p);
195 return TOKEN_EXCEPTION;
200 return TOKEN_EXCLUDE;
202 if (is_filenamechar (*p)) {
203 *extra = get_string (&p);
205 if (strcmp (*extra, "all") == 0)
207 if (strcmp (*extra, "program") == 0)
208 return TOKEN_PROGRAM;
209 if (strcmp (*extra, "wrapper") == 0)
210 return TOKEN_WRAPPER;
211 if (strcmp (*extra, "disabled") == 0)
212 return TOKEN_DISABLED;
218 return TOKEN_SEPARATOR;
221 *errstr = g_strdup_printf ("Syntax error at or around '%s'", p);
225 static int get_spec (char **in, MonoCallSpec *spec, char **errstr)
230 int token = get_token (in, &extra, errstr);
231 gboolean exclude = FALSE;
232 if (token == TOKEN_EXCLUDE) {
234 token = get_token (in, &extra, errstr);
235 if (token == TOKEN_EXCLUDE || token == TOKEN_DISABLED) {
236 *errstr = g_strdup_printf ("Expecting an expression");
241 if (token == TOKEN_END || token == TOKEN_SEPARATOR ||
242 token == TOKEN_ERROR)
245 if (token == TOKEN_DISABLED) {
246 spec->enabled = FALSE;
250 if (token == TOKEN_METHOD) {
251 MonoMethodDesc *desc = mono_method_desc_new (extra, TRUE);
254 g_strdup_printf ("Invalid method name: %s", extra);
258 spec->ops[n].op = MONO_TRACEOP_METHOD;
259 spec->ops[n].data = desc;
260 } else if (token == TOKEN_ALL)
261 spec->ops[n].op = MONO_TRACEOP_ALL;
262 else if (token == TOKEN_PROGRAM)
263 spec->ops[n].op = MONO_TRACEOP_PROGRAM;
264 else if (token == TOKEN_WRAPPER)
265 spec->ops[n].op = MONO_TRACEOP_WRAPPER;
266 else if (token == TOKEN_NAMESPACE) {
267 spec->ops[n].op = MONO_TRACEOP_NAMESPACE;
268 spec->ops[n].data = g_strdup (extra);
269 } else if (token == TOKEN_CLASS || token == TOKEN_EXCEPTION) {
270 char *p = strrchr (extra, '.');
273 spec->ops[n].data = g_strdup (extra);
274 spec->ops[n].data2 = g_strdup (p);
276 spec->ops[n].data = g_strdup ("");
277 spec->ops[n].data2 = g_strdup (extra);
279 spec->ops[n].op = token == TOKEN_CLASS ? MONO_TRACEOP_CLASS
280 : MONO_TRACEOP_EXCEPTION;
281 } else if (token == TOKEN_STRING) {
282 spec->ops[n].op = MONO_TRACEOP_ASSEMBLY;
283 spec->ops[n].data = g_strdup (extra);
286 g_strdup_printf ("Syntax error in method specification");
292 spec->ops[n].exclude = 1;
295 token = TOKEN_SEPARATOR;
304 mono_callspec_parse (const char *options, MonoCallSpec *spec, char **errstr)
306 char *p = (char *)options;
310 memset (spec, 0, sizeof (*spec));
313 spec->enabled = TRUE;
316 spec->ops = g_new0 (MonoTraceOperation, 1);
317 spec->ops[0].op = MONO_TRACEOP_ALL;
321 for (p = (char *)options; *p != 0; p++)
325 spec->ops = g_new0 (MonoTraceOperation, size);
329 while ((token = (get_spec (&p, spec, errstr))) != TOKEN_END) {
330 if (token == TOKEN_ERROR)
336 void mono_callspec_cleanup (MonoCallSpec *spec)
338 if (spec->ops != NULL) {
341 memset (spec, 0, sizeof (*spec));
345 mono_callspec_set_assembly (MonoAssembly *assembly)
347 prog_assembly = assembly;