Revert some changes which don't have proper dependencies.
[mono-project.git] / mono / metadata / callspec.c
blob31deb1389c6eabe2015b98fd2986e1dcc3d7869a
1 /**
2 * \file
3 * Call specification facilities for the Mono Runtime.
5 * Author:
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.
14 #include <config.h>
15 #include "metadata.h"
16 #include "callspec.h"
17 #include "assembly.h"
18 #include "assembly-internals.h"
19 #include "class-internals.h"
20 #include "debug-helpers.h"
22 static MonoAssembly *prog_assembly;
24 gboolean
25 mono_callspec_eval_exception (MonoClass *klass, MonoCallSpec *spec)
27 int include = 0;
28 int i;
30 if (!klass)
31 return FALSE;
33 for (i = 0; i < spec->len; i++) {
34 MonoTraceOperation *op = &spec->ops [i];
35 int inc = 0;
37 switch (op->op) {
38 case MONO_TRACEOP_EXCEPTION:
39 if (strcmp ("", (const char*)op->data) == 0 &&
40 strcmp ("all", (const char*)op->data2) == 0)
41 inc = 1;
42 else if (strcmp ("", (const char*)op->data) == 0 ||
43 strcmp (m_class_get_name_space (klass), (const char*)op->data) == 0)
44 if (strcmp (m_class_get_name (klass), (const char*)op->data2) == 0)
45 inc = 1;
46 break;
47 default:
48 break;
50 if (op->exclude) {
51 if (inc)
52 include = 0;
53 } else if (inc)
54 include = 1;
57 return include;
60 gboolean mono_callspec_eval (MonoMethod *method, const MonoCallSpec *spec)
62 int include = 0;
63 int i;
65 for (i = 0; i < spec->len; i++) {
66 MonoTraceOperation *op = &spec->ops[i];
67 MonoMethodDesc *mdesc;
68 gboolean is_full;
69 int inc = 0;
71 switch (op->op) {
72 case MONO_TRACEOP_ALL:
73 inc = 1;
74 break;
75 case MONO_TRACEOP_PROGRAM:
76 if (prog_assembly &&
77 (m_class_get_image (method->klass) ==
78 mono_assembly_get_image_internal (prog_assembly)))
79 inc = 1;
80 break;
81 case MONO_TRACEOP_WRAPPER:
82 if ((method->wrapper_type ==
83 MONO_WRAPPER_NATIVE_TO_MANAGED) ||
84 (method->wrapper_type ==
85 MONO_WRAPPER_MANAGED_TO_NATIVE))
86 inc = 1;
87 break;
88 case MONO_TRACEOP_METHOD:
89 mdesc = (MonoMethodDesc*)op->data;
90 is_full = mono_method_desc_is_full (mdesc);
91 if (is_full &&
92 mono_method_desc_full_match (mdesc, method))
93 inc = 1;
94 if (!is_full && mono_method_desc_match (mdesc, method))
95 inc = 1;
96 break;
97 case MONO_TRACEOP_CLASS:
98 if (strcmp (m_class_get_name_space (method->klass), (const char*)op->data) == 0)
99 if (strcmp (m_class_get_name (method->klass), (const char*)op->data2) ==
101 inc = 1;
102 break;
103 case MONO_TRACEOP_ASSEMBLY:
104 if (strcmp (mono_image_get_name (m_class_get_image (method->klass)),
105 (const char*)op->data) == 0)
106 inc = 1;
107 break;
108 case MONO_TRACEOP_NAMESPACE:
109 if (strcmp (m_class_get_name_space (method->klass), (const char*)op->data) == 0)
110 inc = 1;
111 break;
112 case MONO_TRACEOP_EXCEPTION:
113 break;
115 if (op->exclude) {
116 if (inc)
117 include = 0;
118 } else if (inc) {
119 include = 1;
122 return include;
125 static int is_filenamechar (char p)
127 if (p >= 'A' && p <= 'Z')
128 return TRUE;
129 if (p >= 'a' && p <= 'z')
130 return TRUE;
131 if (p >= '0' && p <= '9')
132 return TRUE;
133 if (p == '.' || p == ':' || p == '_' || p == '-' || p == '`')
134 return TRUE;
135 return FALSE;
138 static char *get_string (char **in)
140 char *start = *in;
141 char *p = *in;
142 while (is_filenamechar (*p)) {
143 p++;
145 size_t len = p - start;
146 char *ret = (char *)g_malloc (len + 1);
147 memcpy (ret, start, len);
148 ret [len] = 0;
149 *in = p;
150 return ret;
153 enum Token {
154 TOKEN_METHOD,
155 TOKEN_CLASS,
156 TOKEN_ALL,
157 TOKEN_PROGRAM,
158 TOKEN_EXCEPTION,
159 TOKEN_NAMESPACE,
160 TOKEN_WRAPPER,
161 TOKEN_STRING,
162 TOKEN_EXCLUDE,
163 TOKEN_DISABLED,
164 TOKEN_SEPARATOR,
165 TOKEN_END,
166 TOKEN_ERROR
169 static int get_token (char **in, char **extra, char **errstr)
171 char *p = *in;
172 while (p[0] == '+')
173 p++;
175 *extra = NULL;
177 if (p[0] == '\0') {
178 *in = p;
179 return TOKEN_END;
181 if (p[0] == 'M' && p[1] == ':') {
182 p += 2;
183 *extra = get_string (&p);
184 *in = p;
185 return TOKEN_METHOD;
187 if (p[0] == 'N' && p[1] == ':') {
188 p += 2;
189 *extra = get_string (&p);
190 *in = p;
191 return TOKEN_NAMESPACE;
193 if (p[0] == 'T' && p[1] == ':') {
194 p += 2;
195 *extra = get_string (&p);
196 *in = p;
197 return TOKEN_CLASS;
199 if (p[0] == 'E' && p[1] == ':') {
200 p += 2;
201 *extra = get_string (&p);
202 *in = p;
203 return TOKEN_EXCEPTION;
205 if (*p == '-') {
206 p++;
207 *in = p;
208 return TOKEN_EXCLUDE;
210 if (is_filenamechar (*p)) {
211 *extra = get_string (&p);
212 *in = p;
213 if (strcmp (*extra, "all") == 0)
214 return TOKEN_ALL;
215 if (strcmp (*extra, "program") == 0)
216 return TOKEN_PROGRAM;
217 if (strcmp (*extra, "wrapper") == 0)
218 return TOKEN_WRAPPER;
219 if (strcmp (*extra, "disabled") == 0)
220 return TOKEN_DISABLED;
221 return TOKEN_STRING;
223 if (*p == ',') {
224 p++;
225 *in = p;
226 return TOKEN_SEPARATOR;
229 *errstr = g_strdup_printf ("Syntax error at or around '%s'", p);
230 return TOKEN_ERROR;
233 static int get_spec (char **in, MonoCallSpec *spec, char **errstr)
235 int n = spec->len;
236 char *extra = NULL;
238 int token = get_token (in, &extra, errstr);
239 gboolean exclude = FALSE;
240 if (token == TOKEN_EXCLUDE) {
241 exclude = TRUE;
242 token = get_token (in, &extra, errstr);
243 if (token == TOKEN_EXCLUDE || token == TOKEN_DISABLED) {
244 *errstr = g_strdup_printf ("Expecting an expression");
245 token = TOKEN_ERROR;
246 goto out;
249 if (token == TOKEN_END || token == TOKEN_SEPARATOR ||
250 token == TOKEN_ERROR)
251 goto out;
253 if (token == TOKEN_DISABLED) {
254 spec->enabled = FALSE;
255 goto out;
258 if (token == TOKEN_METHOD) {
259 MonoMethodDesc *desc = mono_method_desc_new (extra, TRUE);
260 if (desc == NULL) {
261 *errstr =
262 g_strdup_printf ("Invalid method name: %s", extra);
263 token = TOKEN_ERROR;
264 goto out;
266 spec->ops[n].op = MONO_TRACEOP_METHOD;
267 spec->ops[n].data = desc;
268 } else if (token == TOKEN_ALL)
269 spec->ops[n].op = MONO_TRACEOP_ALL;
270 else if (token == TOKEN_PROGRAM)
271 spec->ops[n].op = MONO_TRACEOP_PROGRAM;
272 else if (token == TOKEN_WRAPPER)
273 spec->ops[n].op = MONO_TRACEOP_WRAPPER;
274 else if (token == TOKEN_NAMESPACE) {
275 spec->ops[n].op = MONO_TRACEOP_NAMESPACE;
276 spec->ops[n].data = g_strdup (extra);
277 } else if (token == TOKEN_CLASS || token == TOKEN_EXCEPTION) {
278 char *p = strrchr (extra, '.');
279 if (p) {
280 *p++ = 0;
281 spec->ops[n].data = g_strdup (extra);
282 spec->ops[n].data2 = g_strdup (p);
283 } else {
284 spec->ops[n].data = g_strdup ("");
285 spec->ops[n].data2 = g_strdup (extra);
287 spec->ops[n].op = token == TOKEN_CLASS ? MONO_TRACEOP_CLASS
288 : MONO_TRACEOP_EXCEPTION;
289 } else if (token == TOKEN_STRING) {
290 spec->ops[n].op = MONO_TRACEOP_ASSEMBLY;
291 spec->ops[n].data = g_strdup (extra);
292 } else {
293 *errstr =
294 g_strdup_printf ("Syntax error in method specification");
295 token = TOKEN_ERROR;
296 goto out;
299 if (exclude)
300 spec->ops[n].exclude = 1;
302 spec->len = n + 1;
303 token = TOKEN_SEPARATOR;
304 out:
305 if (extra != NULL) {
306 g_free (extra);
308 return token;
311 gboolean
312 mono_callspec_parse (const char *options, MonoCallSpec *spec, char **errstr)
314 char *p = (char *)options;
315 int size = 1;
316 int token;
318 memset (spec, 0, sizeof (*spec));
319 *errstr = NULL;
321 spec->enabled = TRUE;
322 if (*p == 0) {
323 spec->len = 1;
324 spec->ops = g_new0 (MonoTraceOperation, 1);
325 spec->ops[0].op = MONO_TRACEOP_ALL;
326 return TRUE;
329 for (p = (char *)options; *p != 0; p++)
330 if (*p == ',')
331 size++;
333 spec->ops = g_new0 (MonoTraceOperation, size);
335 p = (char *)options;
337 while ((token = (get_spec (&p, spec, errstr))) != TOKEN_END) {
338 if (token == TOKEN_ERROR)
339 return FALSE;
341 return TRUE;
344 void mono_callspec_cleanup (MonoCallSpec *spec)
346 g_free (spec->ops);
347 memset (spec, 0, sizeof (*spec));
350 void
351 mono_callspec_set_assembly (MonoAssembly *assembly)
353 prog_assembly = assembly;