Xmethod support in Python.
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.python / py-xmethods.py
1 # Copyright 2014 Free Software Foundation, Inc.
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16 # This file is part of the GDB testsuite. It test the xmethods support
17 # in the Python extension language.
18
19 import gdb
20 import re
21
22 from gdb.xmethod import XMethod
23 from gdb.xmethod import XMethodMatcher, XMethodWorker
24 from gdb.xmethod import SimpleXMethodMatcher
25
26
27 def A_plus_A(obj, opr):
28 print ('From Python <A_plus_A>:')
29 return obj['a'] + opr['a']
30
31
32 def plus_plus_A(obj):
33 print ('From Python <plus_plus_A>:')
34 return obj['a'] + 1
35
36
37 def A_geta(obj):
38 print ('From Python <A_geta>:')
39 return obj['a']
40
41
42 def A_getarrayind(obj, index):
43 print 'From Python <A_getarrayind>:'
44 return obj['array'][index]
45
46
47 type_A = gdb.parse_and_eval('(dop::A *) 0').type.target()
48 type_B = gdb.parse_and_eval('(dop::B *) 0').type.target()
49 type_int = gdb.parse_and_eval('(int *) 0').type.target()
50
51
52 # The E class matcher and worker test two things:
53 # 1. xmethod returning None.
54 # 2. Matcher returning a list of workers.
55
56 class E_method_char_worker(XMethodWorker):
57 def __init__(self):
58 pass
59
60 def get_arg_types(self):
61 return gdb.lookup_type('char')
62
63 def __call__(self, obj, arg):
64 print 'From Python <E_method_char>'
65 return None
66
67
68 class E_method_int_worker(XMethodWorker):
69 def __init__(self):
70 pass
71
72 def get_arg_types(self):
73 return gdb.lookup_type('int')
74
75 def __call__(self, obj, arg):
76 print 'From Python <E_method_int>'
77 return None
78
79
80 class E_method_matcher(XMethodMatcher):
81 def __init__(self):
82 XMethodMatcher.__init__(self, 'E_methods')
83 self.methods = [XMethod('method_int'), XMethod('method_char')]
84
85 def match(self, class_type, method_name):
86 class_tag = class_type.unqualified().tag
87 if not re.match('^dop::E$', class_tag):
88 return None
89 if not re.match('^method$', method_name):
90 return None
91 workers = []
92 if self.methods[0].enabled:
93 workers.append(E_method_int_worker())
94 if self.methods[1].enabled:
95 workers.append(E_method_char_worker())
96 return workers
97
98
99 # The G class method matcher and worker illustrate how to write
100 # xmethod matchers and workers for template classes and template
101 # methods.
102
103 class G_size_diff_worker(XMethodWorker):
104 def __init__(self, class_template_type, method_template_type):
105 self._class_template_type = class_template_type
106 self._method_template_type = method_template_type
107
108 def get_arg_types(self):
109 pass
110
111 def __call__(self, obj):
112 print ('From Python G<>::size_diff()')
113 return (self._method_template_type.sizeof -
114 self._class_template_type.sizeof)
115
116
117 class G_size_mul_worker(XMethodWorker):
118 def __init__(self, class_template_type, method_template_val):
119 self._class_template_type = class_template_type
120 self._method_template_val = method_template_val
121
122 def get_arg_types(self):
123 pass
124
125 def __call__(self, obj):
126 print ('From Python G<>::size_mul()')
127 return self._class_template_type.sizeof * self._method_template_val
128
129
130 class G_mul_worker(XMethodWorker):
131 def __init__(self, class_template_type, method_template_type):
132 self._class_template_type = class_template_type
133 self._method_template_type = method_template_type
134
135 def get_arg_types(self):
136 return self._method_template_type
137
138 def __call__(self, obj, arg):
139 print ('From Python G<>::mul()')
140 return obj['t'] * arg
141
142
143 class G_methods_matcher(XMethodMatcher):
144 def __init__(self):
145 XMethodMatcher.__init__(self, 'G_methods')
146 self.methods = [XMethod('size_diff'),
147 XMethod('size_mul'),
148 XMethod('mul')]
149
150 def _is_enabled(self, name):
151 for method in self.methods:
152 if method.name == name and method.enabled:
153 return True
154
155 def match(self, class_type, method_name):
156 class_tag = class_type.unqualified().tag
157 if not re.match('^dop::G<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$',
158 class_tag):
159 return None
160 t_name = class_tag[7:-1]
161 try:
162 t_type = gdb.lookup_type(t_name)
163 except gdb.error:
164 return None
165 if re.match('^size_diff<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name):
166 if not self._is_enabled('size_diff'):
167 return None
168 t1_name = method_name[10:-1]
169 try:
170 t1_type = gdb.lookup_type(t1_name)
171 return G_size_diff_worker(t_type, t1_type)
172 except gdb.error:
173 return None
174 if re.match('^size_mul<[ ]*[0-9]+[ ]*>$', method_name):
175 if not self._is_enabled('size_mul'):
176 return None
177 m_val = int(method_name[9:-1])
178 return G_size_mul_worker(t_type, m_val)
179 if re.match('^mul<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name):
180 if not self._is_enabled('mul'):
181 return None
182 t1_name = method_name[4:-1]
183 try:
184 t1_type = gdb.lookup_type(t1_name)
185 return G_mul_worker(t_type, t1_type)
186 except gdb.error:
187 return None
188
189
190 global_dm_list = [
191 SimpleXMethodMatcher('A_plus_A',
192 '^dop::A$',
193 'operator\+',
194 A_plus_A,
195 # This is a replacement, hence match the arg type
196 # exactly!
197 type_A.const().reference()),
198 SimpleXMethodMatcher('plus_plus_A',
199 '^dop::A$',
200 'operator\+\+',
201 plus_plus_A),
202 SimpleXMethodMatcher('A_geta',
203 '^dop::A$',
204 '^geta$',
205 A_geta),
206 SimpleXMethodMatcher('A_getarrayind',
207 '^dop::A$',
208 '^getarrayind$',
209 A_getarrayind,
210 type_int),
211 ]
212
213 for matcher in global_dm_list:
214 gdb.xmethod.register_xmethod_matcher(gdb, matcher)
215 gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(),
216 G_methods_matcher())
217 gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(),
218 E_method_matcher())
This page took 0.035473 seconds and 4 git commands to generate.