Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -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) + ']'
@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'
)