1074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granataimport re
266148c695df271003a3940a2bce775d26e44be6eEnrico Granataimport lldb.formatters.Logger
3074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
4074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata# C++ STL formatters for LLDB
568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata# These formatters are based upon the version of the GNU libstdc++
65b8bfab161eb889fde856b8ed9ee225fc94be2d2Enrico Granata# as it ships with Mac OS X 10.6.8 thru 10.8.0
768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata# You are encouraged to look at the STL implementation for your platform
868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata# before relying on these formatters to do the right thing for your setup
9074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
10074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granataclass StdListSynthProvider:
11074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
12074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def __init__(self, valobj, dict):
13a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
14074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		self.valobj = valobj
151aa54057bbfe14deb5be7037eb2e378eb5229092Enrico Granata		self.count = None
161aa54057bbfe14deb5be7037eb2e378eb5229092Enrico Granata		logger >> "Providing synthetic children for a map named " + str(valobj.GetName())
17074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
1806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	def next_node(self,node):
19a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
2006cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		return node.GetChildMemberWithName('_M_next')
2106cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata
2206cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	def is_valid(self,node):
23a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
2406cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		return self.value(self.next_node(node)) != self.node_address
2506cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata
2606cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	def value(self,node):
27a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
2806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		return node.GetValueAsUnsigned()
2906cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata
3006cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	# Floyd's cyle-finding algorithm
3106cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	# try to detect if this list has a loop
3206cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	def has_loop(self):
337e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		global _list_uses_loop_detector
34a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
357e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		if _list_uses_loop_detector == False:
367e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			logger >> "Asked not to use loop detection"
377e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			return False
3806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		slow = self.next
3906cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		fast1 = self.next
4006cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		fast2 = self.next
4106cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		while self.is_valid(slow):
4206cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			slow_value = self.value(slow)
4306cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			fast1 = self.next_node(fast2)
4406cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			fast2 = self.next_node(fast1)
4506cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			if self.value(fast1) == slow_value or self.value(fast2) == slow_value:
4606cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata				return True
4706cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			slow = self.next_node(slow)
4806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		return False
4906cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata
50074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def num_children(self):
517e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		global _list_capping_size
52a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
5306cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		if self.count == None:
5406cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			self.count = self.num_children_impl()
557e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			if self.count > _list_capping_size:
567e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				self.count = _list_capping_size
5706cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		return self.count
5806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata
5906cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	def num_children_impl(self):
60a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
617e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		global _list_capping_size
6268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
6368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			next_val = self.next.GetValueAsUnsigned(0)
6468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			prev_val = self.prev.GetValueAsUnsigned(0)
6568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# After a std::list has been initialized, both next and prev will be non-NULL
6668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			if next_val == 0 or prev_val == 0:
6768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				return 0
6868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			if next_val == self.node_address:
6968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				return 0
7068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			if next_val == prev_val:
7168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				return 1
7206cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			if self.has_loop():
7306cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata				return 0
7468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			size = 2
7568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			current = self.next
7668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			while current.GetChildMemberWithName('_M_next').GetValueAsUnsigned(0) != self.node_address:
7768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				size = size + 1
7868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				current = current.GetChildMemberWithName('_M_next')
797e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				if size > _list_capping_size:
807e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata					return _list_capping_size
8168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return (size - 1)
8268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
8368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return 0;
84074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
85074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def get_child_index(self,name):
86a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
8768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
8868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return int(name.lstrip('[').rstrip(']'))
8968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
9068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return -1
91074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
92074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def get_child_at_index(self,index):
93a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
943ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata		logger >> "Fetching child " + str(index)
9568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		if index < 0:
9668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return None;
97074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		if index >= self.num_children():
98074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			return None;
9968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
10068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			offset = index
10168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			current = self.next
10268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			while offset > 0:
10368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				current = current.GetChildMemberWithName('_M_next')
10468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				offset = offset - 1
10568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return current.CreateChildAtOffset('['+str(index)+']',2*current.GetType().GetByteSize(),self.data_type)
10668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
107278bc67b4d2c0680bd433b46c5812e6c98c71ceeEnrico Granata			return None
108074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
1096bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	def extract_type(self):
110a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
1116bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata		list_type = self.valobj.GetType().GetUnqualifiedType()
112dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata		if list_type.IsReferenceType():
113dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			list_type = list_type.GetDereferencedType()
1146bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata		if list_type.GetNumberOfTemplateArguments() > 0:
1156bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata			data_type = list_type.GetTemplateArgumentType(0)
1166bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata		else:
1176bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata			data_type = None
1186bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata		return data_type
119074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
120074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def update(self):
121a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
122a57f3c69bde02d4d87fd9072c439be116240a4e8Enrico Granata		# preemptively setting this to None - we might end up changing our mind later
123a57f3c69bde02d4d87fd9072c439be116240a4e8Enrico Granata		self.count = None
12468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
12568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			impl = self.valobj.GetChildMemberWithName('_M_impl')
12668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			node = impl.GetChildMemberWithName('_M_node')
12768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
12868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.next = node.GetChildMemberWithName('_M_next')
12968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.prev = node.GetChildMemberWithName('_M_prev')
1306bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata			self.data_type = self.extract_type()
13168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.data_size = self.data_type.GetByteSize()
13268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
13368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			pass
134074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
135c01344c2c90c44375f39d7160c44ee3b8abce656Enrico Granata	def has_children(self):
136c01344c2c90c44375f39d7160c44ee3b8abce656Enrico Granata		return True
137c01344c2c90c44375f39d7160c44ee3b8abce656Enrico Granata
138074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granataclass StdVectorSynthProvider:
139074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
140074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def __init__(self, valobj, dict):
141a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
1421aa54057bbfe14deb5be7037eb2e378eb5229092Enrico Granata		self.count = None
1431aa54057bbfe14deb5be7037eb2e378eb5229092Enrico Granata		self.valobj = valobj
1441aa54057bbfe14deb5be7037eb2e378eb5229092Enrico Granata		logger >> "Providing synthetic children for a map named " + str(valobj.GetName())
145074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
146074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def num_children(self):
147a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
14806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		if self.count == None:
14906cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			self.count = self.num_children_impl()
15006cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		return self.count
15106cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata
15206cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	def is_valid_pointer(ptr,process):
153a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
15406cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		error = lldb.SBError()
15506cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		process.ReadMemory(ptr,1,error)
15606cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata		return False if error.Fail() else True
15706cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata
15806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata	def num_children_impl(self):
159a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
16068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
16168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			start_val = self.start.GetValueAsUnsigned(0)
16268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			finish_val = self.finish.GetValueAsUnsigned(0)
16368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			end_val  = self.end.GetValueAsUnsigned(0)
16468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# Before a vector has been constructed, it will contain bad values
16568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# so we really need to be careful about the length we return since
16668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# unitialized data can cause us to return a huge number. We need
16768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# to also check for any of the start, finish or end of storage values
16868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# being zero (NULL). If any are, then this vector has not been
16968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# initialized yet and we should return zero
17068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata
17168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# Make sure nothing is NULL
17268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			if start_val == 0 or finish_val == 0 or end_val == 0:
17368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				return 0
17468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# Make sure start is less than finish
17568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			if start_val >= finish_val:
17668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				return 0
17768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# Make sure finish is less than or equal to end of storage
17868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			if finish_val > end_val:
17968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				return 0
18068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata
18106cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			# if we have a struct (or other data type that the compiler pads to native word size)
18206cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			# this check might fail, unless the sizeof() we get is itself incremented to take the
18306cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			# padding bytes into account - on current clang it looks like this is the case
18406cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			num_children = (finish_val-start_val)
18506cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			if (num_children % self.data_size) != 0:
18606cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata				return 0
18706cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			else:
18806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata				num_children = num_children/self.data_size
18968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return num_children
19068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
19168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return 0;
192074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
193074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def get_child_index(self,name):
194a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
19568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
19668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return int(name.lstrip('[').rstrip(']'))
19768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
19868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return -1
199074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
200074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def get_child_at_index(self,index):
201a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
2023ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata		logger >> "Retrieving child " + str(index)
20368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		if index < 0:
20468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return None;
205074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		if index >= self.num_children():
206074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			return None;
20768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
20868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			offset = index * self.data_size
20968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
21068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
21168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return None
212074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
213074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def update(self):
214a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
215a57f3c69bde02d4d87fd9072c439be116240a4e8Enrico Granata		# preemptively setting this to None - we might end up changing our mind later
216a57f3c69bde02d4d87fd9072c439be116240a4e8Enrico Granata		self.count = None
21768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
21868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			impl = self.valobj.GetChildMemberWithName('_M_impl')
21968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.start = impl.GetChildMemberWithName('_M_start')
22068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.finish = impl.GetChildMemberWithName('_M_finish')
22168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.end = impl.GetChildMemberWithName('_M_end_of_storage')
22268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.data_type = self.start.GetType().GetPointeeType()
22368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.data_size = self.data_type.GetByteSize()
22406cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			# if any of these objects is invalid, it means there is no point in trying to fetch anything
22506cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			if self.start.IsValid() and self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid():
22606cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata				self.count = None
22706cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata			else:
22806cdb8d50b916a0ef1b8d65e3cfd48a26e3d7541Enrico Granata				self.count = 0
22968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
23068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			pass
231c01344c2c90c44375f39d7160c44ee3b8abce656Enrico Granata
232c01344c2c90c44375f39d7160c44ee3b8abce656Enrico Granata
233c01344c2c90c44375f39d7160c44ee3b8abce656Enrico Granata	def has_children(self):
234f3c10481f8ea2aa45ea02ec24dd70cbe3f7b24f9Enrico Granata		return True
235074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
236074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
237074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granataclass StdMapSynthProvider:
238074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
239074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def __init__(self, valobj, dict):
240a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
241074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		self.valobj = valobj;
2421aa54057bbfe14deb5be7037eb2e378eb5229092Enrico Granata		self.count = None
2437e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		logger >> "Providing synthetic children for a map named " + str(valobj.GetName())
2446bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata
2456bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	# we need this function as a temporary workaround for rdar://problem/10801549
2466bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	# which prevents us from extracting the std::pair<K,V> SBType out of the template
2476bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	# arguments for _Rep_Type _M_t in the map itself - because we have to make up the
2486bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	# typename and then find it, we may hit the situation were std::string has multiple
2496bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	# names but only one is actually referenced in the debug information. hence, we need
2506bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	# to replace the longer versions of std::string with the shorter one in order to be able
2516bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	# to find the type name
2526bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata	def fixup_class_name(self, class_name):
253a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
2546bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata		if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
255dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			return 'std::basic_string<char>',True
2566bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata		if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
257dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			return 'std::basic_string<char>',True
258dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata		if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
259dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			return 'std::basic_string<char>',True
260dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata		if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
261dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			return 'std::basic_string<char>',True
262dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata		return class_name,False
263074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
264074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def update(self):
265a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
266a57f3c69bde02d4d87fd9072c439be116240a4e8Enrico Granata		# preemptively setting this to None - we might end up changing our mind later
267a57f3c69bde02d4d87fd9072c439be116240a4e8Enrico Granata		self.count = None
26868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
2697e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			# we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree
2707e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			# if this gets set to True, then we will merrily return None for any child from that moment on
2717e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			self.garbage = False
27268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.Mt = self.valobj.GetChildMemberWithName('_M_t')
27368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
27468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
2756bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata
276dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			map_type = self.valobj.GetType()
277dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			if map_type.IsReferenceType():
2783ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata				logger >> "Dereferencing type"
279dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata				map_type = map_type.GetDereferencedType()
280dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata
281dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			map_arg_0 = str(map_type.GetTemplateArgumentType(0).GetName())
282dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			map_arg_1 = str(map_type.GetTemplateArgumentType(1).GetName())
2836bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata
2843ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata			logger >> "map has args " + str(map_arg_0) + " and " + str(map_arg_1)
2853ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata
286dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			map_arg_0,fixed_0 = self.fixup_class_name(map_arg_0)
287dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			map_arg_1,fixed_1 = self.fixup_class_name(map_arg_1)
288dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata
2893ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata			logger >> "arg_0 has become: " + str(map_arg_0) + " (fixed: " + str(fixed_0) + ")"
2903ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata			logger >> "arg_1 has become: " + str(map_arg_1) + " (fixed: " + str(fixed_1) + ")"
2913ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata
292dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			# HACK: this is related to the above issue with the typename for std::string
293dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			# being shortened by clang - the changes to typename display and searching to honor
294dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			# namespaces make it so that we go looking for std::pair<const std::basic_string<char>, ...>
295dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			# but when we find a type for this, we then compare it against the fully-qualified
296dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			# std::pair<const std::basic_string<char, std::char_traits... and of course fail
297dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			# the way to bypass this problem is to avoid using the std:: prefix in this specific case
298dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			if fixed_0 or fixed_1:
299dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata				map_arg_type = "pair<const " + map_arg_0 + ", " + map_arg_1
300dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata			else:
301dba1de8d585f27601162f674d30ab71d9c83ccdeEnrico Granata				map_arg_type = "std::pair<const " + map_arg_0 + ", " + map_arg_1
3026bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata
3036bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata			if map_arg_1[-1] == '>':
3046bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata				map_arg_type = map_arg_type + " >"
3056bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata			else:
3066bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata				map_arg_type = map_arg_type + ">"
3076bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata
3083ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata			logger >> "final contents datatype is: " + str(map_arg_type)
3093ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata
3106bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata			self.data_type = self.valobj.GetTarget().FindFirstType(map_arg_type)
3116bbfa6c421db7b1aec5d6c04a572d6ec6381a343Enrico Granata
3123ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata			logger >> "and the SBType is: " + str(self.data_type)
3133ce15b03038c4d26506e5b7119eb4d5faf2fa363Enrico Granata
31468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# from libstdc++ implementation of _M_root for rbtree
31568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent')
31668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.data_size = self.data_type.GetByteSize()
31768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			self.skip_size = self.Mheader.GetType().GetByteSize()
31868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
31968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			pass
320074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
321074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def num_children(self):
3227e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		global _map_capping_size
323a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
3247e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		if self.count == None:
3257e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			self.count = self.num_children_impl()
3267e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			if self.count > _map_capping_size:
3277e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				self.count = _map_capping_size
3287e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		return self.count
3297e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata
3307e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata	def num_children_impl(self):
331a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
33268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
33368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			root_ptr_val = self.node_ptr_value(self.Mroot)
33468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			if root_ptr_val == 0:
33568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				return 0;
3367e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			count = self.Mimpl.GetChildMemberWithName('_M_node_count').GetValueAsUnsigned(0)
3377e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			logger >> "I have " + str(count) + " children available"
3387e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			return count
33968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
340074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			return 0;
341074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
342074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def get_child_index(self,name):
343a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
34468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
34568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return int(name.lstrip('[').rstrip(']'))
34668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
34768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return -1
348074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
349074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def get_child_at_index(self,index):
350a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
3517e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		logger >> "Being asked to fetch child[" + str(index) + "]"
35268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		if index < 0:
35368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return None
354074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		if index >= self.num_children():
355074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			return None;
3567e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		if self.garbage:
3577e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			logger >> "Returning None since we are a garbage tree"
3587e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			return None
35968506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		try:
36068506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			offset = index
36168506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			current = self.left(self.Mheader);
36268506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			while offset > 0:
36368506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				current = self.increment_node(current)
36468506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata				offset = offset - 1;
36568506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			# skip all the base stuff and get at the data
36668506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return current.CreateChildAtOffset('['+str(index)+']',self.skip_size,self.data_type)
36768506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata		except:
36868506fbd4233cfc9a7c7dbc6728a0b7c8ed02abcEnrico Granata			return None
369074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
370074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	# utility functions
371074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def node_ptr_value(self,node):
372a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
373074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		return node.GetValueAsUnsigned(0)
374074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
375074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def right(self,node):
376a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
377074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		return node.GetChildMemberWithName("_M_right");
378074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
379074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def left(self,node):
380a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
381074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		return node.GetChildMemberWithName("_M_left");
382074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
383074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def parent(self,node):
384a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
385074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		return node.GetChildMemberWithName("_M_parent");
386074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
387074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	# from libstdc++ implementation of iterator for rbtree
388074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata	def increment_node(self,node):
389a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		logger = lldb.formatters.Logger.Logger()
3907e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata		max_steps = self.num_children()
391074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		if self.node_ptr_value(self.right(node)) != 0:
392074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			x = self.right(node);
3937e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			max_steps -= 1
394074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			while self.node_ptr_value(self.left(x)) != 0:
395074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata				x = self.left(x);
3967e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				max_steps -= 1
3977e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				logger >> str(max_steps) + " more to go before giving up"
3987e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				if max_steps <= 0:
3997e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata					self.garbage = True
4007e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata					return None
401074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			return x;
402074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata		else:
403074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			x = node;
404074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			y = self.parent(x)
4057e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata			max_steps -= 1
406074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))):
407074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata				x = y;
408074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata				y = self.parent(y);
4097e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				max_steps -= 1
4107e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				logger >> str(max_steps) + " more to go before giving up"
4117e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata				if max_steps <= 0:
4127e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata					self.garbage = True
4137e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata					return None
414074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y):
415074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata				x = y;
416074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata			return x;
417074e3b6c2eac1438a85e464796cbc19b4354d5adEnrico Granata
418c01344c2c90c44375f39d7160c44ee3b8abce656Enrico Granata	def has_children(self):
419f3c10481f8ea2aa45ea02ec24dd70cbe3f7b24f9Enrico Granata		return True
4207e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata
4217e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata_map_capping_size = 255
4227e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata_list_capping_size = 255
4237e202269d09cebf2f5047bf92fff8c8ecf732448Enrico Granata_list_uses_loop_detector = True
424