47fb00beec5b1cb108b23c3d01d3b844dcf63b8c
[platform/upstream/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())