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