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