Merge branch '1447-date-tests-again' into 'master'
[glib.git] / glib / glib_gdb.py
blob1cf2ed93645b6a28329b87a0662338cde67f45ef
1 import gdb
2 import sys
4 if sys.version_info[0] >= 3:
5 long = int
7 # This is not quite right, as local vars may override symname
8 def read_global_var (symname):
9 return gdb.selected_frame().read_var(symname)
11 def g_quark_to_string (quark):
12 if quark is None:
13 return None
14 quark = long(quark)
15 if quark == 0:
16 return None
17 try:
18 val = read_global_var ("quarks")
19 max_q = long(read_global_var ("quark_seq_id"))
20 except:
21 try:
22 val = read_global_var ("g_quarks")
23 max_q = long(read_global_var ("g_quark_seq_id"))
24 except:
25 return None;
26 if quark < max_q:
27 return val[quark].string()
28 return None
30 # We override the node printers too, so that node->next is not expanded
31 class GListNodePrinter:
32 "Prints a GList node"
34 def __init__ (self, val):
35 self.val = val
37 def to_string (self):
38 return "{data=%s, next=0x%x, prev=0x%x}" % (str(self.val["data"]), long(self.val["next"]), long(self.val["prev"]))
40 class GSListNodePrinter:
41 "Prints a GSList node"
43 def __init__ (self, val):
44 self.val = val
46 def to_string (self):
47 return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
49 class GListPrinter:
50 "Prints a GList"
52 class _iterator:
53 def __init__(self, head, listtype):
54 self.link = head
55 self.listtype = listtype
56 self.count = 0
58 def __iter__(self):
59 return self
61 def next(self):
62 if self.link == 0:
63 raise StopIteration
64 data = self.link['data']
65 self.link = self.link['next']
66 count = self.count
67 self.count = self.count + 1
68 return ('[%d]' % count, data)
70 __next__ = next
72 def __init__ (self, val, listtype):
73 self.val = val
74 self.listtype = listtype
76 def children(self):
77 return self._iterator(self.val, self.listtype)
79 def to_string (self):
80 return "0x%x" % (long(self.val))
82 def display_hint (self):
83 return "array"
85 class GHashPrinter:
86 "Prints a GHashTable"
88 class _iterator:
89 def __init__(self, ht, keys_are_strings):
90 self.ht = ht
91 if ht != 0:
92 self.keys = ht["keys"]
93 self.values = ht["values"]
94 self.hashes = ht["hashes"]
95 self.size = ht["size"]
96 self.pos = 0
97 self.keys_are_strings = keys_are_strings
98 self.value = None
100 def __iter__(self):
101 return self
103 def next(self):
104 if self.ht == 0:
105 raise StopIteration
106 if self.value != None:
107 v = self.value
108 self.value = None
109 return v
110 while long(self.pos) < long(self.size):
111 self.pos = self.pos + 1
112 if long (self.hashes[self.pos]) >= 2:
113 key = self.keys[self.pos]
114 val = self.values[self.pos]
116 if self.keys_are_strings:
117 key = key.cast (gdb.lookup_type("char").pointer())
119 # Queue value for next result
120 self.value = ('[%dv]'% (self.pos), val)
122 # Return key
123 return ('[%dk]'% (self.pos), key)
124 raise StopIteration
126 __next__ = next
128 def __init__ (self, val):
129 self.val = val
130 self.keys_are_strings = False
131 try:
132 string_hash = read_global_var ("g_str_hash")
133 except:
134 string_hash = None
135 if self.val != 0 and string_hash != None and self.val["hash_func"] == string_hash:
136 self.keys_are_strings = True
138 def children(self):
139 return self._iterator(self.val, self.keys_are_strings)
141 def to_string (self):
142 return "0x%x" % (long(self.val))
144 def display_hint (self):
145 return "map"
147 def pretty_printer_lookup (val):
148 # None yet, want things like hash table and list
150 type = val.type.unqualified()
152 # If it points to a reference, get the reference.
153 if type.code == gdb.TYPE_CODE_REF:
154 type = type.target ()
156 if type.code == gdb.TYPE_CODE_PTR:
157 type = type.target().unqualified()
158 t = str(type)
159 if t == "GList":
160 return GListPrinter(val, "GList")
161 if t == "GSList":
162 return GListPrinter(val, "GSList")
163 if t == "GHashTable":
164 return GHashPrinter(val)
165 else:
166 t = str(type)
167 if t == "GList":
168 return GListNodePrinter(val)
169 if t == "GSList *":
170 return GListPrinter(val, "GSList")
171 return None
173 def register (obj):
174 if obj is None:
175 obj = gdb
177 obj.pretty_printers.append(pretty_printer_lookup)
179 class ForeachCommand (gdb.Command):
180 """Foreach on list"""
182 def __init__ (self):
183 super (ForeachCommand, self).__init__ ("gforeach",
184 gdb.COMMAND_DATA,
185 gdb.COMPLETE_SYMBOL)
187 def valid_name (self, name):
188 if not name[0].isalpha():
189 return False
190 return True
192 def parse_args (self, arg):
193 i = arg.find(" ")
194 if i <= 0:
195 raise Exception ("No var specified")
196 var = arg[:i]
197 if not self.valid_name(var):
198 raise Exception ("Invalid variable name")
200 while i < len (arg) and arg[i].isspace():
201 i = i + 1
203 if arg[i:i+2] != "in":
204 raise Exception ("Invalid syntax, missing in")
206 i = i + 2
208 while i < len (arg) and arg[i].isspace():
209 i = i + 1
211 colon = arg.find (":", i)
212 if colon == -1:
213 raise Exception ("Invalid syntax, missing colon")
215 val = arg[i:colon]
217 colon = colon + 1
218 while colon < len (arg) and arg[colon].isspace():
219 colon = colon + 1
221 command = arg[colon:]
223 return (var, val, command)
225 def do_iter(self, arg, item, command):
226 item = item.cast (gdb.lookup_type("void").pointer())
227 item = long(item)
228 to_eval = "set $%s = (void *)0x%x\n"%(arg, item)
229 gdb.execute(to_eval)
230 gdb.execute(command)
232 def slist_iterator (self, arg, container, command):
233 l = container.cast (gdb.lookup_type("GSList").pointer())
234 while long(l) != 0:
235 self.do_iter (arg, l["data"], command)
236 l = l["next"]
238 def list_iterator (self, arg, container, command):
239 l = container.cast (gdb.lookup_type("GList").pointer())
240 while long(l) != 0:
241 self.do_iter (arg, l["data"], command)
242 l = l["next"]
244 def pick_iterator (self, container):
245 t = container.type.unqualified()
246 if t.code == gdb.TYPE_CODE_PTR:
247 t = t.target().unqualified()
248 t = str(t)
249 if t == "GSList":
250 return self.slist_iterator
251 if t == "GList":
252 return self.list_iterator
253 raise Exception("Invalid container type %s"%(str(container.type)))
255 def invoke (self, arg, from_tty):
256 (var, container, command) = self.parse_args(arg)
257 container = gdb.parse_and_eval (container)
258 func = self.pick_iterator(container)
259 func(var, container, command)
261 ForeachCommand ()