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             try:
119                 string_hash = read_global_var ("IA__g_str_hash")
120             except:
121                 string_hash = None
122         if self.val != 0 and string_hash != None and self.val["hash_func"] == string_hash:
123             self.keys_are_strings = True
124
125     def children(self):
126         return self._iterator(self.val, self.keys_are_strings)
127
128     def to_string (self):
129         return  "0x%x" % (long(self.val))
130
131     def display_hint (self):
132         return "map"
133
134 def pretty_printer_lookup (val):
135     if is_g_type_instance (val):
136         return GTypePrettyPrinter (val)
137
138 def pretty_printer_lookup (val):
139     # None yet, want things like hash table and list
140
141     type = val.type.unqualified()
142
143     # If it points to a reference, get the reference.
144     if type.code == gdb.TYPE_CODE_REF:
145         type = type.target ()
146
147     if type.code == gdb.TYPE_CODE_PTR:
148         type = type.target().unqualified()
149         t = str(type)
150         if t == "GList":
151             return GListPrinter(val, "GList")
152         if t == "GSList":
153             return GListPrinter(val, "GSList")
154         if t == "GHashTable":
155             return GHashPrinter(val)
156     else:
157         t = str(type)
158         if t == "GList":
159             return GListNodePrinter(val)
160         if t == "GSList *":
161             return GListPrinter(val, "GSList")
162     return None
163
164 def register (obj):
165     if obj == None:
166         obj = gdb
167
168     obj.pretty_printers.append(pretty_printer_lookup)
169
170 class ForeachCommand (gdb.Command):
171     """Foreach on list"""
172
173     def __init__ (self):
174         super (ForeachCommand, self).__init__ ("gforeach",
175                                                gdb.COMMAND_DATA,
176                                                gdb.COMPLETE_SYMBOL)
177
178     def valid_name (self, name):
179         if not name[0].isalpha():
180             return False
181         return True
182
183     def parse_args (self, arg):
184         i = arg.find(" ")
185         if i <= 0:
186             raise Exception ("No var specified")
187         var = arg[:i]
188         if not self.valid_name(var):
189             raise Exception ("Invalid variable name")
190
191         while i < len (arg) and arg[i].isspace():
192             i = i + 1
193
194         if arg[i:i+2] != "in":
195             raise Exception ("Invalid syntax, missing in")
196
197         i = i + 2
198
199         while i < len (arg) and arg[i].isspace():
200             i = i + 1
201
202         colon = arg.find (":", i)
203         if colon == -1:
204             raise Exception ("Invalid syntax, missing colon")
205
206         val = arg[i:colon]
207
208         colon = colon + 1
209         while colon < len (arg) and arg[colon].isspace():
210             colon = colon + 1
211
212         command = arg[colon:]
213
214         return (var, val, command)
215
216     def do_iter(self, arg, item, command):
217         item = item.cast (gdb.lookup_type("void").pointer())
218         item = long(item)
219         to_eval = "set $%s = (void *)0x%x\n"%(arg, item)
220         gdb.execute(to_eval)
221         gdb.execute(command)
222
223     def slist_iterator (self, arg, container, command):
224         l = container.cast (gdb.lookup_type("GSList").pointer())
225         while long(l) != 0:
226             self.do_iter (arg, l["data"], command)
227             l = l["next"]
228
229     def list_iterator (self, arg, container, command):
230         l = container.cast (gdb.lookup_type("GList").pointer())
231         while long(l) != 0:
232             self.do_iter (arg, l["data"], command)
233             l = l["next"]
234
235     def pick_iterator (self, container):
236         t = container.type.unqualified()
237         if t.code == gdb.TYPE_CODE_PTR:
238             t = t.target().unqualified()
239             t = str(t)
240             if t == "GSList":
241                 return self.slist_iterator
242             if t == "GList":
243                 return self.list_iterator
244         raise Exception("Invalid container type %s"%(str(container.type)))
245
246     def invoke (self, arg, from_tty):
247         (var, container, command) = self.parse_args(arg)
248         container = gdb.parse_and_eval (container)
249         func = self.pick_iterator(container)
250         func(var, container, command)
251
252 ForeachCommand ()