From 58e4ec577f3168eba282e9ad36257e9bee0702f2 Mon Sep 17 00:00:00 2001
From: Ben Longbons <b.r.longbons@gmail.com>
Date: Wed, 15 Oct 2014 16:41:14 -0700
Subject: Always print symbols if known for pointers

---
 src/compat/option.py         |  2 +-
 src/main-gdb-head.py         | 79 +++++++++++++++++++++++++++++++++++++++++---
 src/map/magic-expr.py        |  2 +-
 src/map/magic-interpreter.py |  4 +--
 src/map/magic-stmt.py        |  2 +-
 src/map/script-persist.py    | 18 +++++++---
 src/strings/xstring.py       | 12 +++----
 src/strings/zstring.py       | 12 +++----
 8 files changed, 104 insertions(+), 27 deletions(-)

(limited to 'src')

diff --git a/src/compat/option.py b/src/compat/option.py
index a410ac8..60a98d9 100644
--- a/src/compat/option.py
+++ b/src/compat/option.py
@@ -33,5 +33,5 @@ class Option(object):
             ('tmwa::None<int>()', 'None<int>'),
             ('tmwa::Some(1)', 'Some<int>(1)'),
             ('tmwa::Option<tmwa::Borrowed<int>>(tmwa::None)', 'None<tmwa::Borrowed<int>>'),
-            ('tmwa::Some(tmwa::borrow(option_borrow_thingy))', 'regex:Some<tmwa::Borrowed<int>>\(0x[0-9a-f]* <option_borrow_thingy>\)'),
+            ('tmwa::Some(tmwa::borrow(option_borrow_thingy))', 'Some<tmwa::Borrowed<int>>(<option_borrow_thingy>)'),
     ]
diff --git a/src/main-gdb-head.py b/src/main-gdb-head.py
index 2dac471..6ae204b 100644
--- a/src/main-gdb-head.py
+++ b/src/main-gdb-head.py
@@ -29,22 +29,55 @@ def get_basic_type(type_):
             type_ = type_.strip_typedefs()
     return type_.unqualified()
 
+def info_symbol(addr):
+    ''' returns (symbol, offset, section, lib or None) or None?
+    '''
+    info = gdb.execute('info symbol %d' % addr, to_string=True)
+    try:
+        sym_and_off, sec_and_lib = info.split(' in section ')
+    except ValueError:
+        return None
+    try:
+        sym, off = sym_and_off.split(' + ')
+    except ValueError:
+        sym = sym_and_off
+        off = 0
+    else:
+        off = int(off, 10)
+    try:
+        sec, lib = sec_and_lib.split(' of ')
+    except ValueError:
+        sec = sec_and_lib
+        lib = None
+    return (sym, off, sec, lib)
+
 def finish():
-    global finish, initial_globals, FastPrinters, EnumPrinter
+    global finish, initial_globals, FastPrinters, EnumPrinter, PointerPrinter
 
     final_globals = {id(v):v for v in globals().values()}
     diff = set(final_globals.keys()) - set(initial_globals.keys()) \
-            - {'finish', 'initial_globals', 'FastPrinters'}
+            - {
+                    'finish',
+                    'initial_globals',
+                    'FastPrinters',
+                    'EnumPrinter',
+                    'PointerPrinter',
+            }
     fp = FastPrinters()
     ep = EnumPrinter
+    ptrp = PointerPrinter
 
     # After this, don't access any more globals in this function.
-    del finish, initial_globals, FastPrinters, EnumPrinter
+    del finish, initial_globals, FastPrinters, EnumPrinter, PointerPrinter
 
     for i in diff:
         v = final_globals[i]
         if hasattr(v, 'children') or hasattr(v, 'to_string'):
             fp.add_printer(v)
+        # TODO see if there's a way to detect the top-level printers too
+        # the problem is that some of them collide and the order *is*
+        # important, but sets and dicts don't preserve order.
+        # Particularly, 'PointerPrinter' must come after 'FastPrinters'.
 
     obj = gdb.current_objfile()
     if obj is None:
@@ -53,9 +86,12 @@ def finish():
     else:
         filename = obj.filename
     obj.pretty_printers.append(fp)
+    n = len(obj.pretty_printers)
     obj.pretty_printers.append(ep)
-    print('Added %d+1 custom printers for %s'
-            % (len(fp.printers), filename))
+    obj.pretty_printers.append(ptrp)
+    n = len(obj.pretty_printers) - n
+    print('Added %d+%d custom printers for %s'
+            % (len(fp.printers), n, filename))
 
 class EnumPrinter(object):
     __slots__ = ('_value')
@@ -82,6 +118,39 @@ class EnumPrinter(object):
         scope = get_basic_type(v.type).tag
         return '%s::%s' % (scope, name)
 
+class PointerPrinter(object):
+    __slots__ = ('_value')
+    name = 'any-symbol-pointer'
+    enabled = True
+
+    def __new__(cls, v):
+        type = get_basic_type(v.type)
+        if type.code != gdb.TYPE_CODE_PTR:
+            return None
+        return object.__new__(cls)
+
+    def __init__(self, v):
+        self._value = v
+
+    def to_string(self):
+        v = self._value
+        addr = int(v.cast(gdb.lookup_type('uintptr_t')))
+        if not addr:
+            s = 'nullptr'
+        else:
+            try:
+                sym, off, sec, lib = info_symbol(addr)
+            except:
+                s = '<heap 0x%x>' % addr
+            else:
+                if off:
+                    s = '<%s+%d>' % off
+                else:
+                    s = '<%s>' % sym
+        # TODO should I add (type *) ?
+        return s
+
+
 class FastPrinters(object):
     ''' printer dispatch the way gdb *should* have done it
     '''
diff --git a/src/map/magic-expr.py b/src/map/magic-expr.py
index 0d9db55..c48b79b 100644
--- a/src/map/magic-expr.py
+++ b/src/map/magic-expr.py
@@ -34,5 +34,5 @@ class fun_t(object):
             ('static_cast<tmwa::magic::fun_t *>(nullptr)',
                 '(fun_t *) nullptr'),
             ('new tmwa::magic::fun_t{"name"_s, "sig"_s, \'\\0\', nullptr}',
-                'regex:\(fun_t \*\) = \{->name = "name", ->signature = "sig", ->ret_ty = 0 \'\\\\000\', ->fun = (0x)?0}'),
+                '(fun_t *) = {->name = "name", ->signature = "sig", ->ret_ty = 0 \'\\000\', ->fun = nullptr}'),
     ]
diff --git a/src/map/magic-interpreter.py b/src/map/magic-interpreter.py
index bbf135c..141cd22 100644
--- a/src/map/magic-interpreter.py
+++ b/src/map/magic-interpreter.py
@@ -177,7 +177,7 @@ class effect_t(object):
             ('tmwa::magic::effect_t(tmwa::magic::EffectEnd{}, tmwa::dumb_ptr<tmwa::magic::effect_t>())',
                 '{<tmwa::sexpr::Variant<tmwa::magic::EffectSkip, tmwa::magic::EffectAbort, tmwa::magic::EffectAssign, tmwa::magic::EffectForEach, tmwa::magic::EffectFor, tmwa::magic::EffectIf, tmwa::magic::EffectSleep, tmwa::magic::EffectScript, tmwa::magic::EffectBreak, tmwa::magic::EffectOp, tmwa::magic::EffectEnd, tmwa::magic::EffectCall>> = {(tmwa::magic::EffectEnd) = {<No data fields>}}, next = 0x0}'),
             ('tmwa::magic::effect_t(tmwa::magic::EffectCall{nullptr, tmwa::dumb_ptr<std::vector<tmwa::dumb_ptr<tmwa::magic::expr_t>>>(), tmwa::dumb_ptr<tmwa::magic::effect_t>()}, tmwa::dumb_ptr<tmwa::magic::effect_t>())',
-                '{<tmwa::sexpr::Variant<tmwa::magic::EffectSkip, tmwa::magic::EffectAbort, tmwa::magic::EffectAssign, tmwa::magic::EffectForEach, tmwa::magic::EffectFor, tmwa::magic::EffectIf, tmwa::magic::EffectSleep, tmwa::magic::EffectScript, tmwa::magic::EffectBreak, tmwa::magic::EffectOp, tmwa::magic::EffectEnd, tmwa::magic::EffectCall>> = {(tmwa::magic::EffectCall) = {formalv = 0x0, actualvp = 0x0, body = 0x0}}, next = 0x0}'),
+                '{<tmwa::sexpr::Variant<tmwa::magic::EffectSkip, tmwa::magic::EffectAbort, tmwa::magic::EffectAssign, tmwa::magic::EffectForEach, tmwa::magic::EffectFor, tmwa::magic::EffectIf, tmwa::magic::EffectSleep, tmwa::magic::EffectScript, tmwa::magic::EffectBreak, tmwa::magic::EffectOp, tmwa::magic::EffectEnd, tmwa::magic::EffectCall>> = {(tmwa::magic::EffectCall) = {formalv = nullptr, actualvp = 0x0, body = 0x0}}, next = 0x0}'),
     ]
 
 
@@ -211,5 +211,5 @@ class cont_activation_record_t(object):
             ('tmwa::magic::cont_activation_record_t(tmwa::magic::CarFor{42, tmwa::dumb_ptr<tmwa::magic::effect_t>(), 123, 456}, tmwa::dumb_ptr<tmwa::magic::effect_t>())',
                 '{<tmwa::sexpr::Variant<tmwa::magic::CarForEach, tmwa::magic::CarFor, tmwa::magic::CarProc>> = {(tmwa::magic::CarFor) = {id = 42, body = 0x0, current = 123, stop = 456}}, return_location = 0x0}'),
             ('tmwa::magic::cont_activation_record_t(tmwa::magic::CarProc{123, nullptr, tmwa::dumb_ptr<tmwa::magic::val_t[]>()}, tmwa::dumb_ptr<tmwa::magic::effect_t>())',
-                '{<tmwa::sexpr::Variant<tmwa::magic::CarForEach, tmwa::magic::CarFor, tmwa::magic::CarProc>> = {(tmwa::magic::CarProc) = {args_nr = 123, formalap = 0x0, old_actualpa = 0x0 = {sz = 0}}}, return_location = 0x0}'),
+                '{<tmwa::sexpr::Variant<tmwa::magic::CarForEach, tmwa::magic::CarFor, tmwa::magic::CarProc>> = {(tmwa::magic::CarProc) = {args_nr = 123, formalap = nullptr, old_actualpa = 0x0 = {sz = 0}}}, return_location = 0x0}'),
     ]
diff --git a/src/map/magic-stmt.py b/src/map/magic-stmt.py
index 14289ef..65f44a7 100644
--- a/src/map/magic-stmt.py
+++ b/src/map/magic-stmt.py
@@ -33,5 +33,5 @@ class op_t(object):
             ('static_cast<tmwa::magic::op_t *>(nullptr)',
                 '(op_t *) nullptr'),
             ('new tmwa::magic::op_t{"name"_s, "sig"_s, nullptr}',
-                'regex:\(op_t \*\) = \{->name = "name", ->signature = "sig", ->op = (0x)?0}'),
+                '(op_t *) = {->name = "name", ->signature = "sig", ->op = nullptr}'),
     ]
diff --git a/src/map/script-persist.py b/src/map/script-persist.py
index 454c828..df60cf4 100644
--- a/src/map/script-persist.py
+++ b/src/map/script-persist.py
@@ -3,7 +3,17 @@ class script_data(object):
 
     test_extra = '''
     using tmwa::operator "" _s;
-    #include "../map/script-parse.hpp"
+
+    #include "../map/script-parse-internal.hpp"
+
+    static
+    tmwa::Borrowed<const tmwa::ScriptBuffer> fake_script()
+    {
+        static
+        const std::vector<tmwa::ByteCode> buffer;
+        return borrow(reinterpret_cast<const tmwa::ScriptBuffer&>(buffer));
+    }
+
     '''
 
     tests = [
@@ -19,10 +29,8 @@ class script_data(object):
                 '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataArg) = {numi = 0}}, <No data fields>}'),
     ('tmwa::script_data(tmwa::ScriptDataVariable{tmwa::SIR()})',
                 '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataVariable) = {reg = {impl = 0}}}, <No data fields>}'),
-    # the {script = } is almost certainly a bug in gdb's 'set print address'
-    # but the most I can do is check for changes.
-    ('tmwa::script_data(tmwa::ScriptDataRetInfo{tmwa::borrow(*tmwa::parse_script("{}"_s, 1, true).release())})',
-        'regex:\{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = \{\(tmwa::ScriptDataRetInfo\) = \{script = \}\}, <No data fields>\}'),
+    ('tmwa::script_data(tmwa::ScriptDataRetInfo{fake_script()})',
+        '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataRetInfo) = {script = <fake_script()::buffer>}}, <No data fields>}'),
     ('tmwa::script_data(tmwa::ScriptDataFuncRef{404})',
                 '{<tmwa::sexpr::Variant<tmwa::ScriptDataPos, tmwa::ScriptDataInt, tmwa::ScriptDataParam, tmwa::ScriptDataStr, tmwa::ScriptDataArg, tmwa::ScriptDataVariable, tmwa::ScriptDataRetInfo, tmwa::ScriptDataFuncRef>> = {(tmwa::ScriptDataFuncRef) = {numi = 404}}, <No data fields>}'),
     ]
diff --git a/src/strings/xstring.py b/src/strings/xstring.py
index b2e33bb..ae764df 100644
--- a/src/strings/xstring.py
+++ b/src/strings/xstring.py
@@ -22,10 +22,10 @@ class XString(object):
     '''
 
     tests = [
-            ('tmwa::XString(""_s)', '"" = {base = 0x0}'),
-            ('tmwa::XString("Hello"_s)', '"Hello" = {base = 0x0}'),
-            ('tmwa::XString("' + str256[:-2] + '"_s)', '"' + str256[:-2] + '" = {base = 0x0}'),
-            ('tmwa::XString("' + str256[:-1] + '"_s)', '"' + str256[:-1] + '" = {base = 0x0}'),
-            ('tmwa::XString("' + str256 + '"_s)', '"' + str256 + '" = {base = 0x0}'),
-            ('tmwa::XString("' + str256 + 'x"_s)', '"' + str256 + 'x" = {base = 0x0}'),
+            ('tmwa::XString(""_s)', '"" = {base = nullptr}'),
+            ('tmwa::XString("Hello"_s)', '"Hello" = {base = nullptr}'),
+            ('tmwa::XString("' + str256[:-2] + '"_s)', '"' + str256[:-2] + '" = {base = nullptr}'),
+            ('tmwa::XString("' + str256[:-1] + '"_s)', '"' + str256[:-1] + '" = {base = nullptr}'),
+            ('tmwa::XString("' + str256 + '"_s)', '"' + str256 + '" = {base = nullptr}'),
+            ('tmwa::XString("' + str256 + 'x"_s)', '"' + str256 + 'x" = {base = nullptr}'),
     ]
diff --git a/src/strings/zstring.py b/src/strings/zstring.py
index f57252f..570c8f1 100644
--- a/src/strings/zstring.py
+++ b/src/strings/zstring.py
@@ -22,10 +22,10 @@ class ZString(object):
     '''
 
     tests = [
-            ('tmwa::ZString(""_s)', '"" = {base = 0x0}'),
-            ('tmwa::ZString("Hello"_s)', '"Hello" = {base = 0x0}'),
-            ('tmwa::ZString("' + str256[:-2] + '"_s)', '"' + str256[:-2] + '" = {base = 0x0}'),
-            ('tmwa::ZString("' + str256[:-1] + '"_s)', '"' + str256[:-1] + '" = {base = 0x0}'),
-            ('tmwa::ZString("' + str256 + '"_s)', '"' + str256 + '" = {base = 0x0}'),
-            ('tmwa::ZString("' + str256 + 'x"_s)', '"' + str256 + 'x" = {base = 0x0}'),
+            ('tmwa::ZString(""_s)', '"" = {base = nullptr}'),
+            ('tmwa::ZString("Hello"_s)', '"Hello" = {base = nullptr}'),
+            ('tmwa::ZString("' + str256[:-2] + '"_s)', '"' + str256[:-2] + '" = {base = nullptr}'),
+            ('tmwa::ZString("' + str256[:-1] + '"_s)', '"' + str256[:-1] + '" = {base = nullptr}'),
+            ('tmwa::ZString("' + str256 + '"_s)', '"' + str256 + '" = {base = nullptr}'),
+            ('tmwa::ZString("' + str256 + 'x"_s)', '"' + str256 + 'x" = {base = nullptr}'),
     ]
-- 
cgit v1.2.3-70-g09d2