PR python/18285
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.python / py-xmethods.py
1 # Copyright 2014-2015 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 get_result_type(self, obj, arg):
64 return gdb.lookup_type('void')
65
66 def __call__(self, obj, arg):
67 print('From Python <E_method_char>')
68 return None
69
70
71 class E_method_int_worker(XMethodWorker):
72 def __init__(self):
73 pass
74
75 def get_arg_types(self):
76 return gdb.lookup_type('int')
77
78 # Note: get_result_type method elided on purpose
79
80 def __call__(self, obj, arg):
81 print('From Python <E_method_int>')
82 return None
83
84
85 class E_method_matcher(XMethodMatcher):
86 def __init__(self):
87 XMethodMatcher.__init__(self, 'E_methods')
88 self.methods = [XMethod('method_int'), XMethod('method_char')]
89
90 def match(self, class_type, method_name):
91 class_tag = class_type.unqualified().tag
92 if not re.match('^dop::E$', class_tag):
93 return None
94 if not re.match('^method$', method_name):
95 return None
96 workers = []
97 if self.methods[0].enabled:
98 workers.append(E_method_int_worker())
99 if self.methods[1].enabled:
100 workers.append(E_method_char_worker())
101 return workers
102
103
104 # The G class method matcher and worker illustrate how to write
105 # xmethod matchers and workers for template classes and template
106 # methods.
107
108 class G_size_diff_worker(XMethodWorker):
109 def __init__(self, class_template_type, method_template_type):
110 self._class_template_type = class_template_type
111 self._method_template_type = method_template_type
112
113 def get_arg_types(self):
114 pass
115
116 def __call__(self, obj):
117 print('From Python G<>::size_diff()')
118 return (self._method_template_type.sizeof -
119 self._class_template_type.sizeof)
120
121
122 class G_size_mul_worker(XMethodWorker):
123 def __init__(self, class_template_type, method_template_val):
124 self._class_template_type = class_template_type
125 self._method_template_val = method_template_val
126
127 def get_arg_types(self):
128 pass
129
130 def __call__(self, obj):
131 print('From Python G<>::size_mul()')
132 return self._class_template_type.sizeof * self._method_template_val
133
134
135 class G_mul_worker(XMethodWorker):
136 def __init__(self, class_template_type, method_template_type):
137 self._class_template_type = class_template_type
138 self._method_template_type = method_template_type
139
140 def get_arg_types(self):
141 return self._method_template_type
142
143 def __call__(self, obj, arg):
144 print('From Python G<>::mul()')
145 return obj['t'] * arg
146
147
148 class G_methods_matcher(XMethodMatcher):
149 def __init__(self):
150 XMethodMatcher.__init__(self, 'G_methods')
151 self.methods = [XMethod('size_diff'),
152 XMethod('size_mul'),
153 XMethod('mul')]
154
155 def _is_enabled(self, name):
156 for method in self.methods:
157 if method.name == name and method.enabled:
158 return True
159
160 def match(self, class_type, method_name):
161 class_tag = class_type.unqualified().tag
162 if not re.match('^dop::G<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$',
163 class_tag):
164 return None
165 t_name = class_tag[7:-1]
166 try:
167 t_type = gdb.lookup_type(t_name)
168 except gdb.error:
169 return None
170 if re.match('^size_diff<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name):
171 if not self._is_enabled('size_diff'):
172 return None
173 t1_name = method_name[10:-1]
174 try:
175 t1_type = gdb.lookup_type(t1_name)
176 return G_size_diff_worker(t_type, t1_type)
177 except gdb.error:
178 return None
179 if re.match('^size_mul<[ ]*[0-9]+[ ]*>$', method_name):
180 if not self._is_enabled('size_mul'):
181 return None
182 m_val = int(method_name[9:-1])
183 return G_size_mul_worker(t_type, m_val)
184 if re.match('^mul<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$', method_name):
185 if not self._is_enabled('mul'):
186 return None
187 t1_name = method_name[4:-1]
188 try:
189 t1_type = gdb.lookup_type(t1_name)
190 return G_mul_worker(t_type, t1_type)
191 except gdb.error:
192 return None
193
194
195 global_dm_list = [
196 SimpleXMethodMatcher('A_plus_A',
197 '^dop::A$',
198 'operator\+',
199 A_plus_A,
200 # This is a replacement, hence match the arg type
201 # exactly!
202 type_A.const().reference()),
203 SimpleXMethodMatcher('plus_plus_A',
204 '^dop::A$',
205 'operator\+\+',
206 plus_plus_A),
207 SimpleXMethodMatcher('A_geta',
208 '^dop::A$',
209 '^geta$',
210 A_geta),
211 SimpleXMethodMatcher('A_getarrayind',
212 '^dop::A$',
213 '^getarrayind$',
214 A_getarrayind,
215 type_int),
216 ]
217
218 for matcher in global_dm_list:
219 gdb.xmethod.register_xmethod_matcher(gdb, matcher)
220 gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(),
221 G_methods_matcher())
222 gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(),
223 E_method_matcher())
This page took 0.033784 seconds and 4 git commands to generate.