[Scummvm-git-logs] scummvm master -> d8fa25e3e74285e7882b68f980cc084e13da4c9b
sev-
noreply at scummvm.org
Tue Jan 6 23:44:13 UTC 2026
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
d8fa25e3e7 DEVTOOLS: Add LLDB pretty-printers
Commit: d8fa25e3e74285e7882b68f980cc084e13da4c9b
https://github.com/scummvm/scummvm/commit/d8fa25e3e74285e7882b68f980cc084e13da4c9b
Author: Dries Harnie (dries at harnie.be)
Date: 2026-01-07T02:44:08+03:00
Commit Message:
DEVTOOLS: Add LLDB pretty-printers
Changed paths:
A devtools/lldb_pretty_printers.py
diff --git a/devtools/lldb_pretty_printers.py b/devtools/lldb_pretty_printers.py
new file mode 100644
index 00000000000..236705e3a50
--- /dev/null
+++ b/devtools/lldb_pretty_printers.py
@@ -0,0 +1,206 @@
+'''
+This file contains LLDB pretty-printers for common ScummVM data types.
+To enable it, add the following line to the .lldbinit file for this project:
+
+ command script import devtools.lldb_pretty_printers
+
+LLDB disallows loading .lldbinit files from source directories by default, so
+you may need to add the following to your global ~/.lldbinit:
+
+ settings set target.load-cwd-lldbinit true
+
+
+'''
+from dataclasses import dataclass
+import lldb
+
+
+class ArrayProvider:
+ '''Formatter for Common::Array'''
+ def __init__(self, valobj, internal_dict):
+ self.valobj = valobj
+ self.data_type = self.valobj.GetChildMemberWithName("_storage").GetType().GetPointeeType()
+ self.data_size = self.data_type.GetByteSize()
+ self.update()
+
+ def update(self):
+ self.size = \
+ self.valobj.GetChildMemberWithName("_size").GetValueAsUnsigned()
+ return False
+
+ def num_children(self, _max_children=None):
+ return self.size
+
+ def has_children(self):
+ return self.size > 0
+
+ def get_child_index(self, name):
+ try:
+ return int(name.lstrip("[").rstrip("]"))
+ except ValueError:
+ return -1
+
+ def get_child_at_index(self, index):
+ if index < 0:
+ return None
+ if index >= self.num_children():
+ return None
+ base = self.valobj.GetChildMemberWithName("_storage")
+ offset = index * self.data_size
+ return base.CreateChildAtOffset(
+ f"[{index}]", offset, self.data_type
+ )
+
+
+class HashMapProvider:
+ '''Formatter for Common::HashMap'''
+ def __init__(self, valobj, internal_dict):
+ self.valobj = valobj
+ self.update()
+
+ def update(self):
+ self.children_with_values = []
+ self.size = \
+ self.valobj.GetChildMemberWithName("_size").GetValueAsUnsigned()
+ self.mask = \
+ self.valobj.GetChildMemberWithName("_mask").GetValueAsUnsigned()
+ self.storage = self.valobj.GetChildMemberWithName("_storage")
+ for i in range(self.mask + 1):
+ child = self.storage.GetChildAtIndex(i, lldb.eNoDynamicValues, True)
+ if child.GetValueAsUnsigned() != 0:
+ self.children_with_values.append(child)
+ return False
+
+ def num_children(self, _max_children=None):
+ return self.size
+
+ def has_children(self):
+ return self.size > 0
+
+ def get_child_index(self, name):
+ return next((c for c in self.children_with_values if c.GetName() == name), -1)
+
+ def get_child_at_index(self, index):
+ if index < 0:
+ return None
+ if index >= self.num_children():
+ return None
+
+ return self.children_with_values[index].Dereference()
+
+
+class ListProvider:
+ '''Formatter for Common::List'''
+ def __init__(self, valobj, internal_dict):
+ self.valobj = valobj
+ self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
+ self.node_offset = self.valobj.GetType().FindDirectNestedType("NodeBase").GetByteSize()
+ self.update()
+
+ def update(self):
+ self.anchor = self.valobj.GetChildMemberWithName("_anchor")
+
+ self.size = 0
+ cur = self.anchor
+ while True:
+ cur = cur.GetChildMemberWithName("_next").Dereference()
+ if cur.AddressOf().GetValueAsUnsigned() == self.anchor.AddressOf().GetValueAsUnsigned():
+ break
+ self.size = self.size + 1
+ return False
+
+ def num_children(self, _max_children=None):
+ return self.size
+
+ def has_children(self):
+ _prev = self.anchor.GetChildMemberWithName("_prev").GetValueAsUnsigned()
+ _next = self.anchor.AddressOf().GetValueAsUnsigned()
+ return _prev != _next
+
+ def get_child_index(self, name):
+ try:
+ return int(name.lstrip("[").rstrip("]"))
+ except:
+ return -1
+
+ def get_child_at_index(self, index):
+ if index < 0 or index >= self.size:
+ return None
+
+ cur = self.anchor
+ for _ in range(index):
+ cur = cur.GetChildMemberWithName("_next").Dereference()
+
+ return cur.CreateChildAtOffset(f'[{index}]', self.node_offset, self.element_type)
+
+
+def array_summary(valobj, internal):
+ size = valobj.GetNonSyntheticValue().GetChildMemberWithName('_size').GetValueAsUnsigned()
+ if size == 0:
+ return "(empty)"
+ if size == 1:
+ return "1 item"
+ return f"{size} items"
+
+
+def construct_matrix_summary(rows, cols):
+ lines = []
+ for r in range(rows):
+ line = " ".join(f'${{var._values[{r*cols+c}]}}' for c in range(cols))
+ lines.append(line)
+ return '[' + "; ".join(lines) + ']'
+
+ at dataclass(frozen=True)
+class Pattern:
+ pattern: str
+
+summaries = {
+ 'Common::String': r'${var._str%s}',
+
+ 'Common::Rect': r'(${var.left},${var.top}) -> (${var.right}, ${var.bottom})',
+ 'Math::Vector2d': r'(${var._values[0]}, ${var._values[1]})',
+ 'Math::Vector3d': r'(${var._values[0]}, ${var._values[1]}, ${var._values[2]})',
+ 'Math::Vector4d': r'(${var._values[0]}, ${var._values[1]}, ${var._values[2]}, ${var._values[3]})',
+ 'Math::Quaternion': r'(${var._values[0]}, ${var._values[1]}, ${var._values[2]}, ${var._values[3]})',
+ 'Math::Matrix4': construct_matrix_summary(4,4),
+ 'Math::Matrix3': construct_matrix_summary(3,3),
+
+ 'Graphics::Surface': r'(${var.w},${var.h}) (bpp=${var.format.bytesPerPixel:d})',
+ Pattern('^Common::HashMap<.*>::Node'): r'\{key: ${var._key}, value: ${var._value}\}',
+ Pattern('^Common::Array<.*>$'): array_summary,
+ Pattern('^Common::List<.*>$'): r'${svar%#} items',
+}
+
+providers = {
+ Pattern('^Common::Array<.*>$'): ArrayProvider,
+ Pattern('^Common::HashMap<.*>$'): HashMapProvider,
+ Pattern('^Common::List<.*>$'): ListProvider,
+}
+
+
+def __lldb_init_module(debugger, unused):
+ #lldb.formatters.Logger._lldb_formatters_debug_level = 2
+ print('Loading ScummVM formatters...')
+ for klass, summary in summaries.items():
+ if callable(summary):
+ summary = f'-F {__name__}.{summary.__name__}'
+ else:
+ summary = f'--summary-string "{summary}"'
+
+ if isinstance(klass, Pattern):
+ debugger.HandleCommand(
+ f'type summary add -x "{klass.pattern}" --category scummvm {summary}'
+ )
+ else:
+ debugger.HandleCommand(
+ f'type summary add "{klass}" --category scummvm {summary}'
+ )
+
+ for klass, provider in providers.items():
+ debugger.HandleCommand(
+ f'type synthetic add -x --category scummvm --python-class {__name__}.{provider.__name__} "{klass.pattern}"'
+ )
+
+ debugger.HandleCommand(
+ r'type category enable scummvm'
+ )
More information about the Scummvm-git-logs
mailing list