Add pretty printer for hashtables
[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)