[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / glib / glib.py
index b2cccb3..f7fe22b 100644 (file)
@@ -1,4 +1,8 @@
 import gdb
+import sys
+
+if sys.version_info[0] >= 3:
+    long = int
 
 # This is not quite right, as local vars may override symname
 def read_global_var (symname):
@@ -10,14 +14,156 @@ def g_quark_to_string (quark):
     quark = long(quark)
     if quark == 0:
         return None
-    val = read_global_var ("g_quarks")
-    max_q = long(read_global_var ("g_quark_seq_id"))
+    try:
+        val = read_global_var ("quarks")
+        max_q = long(read_global_var ("quark_seq_id"))
+    except:
+        try:
+            val = read_global_var ("g_quarks")
+            max_q = long(read_global_var ("g_quark_seq_id"))
+        except:
+            return None;
     if quark < max_q:
         return val[quark].string()
     return None
 
+# We override the node printers too, so that node->next is not expanded
+class GListNodePrinter:
+    "Prints a GList node"
+
+    def __init__ (self, val):
+        self.val = val
+
+    def to_string (self):
+        return "{data=%s, next=0x%x, prev=0x%x}" % (str(self.val["data"]), long(self.val["next"]), long(self.val["prev"]))
+
+class GSListNodePrinter:
+    "Prints a GSList node"
+
+    def __init__ (self, val):
+        self.val = val
+
+    def to_string (self):
+        return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
+
+class GListPrinter:
+    "Prints a GList"
+
+    class _iterator:
+        def __init__(self, head, listtype):
+            self.link = head
+            self.listtype = listtype
+            self.count = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.link == 0:
+                raise StopIteration
+            data = self.link['data']
+            self.link = self.link['next']
+            count = self.count
+            self.count = self.count + 1
+            return ('[%d]' % count, data)
+
+    def __init__ (self, val, listtype):
+        self.val = val
+        self.listtype = listtype
+
+    def children(self):
+        return self._iterator(self.val, self.listtype)
+
+    def to_string (self):
+        return  "0x%x" % (long(self.val))
+
+    def display_hint (self):
+        return "array"
+
+class GHashPrinter:
+    "Prints a GHashTable"
+
+    class _iterator:
+        def __init__(self, ht, keys_are_strings):
+            self.ht = ht
+            if ht != 0:
+                self.keys = ht["keys"]
+                self.values = ht["values"]
+                self.hashes = ht["hashes"]
+                self.size = ht["size"]
+            self.pos = 0
+            self.keys_are_strings = keys_are_strings
+            self.value = None
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            if self.ht == 0:
+                raise StopIteration
+            if self.value != None:
+                v = self.value
+                self.value = None
+                return v
+            while long(self.pos) < long(self.size):
+                self.pos = self.pos + 1
+                if long (self.hashes[self.pos]) >= 2:
+                    key = self.keys[self.pos]
+                    val = self.values[self.pos]
+
+                    if self.keys_are_strings:
+                        key = key.cast (gdb.lookup_type("char").pointer())
+
+                    # Queue value for next result
+                    self.value = ('[%dv]'% (self.pos), val)
+
+                    # Return key
+                    return ('[%dk]'% (self.pos), key)
+            raise StopIteration
+
+    def __init__ (self, val):
+        self.val = val
+        self.keys_are_strings = False
+        try:
+            string_hash = read_global_var ("g_str_hash")
+        except:
+            string_hash = None
+        if self.val != 0 and string_hash != None and self.val["hash_func"] == string_hash:
+            self.keys_are_strings = True
+
+    def children(self):
+        return self._iterator(self.val, self.keys_are_strings)
+
+    def to_string (self):
+        return  "0x%x" % (long(self.val))
+
+    def display_hint (self):
+        return "map"
+
 def pretty_printer_lookup (val):
     # None yet, want things like hash table and list
+
+    type = val.type.unqualified()
+
+    # If it points to a reference, get the reference.
+    if type.code == gdb.TYPE_CODE_REF:
+        type = type.target ()
+
+    if type.code == gdb.TYPE_CODE_PTR:
+        type = type.target().unqualified()
+        t = str(type)
+        if t == "GList":
+            return GListPrinter(val, "GList")
+        if t == "GSList":
+            return GListPrinter(val, "GSList")
+        if t == "GHashTable":
+            return GHashPrinter(val)
+    else:
+        t = str(type)
+        if t == "GList":
+            return GListNodePrinter(val)
+        if t == "GSList *":
+            return GListPrinter(val, "GSList")
     return None
 
 def register (obj):
@@ -25,3 +171,87 @@ def register (obj):
         obj = gdb
 
     obj.pretty_printers.append(pretty_printer_lookup)
+
+class ForeachCommand (gdb.Command):
+    """Foreach on list"""
+
+    def __init__ (self):
+        super (ForeachCommand, self).__init__ ("gforeach",
+                                               gdb.COMMAND_DATA,
+                                               gdb.COMPLETE_SYMBOL)
+
+    def valid_name (self, name):
+        if not name[0].isalpha():
+            return False
+        return True
+
+    def parse_args (self, arg):
+        i = arg.find(" ")
+        if i <= 0:
+            raise Exception ("No var specified")
+        var = arg[:i]
+        if not self.valid_name(var):
+            raise Exception ("Invalid variable name")
+
+        while i < len (arg) and arg[i].isspace():
+            i = i + 1
+
+        if arg[i:i+2] != "in":
+            raise Exception ("Invalid syntax, missing in")
+
+        i = i + 2
+
+        while i < len (arg) and arg[i].isspace():
+            i = i + 1
+
+        colon = arg.find (":", i)
+        if colon == -1:
+            raise Exception ("Invalid syntax, missing colon")
+
+        val = arg[i:colon]
+
+        colon = colon + 1
+        while colon < len (arg) and arg[colon].isspace():
+            colon = colon + 1
+
+        command = arg[colon:]
+
+        return (var, val, command)
+
+    def do_iter(self, arg, item, command):
+        item = item.cast (gdb.lookup_type("void").pointer())
+        item = long(item)
+        to_eval = "set $%s = (void *)0x%x\n"%(arg, item)
+        gdb.execute(to_eval)
+        gdb.execute(command)
+
+    def slist_iterator (self, arg, container, command):
+        l = container.cast (gdb.lookup_type("GSList").pointer())
+        while long(l) != 0:
+            self.do_iter (arg, l["data"], command)
+            l = l["next"]
+
+    def list_iterator (self, arg, container, command):
+        l = container.cast (gdb.lookup_type("GList").pointer())
+        while long(l) != 0:
+            self.do_iter (arg, l["data"], command)
+            l = l["next"]
+
+    def pick_iterator (self, container):
+        t = container.type.unqualified()
+        if t.code == gdb.TYPE_CODE_PTR:
+            t = t.target().unqualified()
+            t = str(t)
+            if t == "GSList":
+                return self.slist_iterator
+            if t == "GList":
+                return self.list_iterator
+        raise Exception("Invalid container type %s"%(str(container.type)))
+
+    def invoke (self, arg, from_tty):
+        (var, container, command) = self.parse_args(arg)
+        container = gdb.parse_and_eval (container)
+        func = self.pick_iterator(container)
+        func(var, container, command)
+
+ForeachCommand ()