* [RFA][python] Fixes for existing Python code.
@ 2009-02-02 13:06 Thiago Jung Bauermann
2009-02-02 13:19 ` Thiago Jung Bauermann
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Thiago Jung Bauermann @ 2009-02-02 13:06 UTC (permalink / raw)
To: gdb-patches ml
Hi,
This patch has some fixes for the Python code which is currently in.
They are the following:
- add from_tty argument to execute_gdb_command;
- fix error checking of function PyRun_SimpleString;
- reorganize python.c to minimize forward declarations;
- properly check Python booleans.
I'd also like to remind that the following patches for Python support
are still pending:
http://sourceware.org/ml/gdb-patches/2009-01/msg00016.html
http://sourceware.org/ml/gdb-patches/2009-01/msg00003.html
http://sourceware.org/ml/gdb-patches/2009-01/msg00004.html
This patch and the next two that I'm posting are on top of the three
patches above.
Ok to commit?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
gdb/
2009-02-02 Tom Tromey <tromey@redhat.com>
Phil Muldoon <pmuldoon@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* python/python-value.c (convert_value_from_python): Properly check
Python booleans.
* python/python.c (GdbMethods): Move to bottom of file.
(get_parameter, execute_gdb_command, gdbpy_write,
gdbpy_flush): Remove forward declarations.
(eval_python_from_control_command): Fix error checking of function
PyRun_SimpleString. Fix error string.
(python_command): Likewise.
(execute_gdb_command): Added from_tty argument.
gdb/doc/
2009-02-02 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Basic Python): Document execute's from_tty
argument.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 45cad64..2c6c2ea 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18078,11 +18078,15 @@ methods and classes added by @value{GDBN} are placed in this module.
use in all scripts evaluated by the @code{python} command.
@findex gdb.execute
-@defun execute command
+@defun execute command [from_tty]
Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
If a GDB exception happens while @var{command} runs, it is
translated as described in @ref{Exception Handling,,Exception Handling}.
If no exceptions occur, this function returns @code{None}.
+
+@var{from_tty} specifies whether @value{GDBN} ought to consider this
+command as having originated from the user invoking it interactively.
+It must be a boolean value. If omitted, it defaults to @code{False}.
@end defun
@findex gdb.get_parameter
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index c6775b2..d407d05 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -732,12 +732,17 @@ convert_value_from_python (PyObject *obj)
struct value *value = NULL; /* -Wall */
PyObject *target_str, *unicode_str;
struct cleanup *old;
+ int cmp;
if (! obj)
error (_("Internal error while converting Python value."));
- if (PyBool_Check (obj))
- value = value_from_longest (builtin_type_pybool, obj == Py_True);
+ if (PyBool_Check (obj))
+ {
+ cmp = PyObject_IsTrue (obj);
+ if (cmp >= 0)
+ value = value_from_longest (builtin_type_pybool, cmp);
+ }
else if (PyInt_Check (obj))
value = value_from_longest (builtin_type_pyint, PyInt_AsLong (obj));
else if (PyLong_Check (obj))
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 991321f..96bb5f5 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -42,31 +42,10 @@ static int gdbpy_should_print_stack = 1;
#include "target.h"
#include "gdbthread.h"
+static PyMethodDef GdbMethods[];
PyObject *gdb_module;
-static PyObject *get_parameter (PyObject *, PyObject *);
-static PyObject *execute_gdb_command (PyObject *, PyObject *);
-static PyObject *gdbpy_write (PyObject *, PyObject *);
-static PyObject *gdbpy_flush (PyObject *, PyObject *);
-
-static PyMethodDef GdbMethods[] =
-{
- { "history", gdbpy_history, METH_VARARGS,
- "Get a value from history" },
- { "execute", execute_gdb_command, METH_VARARGS,
- "Execute a gdb command" },
- { "get_parameter", get_parameter, METH_VARARGS,
- "Return a gdb parameter's value" },
-
- { "write", gdbpy_write, METH_VARARGS,
- "Write a string using gdb's filtered stream." },
- { "flush", gdbpy_flush, METH_NOARGS,
- "Flush gdb's filtered stdout stream." },
-
- {NULL, NULL, 0, NULL}
-};
-
/* Given a command_line, return a command string suitable for passing
to Python. Lines in the string are separated by newlines. The
return value is allocated using xmalloc and the caller is
@@ -102,6 +81,7 @@ compute_python_string (struct command_line *l)
void
eval_python_from_control_command (struct command_line *cmd)
{
+ int ret;
char *script;
struct cleanup *cleanup;
PyGILState_STATE state;
@@ -113,12 +93,12 @@ eval_python_from_control_command (struct command_line *cmd)
cleanup = make_cleanup_py_restore_gil (&state);
script = compute_python_string (cmd->body_list[0]);
- PyRun_SimpleString (script);
+ ret = PyRun_SimpleString (script);
xfree (script);
- if (PyErr_Occurred ())
+ if (ret)
{
gdbpy_print_stack ();
- error (_("error while executing Python code"));
+ error (_("Error while executing Python code."));
}
do_cleanups (cleanup);
@@ -139,11 +119,10 @@ python_command (char *arg, int from_tty)
++arg;
if (arg && *arg)
{
- PyRun_SimpleString (arg);
- if (PyErr_Occurred ())
+ if (PyRun_SimpleString (arg))
{
gdbpy_print_stack ();
- error (_("error while executing Python code"));
+ error (_("Error while executing Python code."));
}
}
else
@@ -256,14 +235,26 @@ execute_gdb_command (PyObject *self, PyObject *args)
{
struct cmd_list_element *alias, *prefix, *cmd;
char *arg, *newarg;
+ PyObject *from_tty_obj = NULL;
+ int from_tty;
+ int cmp;
volatile struct gdb_exception except;
- if (! PyArg_ParseTuple (args, "s", &arg))
+ if (! PyArg_ParseTuple (args, "s|O!", &arg, &PyBool_Type, &from_tty_obj))
return NULL;
+ from_tty = 0;
+ if (from_tty_obj)
+ {
+ cmp = PyObject_IsTrue (from_tty_obj);
+ if (cmp < 0)
+ return NULL;
+ from_tty = cmp;
+ }
+
TRY_CATCH (except, RETURN_MASK_ALL)
{
- execute_command (arg, 0);
+ execute_command (arg, from_tty);
}
GDB_PY_HANDLE_EXCEPTION (except);
@@ -451,3 +442,26 @@ sys.stdout = GdbOutputFile()\n\
#endif /* HAVE_PYTHON */
}
+
+\f
+
+#if HAVE_PYTHON
+
+static PyMethodDef GdbMethods[] =
+{
+ { "history", gdbpy_history, METH_VARARGS,
+ "Get a value from history" },
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "get_parameter", get_parameter, METH_VARARGS,
+ "Return a gdb parameter's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, NULL}
+};
+
+#endif /* HAVE_PYTHON */
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [RFA][python] Fixes for existing Python code.
2009-02-02 13:06 [RFA][python] Fixes for existing Python code Thiago Jung Bauermann
@ 2009-02-02 13:19 ` Thiago Jung Bauermann
2009-02-02 17:28 ` Tom Tromey
` (2 subsequent siblings)
3 siblings, 0 replies; 15+ messages in thread
From: Thiago Jung Bauermann @ 2009-02-02 13:19 UTC (permalink / raw)
To: gdb-patches ml
El lun, 02-02-2009 a las 11:06 -0200, Thiago Jung Bauermann escribió:
> Ok to commit?
I forgot to mention that this was regtested on ppc-linux.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [RFA][python] Fixes for existing Python code.
2009-02-02 13:06 [RFA][python] Fixes for existing Python code Thiago Jung Bauermann
2009-02-02 13:19 ` Thiago Jung Bauermann
@ 2009-02-02 17:28 ` Tom Tromey
2009-02-05 16:43 ` Thiago Jung Bauermann
2009-02-02 18:30 ` Tom Tromey
2009-02-02 19:23 ` [RFA][python] Fixes for existing Python code Eli Zaretskii
3 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2009-02-02 17:28 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches ml
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
Thiago> This patch has some fixes for the Python code which is currently in.
Thiago> They are the following:
Thiago> - add from_tty argument to execute_gdb_command;
Thiago> - fix error checking of function PyRun_SimpleString;
Thiago> - reorganize python.c to minimize forward declarations;
Thiago> - properly check Python booleans.
The code bits are ok. Please wait for Eli to review the documentation
before committing.
thanks,
Tom
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFA][python] Fixes for existing Python code.
2009-02-02 17:28 ` Tom Tromey
@ 2009-02-05 16:43 ` Thiago Jung Bauermann
0 siblings, 0 replies; 15+ messages in thread
From: Thiago Jung Bauermann @ 2009-02-05 16:43 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches ml
El lun, 02-02-2009 a las 10:27 -0700, Tom Tromey escribió:
> >>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
> Thiago> This patch has some fixes for the Python code which is currently in.
> Thiago> They are the following:
> Thiago> - add from_tty argument to execute_gdb_command;
> Thiago> - fix error checking of function PyRun_SimpleString;
> Thiago> - reorganize python.c to minimize forward declarations;
> Thiago> - properly check Python booleans.
>
> The code bits are ok. Please wait for Eli to review the documentation
> before committing.
Eli had approved, so I committed this. Except for the boolean fix, which
went in the other patch which I committed earlier. Thanks!
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
gdb/
2009-02-05 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* python/python.c (GdbMethods): Move to bottom of file.
(get_parameter, execute_gdb_command, gdbpy_write,
gdbpy_flush): Remove forward declarations.
(eval_python_from_control_command): Fix error checking of function
PyRun_SimpleString. Fix error string.
(python_command): Likewise.
(execute_gdb_command): Added from_tty argument.
gdb/doc/
2009-02-05 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Basic Python): Document execute's from_tty
argument.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 45cad64..2c6c2ea 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18078,11 +18078,15 @@ methods and classes added by @value{GDBN} are placed in this module.
use in all scripts evaluated by the @code{python} command.
@findex gdb.execute
-@defun execute command
+@defun execute command [from_tty]
Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
If a GDB exception happens while @var{command} runs, it is
translated as described in @ref{Exception Handling,,Exception Handling}.
If no exceptions occur, this function returns @code{None}.
+
+@var{from_tty} specifies whether @value{GDBN} ought to consider this
+command as having originated from the user invoking it interactively.
+It must be a boolean value. If omitted, it defaults to @code{False}.
@end defun
@findex gdb.get_parameter
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 991321f..96bb5f5 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -42,31 +42,10 @@ static int gdbpy_should_print_stack = 1;
#include "target.h"
#include "gdbthread.h"
+static PyMethodDef GdbMethods[];
PyObject *gdb_module;
-static PyObject *get_parameter (PyObject *, PyObject *);
-static PyObject *execute_gdb_command (PyObject *, PyObject *);
-static PyObject *gdbpy_write (PyObject *, PyObject *);
-static PyObject *gdbpy_flush (PyObject *, PyObject *);
-
-static PyMethodDef GdbMethods[] =
-{
- { "history", gdbpy_history, METH_VARARGS,
- "Get a value from history" },
- { "execute", execute_gdb_command, METH_VARARGS,
- "Execute a gdb command" },
- { "get_parameter", get_parameter, METH_VARARGS,
- "Return a gdb parameter's value" },
-
- { "write", gdbpy_write, METH_VARARGS,
- "Write a string using gdb's filtered stream." },
- { "flush", gdbpy_flush, METH_NOARGS,
- "Flush gdb's filtered stdout stream." },
-
- {NULL, NULL, 0, NULL}
-};
-
/* Given a command_line, return a command string suitable for passing
to Python. Lines in the string are separated by newlines. The
return value is allocated using xmalloc and the caller is
@@ -102,6 +81,7 @@ compute_python_string (struct command_line *l)
void
eval_python_from_control_command (struct command_line *cmd)
{
+ int ret;
char *script;
struct cleanup *cleanup;
PyGILState_STATE state;
@@ -113,12 +93,12 @@ eval_python_from_control_command (struct command_line *cmd)
cleanup = make_cleanup_py_restore_gil (&state);
script = compute_python_string (cmd->body_list[0]);
- PyRun_SimpleString (script);
+ ret = PyRun_SimpleString (script);
xfree (script);
- if (PyErr_Occurred ())
+ if (ret)
{
gdbpy_print_stack ();
- error (_("error while executing Python code"));
+ error (_("Error while executing Python code."));
}
do_cleanups (cleanup);
@@ -139,11 +119,10 @@ python_command (char *arg, int from_tty)
++arg;
if (arg && *arg)
{
- PyRun_SimpleString (arg);
- if (PyErr_Occurred ())
+ if (PyRun_SimpleString (arg))
{
gdbpy_print_stack ();
- error (_("error while executing Python code"));
+ error (_("Error while executing Python code."));
}
}
else
@@ -256,14 +235,26 @@ execute_gdb_command (PyObject *self, PyObject *args)
{
struct cmd_list_element *alias, *prefix, *cmd;
char *arg, *newarg;
+ PyObject *from_tty_obj = NULL;
+ int from_tty;
+ int cmp;
volatile struct gdb_exception except;
- if (! PyArg_ParseTuple (args, "s", &arg))
+ if (! PyArg_ParseTuple (args, "s|O!", &arg, &PyBool_Type, &from_tty_obj))
return NULL;
+ from_tty = 0;
+ if (from_tty_obj)
+ {
+ cmp = PyObject_IsTrue (from_tty_obj);
+ if (cmp < 0)
+ return NULL;
+ from_tty = cmp;
+ }
+
TRY_CATCH (except, RETURN_MASK_ALL)
{
- execute_command (arg, 0);
+ execute_command (arg, from_tty);
}
GDB_PY_HANDLE_EXCEPTION (except);
@@ -451,3 +442,26 @@ sys.stdout = GdbOutputFile()\n\
#endif /* HAVE_PYTHON */
}
+
+\f
+
+#if HAVE_PYTHON
+
+static PyMethodDef GdbMethods[] =
+{
+ { "history", gdbpy_history, METH_VARARGS,
+ "Get a value from history" },
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "get_parameter", get_parameter, METH_VARARGS,
+ "Return a gdb parameter's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, NULL}
+};
+
+#endif /* HAVE_PYTHON */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFA][python] Fixes for existing Python code.
2009-02-02 13:06 [RFA][python] Fixes for existing Python code Thiago Jung Bauermann
2009-02-02 13:19 ` Thiago Jung Bauermann
2009-02-02 17:28 ` Tom Tromey
@ 2009-02-02 18:30 ` Tom Tromey
2009-02-04 1:01 ` [RFC][python] Fixes and improvements to gdb.Value. (was Re: [RFA][python] Fixes for existing Python code.) Thiago Jung Bauermann
2009-02-02 19:23 ` [RFA][python] Fixes for existing Python code Eli Zaretskii
3 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2009-02-02 18:30 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches ml
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
Thiago> I'd also like to remind that the following patches for Python support
Thiago> are still pending:
Thiago> http://sourceware.org/ml/gdb-patches/2009-01/msg00016.html
This one is the patch to add more methods to Value. I have two
comments on it.
First, in convert_value_from_python, I see:
- return NULL;
+ {
+ PyErr_Clear ();
+ error (_("Error converting Python value."));
+ }
This should call gdbpy_print_stack instead of PyErr_Clear. I think we
have -- or should have -- a general rule that we call
gdbpy_print_stack when "converting" a Python exception to a gdb
exception. Using this lets the user control whether stack traces are
printed for Python errors, which is handy for debugging Python code.
My other comment is just to make sure that all of Eli's documentation
comments have been addressed.
The patch is ok with the above change.
Thiago> http://sourceware.org/ml/gdb-patches/2009-01/msg00003.html
This is the patch to add la_getstr.
I'll reply to it separately.
Thiago> http://sourceware.org/ml/gdb-patches/2009-01/msg00004.html
This adds Value.string, using la_getstr.
This patch is ok once the la_getstr code goes in, and provided that
Eli oks the documentation.
Tom
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [RFC][python] Fixes and improvements to gdb.Value. (was Re: [RFA][python] Fixes for existing Python code.)
2009-02-02 18:30 ` Tom Tromey
@ 2009-02-04 1:01 ` Thiago Jung Bauermann
2009-02-04 19:40 ` [RFC][python] Fixes and improvements to gdb.Value Tom Tromey
0 siblings, 1 reply; 15+ messages in thread
From: Thiago Jung Bauermann @ 2009-02-04 1:01 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches ml
[-- Attachment #1: Type: text/plain, Size: 26859 bytes --]
El lun, 02-02-2009 a las 11:28 -0700, Tom Tromey escribió:
> >>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
>
> Thiago> I'd also like to remind that the following patches for Python support
> Thiago> are still pending:
>
> Thiago> http://sourceware.org/ml/gdb-patches/2009-01/msg00016.html
>
> This one is the patch to add more methods to Value. I have two
> comments on it.
>
> First, in convert_value_from_python, I see:
>
> - return NULL;
> + {
> + PyErr_Clear ();
> + error (_("Error converting Python value."));
> + }
>
> This should call gdbpy_print_stack instead of PyErr_Clear. I think we
> have -- or should have -- a general rule that we call
> gdbpy_print_stack when "converting" a Python exception to a gdb
> exception. Using this lets the user control whether stack traces are
> printed for Python errors, which is handy for debugging Python code.
Ok, as we discussed on IRC, convert_value_from_python now throws a
Python exception instead of a GDB exception. I adapted the callers
(including a call in fnpy_call in the convenience function patch, I'll
repost it with the change). Also, I moved the boolean check fix to this
patch, it was easier that way for me. The rest of the patch is
unchanged. Ok?
I'm attaching a diff which ignores whitespace changes for the
convert_value_from_python function, since there was a change in
indentation there.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
gdb/
2009-02-03 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>
* python/python-internal.h (gdbpy_get_value_from_history): Rename
prototype to gdbpy_history.
(gdbpy_is_string): Declare.
(python_string_to_host_string): Declare.
* python/python-utils.c (gdbpy_is_string): New function.
(unicode_to_encoded_string): New function.
(unicode_to_target_string): Use it.
(python_string_to_host_string): New function.
* python/python-value.c (valpy_address): New function.
(convert_value_from_python): Use gdbpy_is_string. Change to throw
Python exception instead of a GDB exception on error. Properly check
Python booleans.
(valpy_getitem): Convert field name to host string. Handle array
accesses. Adapt to new behaviour of convert_value_from_python.
(valpy_new): Adapt to new behaviour of convert_value_from_python.
(enum valpy_opcode) <VALPY_LSH, VALPY_RSH, VALPY_BITAND,
VALPY_BITXOR, VALPY_BITOR>: New constants.
(valpy_binop): Update. Adapt to new behaviour of
convert_value_from_python.
(valpy_invert): New function.
(valpy_lsh): Likewise.
(valpy_rsh): Likewise.
(valpy_and): Likewise.
(valpy_or): Likewise.
(valpy_xor): Likewise.
(valpy_richcompare): Call convert_value_from_python instead of doing
conversions itself.
(is_intlike, valpy_int, valpy_long, valpy_float): New functions.
(gdbpy_get_value_from_history): Rename
function to gdbpy_history.
(gdbpy_initialize_values): Don't set tp_new.
(value_object_type): Add valpy_new.
(value_object_methods): Add `address' entry.
(value_object_as_number): Update for new methods.
* python/python.c (GdbMethods): Rename entry from
`get_value_from_history' to `history'.
gdb/doc/
2009-02-03 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Basic Python): Document gdb.history.
gdb/testsuite/
2009-02-03 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.python/python-value.exp: Use `gdb.history' instead of
`gdb.value_from_history'.
(test_value_numeric_ops): Add test for conversion of enum constant.
* gdb.python/python-value.c (enum e): New type.
(evalue): New global.
(main): Use argv.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 166b84d..884f50b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18097,6 +18097,21 @@ If the named parameter does not exist, this function throws a
a Python value of the appropriate type, and returned.
@end defun
+@findex gdb.history
+@defun history number
+Return a value from @value{GDBN}'s value history (@pxref{Value
+History}). @var{number} indicates which history element to return.
+If @var{number} is negative, then @value{GDBN} will take its absolute value
+and count backward from the last element (i.e., the most recent element) to
+find the value to return. If @var{number} is zero, then @value{GDBN} will
+return the most recent element. If the element specified by @value{number}
+doesn't exist in the value history, a @code{RuntimeError} exception will be
+raised.
+
+If no exception is raised, the return value is always an instance of
+@code{gdb.Value} (@pxref{Values From Inferior}).
+@end defun
+
@findex gdb.write
@defun write string
Print a string to @value{GDBN}'s paginated standard output stream.
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 4e9da33..672d8a4 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -63,7 +63,7 @@ struct value;
extern PyObject *gdb_module;
extern PyTypeObject value_object_type;
-PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *value_to_value_object (struct value *v);
@@ -90,5 +90,7 @@ void gdbpy_print_stack (void);
PyObject *python_string_to_unicode (PyObject *obj);
char *unicode_to_target_string (PyObject *unicode_str);
char *python_string_to_target_string (PyObject *obj);
+char *python_string_to_host_string (PyObject *obj);
+int gdbpy_is_string (PyObject *obj);
#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index 9aae43f..6a95939 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -95,26 +95,37 @@ python_string_to_unicode (PyObject *obj)
}
/* Returns a newly allocated string with the contents of the given unicode
- string object converted to the target's charset. If an error occurs during
- the conversion, NULL will be returned and a python exception will be set.
+ string object converted to CHARSET. If an error occurs during the
+ conversion, NULL will be returned and a python exception will be set.
The caller is responsible for xfree'ing the string. */
-char *
-unicode_to_target_string (PyObject *unicode_str)
+static char *
+unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
{
- char *target_string;
+ char *result;
PyObject *string;
- /* Translate string to target's charset. */
- string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ /* Translate string to named charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
if (string == NULL)
return NULL;
- target_string = xstrdup (PyString_AsString (string));
+ result = xstrdup (PyString_AsString (string));
Py_DECREF (string);
- return target_string;
+ return result;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ return unicode_to_encoded_string (unicode_str, target_charset ());
}
/* Converts a python string (8-bit or unicode) to a target string in
@@ -132,3 +143,28 @@ python_string_to_target_string (PyObject *obj)
return unicode_to_target_string (str);
}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the host's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_host_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_encoded_string (str, host_charset ());
+}
+
+/* Return true if OBJ is a Python string or unicode object, false
+ otherwise. */
+
+int
+gdbpy_is_string (PyObject *obj)
+{
+ return PyString_Check (obj) || PyUnicode_Check (obj);
+}
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 92e0431..420d26f 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
+#include "gdb_assert.h"
#include "charset.h"
#include "value.h"
#include "exceptions.h"
@@ -79,7 +80,6 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
{
struct value *value = NULL; /* Initialize to appease gcc warning. */
value_object *value_obj;
- volatile struct gdb_exception except;
if (PyTuple_Size (args) != 1)
{
@@ -96,16 +96,11 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
return NULL;
}
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- value = convert_value_from_python (PyTuple_GetItem (args, 0));
- }
- if (except.reason < 0)
+ value = convert_value_from_python (PyTuple_GetItem (args, 0));
+ if (value == NULL)
{
subtype->tp_free (value_obj);
- return PyErr_Format (except.reason == RETURN_QUIT
- ? PyExc_KeyboardInterrupt : PyExc_TypeError,
- "%s", except.message);
+ return NULL;
}
value_obj->value = value;
@@ -132,6 +127,22 @@ valpy_dereference (PyObject *self, PyObject *args)
return value_to_value_object (res_val);
}
+/* Return "&value". */
+static PyObject *
+valpy_address (PyObject *self, PyObject *args)
+{
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ res_val = value_addr (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return value_to_value_object (res_val);
+}
+
static Py_ssize_t
valpy_length (PyObject *self)
{
@@ -147,26 +158,40 @@ static PyObject *
valpy_getitem (PyObject *self, PyObject *key)
{
value_object *self_value = (value_object *) self;
- char *field;
+ char *field = NULL;
+ struct value *idx = NULL;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
- struct cleanup *old;
volatile struct gdb_exception except;
- field = python_string_to_target_string (key);
- if (field == NULL)
- return NULL;
-
- old = make_cleanup (xfree, field);
+ if (gdbpy_is_string (key))
+ {
+ field = python_string_to_host_string (key);
+ if (field == NULL)
+ return NULL;
+ }
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct value *tmp = self_value->value;
- res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
+
+ if (field)
+ res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
+ else
+ {
+ /* Assume we are attempting an array access, and let the
+ value code throw an exception if the index has an invalid
+ type. */
+ struct value *idx = convert_value_from_python (key);
+ if (idx == NULL)
+ return NULL;
+
+ res_val = value_subscript (tmp, idx);
+ }
}
+ if (field)
+ xfree (field);
GDB_PY_HANDLE_EXCEPTION (except);
- do_cleanups (old);
-
return value_to_value_object (res_val);
}
@@ -220,7 +245,12 @@ enum valpy_opcode
VALPY_MUL,
VALPY_DIV,
VALPY_REM,
- VALPY_POW
+ VALPY_POW,
+ VALPY_LSH,
+ VALPY_RSH,
+ VALPY_BITAND,
+ VALPY_BITOR,
+ VALPY_BITXOR
};
/* If TYPE is a reference, return the target; otherwise return TYPE. */
@@ -244,7 +274,12 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
kind of object, altogether. Because of this, we can't assume self is
a gdb.Value object and need to convert it from python as well. */
arg1 = convert_value_from_python (self);
+ if (arg1 == NULL)
+ return NULL;
+
arg2 = convert_value_from_python (other);
+ if (arg2 == NULL)
+ return NULL;
switch (opcode)
{
@@ -302,6 +337,21 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
case VALPY_POW:
res_val = value_binop (arg1, arg2, BINOP_EXP);
break;
+ case VALPY_LSH:
+ res_val = value_binop (arg1, arg2, BINOP_LSH);
+ break;
+ case VALPY_RSH:
+ res_val = value_binop (arg1, arg2, BINOP_RSH);
+ break;
+ case VALPY_BITAND:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_AND);
+ break;
+ case VALPY_BITOR:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_IOR);
+ break;
+ case VALPY_BITXOR:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR);
+ break;
}
}
GDB_PY_HANDLE_EXCEPTION (except);
@@ -412,45 +462,66 @@ valpy_nonzero (PyObject *self)
}
}
-/* Implements comparison operations for value objects. */
+/* Implements ~ for value objects. */
static PyObject *
-valpy_richcompare (PyObject *self, PyObject *other, int op)
+valpy_invert (PyObject *self)
{
- int result = 0;
- struct value *value_self, *value_other;
+ struct value *val = NULL;
volatile struct gdb_exception except;
- if (PyObject_TypeCheck (other, &value_object_type))
- value_other = ((value_object *) other)->value;
- else if (PyInt_Check (other))
+ TRY_CATCH (except, RETURN_MASK_ALL)
{
- LONGEST l;
+ val = value_complement (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
- l = PyInt_AsLong (other);
- if (PyErr_Occurred ())
- return NULL;
+ return value_to_value_object (val);
+}
- value_other = value_from_longest (builtin_type_pyint, l);
- }
- else if (PyFloat_Check (other))
- {
- DOUBLEST d;
+/* Implements left shift for value objects. */
+static PyObject *
+valpy_lsh (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_LSH, self, other);
+}
- d = PyFloat_AsDouble (other);
- if (PyErr_Occurred ())
- return NULL;
+/* Implements right shift for value objects. */
+static PyObject *
+valpy_rsh (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_RSH, self, other);
+}
- value_other = value_from_double (builtin_type_pyfloat, d);
- }
- else if (PyString_Check (other) || PyUnicode_Check (other))
- {
- char *str;
+/* Implements bitwise and for value objects. */
+static PyObject *
+valpy_and (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITAND, self, other);
+}
- str = python_string_to_target_string (other);
- value_other = value_from_string (str);
- xfree (str);
- }
- else if (other == Py_None)
+/* Implements bitwise or for value objects. */
+static PyObject *
+valpy_or (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITOR, self, other);
+}
+
+/* Implements bitwise xor for value objects. */
+static PyObject *
+valpy_xor (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITXOR, self, other);
+}
+
+/* Implements comparison operations for value objects. */
+static PyObject *
+valpy_richcompare (PyObject *self, PyObject *other, int op)
+{
+ int result = 0;
+ struct value *value_other;
+ volatile struct gdb_exception except;
+
+ if (other == Py_None)
/* Comparing with None is special. From what I can tell, in Python
None is smaller than anything else. */
switch (op) {
@@ -468,15 +539,13 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
"Invalid operation on gdb.Value.");
return NULL;
}
- else
- {
- PyErr_SetString (PyExc_NotImplementedError,
- "Operation not supported on gdb.Value of this type.");
- return NULL;
- }
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ value_other = convert_value_from_python (other);
+ if (value_other == NULL)
+ return NULL;
+
switch (op) {
case Py_LT:
result = value_less (((value_object *) self)->value, value_other);
@@ -513,6 +582,92 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
Py_RETURN_FALSE;
}
+/* Helper function to determine if a type is "int-like". */
+static int
+is_intlike (struct type *type, int ptr_ok)
+{
+ CHECK_TYPEDEF (type);
+ return (TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_ENUM
+ || TYPE_CODE (type) == TYPE_CODE_BOOL
+ || TYPE_CODE (type) == TYPE_CODE_CHAR
+ || (ptr_ok && TYPE_CODE (type) == TYPE_CODE_PTR));
+}
+
+/* Implements conversion to int. */
+static PyObject *
+valpy_int (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ LONGEST l = 0;
+ volatile struct gdb_exception except;
+
+ CHECK_TYPEDEF (type);
+ if (!is_intlike (type, 0))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to int");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ l = value_as_long (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyInt_FromLong (l);
+}
+
+/* Implements conversion to long. */
+static PyObject *
+valpy_long (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ LONGEST l = 0;
+ volatile struct gdb_exception except;
+
+ if (!is_intlike (type, 1))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to long");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ l = value_as_long (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromLong (l);
+}
+
+/* Implements conversion to float. */
+static PyObject *
+valpy_float (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ double d = 0;
+ volatile struct gdb_exception except;
+
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) != TYPE_CODE_FLT)
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to float");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ d = value_as_double (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyFloat_FromDouble (d);
+}
+
/* Returns an object for a value which is released from the all_values chain,
so its lifetime is not bound to the execution of a command. */
PyObject *
@@ -533,7 +688,7 @@ value_to_value_object (struct value *val)
}
/* Try to convert a Python value to a gdb value. If the value cannot
- be converted, throw a gdb exception. */
+ be converted, set a Python exception and return NULL. */
struct value *
convert_value_from_python (PyObject *obj)
@@ -541,53 +696,72 @@ convert_value_from_python (PyObject *obj)
struct value *value = NULL; /* -Wall */
PyObject *target_str, *unicode_str;
struct cleanup *old;
+ volatile struct gdb_exception except;
+ int cmp;
- if (! obj)
- error (_("Internal error while converting Python value."));
+ gdb_assert (obj != NULL);
- if (PyBool_Check (obj))
- value = value_from_longest (builtin_type_pybool, obj == Py_True);
- else if (PyInt_Check (obj))
- value = value_from_longest (builtin_type_pyint, PyInt_AsLong (obj));
- else if (PyLong_Check (obj))
- {
- LONGEST l = PyLong_AsLongLong (obj);
- if (! PyErr_Occurred ())
- value = value_from_longest (builtin_type_pylong, l);
- }
- else if (PyFloat_Check (obj))
- {
- double d = PyFloat_AsDouble (obj);
- if (! PyErr_Occurred ())
- value = value_from_double (builtin_type_pyfloat, d);
- }
- else if (PyString_Check (obj) || PyUnicode_Check (obj))
+ TRY_CATCH (except, RETURN_MASK_ALL)
{
- char *s;
+ if (PyBool_Check (obj))
+ {
+ cmp = PyObject_IsTrue (obj);
+ if (cmp >= 0)
+ value = value_from_longest (builtin_type_pybool, cmp);
+ }
+ else if (PyInt_Check (obj))
+ {
+ long l = PyInt_AsLong (obj);
- s = python_string_to_target_string (obj);
- if (s == NULL)
- return NULL;
+ if (! PyErr_Occurred ())
+ value = value_from_longest (builtin_type_pyint, l);
+ }
+ else if (PyLong_Check (obj))
+ {
+ LONGEST l = PyLong_AsLongLong (obj);
- old = make_cleanup (xfree, s);
- value = value_from_string (s);
- do_cleanups (old);
- }
- else if (PyObject_TypeCheck (obj, &value_object_type))
- value = ((value_object *) obj)->value;
- else
- error (_("Could not convert Python object: %s"),
- PyString_AsString (PyObject_Str (obj)));
+ if (! PyErr_Occurred ())
+ value = value_from_longest (builtin_type_pylong, l);
+ }
+ else if (PyFloat_Check (obj))
+ {
+ double d = PyFloat_AsDouble (obj);
- if (PyErr_Occurred ())
- error (_("Error converting Python value."));
+ if (! PyErr_Occurred ())
+ value = value_from_double (builtin_type_pyfloat, d);
+ }
+ else if (gdbpy_is_string (obj))
+ {
+ char *s;
+
+ s = python_string_to_target_string (obj);
+ if (s != NULL)
+ {
+ old = make_cleanup (xfree, s);
+ value = value_from_string (s);
+ do_cleanups (old);
+ }
+ }
+ else if (PyObject_TypeCheck (obj, &value_object_type))
+ value = ((value_object *) obj)->value;
+ else
+ PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"),
+ PyString_AsString (PyObject_Str (obj)));
+ }
+ if (except.reason < 0)
+ {
+ PyErr_Format (except.reason == RETURN_QUIT
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+ "%s", except.message);
+ return NULL;
+ }
return value;
}
/* Returns value object in the ARGth position in GDB's history. */
PyObject *
-gdbpy_get_value_from_history (PyObject *self, PyObject *args)
+gdbpy_history (PyObject *self, PyObject *args)
{
int i;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
@@ -608,7 +782,6 @@ gdbpy_get_value_from_history (PyObject *self, PyObject *args)
void
gdbpy_initialize_values (void)
{
- value_object_type.tp_new = valpy_new;
if (PyType_Ready (&value_object_type) < 0)
return;
@@ -619,6 +792,7 @@ gdbpy_initialize_values (void)
}
static PyMethodDef value_object_methods[] = {
+ { "address", valpy_address, METH_NOARGS, "Return the address of the value." },
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{NULL} /* Sentinel */
};
@@ -634,7 +808,19 @@ static PyNumberMethods value_object_as_number = {
valpy_negative, /* nb_negative */
valpy_positive, /* nb_positive */
valpy_absolute, /* nb_absolute */
- valpy_nonzero /* nb_nonzero */
+ valpy_nonzero, /* nb_nonzero */
+ valpy_invert, /* nb_invert */
+ valpy_lsh, /* nb_lshift */
+ valpy_rsh, /* nb_rshift */
+ valpy_and, /* nb_and */
+ valpy_xor, /* nb_xor */
+ valpy_or, /* nb_or */
+ NULL, /* nb_coerce */
+ valpy_int, /* nb_int */
+ valpy_long, /* nb_long */
+ valpy_float, /* nb_float */
+ NULL, /* nb_oct */
+ NULL /* nb_hex */
};
static PyMappingMethods value_object_as_mapping = {
@@ -672,7 +858,17 @@ PyTypeObject value_object_type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- value_object_methods /* tp_methods */
+ value_object_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ valpy_new /* tp_new */
};
#endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e778ac4..991321f 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -52,7 +52,7 @@ static PyObject *gdbpy_flush (PyObject *, PyObject *);
static PyMethodDef GdbMethods[] =
{
- { "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS,
+ { "history", gdbpy_history, METH_VARARGS,
"Get a value from history" },
{ "execute", execute_gdb_command, METH_VARARGS,
"Execute a gdb command" },
diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c
index 8c10956..17e5c62 100644
--- a/gdb/testsuite/gdb.python/python-value.c
+++ b/gdb/testsuite/gdb.python/python-value.c
@@ -27,6 +27,14 @@ union u
float b;
};
+enum e
+ {
+ ONE = 1,
+ TWO = 2
+ };
+
+enum e evalue = TWO;
+
int
main (int argc, char *argv[])
{
@@ -37,5 +45,7 @@ main (int argc, char *argv[])
s.b = 5;
u.a = 7;
+ argv[0][0] = 'a'; /* Just to avoid getting argv optimized out. */
+
return 0; /* break to inspect struct and union */
}
diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp
index 2057e61..8f5e0ab 100644
--- a/gdb/testsuite/gdb.python/python-value.exp
+++ b/gdb/testsuite/gdb.python/python-value.exp
@@ -111,13 +111,18 @@ proc test_value_numeric_ops {} {
gdb_test "python print 'result = ' + str(1-i)" " = -4" "subtract python integer from integer value"
gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value"
+ # Conversion test.
+ gdb_test "print evalue" " = TWO"
+ gdb_test "python evalue = gdb.history (0)" ""
+ gdb_test "python print int (evalue)" "2"
+
# Test pointer arithmethic
# First, obtain the pointers
gdb_test "print (void *) 2" "" ""
- gdb_test "python a = gdb.get_value_from_history (0)" "" ""
+ gdb_test "python a = gdb.history (0)" "" ""
gdb_test "print (void *) 5" "" ""
- gdb_test "python b = gdb.get_value_from_history (0)" "" ""
+ gdb_test "python b = gdb.history (0)" "" ""
gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer"
gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value"
@@ -205,7 +210,7 @@ proc test_value_in_inferior {} {
# Just get inferior variable s in the value history, available to python.
gdb_test "print s" " = {a = 3, b = 5}" ""
- gdb_py_test_silent_cmd "python s = gdb.get_value_from_history (0)" "get value from history" 1
+ gdb_py_test_silent_cmd "python s = gdb.history (0)" "get value from history" 1
gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name"
gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name"
@@ -215,7 +220,7 @@ proc test_value_in_inferior {} {
# Just get inferior variable argv the value history, available to python.
gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" ""
- gdb_py_test_silent_cmd "python argv = gdb.get_value_from_history (0)" "" 0
+ gdb_py_test_silent_cmd "python argv = gdb.history (0)" "" 0
gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1
# Check that the dereferenced value is sane
[-- Attachment #2: fixes-whitespace.diff --]
[-- Type: text/x-patch, Size: 2880 bytes --]
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 92e0431..420d26f 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -533,7 +688,7 @@ value_to_value_object (struct value *val)
}
/* Try to convert a Python value to a gdb value. If the value cannot
- be converted, throw a gdb exception. */
+ be converted, set a Python exception and return NULL. */
struct value *
convert_value_from_python (PyObject *obj)
@@ -541,53 +696,72 @@ convert_value_from_python (PyObject *obj)
struct value *value = NULL; /* -Wall */
PyObject *target_str, *unicode_str;
struct cleanup *old;
+ volatile struct gdb_exception except;
+ int cmp;
- if (! obj)
- error (_("Internal error while converting Python value."));
+ gdb_assert (obj != NULL);
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
if (PyBool_Check (obj))
- value = value_from_longest (builtin_type_pybool, obj == Py_True);
+ {
+ cmp = PyObject_IsTrue (obj);
+ if (cmp >= 0)
+ value = value_from_longest (builtin_type_pybool, cmp);
+ }
else if (PyInt_Check (obj))
- value = value_from_longest (builtin_type_pyint, PyInt_AsLong (obj));
+ {
+ long l = PyInt_AsLong (obj);
+
+ if (! PyErr_Occurred ())
+ value = value_from_longest (builtin_type_pyint, l);
+ }
else if (PyLong_Check (obj))
{
LONGEST l = PyLong_AsLongLong (obj);
+
if (! PyErr_Occurred ())
value = value_from_longest (builtin_type_pylong, l);
}
else if (PyFloat_Check (obj))
{
double d = PyFloat_AsDouble (obj);
+
if (! PyErr_Occurred ())
value = value_from_double (builtin_type_pyfloat, d);
}
- else if (PyString_Check (obj) || PyUnicode_Check (obj))
+ else if (gdbpy_is_string (obj))
{
char *s;
s = python_string_to_target_string (obj);
- if (s == NULL)
- return NULL;
-
+ if (s != NULL)
+ {
old = make_cleanup (xfree, s);
value = value_from_string (s);
do_cleanups (old);
}
+ }
else if (PyObject_TypeCheck (obj, &value_object_type))
value = ((value_object *) obj)->value;
else
- error (_("Could not convert Python object: %s"),
+ PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"),
PyString_AsString (PyObject_Str (obj)));
-
- if (PyErr_Occurred ())
- error (_("Error converting Python value."));
+ }
+ if (except.reason < 0)
+ {
+ PyErr_Format (except.reason == RETURN_QUIT
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+ "%s", except.message);
+ return NULL;
+ }
return value;
}
/* Returns value object in the ARGth position in GDB's history. */
PyObject *
-gdbpy_get_value_from_history (PyObject *self, PyObject *args)
+gdbpy_history (PyObject *self, PyObject *args)
{
int i;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFA][python] Fixes for existing Python code.
2009-02-02 13:06 [RFA][python] Fixes for existing Python code Thiago Jung Bauermann
` (2 preceding siblings ...)
2009-02-02 18:30 ` Tom Tromey
@ 2009-02-02 19:23 ` Eli Zaretskii
3 siblings, 0 replies; 15+ messages in thread
From: Eli Zaretskii @ 2009-02-02 19:23 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Date: Mon, 02 Feb 2009 11:06:12 -0200
>
> gdb/doc/
> 2009-02-02 Tom Tromey <tromey@redhat.com>
>
> * gdb.texinfo (Basic Python): Document execute's from_tty
> argument.
This part is approved, thanks.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC][python] Fixes and improvements to gdb.Value.
@ 2009-01-03 2:25 Thiago Jung Bauermann
2009-01-03 9:42 ` Eli Zaretskii
0 siblings, 1 reply; 15+ messages in thread
From: Thiago Jung Bauermann @ 2009-01-03 2:25 UTC (permalink / raw)
To: gdb-patches ml
Hi,
This patch has fixes and improvements made to the value python bindings
that have been made in the python branch since this code has been
committed to CVS. Ok?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
gdb/
2009-01-03 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* python/python-internal.h (gdbpy_get_value_from_history): Rename
prototype to gdbpy_history.
(gdbpy_is_string): Declare.
(python_string_to_host_string): Declare.
* python/python-utils.c (gdbpy_is_string): New function.
(unicode_to_encoded_string): New function.
(unicode_to_target_string): Use it.
(python_string_to_host_string): New function.
* python/python-value.c (valpy_address): New function.
(valpy_getitem): Convert field name to
host string. Handle array accesses.
(enum valpy_opcode) <VALPY_LSH, VALPY_RSH, VALPY_BITAND,
VALPY_BITXOR, VALPY_BITOR>: New constants.
(valpy_binop): Update.
(valpy_invert): New function.
(valpy_lsh): Likewise.
(valpy_rsh): Likewise.
(valpy_and): Likewise.
(valpy_or): Likewise.
(valpy_xor): Likewise.
(valpy_richcompare): Call
convert_value_from_python instead of doing conversions itself.
(is_intlike, valpy_int, valpy_long, valpy_float): New functions.
(convert_value_from_python): Use gdbpy_is_string. Clear Python
exception and throw GDB exception if python_string_to_target_string
fails.
(gdbpy_get_value_from_history): Rename
function to gdbpy_history.
(gdbpy_initialize_values): Don't set tp_new.
(value_object_type): Add valpy_new.
(value_object_methods): Add `address' entry.
(value_object_as_number): Update for new methods.
* python/python.c (GdbMethods): Rename entry from
`get_value_from_history' to `history'.
gdb/doc/
2009-01-03 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Basic Python): Document gdb.history.
gdb/testsuite/
2009-01-03 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.python/python-value.exp: Use `gdb.history' instead of
`gdb.value_from_history'.
(test_value_numeric_ops): Add test for conversion of enum constant.
* gdb.python/python-value.c (enum e): New type.
(evalue): New global.
(main): Use argv.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6ef124c..030d4b3 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
-@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
@c Free Software Foundation, Inc.
@c
@c %**start of header
@@ -18086,6 +18086,19 @@ If the named parameter does not exist, this function throws a
a Python value of the appropriate type, and returned.
@end defun
+@findex gdb.history
+@defun history number
+Return a value from @value{GDBN}'s value history (@pxref{Value
+History}). @var{number} indicates which history element to return.
+If @var{number} is less than or equal to zero, then @value{GDBN} will
+take the absolute value of @var{number} and count backward from the
+last element to find the value to return. If there is no such element
+in the value history, an exception will be raised.
+
+The return value is always an instance of @code{gdb.Value}
+(@pxref{Values From Inferior}).
+@end defun
+
@findex gdb.write
@defun write string
Print a string to @value{GDBN}'s paginated standard output stream.
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index b2d7757..bcd37e4 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -1,6 +1,6 @@
/* Gdb/Python header for private use by Python module.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
@@ -60,7 +60,7 @@ struct value;
extern PyObject *gdb_module;
extern PyTypeObject value_object_type;
-PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *value_to_value_object (struct value *v);
@@ -87,5 +87,7 @@ void gdbpy_print_stack (void);
PyObject *python_string_to_unicode (PyObject *obj);
char *unicode_to_target_string (PyObject *unicode_str);
char *python_string_to_target_string (PyObject *obj);
+char *python_string_to_host_string (PyObject *obj);
+int gdbpy_is_string (PyObject *obj);
#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index 8db81ec..c27a930 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -1,6 +1,6 @@
/* General utility routines for GDB/Python.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
@@ -95,26 +95,37 @@ python_string_to_unicode (PyObject *obj)
}
/* Returns a newly allocated string with the contents of the given unicode
- string object converted to the target's charset. If an error occurs during
+ string object converted to a named charset. If an error occurs during
the conversion, NULL will be returned and a python exception will be set.
The caller is responsible for xfree'ing the string. */
-char *
-unicode_to_target_string (PyObject *unicode_str)
+static char *
+unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
{
- char *target_string;
+ char *result;
PyObject *string;
- /* Translate string to target's charset. */
- string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ /* Translate string to named charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
if (string == NULL)
return NULL;
- target_string = xstrdup (PyString_AsString (string));
+ result = xstrdup (PyString_AsString (string));
Py_DECREF (string);
- return target_string;
+ return result;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ return unicode_to_encoded_string (unicode_str, target_charset ());
}
/* Converts a python string (8-bit or unicode) to a target string in
@@ -132,3 +143,28 @@ python_string_to_target_string (PyObject *obj)
return unicode_to_target_string (str);
}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the host's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_host_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_encoded_string (str, host_charset ());
+}
+
+/* Return true if OBJ is a Python string or unicode object, false
+ otherwise. */
+
+int
+gdbpy_is_string (PyObject *obj)
+{
+ return PyString_Check (obj) || PyUnicode_Check (obj);
+}
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 9db7208..4d1f864 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -1,6 +1,6 @@
/* Python interface to values.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
@@ -132,6 +132,22 @@ valpy_dereference (PyObject *self, PyObject *args)
return value_to_value_object (res_val);
}
+/* Return "&value". */
+static PyObject *
+valpy_address (PyObject *self, PyObject *args)
+{
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ res_val = value_addr (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return value_to_value_object (res_val);
+}
+
static Py_ssize_t
valpy_length (PyObject *self)
{
@@ -147,26 +163,37 @@ static PyObject *
valpy_getitem (PyObject *self, PyObject *key)
{
value_object *self_value = (value_object *) self;
- char *field;
+ char *field = NULL;
+ struct value *idx = NULL;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
- struct cleanup *old;
volatile struct gdb_exception except;
- field = python_string_to_target_string (key);
- if (field == NULL)
- return NULL;
-
- old = make_cleanup (xfree, field);
+ if (gdbpy_is_string (key))
+ {
+ field = python_string_to_host_string (key);
+ if (field == NULL)
+ return NULL;
+ }
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct value *tmp = self_value->value;
- res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
+
+ if (field)
+ res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
+ else
+ {
+ /* Assume we are attempting an array access, and let the
+ value code throw an exception if the index has an invalid
+ type. */
+ struct value *idx = convert_value_from_python (key);
+ res_val = value_subscript (tmp, idx);
+ }
}
+ if (field)
+ xfree (field);
GDB_PY_HANDLE_EXCEPTION (except);
- do_cleanups (old);
-
return value_to_value_object (res_val);
}
@@ -220,7 +247,12 @@ enum valpy_opcode
VALPY_MUL,
VALPY_DIV,
VALPY_REM,
- VALPY_POW
+ VALPY_POW,
+ VALPY_LSH,
+ VALPY_RSH,
+ VALPY_BITAND,
+ VALPY_BITOR,
+ VALPY_BITXOR
};
/* If TYPE is a reference, return the target; otherwise return TYPE. */
@@ -302,6 +334,21 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
case VALPY_POW:
res_val = value_binop (arg1, arg2, BINOP_EXP);
break;
+ case VALPY_LSH:
+ res_val = value_binop (arg1, arg2, BINOP_LSH);
+ break;
+ case VALPY_RSH:
+ res_val = value_binop (arg1, arg2, BINOP_RSH);
+ break;
+ case VALPY_BITAND:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_AND);
+ break;
+ case VALPY_BITOR:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_IOR);
+ break;
+ case VALPY_BITXOR:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR);
+ break;
}
}
GDB_PY_HANDLE_EXCEPTION (except);
@@ -412,45 +459,66 @@ valpy_nonzero (PyObject *self)
}
}
-/* Implements comparison operations for value objects. */
+/* Implements ~ for value objects. */
static PyObject *
-valpy_richcompare (PyObject *self, PyObject *other, int op)
+valpy_invert (PyObject *self)
{
- int result = 0;
- struct value *value_self, *value_other;
+ struct value *val = NULL;
volatile struct gdb_exception except;
- if (PyObject_TypeCheck (other, &value_object_type))
- value_other = ((value_object *) other)->value;
- else if (PyInt_Check (other))
+ TRY_CATCH (except, RETURN_MASK_ALL)
{
- LONGEST l;
+ val = value_complement (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
- l = PyInt_AsLong (other);
- if (PyErr_Occurred ())
- return NULL;
+ return value_to_value_object (val);
+}
- value_other = value_from_longest (builtin_type_pyint, l);
- }
- else if (PyFloat_Check (other))
- {
- DOUBLEST d;
+/* Implements left shift for value objects. */
+static PyObject *
+valpy_lsh (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_LSH, self, other);
+}
- d = PyFloat_AsDouble (other);
- if (PyErr_Occurred ())
- return NULL;
+/* Implements right shift for value objects. */
+static PyObject *
+valpy_rsh (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_RSH, self, other);
+}
- value_other = value_from_double (builtin_type_pyfloat, d);
- }
- else if (PyString_Check (other) || PyUnicode_Check (other))
- {
- char *str;
+/* Implements bitwise and for value objects. */
+static PyObject *
+valpy_and (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITAND, self, other);
+}
- str = python_string_to_target_string (other);
- value_other = value_from_string (str);
- xfree (str);
- }
- else if (other == Py_None)
+/* Implements bitwise or for value objects. */
+static PyObject *
+valpy_or (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITOR, self, other);
+}
+
+/* Implements bitwise xor for value objects. */
+static PyObject *
+valpy_xor (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITXOR, self, other);
+}
+
+/* Implements comparison operations for value objects. */
+static PyObject *
+valpy_richcompare (PyObject *self, PyObject *other, int op)
+{
+ int result = 0;
+ struct value *value_other;
+ volatile struct gdb_exception except;
+
+ if (other == Py_None)
/* Comparing with None is special. From what I can tell, in Python
None is smaller than anything else. */
switch (op) {
@@ -468,15 +536,11 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
"Invalid operation on gdb.Value.");
return NULL;
}
- else
- {
- PyErr_SetString (PyExc_NotImplementedError,
- "Operation not supported on gdb.Value of this type.");
- return NULL;
- }
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ value_other = convert_value_from_python (other);
+
switch (op) {
case Py_LT:
result = value_less (((value_object *) self)->value, value_other);
@@ -513,6 +577,92 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
Py_RETURN_FALSE;
}
+/* Helper function to determine if a type is "int-like". */
+static int
+is_intlike (struct type *type, int ptr_ok)
+{
+ CHECK_TYPEDEF (type);
+ return (TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_ENUM
+ || TYPE_CODE (type) == TYPE_CODE_BOOL
+ || TYPE_CODE (type) == TYPE_CODE_CHAR
+ || (ptr_ok && TYPE_CODE (type) == TYPE_CODE_PTR));
+}
+
+/* Implements conversion to int. */
+static PyObject *
+valpy_int (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ LONGEST l = 0;
+ volatile struct gdb_exception except;
+
+ CHECK_TYPEDEF (type);
+ if (!is_intlike (type, 0))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to int");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ l = value_as_long (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyInt_FromLong (l);
+}
+
+/* Implements conversion to long. */
+static PyObject *
+valpy_long (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ LONGEST l = 0;
+ volatile struct gdb_exception except;
+
+ if (!is_intlike (type, 1))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to long");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ l = value_as_long (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromLong (l);
+}
+
+/* Implements conversion to float. */
+static PyObject *
+valpy_float (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ double d = 0;
+ volatile struct gdb_exception except;
+
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) != TYPE_CODE_FLT)
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to float");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ d = value_as_double (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyFloat_FromDouble (d);
+}
+
/* Returns an object for a value which is released from the all_values chain,
so its lifetime is not bound to the execution of a command. */
PyObject *
@@ -561,13 +711,16 @@ convert_value_from_python (PyObject *obj)
if (! PyErr_Occurred ())
value = value_from_double (builtin_type_pyfloat, d);
}
- else if (PyString_Check (obj) || PyUnicode_Check (obj))
+ else if (gdbpy_is_string (obj))
{
char *s;
s = python_string_to_target_string (obj);
if (s == NULL)
- return NULL;
+ {
+ PyErr_Clear ();
+ error (_("Error converting Python value."));
+ }
old = make_cleanup (xfree, s);
value = value_from_string (s);
@@ -587,7 +740,7 @@ convert_value_from_python (PyObject *obj)
/* Returns value object in the ARGth position in GDB's history. */
PyObject *
-gdbpy_get_value_from_history (PyObject *self, PyObject *args)
+gdbpy_history (PyObject *self, PyObject *args)
{
int i;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
@@ -608,7 +761,6 @@ gdbpy_get_value_from_history (PyObject *self, PyObject *args)
void
gdbpy_initialize_values (void)
{
- value_object_type.tp_new = valpy_new;
if (PyType_Ready (&value_object_type) < 0)
return;
@@ -619,6 +771,7 @@ gdbpy_initialize_values (void)
}
static PyMethodDef value_object_methods[] = {
+ { "address", valpy_address, METH_NOARGS, "Return the address of the value." },
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{NULL} /* Sentinel */
};
@@ -634,7 +787,19 @@ static PyNumberMethods value_object_as_number = {
valpy_negative, /* nb_negative */
valpy_positive, /* nb_positive */
valpy_absolute, /* nb_absolute */
- valpy_nonzero /* nb_nonzero */
+ valpy_nonzero, /* nb_nonzero */
+ valpy_invert, /* nb_invert */
+ valpy_lsh, /* nb_lshift */
+ valpy_rsh, /* nb_rshift */
+ valpy_and, /* nb_and */
+ valpy_xor, /* nb_xor */
+ valpy_or, /* nb_or */
+ NULL, /* nb_coerce */
+ valpy_int, /* nb_int */
+ valpy_long, /* nb_long */
+ valpy_float, /* nb_float */
+ NULL, /* nb_oct */
+ NULL /* nb_hex */
};
static PyMappingMethods value_object_as_mapping = {
@@ -672,7 +837,17 @@ PyTypeObject value_object_type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- value_object_methods /* tp_methods */
+ value_object_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ valpy_new /* tp_new */
};
#endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 50277d4..991321f 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1,6 +1,6 @@
/* General python/gdb code
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
@@ -52,7 +52,7 @@ static PyObject *gdbpy_flush (PyObject *, PyObject *);
static PyMethodDef GdbMethods[] =
{
- { "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS,
+ { "history", gdbpy_history, METH_VARARGS,
"Get a value from history" },
{ "execute", execute_gdb_command, METH_VARARGS,
"Execute a gdb command" },
diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c
index 82cfd9a..17e5c62 100644
--- a/gdb/testsuite/gdb.python/python-value.c
+++ b/gdb/testsuite/gdb.python/python-value.c
@@ -1,6 +1,6 @@
/* This testcase is part of GDB, the GNU debugger.
- Copyright 2008 Free Software Foundation, Inc.
+ Copyright 2008, 2009 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,6 +27,14 @@ union u
float b;
};
+enum e
+ {
+ ONE = 1,
+ TWO = 2
+ };
+
+enum e evalue = TWO;
+
int
main (int argc, char *argv[])
{
@@ -37,5 +45,7 @@ main (int argc, char *argv[])
s.b = 5;
u.a = 7;
+ argv[0][0] = 'a'; /* Just to avoid getting argv optimized out. */
+
return 0; /* break to inspect struct and union */
}
diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp
index 99b576a..8f5e0ab 100644
--- a/gdb/testsuite/gdb.python/python-value.exp
+++ b/gdb/testsuite/gdb.python/python-value.exp
@@ -1,4 +1,4 @@
-# Copyright (C) 2008 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -111,13 +111,18 @@ proc test_value_numeric_ops {} {
gdb_test "python print 'result = ' + str(1-i)" " = -4" "subtract python integer from integer value"
gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value"
+ # Conversion test.
+ gdb_test "print evalue" " = TWO"
+ gdb_test "python evalue = gdb.history (0)" ""
+ gdb_test "python print int (evalue)" "2"
+
# Test pointer arithmethic
# First, obtain the pointers
gdb_test "print (void *) 2" "" ""
- gdb_test "python a = gdb.get_value_from_history (0)" "" ""
+ gdb_test "python a = gdb.history (0)" "" ""
gdb_test "print (void *) 5" "" ""
- gdb_test "python b = gdb.get_value_from_history (0)" "" ""
+ gdb_test "python b = gdb.history (0)" "" ""
gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer"
gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value"
@@ -205,7 +210,7 @@ proc test_value_in_inferior {} {
# Just get inferior variable s in the value history, available to python.
gdb_test "print s" " = {a = 3, b = 5}" ""
- gdb_py_test_silent_cmd "python s = gdb.get_value_from_history (0)" "get value from history" 1
+ gdb_py_test_silent_cmd "python s = gdb.history (0)" "get value from history" 1
gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name"
gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name"
@@ -215,7 +220,7 @@ proc test_value_in_inferior {} {
# Just get inferior variable argv the value history, available to python.
gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" ""
- gdb_py_test_silent_cmd "python argv = gdb.get_value_from_history (0)" "" 0
+ gdb_py_test_silent_cmd "python argv = gdb.history (0)" "" 0
gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1
# Check that the dereferenced value is sane
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [RFC][python] Fixes and improvements to gdb.Value.
2009-01-03 2:25 [RFC][python] Fixes and improvements to gdb.Value Thiago Jung Bauermann
@ 2009-01-03 9:42 ` Eli Zaretskii
2009-01-03 23:09 ` Thiago Jung Bauermann
0 siblings, 1 reply; 15+ messages in thread
From: Eli Zaretskii @ 2009-01-03 9:42 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Date: Sat, 03 Jan 2009 00:24:59 -0200
>
> This patch has fixes and improvements made to the value python bindings
> that have been made in the python branch since this code has been
> committed to CVS. Ok?
Thanks.
> gdb/doc/
> 2009-01-03 Tom Tromey <tromey@redhat.com>
>
> * gdb.texinfo (Basic Python): Document gdb.history.
This part is approved, but I have a few comments:
> +@findex gdb.history
The text below this does not mention "gdb.history" at all. Should it?
I could imagine a reader who gets here by following the "gdb.history"
index entry, and is then puzzled by not finding that text anywhere.
> +If @var{number} is less than or equal to zero, then @value{GDBN} will
> +take the absolute value of @var{number} and count backward from the
> +last element to find the value to return.
For clarity, I'd separate the zero case and the negative case. First,
"is less than or equal to zero" is a mouthful that would be eliminated
then; you could simply say "negative". And second, "count zero
elements backward" is an abstraction that is a better avoided.
> If there is no such element
> +in the value history, an exception will be raised.
Should we say which exception will be raised, and perhaps have a
cross-reference to where exceptions raised in Python code are
described?
> +The return value is always an instance of @code{gdb.Value}
> +(@pxref{Values From Inferior}).
> +@end defun
I'd modify this thusly:
If no exception is raised, the return value is always an instance of
@code{gdb.Value} (@pxref{Values From Inferior}).
The point is that we should be crystal clear that a value is returned
only if there's no exception (since there are languages where an
exception, too, can return a value), and that "always" does not
include the case with an exception.
> + string object converted to a named charset. If an error occurs during
> the conversion, NULL will be returned and a python exception will be set.
>
> The caller is responsible for xfree'ing the string. */
> -char *
> -unicode_to_target_string (PyObject *unicode_str)
> +static char *
> +unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
I think our convention is to up-case references to arguments in
comments that describe the function. So please use "named CHARSET" in
the above comment.
> +/* Converts a python string (8-bit or unicode) to a target string in
Is 8-bit and Unicode the only 2 alternatives here? IOW, doesn;t this
support Far Eastern multibyte encodings, such as ISO-2022, Big-5,
etc.? Sorry if I'm talking nonsense out of ignorance about Python's
support of non-ASCII characters.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [RFC][python] Fixes and improvements to gdb.Value.
2009-01-03 9:42 ` Eli Zaretskii
@ 2009-01-03 23:09 ` Thiago Jung Bauermann
2009-01-04 4:20 ` Eli Zaretskii
2009-01-05 21:01 ` Tom Tromey
0 siblings, 2 replies; 15+ messages in thread
From: Thiago Jung Bauermann @ 2009-01-03 23:09 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
Hi Eli,
El sáb, 03-01-2009 a las 11:41 +0200, Eli Zaretskii escribió:
> > * gdb.texinfo (Basic Python): Document gdb.history.
>
> This part is approved, but I have a few comments:
Thanks for the review and the comments. The patch below addresses them,
and removes the copyright updates since they were already made.
> > +@findex gdb.history
>
> The text below this does not mention "gdb.history" at all. Should it?
> I could imagine a reader who gets here by following the "gdb.history"
> index entry, and is then puzzled by not finding that text anywhere.
Well, the text is in the section which describes functions in the gdb
module, so the reader should be aware that the function is inside it.
Also, in Python "gdb.history" wouldn't be the only possible way of
referencing the function. If the user imports the gdb module with
"from gdb import *", then he would just need to type "history" to use
it. "gdb.history" is only special in that from the CLI, the gdb module
is automatically imported and would be accessible to the user spelled
like that. But (s)he could type "python from gdb import *" and then use
the other way to access it.
In a nutshell, my answer is "no, I don't think it should". :-)
> > +If @var{number} is less than or equal to zero, then @value{GDBN} will
> > +take the absolute value of @var{number} and count backward from the
> > +last element to find the value to return.
>
> For clarity, I'd separate the zero case and the negative case. First,
> "is less than or equal to zero" is a mouthful that would be eliminated
> then; you could simply say "negative". And second, "count zero
> elements backward" is an abstraction that is a better avoided.
Good point. I reworded it to:
If @var{number} is negative, then @value{GDBN} will take its absolute value
and count backward from the last element (i.e., the most recent element) to
find the value to return. If @var{number} is zero, then @value{GDBN} will
return the most recent element. If the element specified by @value{number}
doesn't exist in the value history, a @code{RuntimeError} exception will be
raised.
What do you think?
> > If there is no such element
> > +in the value history, an exception will be raised.
>
> Should we say which exception will be raised, and perhaps have a
> cross-reference to where exceptions raised in Python code are
> described?
I changed it to mention that the RuntimeError exception will be raised.
Since exceptions are a common occurence in Python (and in GDB's Python
API), I think we would have too many references to the exceptions
section if we added a link to it from every place which mentions
exceptions.
> > +The return value is always an instance of @code{gdb.Value}
> > +(@pxref{Values From Inferior}).
> > +@end defun
>
> I'd modify this thusly:
>
> If no exception is raised, the return value is always an instance of
> @code{gdb.Value} (@pxref{Values From Inferior}).
>
> The point is that we should be crystal clear that a value is returned
> only if there's no exception (since there are languages where an
> exception, too, can return a value), and that "always" does not
> include the case with an exception.
Right. I wasn't aware that in some languages functions can both return a
value and raise an exception. I adopted your wording.
> > + string object converted to a named charset. If an error occurs during
> > the conversion, NULL will be returned and a python exception will be set.
> >
> > The caller is responsible for xfree'ing the string. */
> > -char *
> > -unicode_to_target_string (PyObject *unicode_str)
> > +static char *
> > +unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
>
> I think our convention is to up-case references to arguments in
> comments that describe the function. So please use "named CHARSET" in
> the above comment.
Changed.
> > +/* Converts a python string (8-bit or unicode) to a target string in
>
> Is 8-bit and Unicode the only 2 alternatives here? IOW, doesn;t this
> support Far Eastern multibyte encodings, such as ISO-2022, Big-5,
> etc.? Sorry if I'm talking nonsense out of ignorance about Python's
> support of non-ASCII characters.
Yes, Python only has those two types of string objects. I'm no expert,
but I think multibyte encodings can be represented in 8-bit Python
strings. They are ill named, with "8-bit string" they really mean "array
of uninterpreted bytes". In Python 3.0, "Unicode string" is now called
"str", and "8-bit string" is called "bytes".
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
gdb/
2009-01-03 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* python/python-internal.h (gdbpy_get_value_from_history): Rename
prototype to gdbpy_history.
(gdbpy_is_string): Declare.
(python_string_to_host_string): Declare.
* python/python-utils.c (gdbpy_is_string): New function.
(unicode_to_encoded_string): New function.
(unicode_to_target_string): Use it.
(python_string_to_host_string): New function.
* python/python-value.c (valpy_address): New function.
(valpy_getitem): Convert field name to
host string. Handle array accesses.
(enum valpy_opcode) <VALPY_LSH, VALPY_RSH, VALPY_BITAND,
VALPY_BITXOR, VALPY_BITOR>: New constants.
(valpy_binop): Update.
(valpy_invert): New function.
(valpy_lsh): Likewise.
(valpy_rsh): Likewise.
(valpy_and): Likewise.
(valpy_or): Likewise.
(valpy_xor): Likewise.
(valpy_richcompare): Call
convert_value_from_python instead of doing conversions itself.
(is_intlike, valpy_int, valpy_long, valpy_float): New functions.
(convert_value_from_python): Use gdbpy_is_string. Clear Python
exception and throw GDB exception if python_string_to_target_string
fails.
(gdbpy_get_value_from_history): Rename
function to gdbpy_history.
(gdbpy_initialize_values): Don't set tp_new.
(value_object_type): Add valpy_new.
(value_object_methods): Add `address' entry.
(value_object_as_number): Update for new methods.
* python/python.c (GdbMethods): Rename entry from
`get_value_from_history' to `history'.
gdb/doc/
2009-01-03 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Basic Python): Document gdb.history.
gdb/testsuite/
2009-01-03 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.python/python-value.exp: Use `gdb.history' instead of
`gdb.value_from_history'.
(test_value_numeric_ops): Add test for conversion of enum constant.
* gdb.python/python-value.c (enum e): New type.
(evalue): New global.
(main): Use argv.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6ef124c..4f7888e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
-@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
@c Free Software Foundation, Inc.
@c
@c %**start of header
@@ -18086,6 +18086,21 @@ If the named parameter does not exist, this function throws a
a Python value of the appropriate type, and returned.
@end defun
+@findex gdb.history
+@defun history number
+Return a value from @value{GDBN}'s value history (@pxref{Value
+History}). @var{number} indicates which history element to return.
+If @var{number} is negative, then @value{GDBN} will take its absolute value
+and count backward from the last element (i.e., the most recent element) to
+find the value to return. If @var{number} is zero, then @value{GDBN} will
+return the most recent element. If the element specified by @value{number}
+doesn't exist in the value history, a @code{RuntimeError} exception will be
+raised.
+
+If no exception is raised, the return value is always an instance of
+@code{gdb.Value} (@pxref{Values From Inferior}).
+@end defun
+
@findex gdb.write
@defun write string
Print a string to @value{GDBN}'s paginated standard output stream.
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 24d1b44..bcd37e4 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -60,7 +60,7 @@ struct value;
extern PyObject *gdb_module;
extern PyTypeObject value_object_type;
-PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *value_to_value_object (struct value *v);
@@ -87,5 +87,7 @@ void gdbpy_print_stack (void);
PyObject *python_string_to_unicode (PyObject *obj);
char *unicode_to_target_string (PyObject *unicode_str);
char *python_string_to_target_string (PyObject *obj);
+char *python_string_to_host_string (PyObject *obj);
+int gdbpy_is_string (PyObject *obj);
#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index 9aae43f..6a95939 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -95,26 +95,37 @@ python_string_to_unicode (PyObject *obj)
}
/* Returns a newly allocated string with the contents of the given unicode
- string object converted to the target's charset. If an error occurs during
- the conversion, NULL will be returned and a python exception will be set.
+ string object converted to CHARSET. If an error occurs during the
+ conversion, NULL will be returned and a python exception will be set.
The caller is responsible for xfree'ing the string. */
-char *
-unicode_to_target_string (PyObject *unicode_str)
+static char *
+unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
{
- char *target_string;
+ char *result;
PyObject *string;
- /* Translate string to target's charset. */
- string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ /* Translate string to named charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
if (string == NULL)
return NULL;
- target_string = xstrdup (PyString_AsString (string));
+ result = xstrdup (PyString_AsString (string));
Py_DECREF (string);
- return target_string;
+ return result;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ return unicode_to_encoded_string (unicode_str, target_charset ());
}
/* Converts a python string (8-bit or unicode) to a target string in
@@ -132,3 +143,28 @@ python_string_to_target_string (PyObject *obj)
return unicode_to_target_string (str);
}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the host's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_host_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_encoded_string (str, host_charset ());
+}
+
+/* Return true if OBJ is a Python string or unicode object, false
+ otherwise. */
+
+int
+gdbpy_is_string (PyObject *obj)
+{
+ return PyString_Check (obj) || PyUnicode_Check (obj);
+}
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 92e0431..4d1f864 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -132,6 +132,22 @@ valpy_dereference (PyObject *self, PyObject *args)
return value_to_value_object (res_val);
}
+/* Return "&value". */
+static PyObject *
+valpy_address (PyObject *self, PyObject *args)
+{
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ res_val = value_addr (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return value_to_value_object (res_val);
+}
+
static Py_ssize_t
valpy_length (PyObject *self)
{
@@ -147,26 +163,37 @@ static PyObject *
valpy_getitem (PyObject *self, PyObject *key)
{
value_object *self_value = (value_object *) self;
- char *field;
+ char *field = NULL;
+ struct value *idx = NULL;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
- struct cleanup *old;
volatile struct gdb_exception except;
- field = python_string_to_target_string (key);
- if (field == NULL)
- return NULL;
-
- old = make_cleanup (xfree, field);
+ if (gdbpy_is_string (key))
+ {
+ field = python_string_to_host_string (key);
+ if (field == NULL)
+ return NULL;
+ }
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct value *tmp = self_value->value;
- res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
+
+ if (field)
+ res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
+ else
+ {
+ /* Assume we are attempting an array access, and let the
+ value code throw an exception if the index has an invalid
+ type. */
+ struct value *idx = convert_value_from_python (key);
+ res_val = value_subscript (tmp, idx);
+ }
}
+ if (field)
+ xfree (field);
GDB_PY_HANDLE_EXCEPTION (except);
- do_cleanups (old);
-
return value_to_value_object (res_val);
}
@@ -220,7 +247,12 @@ enum valpy_opcode
VALPY_MUL,
VALPY_DIV,
VALPY_REM,
- VALPY_POW
+ VALPY_POW,
+ VALPY_LSH,
+ VALPY_RSH,
+ VALPY_BITAND,
+ VALPY_BITOR,
+ VALPY_BITXOR
};
/* If TYPE is a reference, return the target; otherwise return TYPE. */
@@ -302,6 +334,21 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
case VALPY_POW:
res_val = value_binop (arg1, arg2, BINOP_EXP);
break;
+ case VALPY_LSH:
+ res_val = value_binop (arg1, arg2, BINOP_LSH);
+ break;
+ case VALPY_RSH:
+ res_val = value_binop (arg1, arg2, BINOP_RSH);
+ break;
+ case VALPY_BITAND:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_AND);
+ break;
+ case VALPY_BITOR:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_IOR);
+ break;
+ case VALPY_BITXOR:
+ res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR);
+ break;
}
}
GDB_PY_HANDLE_EXCEPTION (except);
@@ -412,45 +459,66 @@ valpy_nonzero (PyObject *self)
}
}
-/* Implements comparison operations for value objects. */
+/* Implements ~ for value objects. */
static PyObject *
-valpy_richcompare (PyObject *self, PyObject *other, int op)
+valpy_invert (PyObject *self)
{
- int result = 0;
- struct value *value_self, *value_other;
+ struct value *val = NULL;
volatile struct gdb_exception except;
- if (PyObject_TypeCheck (other, &value_object_type))
- value_other = ((value_object *) other)->value;
- else if (PyInt_Check (other))
+ TRY_CATCH (except, RETURN_MASK_ALL)
{
- LONGEST l;
+ val = value_complement (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
- l = PyInt_AsLong (other);
- if (PyErr_Occurred ())
- return NULL;
+ return value_to_value_object (val);
+}
- value_other = value_from_longest (builtin_type_pyint, l);
- }
- else if (PyFloat_Check (other))
- {
- DOUBLEST d;
+/* Implements left shift for value objects. */
+static PyObject *
+valpy_lsh (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_LSH, self, other);
+}
- d = PyFloat_AsDouble (other);
- if (PyErr_Occurred ())
- return NULL;
+/* Implements right shift for value objects. */
+static PyObject *
+valpy_rsh (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_RSH, self, other);
+}
- value_other = value_from_double (builtin_type_pyfloat, d);
- }
- else if (PyString_Check (other) || PyUnicode_Check (other))
- {
- char *str;
+/* Implements bitwise and for value objects. */
+static PyObject *
+valpy_and (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITAND, self, other);
+}
- str = python_string_to_target_string (other);
- value_other = value_from_string (str);
- xfree (str);
- }
- else if (other == Py_None)
+/* Implements bitwise or for value objects. */
+static PyObject *
+valpy_or (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITOR, self, other);
+}
+
+/* Implements bitwise xor for value objects. */
+static PyObject *
+valpy_xor (PyObject *self, PyObject *other)
+{
+ return valpy_binop (VALPY_BITXOR, self, other);
+}
+
+/* Implements comparison operations for value objects. */
+static PyObject *
+valpy_richcompare (PyObject *self, PyObject *other, int op)
+{
+ int result = 0;
+ struct value *value_other;
+ volatile struct gdb_exception except;
+
+ if (other == Py_None)
/* Comparing with None is special. From what I can tell, in Python
None is smaller than anything else. */
switch (op) {
@@ -468,15 +536,11 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
"Invalid operation on gdb.Value.");
return NULL;
}
- else
- {
- PyErr_SetString (PyExc_NotImplementedError,
- "Operation not supported on gdb.Value of this type.");
- return NULL;
- }
TRY_CATCH (except, RETURN_MASK_ALL)
{
+ value_other = convert_value_from_python (other);
+
switch (op) {
case Py_LT:
result = value_less (((value_object *) self)->value, value_other);
@@ -513,6 +577,92 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
Py_RETURN_FALSE;
}
+/* Helper function to determine if a type is "int-like". */
+static int
+is_intlike (struct type *type, int ptr_ok)
+{
+ CHECK_TYPEDEF (type);
+ return (TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_ENUM
+ || TYPE_CODE (type) == TYPE_CODE_BOOL
+ || TYPE_CODE (type) == TYPE_CODE_CHAR
+ || (ptr_ok && TYPE_CODE (type) == TYPE_CODE_PTR));
+}
+
+/* Implements conversion to int. */
+static PyObject *
+valpy_int (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ LONGEST l = 0;
+ volatile struct gdb_exception except;
+
+ CHECK_TYPEDEF (type);
+ if (!is_intlike (type, 0))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to int");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ l = value_as_long (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyInt_FromLong (l);
+}
+
+/* Implements conversion to long. */
+static PyObject *
+valpy_long (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ LONGEST l = 0;
+ volatile struct gdb_exception except;
+
+ if (!is_intlike (type, 1))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to long");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ l = value_as_long (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromLong (l);
+}
+
+/* Implements conversion to float. */
+static PyObject *
+valpy_float (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ double d = 0;
+ volatile struct gdb_exception except;
+
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) != TYPE_CODE_FLT)
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to float");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ d = value_as_double (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyFloat_FromDouble (d);
+}
+
/* Returns an object for a value which is released from the all_values chain,
so its lifetime is not bound to the execution of a command. */
PyObject *
@@ -561,13 +711,16 @@ convert_value_from_python (PyObject *obj)
if (! PyErr_Occurred ())
value = value_from_double (builtin_type_pyfloat, d);
}
- else if (PyString_Check (obj) || PyUnicode_Check (obj))
+ else if (gdbpy_is_string (obj))
{
char *s;
s = python_string_to_target_string (obj);
if (s == NULL)
- return NULL;
+ {
+ PyErr_Clear ();
+ error (_("Error converting Python value."));
+ }
old = make_cleanup (xfree, s);
value = value_from_string (s);
@@ -587,7 +740,7 @@ convert_value_from_python (PyObject *obj)
/* Returns value object in the ARGth position in GDB's history. */
PyObject *
-gdbpy_get_value_from_history (PyObject *self, PyObject *args)
+gdbpy_history (PyObject *self, PyObject *args)
{
int i;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
@@ -608,7 +761,6 @@ gdbpy_get_value_from_history (PyObject *self, PyObject *args)
void
gdbpy_initialize_values (void)
{
- value_object_type.tp_new = valpy_new;
if (PyType_Ready (&value_object_type) < 0)
return;
@@ -619,6 +771,7 @@ gdbpy_initialize_values (void)
}
static PyMethodDef value_object_methods[] = {
+ { "address", valpy_address, METH_NOARGS, "Return the address of the value." },
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{NULL} /* Sentinel */
};
@@ -634,7 +787,19 @@ static PyNumberMethods value_object_as_number = {
valpy_negative, /* nb_negative */
valpy_positive, /* nb_positive */
valpy_absolute, /* nb_absolute */
- valpy_nonzero /* nb_nonzero */
+ valpy_nonzero, /* nb_nonzero */
+ valpy_invert, /* nb_invert */
+ valpy_lsh, /* nb_lshift */
+ valpy_rsh, /* nb_rshift */
+ valpy_and, /* nb_and */
+ valpy_xor, /* nb_xor */
+ valpy_or, /* nb_or */
+ NULL, /* nb_coerce */
+ valpy_int, /* nb_int */
+ valpy_long, /* nb_long */
+ valpy_float, /* nb_float */
+ NULL, /* nb_oct */
+ NULL /* nb_hex */
};
static PyMappingMethods value_object_as_mapping = {
@@ -672,7 +837,17 @@ PyTypeObject value_object_type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- value_object_methods /* tp_methods */
+ value_object_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ valpy_new /* tp_new */
};
#endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e778ac4..991321f 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -52,7 +52,7 @@ static PyObject *gdbpy_flush (PyObject *, PyObject *);
static PyMethodDef GdbMethods[] =
{
- { "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS,
+ { "history", gdbpy_history, METH_VARARGS,
"Get a value from history" },
{ "execute", execute_gdb_command, METH_VARARGS,
"Execute a gdb command" },
diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c
index 8c10956..17e5c62 100644
--- a/gdb/testsuite/gdb.python/python-value.c
+++ b/gdb/testsuite/gdb.python/python-value.c
@@ -27,6 +27,14 @@ union u
float b;
};
+enum e
+ {
+ ONE = 1,
+ TWO = 2
+ };
+
+enum e evalue = TWO;
+
int
main (int argc, char *argv[])
{
@@ -37,5 +45,7 @@ main (int argc, char *argv[])
s.b = 5;
u.a = 7;
+ argv[0][0] = 'a'; /* Just to avoid getting argv optimized out. */
+
return 0; /* break to inspect struct and union */
}
diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp
index 2057e61..8f5e0ab 100644
--- a/gdb/testsuite/gdb.python/python-value.exp
+++ b/gdb/testsuite/gdb.python/python-value.exp
@@ -111,13 +111,18 @@ proc test_value_numeric_ops {} {
gdb_test "python print 'result = ' + str(1-i)" " = -4" "subtract python integer from integer value"
gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value"
+ # Conversion test.
+ gdb_test "print evalue" " = TWO"
+ gdb_test "python evalue = gdb.history (0)" ""
+ gdb_test "python print int (evalue)" "2"
+
# Test pointer arithmethic
# First, obtain the pointers
gdb_test "print (void *) 2" "" ""
- gdb_test "python a = gdb.get_value_from_history (0)" "" ""
+ gdb_test "python a = gdb.history (0)" "" ""
gdb_test "print (void *) 5" "" ""
- gdb_test "python b = gdb.get_value_from_history (0)" "" ""
+ gdb_test "python b = gdb.history (0)" "" ""
gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer"
gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value"
@@ -205,7 +210,7 @@ proc test_value_in_inferior {} {
# Just get inferior variable s in the value history, available to python.
gdb_test "print s" " = {a = 3, b = 5}" ""
- gdb_py_test_silent_cmd "python s = gdb.get_value_from_history (0)" "get value from history" 1
+ gdb_py_test_silent_cmd "python s = gdb.history (0)" "get value from history" 1
gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name"
gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name"
@@ -215,7 +220,7 @@ proc test_value_in_inferior {} {
# Just get inferior variable argv the value history, available to python.
gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" ""
- gdb_py_test_silent_cmd "python argv = gdb.get_value_from_history (0)" "" 0
+ gdb_py_test_silent_cmd "python argv = gdb.history (0)" "" 0
gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1
# Check that the dereferenced value is sane
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [RFC][python] Fixes and improvements to gdb.Value.
2009-01-03 23:09 ` Thiago Jung Bauermann
@ 2009-01-04 4:20 ` Eli Zaretskii
2009-01-05 21:01 ` Tom Tromey
1 sibling, 0 replies; 15+ messages in thread
From: Eli Zaretskii @ 2009-01-04 4:20 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: gdb-patches@sourceware.org
> Date: Sat, 03 Jan 2009 21:09:07 -0200
>
> In a nutshell, my answer is "no, I don't think it should". :-)
Then perhaps having an index entry "gdb.history" is not important,
either?
> If @var{number} is negative, then @value{GDBN} will take its absolute value
> and count backward from the last element (i.e., the most recent element) to
> find the value to return. If @var{number} is zero, then @value{GDBN} will
> return the most recent element. If the element specified by @value{number}
> doesn't exist in the value history, a @code{RuntimeError} exception will be
> raised.
>
> What do you think?
Sounds good.
> 2009-01-03 Tom Tromey <tromey@redhat.com>
>
> * gdb.texinfo (Basic Python): Document gdb.history.
Thanks, I'm happy now.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [RFC][python] Fixes and improvements to gdb.Value.
2009-01-03 23:09 ` Thiago Jung Bauermann
2009-01-04 4:20 ` Eli Zaretskii
@ 2009-01-05 21:01 ` Tom Tromey
2009-01-29 14:16 ` Thiago Jung Bauermann
1 sibling, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2009-01-05 21:01 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Eli Zaretskii, gdb-patches
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
>> > +@findex gdb.history
>>
>> The text below this does not mention "gdb.history" at all. Should it?
>> I could imagine a reader who gets here by following the "gdb.history"
>> index entry, and is then puzzled by not finding that text anywhere.
Thiago> Well, the text is in the section which describes functions in the gdb
Thiago> module, so the reader should be aware that the function is inside it.
Thiago> Also, in Python "gdb.history" wouldn't be the only possible way of
Thiago> referencing the function. If the user imports the gdb module with
Thiago> "from gdb import *", then he would just need to type "history" to use
Thiago> it. "gdb.history" is only special in that from the CLI, the gdb module
Thiago> is automatically imported and would be accessible to the user spelled
Thiago> like that. But (s)he could type "python from gdb import *" and then use
Thiago> the other way to access it.
Thiago> In a nutshell, my answer is "no, I don't think it should". :-)
I agree.
Note that the existing Python docs in the manual already use this
approach. This patch merely continues it.
My reason for adding these index entries is that a Python programmer
might reasonably expect to find the fully-qualified function name in
the manual's index. However, it is strange to constantly see the
fully-qualified name in the documentation text. So, I used the short
form in the text and added index entries.
Thiago -- I know it is kind of a pain, but would you mind putting any
changes you make back onto the Python branch? Or if you can't do it,
let me know and I will try to. I'd like to keep the branch
"canonical" so that we can diff against mainline to see what Python
bits ought to be merged.
Tom
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFC][python] Fixes and improvements to gdb.Value.
2009-01-05 21:01 ` Tom Tromey
@ 2009-01-29 14:16 ` Thiago Jung Bauermann
0 siblings, 0 replies; 15+ messages in thread
From: Thiago Jung Bauermann @ 2009-01-29 14:16 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches
El lun, 05-01-2009 a las 14:00 -0700, Tom Tromey escribió:
> Thiago -- I know it is kind of a pain, but would you mind putting any
> changes you make back onto the Python branch? Or if you can't do it,
> let me know and I will try to. I'd like to keep the branch
> "canonical" so that we can diff against mainline to see what Python
> bits ought to be merged.
I've been doing that. If you find some discrepancy, please let me know
so I can fix it.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-02-05 16:43 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-02 13:06 [RFA][python] Fixes for existing Python code Thiago Jung Bauermann
2009-02-02 13:19 ` Thiago Jung Bauermann
2009-02-02 17:28 ` Tom Tromey
2009-02-05 16:43 ` Thiago Jung Bauermann
2009-02-02 18:30 ` Tom Tromey
2009-02-04 1:01 ` [RFC][python] Fixes and improvements to gdb.Value. (was Re: [RFA][python] Fixes for existing Python code.) Thiago Jung Bauermann
2009-02-04 19:40 ` [RFC][python] Fixes and improvements to gdb.Value Tom Tromey
2009-02-04 21:57 ` Thiago Jung Bauermann
2009-02-02 19:23 ` [RFA][python] Fixes for existing Python code Eli Zaretskii
-- strict thread matches above, loose matches on Subject: below --
2009-01-03 2:25 [RFC][python] Fixes and improvements to gdb.Value Thiago Jung Bauermann
2009-01-03 9:42 ` Eli Zaretskii
2009-01-03 23:09 ` Thiago Jung Bauermann
2009-01-04 4:20 ` Eli Zaretskii
2009-01-05 21:01 ` Tom Tromey
2009-01-29 14:16 ` Thiago Jung Bauermann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox