From 139b64df4c9dde811f57dbae6451c847e97ce16f Mon Sep 17 00:00:00 2001
From: pompolic <pompolic@special-circumstanc.es>
Date: Fri, 12 Nov 2021 20:56:53 +0100
Subject: [PATCH] Display parser backtrace and input preview on step

---
 gdb-port/parser-name-instrumentation-gdb.py | 32 +++++++++++++++++++--
 gdb-port/utility-commands.py                | 12 ++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/gdb-port/parser-name-instrumentation-gdb.py b/gdb-port/parser-name-instrumentation-gdb.py
index bbd98cb..e2a79d5 100644
--- a/gdb-port/parser-name-instrumentation-gdb.py
+++ b/gdb-port/parser-name-instrumentation-gdb.py
@@ -1,9 +1,9 @@
 # TODO: handlers for filters
 # TODO: postordinate parser fails to get named
 # TODO: step-to-parser command
-# TODO: stop splicing gdb.parse_and_eval commands together in parser-type-instrumentation
 # TODO: "current parser" on GUI is the one on top of the stack, while the argument of h_do_parse is not yet accounted for
 # TODO: possible enhancement, caching the vtable type in Parser objects (allows searching by type)
+# TODO: The parameter given to h_do_parse is not shown in the backtrace, which is confusing
 
 # quick way to get locals from frame.block()
 # {local.name : local for local in block}
@@ -390,6 +390,22 @@ class HArenaMallocRawBreakpoint(gdb.Breakpoint):
 
 		return False
 
+# GDB parameters
+# TODO: hammer parameter prefix
+
+class ExtendedParseStepInfo(gdb.Parameter):
+	"""Controls whether to display parser stack and input preview on stepping the parse."""
+	def __init__(self):
+		super(ExtendedParseStepInfo, self).__init__("hammer-extended-parse-step-info", gdb.COMMAND_OBSCURE, gdb.PARAM_BOOLEAN)
+		self.show_doc = "Show parser stack and input preview after hammer-parse-step:"
+		#self.set_doc = "Show parser stack and input preview after hammer-parse-step:"
+		self.value = True
+
+ExtendedParseStepInfo()
+
+# GDB commands
+
+# TODO: GDB help strings
 
 class HammerParserBacktrace(gdb.Command):
 	def __init__(self):
@@ -488,7 +504,19 @@ HammerParserTopTotalArenaMem()
 
 # TODO: average memory use, per arena and total
 
-# TODO: HammerParserPreviewInput
+class HammerParserPreviewInput(gdb.Command):
+	def __init__(self):
+		super(HammerParserPreviewInput, self).__init__("hammer-parser-preview-input", gdb.COMMAND_OBSCURE)
+
+	def invoke(self, arg, from_tty):
+		args = gdb.string_to_argv(arg)
+
+		print(top_level_parse.input_chunk)
+
+HammerParserPreviewInput()
+
+# TODO: a convenience feature for printing input preview + backtrace after step would be nice
+# idea: a configuration option which HammerParseStep could check, invoke the other 2 commands if true
 
 # Call when execution stopped at breakpoint in main
 def locate_perform_lowlevel_parse_retq():
diff --git a/gdb-port/utility-commands.py b/gdb-port/utility-commands.py
index b94e379..9e4a7ea 100644
--- a/gdb-port/utility-commands.py
+++ b/gdb-port/utility-commands.py
@@ -43,6 +43,18 @@ class HammerParseStep(gdb.Command):
 		if gdb.selected_inferior().pid > 0:
 			gdb.execute("continue")
 
+		# These are defined in parser-name-instrumentation.py, which we load after this, but this should be fine at runtime
+		# TODO: factor out commands into their own file
+		try:
+			if gdb.parameter("hammer-extended-parse-step-info"):
+				gdb.execute("hammer-parser-backtrace")
+				gdb.execute("hammer-parser-preview-input")
+		except RuntimeError as e:
+			# This probably means parser-name-instrumentation.py is not loaded.
+			#pass
+			print("Exception: %s" % e)
+			print("Probably caused by hammer-extended-parse-step-info parameter not existing")
+
 HammerParseStep()
 
 # Analogous to "continue", but for the parse process
-- 
GitLab