blob: 3265f55bb4464bfaaac39aba1470871d15b80053 [file] [log] [blame]
Enrico Granata074e3b62011-08-17 19:07:52 +00001import re
2
3# C++ STL formatters for LLDB
Enrico Granata68506fb2011-08-22 16:10:25 +00004# These formatters are based upon the version of the GNU libstdc++
Enrico Granata7e7f6b92012-02-08 19:57:18 +00005# as it ships with Mac OS X 10.6.8 thru 10.7.3
Enrico Granata68506fb2011-08-22 16:10:25 +00006# You are encouraged to look at the STL implementation for your platform
7# before relying on these formatters to do the right thing for your setup
Enrico Granata074e3b62011-08-17 19:07:52 +00008
9class StdListSynthProvider:
10
11 def __init__(self, valobj, dict):
12 self.valobj = valobj
13 self.update()
14
15 def num_children(self):
Enrico Granata68506fb2011-08-22 16:10:25 +000016 try:
17 next_val = self.next.GetValueAsUnsigned(0)
18 prev_val = self.prev.GetValueAsUnsigned(0)
19 # After a std::list has been initialized, both next and prev will be non-NULL
20 if next_val == 0 or prev_val == 0:
21 return 0
22 if next_val == self.node_address:
23 return 0
24 if next_val == prev_val:
25 return 1
26 size = 2
27 current = self.next
28 while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
29 size = size + 1
30 current = current.GetChildMemberWithName('_M_next')
31 return (size - 1)
32 except:
33 return 0;
Enrico Granata074e3b62011-08-17 19:07:52 +000034
35 def get_child_index(self,name):
Enrico Granata68506fb2011-08-22 16:10:25 +000036 try:
37 return int(name.lstrip('[').rstrip(']'))
38 except:
39 return -1
Enrico Granata074e3b62011-08-17 19:07:52 +000040
41 def get_child_at_index(self,index):
Enrico Granata68506fb2011-08-22 16:10:25 +000042 if index < 0:
43 return None;
Enrico Granata074e3b62011-08-17 19:07:52 +000044 if index >= self.num_children():
45 return None;
Enrico Granata68506fb2011-08-22 16:10:25 +000046 try:
47 offset = index
48 current = self.next
49 while offset > 0:
50 current = current.GetChildMemberWithName('_M_next')
51 offset = offset - 1
52 return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type)
53 except:
Enrico Granata278bc672011-08-22 16:38:44 +000054 return None
Enrico Granata074e3b62011-08-17 19:07:52 +000055
Enrico Granata6bbfa6c2012-02-03 18:11:52 +000056 def extract_type(self):
57 list_type = self.valobj.GetType().GetUnqualifiedType()
58 if list_type.GetNumberOfTemplateArguments() > 0:
59 data_type = list_type.GetTemplateArgumentType(0)
60 else:
61 data_type = None
62 return data_type
Enrico Granata074e3b62011-08-17 19:07:52 +000063
64 def update(self):
Enrico Granata68506fb2011-08-22 16:10:25 +000065 try:
66 impl = self.valobj.GetChildMemberWithName('_M_impl')
67 node = impl.GetChildMemberWithName('_M_node')
Enrico Granata68506fb2011-08-22 16:10:25 +000068 self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
69 self.next = node.GetChildMemberWithName('_M_next')
70 self.prev = node.GetChildMemberWithName('_M_prev')
Enrico Granata6bbfa6c2012-02-03 18:11:52 +000071 self.data_type = self.extract_type()
Enrico Granata68506fb2011-08-22 16:10:25 +000072 self.data_size = self.data_type.GetByteSize()
73 except:
74 pass
Enrico Granata074e3b62011-08-17 19:07:52 +000075
76class StdVectorSynthProvider:
77
78 def __init__(self, valobj, dict):
79 self.valobj = valobj;
80 self.update()
81
82 def num_children(self):
Enrico Granata68506fb2011-08-22 16:10:25 +000083 try:
84 start_val = self.start.GetValueAsUnsigned(0)
85 finish_val = self.finish.GetValueAsUnsigned(0)
86 end_val = self.end.GetValueAsUnsigned(0)
87 # Before a vector has been constructed, it will contain bad values
88 # so we really need to be careful about the length we return since
89 # unitialized data can cause us to return a huge number. We need
90 # to also check for any of the start, finish or end of storage values
91 # being zero (NULL). If any are, then this vector has not been
92 # initialized yet and we should return zero
Enrico Granata074e3b62011-08-17 19:07:52 +000093
Enrico Granata68506fb2011-08-22 16:10:25 +000094 # Make sure nothing is NULL
95 if start_val == 0 or finish_val == 0 or end_val == 0:
96 return 0
97 # Make sure start is less than finish
98 if start_val >= finish_val:
99 return 0
100 # Make sure finish is less than or equal to end of storage
101 if finish_val > end_val:
102 return 0
Enrico Granata074e3b62011-08-17 19:07:52 +0000103
Enrico Granata68506fb2011-08-22 16:10:25 +0000104 num_children = (finish_val-start_val)/self.data_size
105 return num_children
106 except:
107 return 0;
Enrico Granata074e3b62011-08-17 19:07:52 +0000108
109 def get_child_index(self,name):
Enrico Granata68506fb2011-08-22 16:10:25 +0000110 try:
111 return int(name.lstrip('[').rstrip(']'))
112 except:
113 return -1
Enrico Granata074e3b62011-08-17 19:07:52 +0000114
115 def get_child_at_index(self,index):
Enrico Granata68506fb2011-08-22 16:10:25 +0000116 if index < 0:
117 return None;
Enrico Granata074e3b62011-08-17 19:07:52 +0000118 if index >= self.num_children():
119 return None;
Enrico Granata68506fb2011-08-22 16:10:25 +0000120 try:
121 offset = index * self.data_size
122 return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
123 except:
124 return None
Enrico Granata074e3b62011-08-17 19:07:52 +0000125
126 def update(self):
Enrico Granata68506fb2011-08-22 16:10:25 +0000127 try:
128 impl = self.valobj.GetChildMemberWithName('_M_impl')
129 self.start = impl.GetChildMemberWithName('_M_start')
130 self.finish = impl.GetChildMemberWithName('_M_finish')
131 self.end = impl.GetChildMemberWithName('_M_end_of_storage')
132 self.data_type = self.start.GetType().GetPointeeType()
133 self.data_size = self.data_type.GetByteSize()
134 except:
135 pass
Enrico Granata074e3b62011-08-17 19:07:52 +0000136
137
138class StdMapSynthProvider:
139
140 def __init__(self, valobj, dict):
141 self.valobj = valobj;
142 self.update()
Enrico Granata6bbfa6c2012-02-03 18:11:52 +0000143
144 # we need this function as a temporary workaround for rdar://problem/10801549
145 # which prevents us from extracting the std::pair<K,V> SBType out of the template
146 # arguments for _Rep_Type _M_t in the map itself - because we have to make up the
147 # typename and then find it, we may hit the situation were std::string has multiple
148 # names but only one is actually referenced in the debug information. hence, we need
149 # to replace the longer versions of std::string with the shorter one in order to be able
150 # to find the type name
151 def fixup_class_name(self, class_name):
152 if class_name == 'std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >':
153 return 'std::basic_string<char>'
154 if class_name == 'basic_string<char, class std::char_traits<char>, class std::allocator<char> >':
155 return 'std::basic_string<char>'
156 if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
157 return 'std::basic_string<char>'
158 if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
159 return 'std::basic_string<char>'
160 return class_name
Enrico Granata074e3b62011-08-17 19:07:52 +0000161
162 def update(self):
Enrico Granata68506fb2011-08-22 16:10:25 +0000163 try:
164 self.Mt = self.valobj.GetChildMemberWithName('_M_t')
165 self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
166 self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
Enrico Granata6bbfa6c2012-02-03 18:11:52 +0000167
168 map_arg_0 = str(self.valobj.GetType().GetTemplateArgumentType(0).GetName())
169 map_arg_1 = str(self.valobj.GetType().GetTemplateArgumentType(1).GetName())
170
171 map_arg_0 = self.fixup_class_name(map_arg_0)
172 map_arg_1 = self.fixup_class_name(map_arg_1)
173
174 map_arg_type = "std::pair<const " + map_arg_0 + ", " + map_arg_1
175 if map_arg_1[-1] == '>':
176 map_arg_type = map_arg_type + " >"
177 else:
178 map_arg_type = map_arg_type + ">"
179
180 self.data_type = self.valobj.GetTarget().FindFirstType(map_arg_type)
181
Enrico Granata68506fb2011-08-22 16:10:25 +0000182 # from libstdc++ implementation of _M_root for rbtree
183 self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent')
Enrico Granata68506fb2011-08-22 16:10:25 +0000184 self.data_size = self.data_type.GetByteSize()
185 self.skip_size = self.Mheader.GetType().GetByteSize()
186 except:
187 pass
Enrico Granata074e3b62011-08-17 19:07:52 +0000188
Enrico Granata074e3b62011-08-17 19:07:52 +0000189 def num_children(self):
Enrico Granata68506fb2011-08-22 16:10:25 +0000190 try:
191 root_ptr_val = self.node_ptr_value(self.Mroot)
192 if root_ptr_val == 0:
193 return 0;
194 return self.Mimpl.GetChildMemberWithName('_M_node_count').GetValueAsUnsigned(0)
195 except:
Enrico Granata074e3b62011-08-17 19:07:52 +0000196 return 0;
Enrico Granata074e3b62011-08-17 19:07:52 +0000197
198 def get_child_index(self,name):
Enrico Granata68506fb2011-08-22 16:10:25 +0000199 try:
200 return int(name.lstrip('[').rstrip(']'))
201 except:
202 return -1
Enrico Granata074e3b62011-08-17 19:07:52 +0000203
204 def get_child_at_index(self,index):
Enrico Granata68506fb2011-08-22 16:10:25 +0000205 if index < 0:
206 return None
Enrico Granata074e3b62011-08-17 19:07:52 +0000207 if index >= self.num_children():
208 return None;
Enrico Granata68506fb2011-08-22 16:10:25 +0000209 try:
210 offset = index
211 current = self.left(self.Mheader);
212 while offset > 0:
213 current = self.increment_node(current)
214 offset = offset - 1;
215 # skip all the base stuff and get at the data
216 return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type)
217 except:
218 return None
Enrico Granata074e3b62011-08-17 19:07:52 +0000219
220 # utility functions
221 def node_ptr_value(self,node):
222 return node.GetValueAsUnsigned(0)
223
224 def right(self,node):
225 return node.GetChildMemberWithName("_M_right");
226
227 def left(self,node):
228 return node.GetChildMemberWithName("_M_left");
229
230 def parent(self,node):
231 return node.GetChildMemberWithName("_M_parent");
232
233 # from libstdc++ implementation of iterator for rbtree
234 def increment_node(self,node):
235 if self.node_ptr_value(self.right(node)) != 0:
236 x = self.right(node);
237 while self.node_ptr_value(self.left(x)) != 0:
238 x = self.left(x);
239 return x;
240 else:
241 x = node;
242 y = self.parent(x)
243 while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))):
244 x = y;
245 y = self.parent(y);
246 if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y):
247 x = y;
248 return x;
249