Tizen 2.1 base
[platform/upstream/glib2.0.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.keys = ht["keys"]
80                 self.values = ht["values"]
81                 self.hashes = ht["hashes"]
82                 self.size = ht["size"]
83             self.pos = 0
84             self.keys_are_strings = keys_are_strings
85             self.value = None
86
87         def __iter__(self):
88             return self
89
90         def next(self):
91             if self.ht == 0:
92                 raise StopIteration
93             if self.value != None:
94                 v = self.value
95                 self.value = None
96                 return v
97             while long(self.pos) < long(self.size):
98                 self.pos = self.pos + 1
99                 if long (self.hashes[self.pos]) >= 2:
100                     key = self.keys[self.pos]
101                     val = self.values[self.pos]
102
103                     if self.keys_are_strings:
104                         key = key.cast (gdb.lookup_type("char").pointer())
105
106                     # Queue value for next result
107                     self.value = ('[%dv]'% (self.pos), val)
108
109                     # Return key
110                     return ('[%dk]'% (self.pos), key)
111             raise StopIteration
112
113     def __init__ (self, val):
114         self.val = val
115         self.keys_are_strings = False
116         try:
117             string_hash = read_global_var ("g_str_hash")
118         except:
119             string_hash = None
120         if self.val != 0 and string_hash != None and self.val["hash_func"] == string_hash:
121             self.keys_are_strings = True
122
123     def children(self):
124         return self._iterator(self.val, self.keys_are_strings)
125
126     def to_string (self):
127         return  "0x%x" % (long(self.val))
128
129     def display_hint (self):
130         return "map"
131
132 def pretty_printer_lookup (val):
133     if is_g_type_instance (val):
134         return GTypePrettyPrinter (val)
135
136 def pretty_printer_lookup (val):
137     # None yet, want things like hash table and list
138
139     type = val.type.unqualified()
140
141     # If it points to a reference, get the reference.
142     if type.code == gdb.TYPE_CODE_REF:
143         type = type.target ()
144
145     if type.code == gdb.TYPE_CODE_PTR:
146         type = type.target().unqualified()
147         t = str(type)
148         if t == "GList":
149             return GListPrinter(val, "GList")
150         if t == "GSList":
151             return GListPrinter(val, "GSList")
152         if t == "GHashTable":
153             return GHashPrinter(val)
154     else:
155         t = str(type)
156         if t == "GList":
157             return GListNodePrinter(val)
158         if t == "GSList *":
159             return GListPrinter(val, "GSList")
160     return None
161
162 def register (obj):
163     if obj == None:
164         obj = gdb
165
166     obj.pretty_printers.append(pretty_printer_lookup)
167
168 class ForeachCommand (gdb.Command):
169     """Foreach on list"""
170
171     def __init__ (self):
172         super (ForeachCommand, self).__init__ ("gforeach",
173                                                gdb.COMMAND_DATA,
174                                                gdb.COMPLETE_SYMBOL)
175
176     def valid_name (self, name):
177         if not name[0].isalpha():
178             return False
179         return True
180
181     def parse_args (self, arg):
182         i = arg.find(" ")
183         if i <= 0:
184             raise Exception ("No var specified")
185         var = arg[:i]
186         if not self.valid_name(var):
187             raise Exception ("Invalid variable name")
188
189         while i < len (arg) and arg[i].isspace():
190             i = i + 1
191
192         if arg[i:i+2] != "in":
193             raise Exception ("Invalid syntax, missing in")
194
195         i = i + 2
196
197         while i < len (arg) and arg[i].isspace():
198             i = i + 1
199
200         colon = arg.find (":", i)
201         if colon == -1:
202             raise Exception ("Invalid syntax, missing colon")
203
204         val = arg[i:colon]
205
206         colon = colon + 1
207         while colon < len (arg) and arg[colon].isspace():
208             colon = colon + 1
209
210         command = arg[colon:]
211
212         return (var, val, command)
213
214     def do_iter(self, arg, item, command):
215         item = item.cast (gdb.lookup_type("void").pointer())
216         item = long(item)
217         to_eval = "set $%s = (void *)0x%x\n"%(arg, item)
218         gdb.execute(to_eval)
219         gdb.execute(command)
220
221     def slist_iterator (self, arg, container, command):
222         l = container.cast (gdb.lookup_type("GSList").pointer())
223         while long(l) != 0:
224             self.do_iter (arg, l["data"], command)
225             l = l["next"]
226
227     def list_iterator (self, arg, container, command):
228         l = container.cast (gdb.lookup_type("GList").pointer())
229         while long(l) != 0:
230             self.do_iter (arg, l["data"], command)
231             l = l["next"]
232
233     def pick_iterator (self, container):
234         t = container.type.unqualified()
235         if t.code == gdb.TYPE_CODE_PTR:
236             t = t.target().unqualified()
237             t = str(t)
238             if t == "GSList":
239                 return self.slist_iterator
240             if t == "GList":
241                 return self.list_iterator
242         raise Exception("Invalid container type %s"%(str(container.type)))
243
244     def invoke (self, arg, from_tty):
245         (var, container, command) = self.parse_args(arg)
246         container = gdb.parse_and_eval (container)
247         func = self.pick_iterator(container)
248         func(var, container, command)
249
250 ForeachCommand ()