Add new Python APIs to support DAP value display
gdb's language code may know how to display values specially. For example, the Rust code understands that &str is a string-like type, or Ada knows how to handle unconstrained arrays. This knowledge is exposed via val-print, and via varobj -- but currently not via DAP. This patch adds some support code to let DAP also handle these cases, though in a somewhat more generic way. Type.is_array_like and Value.to_array are added to make Python aware of the cases where gdb knows that a structure type is really "array-like". Type.is_string_like is added to make Python aware of cases where gdb's language code knows that a type is string-like. Unlike Value.string, these cases are handled by the type's language, rather than the current language. Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This commit is contained in:
parent
91c7233d2d
commit
59668c9d8c
8
gdb/NEWS
8
gdb/NEWS
@ -269,6 +269,9 @@ info main
|
||||
|
||||
** gdb.Value now has the 'assign' method.
|
||||
|
||||
** gdb.Value now has the 'to_array' method. This converts an
|
||||
array-like Value to an array.
|
||||
|
||||
** gdb.Progspace now has the new method "objfile_for_address". This
|
||||
returns the gdb.Objfile, if any, that covers a given address.
|
||||
|
||||
@ -278,6 +281,11 @@ info main
|
||||
inferior specific, then this field contains None. This field can
|
||||
be written too.
|
||||
|
||||
** gdb.Type now has the "is_array_like" and "is_string_like"
|
||||
methods. These reflect GDB's internal idea of whether a type
|
||||
might be array- or string-like, even if they do not have the
|
||||
corresponding type code.
|
||||
|
||||
*** Changes in GDB 13
|
||||
|
||||
* MI version 1 is deprecated, and will be removed in GDB 14.
|
||||
|
@ -1206,6 +1206,13 @@ print frame-arguments scalars} (@pxref{Print Settings}).
|
||||
@end table
|
||||
@end defun
|
||||
|
||||
@defun Value.to_array ()
|
||||
If this value is array-like (@pxref{Type.is_array_like}), then this
|
||||
method converts it to an array, which is returned. If this value is
|
||||
already an array, it is simply returned. Otherwise, an exception is
|
||||
throw.
|
||||
@end defun
|
||||
|
||||
@defun Value.string (@r{[}encoding@r{[}, errors@r{[}, length@r{]]]})
|
||||
If this @code{gdb.Value} represents a string, then this method
|
||||
converts the contents to a Python string. Otherwise, this method will
|
||||
@ -1392,6 +1399,23 @@ which @code{Type.is_scalar} is @code{False}), will raise a
|
||||
@code{ValueError}.
|
||||
@end defvar
|
||||
|
||||
@defvar Type.is_array_like
|
||||
@anchor{Type.is_array_like}
|
||||
A boolean indicating whether this type is array-like.
|
||||
|
||||
Some languages have array-like objects that are represented internally
|
||||
as structures. For example, this is true for a Rust slice type, or
|
||||
for an Ada unconstrained array. @value{GDBN} may know about these
|
||||
types. This determination is done based on the language from which
|
||||
the type originated.
|
||||
@end defvar
|
||||
|
||||
@defvar Type.is_string_like
|
||||
A boolean indicating whether this type is string-like. Like
|
||||
@code{Type.is_array_like}, this is determined based on the originating
|
||||
language of the type.
|
||||
@end defvar
|
||||
|
||||
The following methods are provided:
|
||||
|
||||
@defun Type.fields ()
|
||||
|
@ -442,6 +442,59 @@ typy_is_signed (PyObject *self, void *closure)
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
|
||||
/* Return true if this type is array-like. */
|
||||
|
||||
static PyObject *
|
||||
typy_is_array_like (PyObject *self, void *closure)
|
||||
{
|
||||
struct type *type = ((type_object *) self)->type;
|
||||
|
||||
try
|
||||
{
|
||||
type = check_typedef (type);
|
||||
}
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
GDB_PY_HANDLE_EXCEPTION (except);
|
||||
}
|
||||
|
||||
if (type->is_array_like ())
|
||||
Py_RETURN_TRUE;
|
||||
else
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* Return true if this type is string-like. */
|
||||
|
||||
static PyObject *
|
||||
typy_is_string_like (PyObject *self, void *closure)
|
||||
{
|
||||
struct type *type = ((type_object *) self)->type;
|
||||
bool result = false;
|
||||
|
||||
try
|
||||
{
|
||||
type = check_typedef (type);
|
||||
|
||||
const language_defn *lang = nullptr;
|
||||
if (HAVE_GNAT_AUX_INFO (type))
|
||||
lang = language_def (language_ada);
|
||||
else if (HAVE_RUST_SPECIFIC (type))
|
||||
lang = language_def (language_rust);
|
||||
if (lang != nullptr)
|
||||
result = lang->is_string_type_p (type);
|
||||
}
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
GDB_PY_HANDLE_EXCEPTION (except);
|
||||
}
|
||||
|
||||
if (result)
|
||||
Py_RETURN_TRUE;
|
||||
else
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* Return the type, stripped of typedefs. */
|
||||
static PyObject *
|
||||
typy_strip_typedefs (PyObject *self, PyObject *args)
|
||||
@ -1525,6 +1578,10 @@ static gdb_PyGetSetDef type_object_getset[] =
|
||||
"Is this a scalar type?", nullptr },
|
||||
{ "is_signed", typy_is_signed, nullptr,
|
||||
"Is this a signed type?", nullptr },
|
||||
{ "is_array_like", typy_is_array_like, nullptr,
|
||||
"Is this an array-like type?", nullptr },
|
||||
{ "is_string_like", typy_is_string_like, nullptr,
|
||||
"Is this a string-like type?", nullptr },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -330,6 +330,40 @@ valpy_rvalue_reference_value (PyObject *self, PyObject *args)
|
||||
return valpy_reference_value (self, args, TYPE_CODE_RVALUE_REF);
|
||||
}
|
||||
|
||||
/* Implement Value.to_array. */
|
||||
|
||||
static PyObject *
|
||||
valpy_to_array (PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *result = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
struct value *val = ((value_object *) self)->value;
|
||||
struct type *type = check_typedef (val->type ());
|
||||
|
||||
if (type->code () == TYPE_CODE_ARRAY)
|
||||
{
|
||||
result = self;
|
||||
Py_INCREF (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = value_to_array (val);
|
||||
if (val == nullptr)
|
||||
PyErr_SetString (PyExc_TypeError, _("Value is not array-like."));
|
||||
else
|
||||
result = value_to_value_object (val);
|
||||
}
|
||||
}
|
||||
catch (const gdb_exception &except)
|
||||
{
|
||||
GDB_PY_HANDLE_EXCEPTION (except);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return a "const" qualified version of the value. */
|
||||
|
||||
static PyObject *
|
||||
@ -2152,6 +2186,9 @@ formatting options" },
|
||||
{ "assign", (PyCFunction) valpy_assign, METH_VARARGS,
|
||||
"assign (VAL) -> None\n\
|
||||
Assign VAL to this value." },
|
||||
{ "to_array", valpy_to_array, METH_NOARGS,
|
||||
"to_array () -> Value\n\
|
||||
Return value as an array, if possible." },
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user