gdb/python: new function to add values into GDB's history
authorAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 30 Jul 2021 11:56:34 +0000 (12:56 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 7 Sep 2021 09:54:07 +0000 (10:54 +0100)
The guile API has (history-append! <value>) to add values into GDB's
history list.  There is currently no equivalent in the Python API.

This commit adds gdb.add_history(<value>) to the Python API, this
function takes <value> a gdb.Value (or anything that can be passed to
the constructor of gdb.Value), and adds the value it represents to
GDB's history list.  The index of the newly added value is returned.

gdb/NEWS
gdb/doc/python.texi
gdb/python/py-value.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/testsuite/gdb.python/py-value.exp

index ec3058ea1187b39c6b510f57b4fafdd0563c4382..f94855204386c4e7e954a42dcba672d18b87e3ce 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -10,6 +10,13 @@ maint show backtrace-on-fatal-signal
   fatal signal.  This only supported on some platforms where the
   backtrace and backtrace_symbols_fd functions are available.
 
+* Python API
+
+  ** New function gdb.add_history(), which takes a gdb.Value object
+     and adds the value it represents to GDB's history list.  An
+     integer, the index of the new item in the history list, is
+     returned.
+
 *** Changes in GDB 11
 
 * The 'set disassembler-options' command now supports specifying options
index f4865b3d6a6bb68a4e8c86c5209a44fe3ef7bb4a..d8f682a091cb801293c1bbc969df7740c2217c63 100644 (file)
@@ -346,6 +346,20 @@ If no exception is raised, the return value is always an instance of
 @code{gdb.Value} (@pxref{Values From Inferior}).
 @end defun
 
+@defun gdb.add_history (value)
+Takes @var{value}, an instance of @code{gdb.Value} (@pxref{Values From
+Inferior}), and appends the value this object represents to
+@value{GDBN}'s value history (@pxref{Value History}), and return an
+integer, its history number.  If @var{value} is not a
+@code{gdb.Value}, it is is converted using the @code{gdb.Value}
+constructor.  If @var{value} can't be converted to a @code{gdb.Value}
+then a @code{TypeError} is raised.
+
+When a command implemented in Python prints a single @code{gdb.Value}
+as its result, then placing the value into the history will allow the
+user convenient access to those values via CLI history facilities.
+@end defun
+
 @findex gdb.convenience_variable
 @defun gdb.convenience_variable (name)
 Return the value of the convenience variable (@pxref{Convenience
index 8df8a15f8d6b2697118cadfd45d7aff55812dc0e..26d5940f8425f9fc93dcb1e68e81c827e211a64a 100644 (file)
@@ -1960,6 +1960,33 @@ gdbpy_history (PyObject *self, PyObject *args)
   return value_to_value_object (res_val);
 }
 
+/* Add a gdb.Value into GDB's history, and return (as an integer) the
+   position of the newly added value.  */
+PyObject *
+gdbpy_add_history (PyObject *self, PyObject *args)
+{
+  PyObject *value_obj;
+
+  if (!PyArg_ParseTuple (args, "O", &value_obj))
+    return nullptr;
+
+  struct value *value = convert_value_from_python (value_obj);
+  if (value == nullptr)
+    return nullptr;
+
+  try
+    {
+      int idx = record_latest_value (value);
+      return gdb_py_object_from_longest (idx).release ();
+    }
+  catch (const gdb_exception &except)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  return nullptr;
+}
+
 /* Return the value of a convenience variable.  */
 PyObject *
 gdbpy_convenience_variable (PyObject *self, PyObject *args)
index 690d2fb43c06c2336799dc9a3ff1816002cdba0f..0e140f1af61ef1e7d9b0ee62fa7115d1d08affda 100644 (file)
@@ -412,6 +412,7 @@ extern enum ext_lang_rc gdbpy_get_matching_xmethod_workers
 
 \f
 PyObject *gdbpy_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_add_history (PyObject *self, PyObject *args);
 PyObject *gdbpy_convenience_variable (PyObject *self, PyObject *args);
 PyObject *gdbpy_set_convenience_variable (PyObject *self, PyObject *args);
 PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
index e42cbc4fd5ee1bd6e85ff6badfcf93a2748e79ec..6af9c722e7b8f9a52f66f88f689845977befdb1b 100644 (file)
@@ -2076,6 +2076,8 @@ PyMethodDef python_GdbMethods[] =
 {
   { "history", gdbpy_history, METH_VARARGS,
     "Get a value from history" },
+  { "add_history", gdbpy_add_history, METH_VARARGS,
+    "Add a value to the value history list" },
   { "execute", (PyCFunction) execute_gdb_command, METH_VARARGS | METH_KEYWORDS,
     "execute (command [, from_tty] [, to_string]) -> [String]\n\
 Evaluate command, a string, as a gdb CLI command.  Optionally returns\n\
index eca4a4747273150170e962eec9658faa50d8f7e0..d9f1a76a388890f5f4f8c6ec800b7e16193baa06 100644 (file)
@@ -575,6 +575,31 @@ proc test_value_from_buffer {} {
           "attempt to construct value with string as type"
 }
 
+# Test the gdb.add_history API.
+proc test_add_to_history {} {
+    # Add a gdb.Value to the value history list.
+    gdb_test_no_output "python idx = gdb.add_history(gdb.Value(42))" \
+       "add value 42 to the history list"
+    gdb_test "python print (\"$%d = %s\" % (idx, gdb.history (idx)))" \
+       " = 42" "print value 42 from the history list"
+    set idx [get_python_valueof "idx" "**DEFAULT**" "get idx for value 42"]
+    gdb_test "print \$${idx}" " = 42"
+
+    # Add something to the history list that can be converted into a
+    # gdb.Value.
+    gdb_test_no_output "python idx = gdb.add_history(84)" \
+       "add value to 84 to the history list"
+    gdb_test "python print (\"$%d = %s\" % (idx, gdb.history (idx)))" \
+       " = 84" "print value 84 from the history list"
+    set idx [get_python_valueof "idx" "**DEFAULT**" "get idx for value 84"]
+    gdb_test "print \$${idx}" " = 84"
+
+    # Try adding something that can't be converted to a gdb.Value,
+    # this should give an error.
+    gdb_test "python idx = gdb.add_history(gdb.GdbError(\"an error\"))" \
+       "TypeError: Could not convert Python object: .*"
+}
+
 # Build C version of executable.  C++ is built later.
 if { [build_inferior "${binfile}" "c"] < 0 } {
     return -1
@@ -594,6 +619,7 @@ test_objfiles
 test_parse_and_eval
 test_value_hash
 test_float_conversion
+test_add_to_history
 
 # The following tests require execution.