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