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.
18 #include "assembly-internals.h"
19 #include "class-internals.h"
20 #include "debug-helpers.h"
22 static MonoAssembly
*prog_assembly
;
25 mono_callspec_eval_exception (MonoClass
*klass
, MonoCallSpec
*spec
)
33 for (i
= 0; i
< spec
->len
; i
++) {
34 MonoTraceOperation
*op
= &spec
->ops
[i
];
38 case MONO_TRACEOP_EXCEPTION
:
39 if (strcmp ("", (const char*)op
->data
) == 0 &&
40 strcmp ("all", (const char*)op
->data2
) == 0)
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)
60 gboolean
mono_callspec_eval (MonoMethod
*method
, const MonoCallSpec
*spec
)
65 for (i
= 0; i
< spec
->len
; i
++) {
66 MonoTraceOperation
*op
= &spec
->ops
[i
];
67 MonoMethodDesc
*mdesc
;
72 case MONO_TRACEOP_ALL
:
75 case MONO_TRACEOP_PROGRAM
:
77 (m_class_get_image (method
->klass
) ==
78 mono_assembly_get_image_internal (prog_assembly
)))
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
))
88 case MONO_TRACEOP_METHOD
:
89 mdesc
= (MonoMethodDesc
*)op
->data
;
90 is_full
= mono_method_desc_is_full (mdesc
);
92 mono_method_desc_full_match (mdesc
, method
))
94 if (!is_full
&& mono_method_desc_match (mdesc
, method
))
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
) ==
103 case MONO_TRACEOP_ASSEMBLY
:
104 if (strcmp (mono_image_get_name (m_class_get_image (method
->klass
)),
105 (const char*)op
->data
) == 0)
108 case MONO_TRACEOP_NAMESPACE
:
109 if (strcmp (m_class_get_name_space (method
->klass
), (const char*)op
->data
) == 0)
112 case MONO_TRACEOP_EXCEPTION
:
125 static int is_filenamechar (char p
)
127 if (p
>= 'A' && p
<= 'Z')
129 if (p
>= 'a' && p
<= 'z')
131 if (p
>= '0' && p
<= '9')
133 if (p
== '.' || p
== ':' || p
== '_' || p
== '-' || p
== '`')
138 static char *get_string (char **in
)
142 while (is_filenamechar (*p
)) {
145 size_t len
= p
- start
;
146 char *ret
= (char *)g_malloc (len
+ 1);
147 memcpy (ret
, start
, len
);
169 static int get_token (char **in
, char **extra
, char **errstr
)
181 if (p
[0] == 'M' && p
[1] == ':') {
183 *extra
= get_string (&p
);
187 if (p
[0] == 'N' && p
[1] == ':') {
189 *extra
= get_string (&p
);
191 return TOKEN_NAMESPACE
;
193 if (p
[0] == 'T' && p
[1] == ':') {
195 *extra
= get_string (&p
);
199 if (p
[0] == 'E' && p
[1] == ':') {
201 *extra
= get_string (&p
);
203 return TOKEN_EXCEPTION
;
208 return TOKEN_EXCLUDE
;
210 if (is_filenamechar (*p
)) {
211 *extra
= get_string (&p
);
213 if (strcmp (*extra
, "all") == 0)
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
;
226 return TOKEN_SEPARATOR
;
229 *errstr
= g_strdup_printf ("Syntax error at or around '%s'", p
);
233 static int get_spec (char **in
, MonoCallSpec
*spec
, char **errstr
)
238 int token
= get_token (in
, &extra
, errstr
);
239 gboolean exclude
= FALSE
;
240 if (token
== TOKEN_EXCLUDE
) {
242 token
= get_token (in
, &extra
, errstr
);
243 if (token
== TOKEN_EXCLUDE
|| token
== TOKEN_DISABLED
) {
244 *errstr
= g_strdup_printf ("Expecting an expression");
249 if (token
== TOKEN_END
|| token
== TOKEN_SEPARATOR
||
250 token
== TOKEN_ERROR
)
253 if (token
== TOKEN_DISABLED
) {
254 spec
->enabled
= FALSE
;
258 if (token
== TOKEN_METHOD
) {
259 MonoMethodDesc
*desc
= mono_method_desc_new (extra
, TRUE
);
262 g_strdup_printf ("Invalid method name: %s", extra
);
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
, '.');
281 spec
->ops
[n
].data
= g_strdup (extra
);
282 spec
->ops
[n
].data2
= g_strdup (p
);
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
);
294 g_strdup_printf ("Syntax error in method specification");
300 spec
->ops
[n
].exclude
= 1;
303 token
= TOKEN_SEPARATOR
;
312 mono_callspec_parse (const char *options
, MonoCallSpec
*spec
, char **errstr
)
314 char *p
= (char *)options
;
318 memset (spec
, 0, sizeof (*spec
));
321 spec
->enabled
= TRUE
;
324 spec
->ops
= g_new0 (MonoTraceOperation
, 1);
325 spec
->ops
[0].op
= MONO_TRACEOP_ALL
;
329 for (p
= (char *)options
; *p
!= 0; p
++)
333 spec
->ops
= g_new0 (MonoTraceOperation
, size
);
337 while ((token
= (get_spec (&p
, spec
, errstr
))) != TOKEN_END
) {
338 if (token
== TOKEN_ERROR
)
344 void mono_callspec_cleanup (MonoCallSpec
*spec
)
347 memset (spec
, 0, sizeof (*spec
));
351 mono_callspec_set_assembly (MonoAssembly
*assembly
)
353 prog_assembly
= assembly
;