]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/gdb.python/py-xmethods.py
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.python / py-xmethods.py
1 # Copyright 2014-2024 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_getarray(obj):
43 print("From Python <A_getarray>:")
44 return obj["array"]
45
46
47 def A_getarrayind(obj, index):
48 print("From Python <A_getarrayind>:")
49 return obj["array"][index]
50
51
52 def A_indexoper(obj, index):
53 return obj["array"][index].reference_value()
54
55
56 def B_getarray(obj):
57 print("From Python <B_getarray>:")
58 return obj["array"].const_value()
59
60
61 def B_indexoper(obj, index):
62 return obj["array"][index].const_value().reference_value()
63
64
65 type_A = gdb.parse_and_eval("(dop::A *) 0").type.target()
66 type_B = gdb.parse_and_eval("(dop::B *) 0").type.target()
67 type_array = gdb.parse_and_eval("(int[10] *) 0").type.target()
68 type_int = gdb.parse_and_eval("(int *) 0").type.target()
69
70
71 # The E class matcher and worker test two things:
72 # 1. xmethod returning None.
73 # 2. Matcher returning a list of workers.
74
75
76 class E_method_char_worker(XMethodWorker):
77 def __init__(self):
78 pass
79
80 def get_arg_types(self):
81 return gdb.lookup_type("char")
82
83 def get_result_type(self, obj, arg):
84 return gdb.lookup_type("void")
85
86 def __call__(self, obj, arg):
87 print("From Python <E_method_char>")
88 return None
89
90
91 class E_method_int_worker(XMethodWorker):
92 def __init__(self):
93 pass
94
95 def get_arg_types(self):
96 return gdb.lookup_type("int")
97
98 # Note: get_result_type method elided on purpose
99
100 def __call__(self, obj, arg):
101 print("From Python <E_method_int>")
102 return None
103
104
105 class E_method_matcher(XMethodMatcher):
106 def __init__(self):
107 XMethodMatcher.__init__(self, "E_methods")
108 self.methods = [XMethod("method_int"), XMethod("method_char")]
109
110 def match(self, class_type, method_name):
111 class_tag = class_type.unqualified().tag
112 if not re.match("^dop::E$", class_tag):
113 return None
114 if not re.match("^method$", method_name):
115 return None
116 workers = []
117 if self.methods[0].enabled:
118 workers.append(E_method_int_worker())
119 if self.methods[1].enabled:
120 workers.append(E_method_char_worker())
121 return workers
122
123
124 # The G class method matcher and worker illustrate how to write
125 # xmethod matchers and workers for template classes and template
126 # methods.
127
128
129 class G_size_diff_worker(XMethodWorker):
130 def __init__(self, class_template_type, method_template_type):
131 self._class_template_type = class_template_type
132 self._method_template_type = method_template_type
133
134 def get_arg_types(self):
135 pass
136
137 def __call__(self, obj):
138 print("From Python G<>::size_diff()")
139 return self._method_template_type.sizeof - self._class_template_type.sizeof
140
141
142 class G_size_mul_worker(XMethodWorker):
143 def __init__(self, class_template_type, method_template_val):
144 self._class_template_type = class_template_type
145 self._method_template_val = method_template_val
146
147 def get_arg_types(self):
148 pass
149
150 def __call__(self, obj):
151 print("From Python G<>::size_mul()")
152 return self._class_template_type.sizeof * self._method_template_val
153
154
155 class G_mul_worker(XMethodWorker):
156 def __init__(self, class_template_type, method_template_type):
157 self._class_template_type = class_template_type
158 self._method_template_type = method_template_type
159
160 def get_arg_types(self):
161 return self._method_template_type
162
163 def __call__(self, obj, arg):
164 print("From Python G<>::mul()")
165 return obj["t"] * arg
166
167
168 class G_methods_matcher(XMethodMatcher):
169 def __init__(self):
170 XMethodMatcher.__init__(self, "G_methods")
171 self.methods = [XMethod("size_diff"), XMethod("size_mul"), XMethod("mul")]
172
173 def _is_enabled(self, name):
174 for method in self.methods:
175 if method.name == name and method.enabled:
176 return True
177
178 def match(self, class_type, method_name):
179 class_tag = class_type.unqualified().tag
180 if not re.match("^dop::G<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$", class_tag):
181 return None
182 t_name = class_tag[7:-1]
183 try:
184 t_type = gdb.lookup_type(t_name)
185 except gdb.error:
186 return None
187 if re.match("^size_diff<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$", method_name):
188 if not self._is_enabled("size_diff"):
189 return None
190 t1_name = method_name[10:-1]
191 try:
192 t1_type = gdb.lookup_type(t1_name)
193 return G_size_diff_worker(t_type, t1_type)
194 except gdb.error:
195 return None
196 if re.match("^size_mul<[ ]*[0-9]+[ ]*>$", method_name):
197 if not self._is_enabled("size_mul"):
198 return None
199 m_val = int(method_name[9:-1])
200 return G_size_mul_worker(t_type, m_val)
201 if re.match("^mul<[ ]*[_a-zA-Z][ _a-zA-Z0-9]*>$", method_name):
202 if not self._is_enabled("mul"):
203 return None
204 t1_name = method_name[4:-1]
205 try:
206 t1_type = gdb.lookup_type(t1_name)
207 return G_mul_worker(t_type, t1_type)
208 except gdb.error:
209 return None
210
211
212 global_dm_list = [
213 SimpleXMethodMatcher(
214 r"A_plus_A",
215 r"^dop::A$",
216 r"operator\+",
217 A_plus_A,
218 # This is a replacement, hence match the arg type
219 # exactly!
220 type_A.const().reference(),
221 ),
222 SimpleXMethodMatcher(r"plus_plus_A", r"^dop::A$", r"operator\+\+", plus_plus_A),
223 SimpleXMethodMatcher(r"A_geta", r"^dop::A$", r"^geta$", A_geta),
224 SimpleXMethodMatcher(
225 r"A_getarray", r"^dop::A$", r"^getarray$", A_getarray, type_array
226 ),
227 SimpleXMethodMatcher(
228 r"A_getarrayind", r"^dop::A$", r"^getarrayind$", A_getarrayind, type_int
229 ),
230 SimpleXMethodMatcher(
231 r"A_indexoper", r"^dop::A$", r"operator\[\]", A_indexoper, type_int
232 ),
233 SimpleXMethodMatcher(
234 r"B_getarray", r"^dop::B$", r"^getarray$", B_getarray, type_array
235 ),
236 SimpleXMethodMatcher(
237 r"B_indexoper", r"^dop::B$", r"operator\[\]", B_indexoper, type_int
238 ),
239 ]
240
241 for matcher in global_dm_list:
242 gdb.xmethod.register_xmethod_matcher(gdb, matcher)
243 gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), G_methods_matcher())
244 gdb.xmethod.register_xmethod_matcher(gdb.current_progspace(), E_method_matcher())