public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] gdb/python: add facility to add values into the history
@ 2021-08-20  8:48 Andrew Burgess
  2021-08-23 20:32 ` Tom Tromey
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Burgess @ 2021-08-20  8:48 UTC (permalink / raw)
  To: gdb-patches

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.history_add(<value>) to the Python API, this
function adds <value> into the history list, and returns the index of
the new item in the history list.

The <value> can be a gdb.Value object, or anything that can be passed
to the constructor of gdb.Value.
---
 gdb/NEWS                              |  6 ++++++
 gdb/doc/python.texi                   | 14 ++++++++++++++
 gdb/python/py-value.c                 | 27 +++++++++++++++++++++++++++
 gdb/python/python-internal.h          |  1 +
 gdb/python/python.c                   |  2 ++
 gdb/testsuite/gdb.python/py-value.exp | 26 ++++++++++++++++++++++++++
 6 files changed, 76 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index ec3058ea118..1436e35a4d0 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -10,6 +10,12 @@ 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.history_add(), which takes a gdb.Value object
+     and adds the value 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
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index f4865b3d6a6..395f49229c4 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -346,6 +346,20 @@
 @code{gdb.Value} (@pxref{Values From Inferior}).
 @end defun
 
+@findex gdb.history_add
+@defun gdb.history_add (value)
+Append @var{value}, an instance of @code{gdb.Value} (@pxref{Values
+From Inferior}), to @value{GDBN}'s value history (@pxref{Value
+History}) and return an integer, its index in the history.  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
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 8df8a15f8d6..e636fbd4cb7 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -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_history_add (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)
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 690d2fb43c0..c74a60c4691 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -412,6 +412,7 @@ extern enum ext_lang_rc gdbpy_get_matching_xmethod_workers
 
 \f
 PyObject *gdbpy_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_history_add (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 *);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e42cbc4fd5e..351b93069a0 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -2076,6 +2076,8 @@ PyMethodDef python_GdbMethods[] =
 {
   { "history", gdbpy_history, METH_VARARGS,
     "Get a value from history" },
+  { "history_add", gdbpy_history_add, 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\
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index eca4a474727..ef0355c76b1 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -575,6 +575,31 @@ proc test_value_from_buffer {} {
 	   "attempt to construct value with string as type"
 }
 
+# Test the gdb.history_add API.
+proc test_add_to_history {} {
+    # Add a gdb.Value to the value history list.
+    gdb_test_no_output "python idx = gdb.history_add(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.history_add(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.history_add(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.
 
-- 
2.25.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] gdb/python: add facility to add values into the history
  2021-08-20  8:48 [PATCH] gdb/python: add facility to add values into the history Andrew Burgess
@ 2021-08-23 20:32 ` Tom Tromey
  2021-08-25 17:27   ` [PATCHv2] " Andrew Burgess
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2021-08-23 20:32 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:

Andrew> The guile API has (history-append! <value>) to add values into GDB's
Andrew> history list.  There is currently no equivalent in the Python API.

Andrew> This commit adds gdb.history_add(<value>) to the Python API, this
Andrew> function adds <value> into the history list, and returns the index of
Andrew> the new item in the history list.

Andrew> The <value> can be a gdb.Value object, or anything that can be passed
Andrew> to the constructor of gdb.Value.

This seems fine to me, though I think that normally the gdb Python API
uses "verb_object" instead of "object_verb", so I'd expect "add_history"
as the name instead.

However I don't feel all that strongly about it.
Thanks for doing this.

Tom

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCHv2] gdb/python: add facility to add values into the history
  2021-08-23 20:32 ` Tom Tromey
@ 2021-08-25 17:27   ` Andrew Burgess
  2021-08-25 18:01     ` Eli Zaretskii
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Burgess @ 2021-08-25 17:27 UTC (permalink / raw)
  To: gdb-patches

Tom,

Thanks for the feedback.  I've changed history_add to add_history
throughout.  Nothing else has changed, so it probably doesn't need a
code review.

I'll just wait for a docs review before merging.

Thanks,
Andrew


---

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 adds <value> into the history list, and returns the index of
the new item in the history list.

The <value> can be a gdb.Value object, or anything that can be passed
to the constructor of gdb.Value.
---
 gdb/NEWS                              |  6 ++++++
 gdb/doc/python.texi                   | 14 ++++++++++++++
 gdb/python/py-value.c                 | 27 +++++++++++++++++++++++++++
 gdb/python/python-internal.h          |  1 +
 gdb/python/python.c                   |  2 ++
 gdb/testsuite/gdb.python/py-value.exp | 26 ++++++++++++++++++++++++++
 6 files changed, 76 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index ec3058ea118..08a7651b08a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -10,6 +10,12 @@ 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 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
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index f4865b3d6a6..1363c539e08 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -346,6 +346,20 @@
 @code{gdb.Value} (@pxref{Values From Inferior}).
 @end defun
 
+@findex gdb.add_history
+@defun gdb.add_history (value)
+Append @var{value}, an instance of @code{gdb.Value} (@pxref{Values
+From Inferior}), 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
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 8df8a15f8d6..26d5940f842 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -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)
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 690d2fb43c0..0e140f1af61 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -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 *);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e42cbc4fd5e..6af9c722e7b 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -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\
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index eca4a474727..d9f1a76a388 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -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.
 
-- 
2.25.4


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2] gdb/python: add facility to add values into the history
  2021-08-25 17:27   ` [PATCHv2] " Andrew Burgess
@ 2021-08-25 18:01     ` Eli Zaretskii
  2021-08-26  9:20       ` Andrew Burgess
  0 siblings, 1 reply; 7+ messages in thread
From: Eli Zaretskii @ 2021-08-25 18:01 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Wed, 25 Aug 2021 18:27:19 +0100
> 
> +* Python API
> +
> +  ** New function gdb.add_history(), which takes a gdb.Value object
> +     and adds the value to GDB's history list.  An integer, the index
                 ^^^^^^^^^
"its value", right?

> +@findex gdb.add_history

You don''t need @findex here, since @defun produces that
automatically.

> +Append @var{value}, an instance of @code{gdb.Value} (@pxref{Values
> +From Inferior}), to @value{GDBN}'s value history (@pxref{Value

This sounds like it appends the Python object to the history, but in
reality it appends its value, right?

> +History}) and return an integer, its history number.  If @var{value}
            ^
Comma missing there.

Thanks.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2] gdb/python: add facility to add values into the history
  2021-08-25 18:01     ` Eli Zaretskii
@ 2021-08-26  9:20       ` Andrew Burgess
  2021-08-26  9:40         ` Eli Zaretskii
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Burgess @ 2021-08-26  9:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

* Eli Zaretskii <eliz@gnu.org> [2021-08-25 21:01:50 +0300]:

> > From: Andrew Burgess <andrew.burgess@embecosm.com>
> > Date: Wed, 25 Aug 2021 18:27:19 +0100
> > 
> > +* Python API
> > +
> > +  ** New function gdb.add_history(), which takes a gdb.Value object
> > +     and adds the value to GDB's history list.  An integer, the index
>                  ^^^^^^^^^
> "its value", right?

I don't know, that doesn't sound right to me.  'its value' seems to
imply a value that belongs to someone/something, but I don't think
that's the case here.

Maybe, '...takes a gdb.Value object and adds it to GDB's history list.' ?

How about that?

> 
> > +@findex gdb.add_history
> 
> You don''t need @findex here, since @defun produces that
> automatically.

OK, thanks.

> 
> > +Append @var{value}, an instance of @code{gdb.Value} (@pxref{Values
> > +From Inferior}), to @value{GDBN}'s value history (@pxref{Value
> 
> This sounds like it appends the Python object to the history, but in
> reality it appends its value, right?

You're absolutely correct, but does the user care?  If the user tries
to get the value back from the history list in Python then they will
always get a gdb.Value object returned, though not the same object, it
will represent the same value.

I guess I'm just wondering if the extra complexity of explaining how
this works actually helps the user at all?

Anyway, here's my attempt to explain all this:

  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.

Thoughts?

> 
> > +History}) and return an integer, its history number.  If @var{value}
>             ^
> Comma missing there.

OK, thanks.

Thanks,
Andrew

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2] gdb/python: add facility to add values into the history
  2021-08-26  9:20       ` Andrew Burgess
@ 2021-08-26  9:40         ` Eli Zaretskii
  2021-09-07  9:56           ` Andrew Burgess
  0 siblings, 1 reply; 7+ messages in thread
From: Eli Zaretskii @ 2021-08-26  9:40 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

> Date: Thu, 26 Aug 2021 10:20:02 +0100
> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Cc: gdb-patches@sourceware.org
> 
> * Eli Zaretskii <eliz@gnu.org> [2021-08-25 21:01:50 +0300]:
> 
> > > From: Andrew Burgess <andrew.burgess@embecosm.com>
> > > Date: Wed, 25 Aug 2021 18:27:19 +0100
> > > 
> > > +* Python API
> > > +
> > > +  ** New function gdb.add_history(), which takes a gdb.Value object
> > > +     and adds the value to GDB's history list.  An integer, the index
> >                  ^^^^^^^^^
> > "its value", right?
> 
> I don't know, that doesn't sound right to me.  'its value' seems to
> imply a value that belongs to someone/something, but I don't think
> that's the case here.
> 
> Maybe, '...takes a gdb.Value object and adds it to GDB's history list.' ?

No, that's worse, because you don't add the Python object to the
history.

How about if you use the same wording you suggested for the manual:
"the value it represents"?

>   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.

This text is fine, thanks.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2] gdb/python: add facility to add values into the history
  2021-08-26  9:40         ` Eli Zaretskii
@ 2021-09-07  9:56           ` Andrew Burgess
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Burgess @ 2021-09-07  9:56 UTC (permalink / raw)
  To: gdb-patches

* Eli Zaretskii <eliz@gnu.org> [2021-08-26 12:40:18 +0300]:

> > Date: Thu, 26 Aug 2021 10:20:02 +0100
> > From: Andrew Burgess <andrew.burgess@embecosm.com>
> > Cc: gdb-patches@sourceware.org
> > 
> > * Eli Zaretskii <eliz@gnu.org> [2021-08-25 21:01:50 +0300]:
> > 
> > > > From: Andrew Burgess <andrew.burgess@embecosm.com>
> > > > Date: Wed, 25 Aug 2021 18:27:19 +0100
> > > > 
> > > > +* Python API
> > > > +
> > > > +  ** New function gdb.add_history(), which takes a gdb.Value object
> > > > +     and adds the value to GDB's history list.  An integer, the index
> > >                  ^^^^^^^^^
> > > "its value", right?
> > 
> > I don't know, that doesn't sound right to me.  'its value' seems to
> > imply a value that belongs to someone/something, but I don't think
> > that's the case here.
> > 
> > Maybe, '...takes a gdb.Value object and adds it to GDB's history list.' ?
> 
> No, that's worse, because you don't add the Python object to the
> history.
> 
> How about if you use the same wording you suggested for the manual:
> "the value it represents"?

Excellent, I'll do that.  The final version of the patch I pushed is
below.

Thanks for the review.

Andrew

---

commit 10effdd0d48947b41eb89426d0a408b2421c3d27
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Fri Jul 30 12:56:34 2021 +0100

    gdb/python: new function to add values into GDB's history
    
    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.

diff --git a/gdb/NEWS b/gdb/NEWS
index ec3058ea118..f9485520438 100644
--- 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
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index f4865b3d6a6..d8f682a091c 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -346,6 +346,20 @@
 @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
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 8df8a15f8d6..26d5940f842 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -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)
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 690d2fb43c0..0e140f1af61 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -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 *);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e42cbc4fd5e..6af9c722e7b 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -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\
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index eca4a474727..d9f1a76a388 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -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.
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-09-07  9:56 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-20  8:48 [PATCH] gdb/python: add facility to add values into the history Andrew Burgess
2021-08-23 20:32 ` Tom Tromey
2021-08-25 17:27   ` [PATCHv2] " Andrew Burgess
2021-08-25 18:01     ` Eli Zaretskii
2021-08-26  9:20       ` Andrew Burgess
2021-08-26  9:40         ` Eli Zaretskii
2021-09-07  9:56           ` Andrew Burgess

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).