OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/gnu-old/gdb-7.1/gdb/python
    from Rev 834 to Rev 842
    Reverse comparison

Rev 834 → Rev 842

/py-frame.c
0,0 → 1,539
/* Python interface to stack frames
 
Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
 
This file is part of GDB.
 
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
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
 
#include "defs.h"
#include "charset.h"
#include "block.h"
#include "frame.h"
#include "exceptions.h"
#include "symtab.h"
#include "stack.h"
#include "value.h"
#include "python-internal.h"
 
typedef struct {
PyObject_HEAD
struct frame_id frame_id;
struct gdbarch *gdbarch;
 
/* Marks that the FRAME_ID member actually holds the ID of the frame next
to this, and not this frames' ID itself. This is a hack to permit Python
frame objects which represent invalid frames (i.e., the last frame_info
in a corrupt stack). The problem arises from the fact that this code
relies on FRAME_ID to uniquely identify a frame, which is not always true
for the last "frame" in a corrupt stack (it can have a null ID, or the same
ID as the previous frame). Whenever get_prev_frame returns NULL, we
record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */
int frame_id_is_next;
} frame_object;
 
/* Require a valid frame. This must be called inside a TRY_CATCH, or
another context in which a gdb exception is allowed. */
#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
do { \
frame = frame_object_to_frame_info (frame_obj); \
if (frame == NULL) \
error ("Frame is invalid."); \
} while (0)
 
static PyTypeObject frame_object_type;
 
/* Returns the frame_info object corresponding to the given Python Frame
object. If the frame doesn't exist anymore (the frame id doesn't
correspond to any frame in the inferior), returns NULL. */
 
static struct frame_info *
frame_object_to_frame_info (frame_object *frame_obj)
{
struct frame_info *frame;
 
frame = frame_find_by_id (frame_obj->frame_id);
if (frame == NULL)
return NULL;
 
if (frame_obj->frame_id_is_next)
frame = get_prev_frame (frame);
 
return frame;
}
 
/* Called by the Python interpreter to obtain string representation
of the object. */
 
static PyObject *
frapy_str (PyObject *self)
{
char *s;
PyObject *result;
struct ui_file *strfile;
 
strfile = mem_fileopen ();
fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
s = ui_file_xstrdup (strfile, NULL);
result = PyString_FromString (s);
xfree (s);
 
return result;
}
 
/* Implementation of gdb.Frame.is_valid (self) -> Boolean.
Returns True if the frame corresponding to the frame_id of this
object still exists in the inferior. */
 
static PyObject *
frapy_is_valid (PyObject *self, PyObject *args)
{
struct frame_info *frame;
 
frame = frame_object_to_frame_info ((frame_object *) self);
if (frame == NULL)
Py_RETURN_FALSE;
 
Py_RETURN_TRUE;
}
 
/* Implementation of gdb.Frame.name (self) -> String.
Returns the name of the function corresponding to this frame. */
 
static PyObject *
frapy_name (PyObject *self, PyObject *args)
{
struct frame_info *frame;
char *name;
enum language lang;
PyObject *result;
volatile struct gdb_exception except;
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
find_frame_funname (frame, &name, &lang);
}
GDB_PY_HANDLE_EXCEPTION (except);
 
if (name)
result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL);
else
{
result = Py_None;
Py_INCREF (Py_None);
}
 
return result;
}
 
/* Implementation of gdb.Frame.type (self) -> Integer.
Returns the frame type, namely one of the gdb.*_FRAME constants. */
 
static PyObject *
frapy_type (PyObject *self, PyObject *args)
{
struct frame_info *frame;
enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning. */
volatile struct gdb_exception except;
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
type = get_frame_type (frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
 
return PyInt_FromLong (type);
}
 
/* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer.
Returns one of the gdb.FRAME_UNWIND_* constants. */
 
static PyObject *
frapy_unwind_stop_reason (PyObject *self, PyObject *args)
{
struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */
volatile struct gdb_exception except;
enum unwind_stop_reason stop_reason;
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
 
stop_reason = get_frame_unwind_stop_reason (frame);
 
return PyInt_FromLong (stop_reason);
}
 
/* Implementation of gdb.Frame.pc (self) -> Long.
Returns the frame's resume address. */
 
static PyObject *
frapy_pc (PyObject *self, PyObject *args)
{
CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */
struct frame_info *frame;
volatile struct gdb_exception except;
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
pc = get_frame_pc (frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
 
return PyLong_FromUnsignedLongLong (pc);
}
 
/* Convert a frame_info struct to a Python Frame object.
Sets a Python exception and returns NULL on error. */
 
static frame_object *
frame_info_to_frame_object (struct frame_info *frame)
{
frame_object *frame_obj;
 
frame_obj = PyObject_New (frame_object, &frame_object_type);
if (frame_obj == NULL)
{
PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object.");
return NULL;
}
 
/* Try to get the previous frame, to determine if this is the last frame
in a corrupt stack. If so, we need to store the frame_id of the next
frame and not of this one (which is possibly invalid). */
if (get_prev_frame (frame) == NULL
&& get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
&& get_next_frame (frame) != NULL)
{
frame_obj->frame_id = get_frame_id (get_next_frame (frame));
frame_obj->frame_id_is_next = 1;
}
else
{
frame_obj->frame_id = get_frame_id (frame);
frame_obj->frame_id_is_next = 0;
}
 
frame_obj->gdbarch = get_frame_arch (frame);
 
return frame_obj;
}
 
/* Implementation of gdb.Frame.older (self) -> gdb.Frame.
Returns the frame immediately older (outer) to this frame, or None if
there isn't one. */
 
static PyObject *
frapy_older (PyObject *self, PyObject *args)
{
struct frame_info *frame, *prev;
volatile struct gdb_exception except;
PyObject *prev_obj = NULL; /* Initialize to appease gcc warning. */
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
prev = get_prev_frame (frame);
if (prev)
prev_obj = (PyObject *) frame_info_to_frame_object (prev);
else
{
Py_INCREF (Py_None);
prev_obj = Py_None;
}
}
GDB_PY_HANDLE_EXCEPTION (except);
 
return prev_obj;
}
 
/* Implementation of gdb.Frame.newer (self) -> gdb.Frame.
Returns the frame immediately newer (inner) to this frame, or None if
there isn't one. */
 
static PyObject *
frapy_newer (PyObject *self, PyObject *args)
{
struct frame_info *frame, *next;
volatile struct gdb_exception except;
PyObject *next_obj = NULL; /* Initialize to appease gcc warning. */
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
next = get_next_frame (frame);
if (next)
next_obj = (PyObject *) frame_info_to_frame_object (next);
else
{
Py_INCREF (Py_None);
next_obj = Py_None;
}
}
GDB_PY_HANDLE_EXCEPTION (except);
 
return next_obj;
}
 
/* Implementation of gdb.Frame.read_var_value (self, variable) -> gdb.Value.
Returns the value of the given variable in this frame. The argument must be
a string. Returns None if GDB can't find the specified variable. */
 
static PyObject *
frapy_read_var (PyObject *self, PyObject *args)
{
struct frame_info *frame;
PyObject *sym_obj;
struct symbol *var = NULL; /* gcc-4.3.2 false warning. */
struct value *val = NULL;
volatile struct gdb_exception except;
 
if (!PyArg_ParseTuple (args, "O", &sym_obj))
return NULL;
 
if (gdbpy_is_string (sym_obj))
{
char *var_name;
struct block *block = NULL;
struct cleanup *cleanup;
volatile struct gdb_exception except;
 
var_name = python_string_to_target_string (sym_obj);
if (!var_name)
return NULL;
cleanup = make_cleanup (xfree, var_name);
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
block = block_for_pc (get_frame_address_in_block (frame));
var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL);
}
GDB_PY_HANDLE_EXCEPTION (except);
 
if (!var)
{
PyErr_Format (PyExc_ValueError,
_("variable '%s' not found"), var_name);
do_cleanups (cleanup);
 
return NULL;
}
 
do_cleanups (cleanup);
}
else
{
PyErr_SetString (PyExc_TypeError,
_("argument must be a symbol or string"));
return NULL;
}
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
val = read_var_value (var, frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
 
if (val)
return value_to_value_object (val);
 
Py_RETURN_NONE;
}
 
/* Implementation of gdb.selected_frame () -> gdb.Frame.
Returns the selected frame object. */
 
PyObject *
gdbpy_selected_frame (PyObject *self, PyObject *args)
{
struct frame_info *frame;
frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
volatile struct gdb_exception except;
 
TRY_CATCH (except, RETURN_MASK_ALL)
{
frame = get_selected_frame ("No frame is currently selected.");
frame_obj = frame_info_to_frame_object (frame);
}
GDB_PY_HANDLE_EXCEPTION (except);
 
return (PyObject *) frame_obj;
}
 
/* Implementation of gdb.stop_reason_string (Integer) -> String.
Return a string explaining the unwind stop reason. */
 
PyObject *
gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
{
int reason;
const char *str;
 
if (!PyArg_ParseTuple (args, "i", &reason))
return NULL;
 
if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
{
PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason.");
return NULL;
}
 
str = frame_stop_reason_string (reason);
return PyUnicode_Decode (str, strlen (str), host_charset (), NULL);
}
 
/* Implements the equality comparison for Frame objects.
All other comparison operators will throw a TypeError Python exception,
as they aren't valid for frames. */
 
static PyObject *
frapy_richcompare (PyObject *self, PyObject *other, int op)
{
int result;
 
if (!PyObject_TypeCheck (other, &frame_object_type)
|| (op != Py_EQ && op != Py_NE))
{
Py_INCREF (Py_NotImplemented);
return Py_NotImplemented;
}
 
if (frame_id_eq (((frame_object *) self)->frame_id,
((frame_object *) other)->frame_id))
result = Py_EQ;
else
result = Py_NE;
 
if (op == result)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
 
/* Sets up the Frame API in the gdb module. */
 
void
gdbpy_initialize_frames (void)
{
if (PyType_Ready (&frame_object_type) < 0)
return;
 
/* Note: These would probably be best exposed as class attributes of Frame,
but I don't know how to do it except by messing with the type's dictionary.
That seems too messy. */
PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
PyModule_AddIntConstant (gdb_module,
"FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
PyModule_AddIntConstant (gdb_module,
"FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
PyModule_AddIntConstant (gdb_module,
"FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
PyModule_AddIntConstant (gdb_module,
"FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
PyModule_AddIntConstant (gdb_module,
"FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
PyModule_AddIntConstant (gdb_module,
"FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
 
Py_INCREF (&frame_object_type);
PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
}
 
 
static PyMethodDef frame_object_methods[] = {
{ "is_valid", frapy_is_valid, METH_NOARGS,
"is_valid () -> Boolean.\n\
Return true if this frame is valid, false if not." },
{ "name", frapy_name, METH_NOARGS,
"name () -> String.\n\
Return the function name of the frame, or None if it can't be determined." },
{ "type", frapy_type, METH_NOARGS,
"type () -> Integer.\n\
Return the type of the frame." },
{ "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS,
"unwind_stop_reason () -> Integer.\n\
Return the reason why it's not possible to find frames older than this." },
{ "pc", frapy_pc, METH_NOARGS,
"pc () -> Long.\n\
Return the frame's resume address." },
{ "older", frapy_older, METH_NOARGS,
"older () -> gdb.Frame.\n\
Return the frame that called this frame." },
{ "newer", frapy_newer, METH_NOARGS,
"newer () -> gdb.Frame.\n\
Return the frame called by this frame." },
{ "read_var", frapy_read_var, METH_VARARGS,
"read_var (variable) -> gdb.Value.\n\
Return the value of the variable in this frame." },
{NULL} /* Sentinel */
};
 
static PyTypeObject frame_object_type = {
PyObject_HEAD_INIT (NULL)
0, /* ob_size */
"gdb.Frame", /* tp_name */
sizeof (frame_object), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
frapy_str, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"GDB frame object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
frapy_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
frame_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 */
PyType_GenericNew /* tp_new */
};
py-frame.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-objfile.c =================================================================== --- py-objfile.c (nonexistent) +++ py-objfile.c (revision 842) @@ -0,0 +1,230 @@ +/* Python interface to objfiles. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "python-internal.h" +#include "charset.h" +#include "objfiles.h" +#include "language.h" + +typedef struct +{ + PyObject_HEAD + + /* The corresponding objfile. */ + struct objfile *objfile; + + /* The pretty-printer list of functions. */ + PyObject *printers; +} objfile_object; + +static PyTypeObject objfile_object_type; + +static const struct objfile_data *objfpy_objfile_data_key; + + + +/* An Objfile method which returns the objfile's file name, or None. */ +static PyObject * +objfpy_get_filename (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + if (obj->objfile && obj->objfile->name) + return PyString_Decode (obj->objfile->name, strlen (obj->objfile->name), + host_charset (), NULL); + Py_RETURN_NONE; +} + +static void +objfpy_dealloc (PyObject *o) +{ + objfile_object *self = (objfile_object *) o; + Py_XDECREF (self->printers); + self->ob_type->tp_free ((PyObject *) self); +} + +static PyObject * +objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) +{ + objfile_object *self = (objfile_object *) type->tp_alloc (type, 0); + if (self) + { + self->objfile = NULL; + + self->printers = PyList_New (0); + if (!self->printers) + { + Py_DECREF (self); + return NULL; + } + } + return (PyObject *) self; +} + +PyObject * +objfpy_get_printers (PyObject *o, void *ignore) +{ + objfile_object *self = (objfile_object *) o; + Py_INCREF (self->printers); + return self->printers; +} + +static int +objfpy_set_printers (PyObject *o, PyObject *value, void *ignore) +{ + PyObject *tmp; + objfile_object *self = (objfile_object *) o; + if (! value) + { + PyErr_SetString (PyExc_TypeError, + "cannot delete the pretty_printers attribute"); + return -1; + } + + if (! PyList_Check (value)) + { + PyErr_SetString (PyExc_TypeError, + "the pretty_printers attribute must be a list"); + return -1; + } + + /* Take care in case the LHS and RHS are related somehow. */ + tmp = self->printers; + Py_INCREF (value); + self->printers = value; + Py_XDECREF (tmp); + + return 0; +} + + + +/* Clear the OBJFILE pointer in an Objfile object and remove the + reference. */ +static void +py_free_objfile (struct objfile *objfile, void *datum) +{ + struct cleanup *cleanup; + objfile_object *object = datum; + + cleanup = ensure_python_env (get_objfile_arch (objfile), current_language); + object->objfile = NULL; + Py_DECREF ((PyObject *) object); + do_cleanups (cleanup); +} + +/* Return a borrowed reference to the Python object of type Objfile + representing OBJFILE. If the object has already been created, + return it. Otherwise, create it. Return NULL and set the Python + error on failure. */ +PyObject * +objfile_to_objfile_object (struct objfile *objfile) +{ + objfile_object *object; + + object = objfile_data (objfile, objfpy_objfile_data_key); + if (!object) + { + object = PyObject_New (objfile_object, &objfile_object_type); + if (object) + { + PyObject *dict; + + object->objfile = objfile; + + object->printers = PyList_New (0); + if (!object->printers) + { + Py_DECREF (object); + return NULL; + } + + set_objfile_data (objfile, objfpy_objfile_data_key, object); + } + } + + return (PyObject *) object; +} + +void +gdbpy_initialize_objfile (void) +{ + objfpy_objfile_data_key + = register_objfile_data_with_cleanup (NULL, py_free_objfile); + + if (PyType_Ready (&objfile_object_type) < 0) + return; + + Py_INCREF (&objfile_object_type); + PyModule_AddObject (gdb_module, "Objfile", (PyObject *) &objfile_object_type); +} + + + +static PyGetSetDef objfile_getset[] = +{ + { "filename", objfpy_get_filename, NULL, + "The objfile's filename, or None.", NULL }, + { "pretty_printers", objfpy_get_printers, objfpy_set_printers, + "Pretty printers.", NULL }, + { NULL } +}; + +static PyTypeObject objfile_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Objfile", /*tp_name*/ + sizeof (objfile_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + objfpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB objfile object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + objfile_getset, /* 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 */ + objfpy_new, /* tp_new */ +};
py-objfile.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: python-internal.h =================================================================== --- python-internal.h (nonexistent) +++ python-internal.h (revision 842) @@ -0,0 +1,141 @@ +/* Gdb/Python header for private use by Python module. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_PYTHON_INTERNAL_H +#define GDB_PYTHON_INTERNAL_H + +/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t + needed by pyport.h. */ +#include + +/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE + if it sees _GNU_SOURCE (which config.h will define). + pyconfig.h defines _POSIX_C_SOURCE to a different value than + /usr/include/features.h does causing compilation to fail. + To work around this, undef _POSIX_C_SOURCE before we include Python.h. */ +#undef _POSIX_C_SOURCE + +#if HAVE_LIBPYTHON2_4 +#include "python2.4/Python.h" +#include "python2.4/frameobject.h" +/* Py_ssize_t is not defined until 2.5. + Logical type for Py_ssize_t is Py_intptr_t, but that fails in 64-bit + compilation due to several apparent mistakes in python2.4 API, so we + use 'int' instead. */ +typedef int Py_ssize_t; +#elif HAVE_LIBPYTHON2_5 +#include "python2.5/Python.h" +#include "python2.5/frameobject.h" +#elif HAVE_LIBPYTHON2_6 +#include "python2.6/Python.h" +#include "python2.6/frameobject.h" +#else +#error "Unable to find usable Python.h" +#endif + +/* If Python.h does not define WITH_THREAD, then the various + GIL-related functions will not be defined. However, + PyGILState_STATE will be. */ +#ifndef WITH_THREAD +#define PyGILState_Ensure() ((PyGILState_STATE) 0) +#define PyGILState_Release(ARG) ((void)(ARG)) +#define PyEval_InitThreads() 0 +#define PyThreadState_Swap(ARG) ((void)(ARG)) +#define PyEval_InitThreads() 0 +#define PyEval_ReleaseLock() 0 +#endif + +struct value; +struct language_defn; + +extern PyObject *gdb_module; +extern PyTypeObject value_object_type; + +PyObject *gdbpy_history (PyObject *self, PyObject *args); +PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); +PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args); +PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw); +PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length, + const char *encoding, struct type *type); + +PyObject *value_to_value_object (struct value *v); +PyObject *type_to_type_object (struct type *); +PyObject *objfile_to_objfile_object (struct objfile *); + +PyObject *objfpy_get_printers (PyObject *, void *); + +struct value *value_object_to_value (PyObject *self); +struct value *convert_value_from_python (PyObject *obj); +struct type *type_object_to_type (PyObject *obj); + +void gdbpy_initialize_values (void); +void gdbpy_initialize_frames (void); +void gdbpy_initialize_commands (void); +void gdbpy_initialize_types (void); +void gdbpy_initialize_functions (void); +void gdbpy_initialize_objfile (void); +void gdbpy_initialize_lazy_string (void); + +struct cleanup *make_cleanup_py_decref (PyObject *py); + +struct cleanup *ensure_python_env (struct gdbarch *gdbarch, + const struct language_defn *language); + +extern struct gdbarch *python_gdbarch; +extern const struct language_defn *python_language; + +/* Use this after a TRY_EXCEPT to throw the appropriate Python + exception. */ +#define GDB_PY_HANDLE_EXCEPTION(Exception) \ + do { \ + if (Exception.reason < 0) \ + return PyErr_Format (Exception.reason == RETURN_QUIT \ + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \ + "%s", Exception.message); \ + } while (0) + + +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); +PyObject *python_string_to_target_python_string (PyObject *obj); +char *python_string_to_host_string (PyObject *obj); +PyObject *target_string_to_unicode (const gdb_byte *str, int length); +int gdbpy_is_string (PyObject *obj); +int gdbpy_is_lazy_string (PyObject *result); +gdb_byte *gdbpy_extract_lazy_string (PyObject *string, + struct type **str_type, + long *length, char **encoding); + +/* Note that these are declared here, and not in python.h with the + other pretty-printer functions, because they refer to PyObject. */ +PyObject *apply_varobj_pretty_printer (PyObject *print_obj, + struct value **replacement); +PyObject *gdbpy_get_varobj_pretty_printer (struct value *value); +char *gdbpy_get_display_hint (PyObject *printer); +PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args); + +extern PyObject *gdbpy_doc_cst; +extern PyObject *gdbpy_children_cst; +extern PyObject *gdbpy_to_string_cst; +extern PyObject *gdbpy_display_hint_cst; + +#endif /* GDB_PYTHON_INTERNAL_H */
python-internal.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: python.c =================================================================== --- python.c (nonexistent) +++ python.c (revision 842) @@ -0,0 +1,741 @@ +/* General python/gdb code + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "arch-utils.h" +#include "command.h" +#include "ui-out.h" +#include "cli/cli-script.h" +#include "gdbcmd.h" +#include "objfiles.h" +#include "observer.h" +#include "value.h" +#include "language.h" +#include "exceptions.h" + +#include + +/* True if we should print the stack when catching a Python error, + false otherwise. */ +static int gdbpy_should_print_stack = 1; + +/* This is true if we should auto-load python code when an objfile is + opened, false otherwise. */ +static int gdbpy_auto_load = 1; + +#ifdef HAVE_PYTHON + +#include "python.h" +#include "libiberty.h" +#include "cli/cli-decode.h" +#include "charset.h" +#include "top.h" +#include "python-internal.h" +#include "version.h" +#include "target.h" +#include "gdbthread.h" + +static PyMethodDef GdbMethods[]; + +PyObject *gdb_module; + +/* Some string constants we may wish to use. */ +PyObject *gdbpy_to_string_cst; +PyObject *gdbpy_children_cst; +PyObject *gdbpy_display_hint_cst; +PyObject *gdbpy_doc_cst; + + +/* Architecture and language to be used in callbacks from + the Python interpreter. */ +struct gdbarch *python_gdbarch; +const struct language_defn *python_language; + +/* Restore global language and architecture and Python GIL state + when leaving the Python interpreter. */ + +struct python_env +{ + PyGILState_STATE state; + struct gdbarch *gdbarch; + const struct language_defn *language; +}; + +static void +restore_python_env (void *p) +{ + struct python_env *env = (struct python_env *)p; + PyGILState_Release (env->state); + python_gdbarch = env->gdbarch; + python_language = env->language; + xfree (env); +} + +/* Called before entering the Python interpreter to install the + current language and architecture to be used for Python values. */ + +struct cleanup * +ensure_python_env (struct gdbarch *gdbarch, + const struct language_defn *language) +{ + struct python_env *env = xmalloc (sizeof *env); + + env->state = PyGILState_Ensure (); + env->gdbarch = python_gdbarch; + env->language = python_language; + + python_gdbarch = gdbarch; + python_language = language; + + return make_cleanup (restore_python_env, env); +} + + +/* 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 + responsible for freeing it. */ + +static char * +compute_python_string (struct command_line *l) +{ + struct command_line *iter; + char *script = NULL; + int size = 0; + int here; + + for (iter = l; iter; iter = iter->next) + size += strlen (iter->line) + 1; + + script = xmalloc (size + 1); + here = 0; + for (iter = l; iter; iter = iter->next) + { + int len = strlen (iter->line); + strcpy (&script[here], iter->line); + here += len; + script[here++] = '\n'; + } + script[here] = '\0'; + return script; +} + +/* Take a command line structure representing a 'python' command, and + evaluate its body using the Python interpreter. */ + +void +eval_python_from_control_command (struct command_line *cmd) +{ + int ret; + char *script; + struct cleanup *cleanup; + + if (cmd->body_count != 1) + error (_("Invalid \"python\" block structure.")); + + cleanup = ensure_python_env (get_current_arch (), current_language); + + script = compute_python_string (cmd->body_list[0]); + ret = PyRun_SimpleString (script); + xfree (script); + if (ret) + { + gdbpy_print_stack (); + error (_("Error while executing Python code.")); + } + + do_cleanups (cleanup); +} + +/* Implementation of the gdb "python" command. */ + +static void +python_command (char *arg, int from_tty) +{ + struct cleanup *cleanup; + cleanup = ensure_python_env (get_current_arch (), current_language); + + while (arg && *arg && isspace (*arg)) + ++arg; + if (arg && *arg) + { + if (PyRun_SimpleString (arg)) + { + gdbpy_print_stack (); + error (_("Error while executing Python code.")); + } + } + else + { + struct command_line *l = get_command_line (python_control, ""); + make_cleanup_free_command_lines (&l); + execute_control_command_untraced (l); + } + + do_cleanups (cleanup); +} + + + +/* Transform a gdb parameters's value into a Python value. May return + NULL (and set a Python exception) on error. Helper function for + get_parameter. */ + +static PyObject * +parameter_to_python (struct cmd_list_element *cmd) +{ + switch (cmd->var_type) + { + case var_string: + case var_string_noescape: + case var_optional_filename: + case var_filename: + case var_enum: + { + char *str = * (char **) cmd->var; + if (! str) + str = ""; + return PyString_Decode (str, strlen (str), host_charset (), NULL); + } + + case var_boolean: + { + if (* (int *) cmd->var) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; + } + + case var_auto_boolean: + { + enum auto_boolean ab = * (enum auto_boolean *) cmd->var; + if (ab == AUTO_BOOLEAN_TRUE) + Py_RETURN_TRUE; + else if (ab == AUTO_BOOLEAN_FALSE) + Py_RETURN_FALSE; + else + Py_RETURN_NONE; + } + + case var_integer: + if ((* (int *) cmd->var) == INT_MAX) + Py_RETURN_NONE; + /* Fall through. */ + case var_zinteger: + return PyLong_FromLong (* (int *) cmd->var); + + case var_uinteger: + { + unsigned int val = * (unsigned int *) cmd->var; + if (val == UINT_MAX) + Py_RETURN_NONE; + return PyLong_FromUnsignedLong (val); + } + } + + return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type"); +} + +/* A Python function which returns a gdb parameter's value as a Python + value. */ + +static PyObject * +gdbpy_parameter (PyObject *self, PyObject *args) +{ + struct cmd_list_element *alias, *prefix, *cmd; + char *arg, *newarg; + int found = -1; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "s", &arg)) + return NULL; + + newarg = concat ("show ", arg, (char *) NULL); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + found = lookup_cmd_composition (newarg, &alias, &prefix, &cmd); + } + xfree (newarg); + GDB_PY_HANDLE_EXCEPTION (except); + if (!found) + return PyErr_Format (PyExc_RuntimeError, + "could not find parameter `%s'", arg); + + if (! cmd->var) + return PyErr_Format (PyExc_RuntimeError, "`%s' is not a parameter", arg); + return parameter_to_python (cmd); +} + +/* A Python function which evaluates a string using the gdb CLI. */ + +static PyObject * +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|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) + { + /* Copy the argument text in case the command modifies it. */ + char *copy = xstrdup (arg); + struct cleanup *cleanup = make_cleanup (xfree, copy); + execute_command (copy, from_tty); + do_cleanups (cleanup); + } + GDB_PY_HANDLE_EXCEPTION (except); + + /* Do any commands attached to breakpoint we stopped at. */ + bpstat_do_actions (); + + Py_RETURN_NONE; +} + +/* Parse a string and evaluate it as an expression. */ +static PyObject * +gdbpy_parse_and_eval (PyObject *self, PyObject *args) +{ + char *expr_str; + struct value *result = NULL; + volatile struct gdb_exception except; + + if (!PyArg_ParseTuple (args, "s", &expr_str)) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + result = parse_and_eval (expr_str); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (result); +} + +/* Read a file as Python code. STREAM is the input file; FILE is the + name of the file. */ + +void +source_python_script (FILE *stream, char *file) +{ + PyGILState_STATE state; + + state = PyGILState_Ensure (); + + PyRun_SimpleFile (stream, file); + + fclose (stream); + PyGILState_Release (state); +} + + + +/* Printing. */ + +/* A python function to write a single string using gdb's filtered + output stream. */ +static PyObject * +gdbpy_write (PyObject *self, PyObject *args) +{ + char *arg; + if (! PyArg_ParseTuple (args, "s", &arg)) + return NULL; + printf_filtered ("%s", arg); + Py_RETURN_NONE; +} + +/* A python function to flush gdb's filtered output stream. */ +static PyObject * +gdbpy_flush (PyObject *self, PyObject *args) +{ + gdb_flush (gdb_stdout); + Py_RETURN_NONE; +} + +/* Print a python exception trace, or print nothing and clear the + python exception, depending on gdbpy_should_print_stack. Only call + this if a python exception is set. */ +void +gdbpy_print_stack (void) +{ + if (gdbpy_should_print_stack) + PyErr_Print (); + else + PyErr_Clear (); +} + + + +/* The "current" objfile. This is set when gdb detects that a new + objfile has been loaded. It is only set for the duration of a call + to gdbpy_new_objfile; it is NULL at other times. */ +static struct objfile *gdbpy_current_objfile; + +/* The file name we attempt to read. */ +#define GDBPY_AUTO_FILENAME "-gdb.py" + +/* This is a new_objfile observer callback which loads python code + based on the path to the objfile. */ +static void +gdbpy_new_objfile (struct objfile *objfile) +{ + char *realname; + char *filename, *debugfile; + int len; + FILE *input; + struct cleanup *cleanups; + + if (!gdbpy_auto_load || !objfile || !objfile->name) + return; + + cleanups = ensure_python_env (get_objfile_arch (objfile), current_language); + + gdbpy_current_objfile = objfile; + + realname = gdb_realpath (objfile->name); + len = strlen (realname); + filename = xmalloc (len + sizeof (GDBPY_AUTO_FILENAME)); + memcpy (filename, realname, len); + strcpy (filename + len, GDBPY_AUTO_FILENAME); + + input = fopen (filename, "r"); + debugfile = filename; + + make_cleanup (xfree, filename); + make_cleanup (xfree, realname); + + if (!input && debug_file_directory) + { + /* Also try the same file in the separate debug info directory. */ + debugfile = xmalloc (strlen (filename) + + strlen (debug_file_directory) + 1); + strcpy (debugfile, debug_file_directory); + /* FILENAME is absolute, so we don't need a "/" here. */ + strcat (debugfile, filename); + + make_cleanup (xfree, debugfile); + input = fopen (debugfile, "r"); + } + + if (!input && gdb_datadir) + { + /* Also try the same file in a subdirectory of gdb's data + directory. */ + debugfile = xmalloc (strlen (gdb_datadir) + strlen (filename) + + strlen ("/auto-load") + 1); + strcpy (debugfile, gdb_datadir); + strcat (debugfile, "/auto-load"); + /* FILENAME is absolute, so we don't need a "/" here. */ + strcat (debugfile, filename); + + make_cleanup (xfree, debugfile); + input = fopen (debugfile, "r"); + } + + if (input) + { + /* We don't want to throw an exception here -- but the user + would like to know that something went wrong. */ + if (PyRun_SimpleFile (input, debugfile)) + gdbpy_print_stack (); + fclose (input); + } + + do_cleanups (cleanups); + gdbpy_current_objfile = NULL; +} + +/* Return the current Objfile, or None if there isn't one. */ +static PyObject * +gdbpy_get_current_objfile (PyObject *unused1, PyObject *unused2) +{ + PyObject *result; + + if (! gdbpy_current_objfile) + Py_RETURN_NONE; + + result = objfile_to_objfile_object (gdbpy_current_objfile); + if (result) + Py_INCREF (result); + return result; +} + +/* Return a sequence holding all the Objfiles. */ +static PyObject * +gdbpy_objfiles (PyObject *unused1, PyObject *unused2) +{ + struct objfile *objf; + PyObject *list; + + list = PyList_New (0); + if (!list) + return NULL; + + ALL_OBJFILES (objf) + { + PyObject *item = objfile_to_objfile_object (objf); + if (!item || PyList_Append (list, item) == -1) + { + Py_DECREF (list); + return NULL; + } + } + + return list; +} + +#else /* HAVE_PYTHON */ + +/* Dummy implementation of the gdb "python" command. */ + +static void +python_command (char *arg, int from_tty) +{ + while (arg && *arg && isspace (*arg)) + ++arg; + if (arg && *arg) + error (_("Python scripting is not supported in this copy of GDB.")); + else + { + struct command_line *l = get_command_line (python_control, ""); + struct cleanup *cleanups = make_cleanup_free_command_lines (&l); + execute_control_command_untraced (l); + do_cleanups (cleanups); + } +} + +void +eval_python_from_control_command (struct command_line *cmd) +{ + error (_("Python scripting is not supported in this copy of GDB.")); +} + +void +source_python_script (FILE *stream, char *file) +{ + fclose (stream); + throw_error (UNSUPPORTED_ERROR, + _("Python scripting is not supported in this copy of GDB.")); +} + +#endif /* HAVE_PYTHON */ + + + +/* Lists for 'maint set python' commands. */ + +static struct cmd_list_element *set_python_list; +static struct cmd_list_element *show_python_list; + +/* Function for use by 'maint set python' prefix command. */ + +static void +set_python (char *args, int from_tty) +{ + help_list (set_python_list, "maintenance set python ", -1, gdb_stdout); +} + +/* Function for use by 'maint show python' prefix command. */ + +static void +show_python (char *args, int from_tty) +{ + cmd_show_list (show_python_list, from_tty, ""); +} + +/* Initialize the Python code. */ + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_python; + +void +_initialize_python (void) +{ + add_com ("python", class_obscure, python_command, +#ifdef HAVE_PYTHON + _("\ +Evaluate a Python command.\n\ +\n\ +The command can be given as an argument, for instance:\n\ +\n\ + python print 23\n\ +\n\ +If no argument is given, the following lines are read and used\n\ +as the Python commands. Type a line containing \"end\" to indicate\n\ +the end of the command.") +#else /* HAVE_PYTHON */ + _("\ +Evaluate a Python command.\n\ +\n\ +Python scripting is not supported in this copy of GDB.\n\ +This command is only a placeholder.") +#endif /* HAVE_PYTHON */ + ); + + add_prefix_cmd ("python", no_class, show_python, + _("Prefix command for python maintenance settings."), + &show_python_list, "maintenance show python ", 0, + &maintenance_show_cmdlist); + add_prefix_cmd ("python", no_class, set_python, + _("Prefix command for python maintenance settings."), + &set_python_list, "maintenance set python ", 0, + &maintenance_set_cmdlist); + + add_setshow_boolean_cmd ("print-stack", class_maintenance, + &gdbpy_should_print_stack, _("\ +Enable or disable printing of Python stack dump on error."), _("\ +Show whether Python stack will be printed on error."), _("\ +Enables or disables printing of Python stack traces."), + NULL, NULL, + &set_python_list, + &show_python_list); + + add_setshow_boolean_cmd ("auto-load", class_maintenance, + &gdbpy_auto_load, _("\ +Enable or disable auto-loading of Python code when an object is opened."), _("\ +Show whether Python code will be auto-loaded when an object is opened."), _("\ +Enables or disables auto-loading of Python code when an object is opened."), + NULL, NULL, + &set_python_list, + &show_python_list); + +#ifdef HAVE_PYTHON + Py_Initialize (); + PyEval_InitThreads (); + + gdb_module = Py_InitModule ("gdb", GdbMethods); + + /* The casts to (char*) are for python 2.4. */ + PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version); + PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name); + PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name); + + gdbpy_initialize_values (); + gdbpy_initialize_frames (); + gdbpy_initialize_commands (); + gdbpy_initialize_functions (); + gdbpy_initialize_types (); + gdbpy_initialize_objfile (); + gdbpy_initialize_lazy_string (); + + PyRun_SimpleString ("import gdb"); + PyRun_SimpleString ("gdb.pretty_printers = []"); + + observer_attach_new_objfile (gdbpy_new_objfile); + + gdbpy_to_string_cst = PyString_FromString ("to_string"); + gdbpy_children_cst = PyString_FromString ("children"); + gdbpy_display_hint_cst = PyString_FromString ("display_hint"); + gdbpy_doc_cst = PyString_FromString ("__doc__"); + + /* Create a couple objects which are used for Python's stdout and + stderr. */ + PyRun_SimpleString ("\ +import sys\n\ +class GdbOutputFile:\n\ + def close(self):\n\ + # Do nothing.\n\ + return None\n\ +\n\ + def isatty(self):\n\ + return False\n\ +\n\ + def write(self, s):\n\ + gdb.write(s)\n\ +\n\ + def writelines(self, iterable):\n\ + for line in iterable:\n\ + self.write(line)\n\ +\n\ + def flush(self):\n\ + gdb.flush()\n\ +\n\ +sys.stderr = GdbOutputFile()\n\ +sys.stdout = GdbOutputFile()\n\ +"); + + /* Release the GIL while gdb runs. */ + PyThreadState_Swap (NULL); + PyEval_ReleaseLock (); + +#endif /* HAVE_PYTHON */ +} + + + +#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" }, + { "parameter", gdbpy_parameter, METH_VARARGS, + "Return a gdb parameter's value" }, + + { "default_visualizer", gdbpy_default_visualizer, METH_VARARGS, + "Find the default visualizer for a Value." }, + + { "current_objfile", gdbpy_get_current_objfile, METH_NOARGS, + "Return the current Objfile being loaded, or None." }, + { "objfiles", gdbpy_objfiles, METH_NOARGS, + "Return a sequence of all loaded objfiles." }, + + { "selected_frame", gdbpy_selected_frame, METH_NOARGS, + "selected_frame () -> gdb.Frame.\n\ +Return the selected frame object." }, + { "frame_stop_reason_string", gdbpy_frame_stop_reason_string, METH_VARARGS, + "stop_reason_string (Integer) -> String.\n\ +Return a string explaining unwind stop reason." }, + + { "lookup_type", (PyCFunction) gdbpy_lookup_type, + METH_VARARGS | METH_KEYWORDS, + "lookup_type (name [, block]) -> type\n\ +Return a Type corresponding to the given name." }, + + { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, + "parse_and_eval (String) -> Value.\n\ +Parse String as an expression, evaluate it, and return the result as a 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 */
python.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-value.c =================================================================== --- py-value.c (nonexistent) +++ py-value.c (revision 842) @@ -0,0 +1,1132 @@ +/* Python interface to values. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "gdb_assert.h" +#include "charset.h" +#include "value.h" +#include "exceptions.h" +#include "language.h" +#include "dfp.h" +#include "valprint.h" + +#ifdef HAVE_PYTHON + +#include "python-internal.h" + +/* Even though Python scalar types directly map to host types, we use + target types here to remain consistent with the the values system in + GDB (which uses target arithmetic). */ + +/* Python's integer type corresponds to C's long type. */ +#define builtin_type_pyint builtin_type (python_gdbarch)->builtin_long + +/* Python's float type corresponds to C's double type. */ +#define builtin_type_pyfloat builtin_type (python_gdbarch)->builtin_double + +/* Python's long type corresponds to C's long long type. */ +#define builtin_type_pylong builtin_type (python_gdbarch)->builtin_long_long + +#define builtin_type_pybool \ + language_bool_type (python_language, python_gdbarch) + +#define builtin_type_pychar \ + language_string_char_type (python_language, python_gdbarch) + +typedef struct value_object { + PyObject_HEAD + struct value_object *next; + struct value_object *prev; + struct value *value; + PyObject *address; + PyObject *type; +} value_object; + +/* List of all values which are currently exposed to Python. It is + maintained so that when an objfile is discarded, preserve_values + can copy the values' types if needed. */ +/* This variable is unnecessarily initialized to NULL in order to + work around a linker bug on MacOS. */ +static value_object *values_in_python = NULL; + +/* Called by the Python interpreter when deallocating a value object. */ +static void +valpy_dealloc (PyObject *obj) +{ + value_object *self = (value_object *) obj; + + /* Remove SELF from the global list. */ + if (self->prev) + self->prev->next = self->next; + else + { + gdb_assert (values_in_python == self); + values_in_python = self->next; + } + if (self->next) + self->next->prev = self->prev; + + value_free (self->value); + + if (self->address) + /* Use braces to appease gcc warning. *sigh* */ + { + Py_DECREF (self->address); + } + + if (self->type) + { + Py_DECREF (self->type); + } + + self->ob_type->tp_free (self); +} + +/* Helper to push a Value object on the global list. */ +static void +note_value (value_object *value_obj) +{ + value_obj->next = values_in_python; + if (value_obj->next) + value_obj->next->prev = value_obj; + value_obj->prev = NULL; + values_in_python = value_obj; +} + +/* Called when a new gdb.Value object needs to be allocated. */ +static PyObject * +valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) +{ + struct value *value = NULL; /* Initialize to appease gcc warning. */ + value_object *value_obj; + + if (PyTuple_Size (args) != 1) + { + PyErr_SetString (PyExc_TypeError, _("Value object creation takes only " + "1 argument")); + return NULL; + } + + value_obj = (value_object *) subtype->tp_alloc (subtype, 1); + if (value_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, _("Could not allocate memory to " + "create Value object.")); + return NULL; + } + + value = convert_value_from_python (PyTuple_GetItem (args, 0)); + if (value == NULL) + { + subtype->tp_free (value_obj); + return NULL; + } + + value_obj->value = value; + value_incref (value); + value_obj->address = NULL; + value_obj->type = NULL; + note_value (value_obj); + + return (PyObject *) value_obj; +} + +/* Iterate over all the Value objects, calling preserve_one_value on + each. */ +void +preserve_python_values (struct objfile *objfile, htab_t copied_types) +{ + value_object *iter; + + for (iter = values_in_python; iter; iter = iter->next) + preserve_one_value (iter->value, objfile, copied_types); +} + +/* Given a value of a pointer type, apply the C unary * operator to it. */ +static PyObject * +valpy_dereference (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_ind (((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (res_val); +} + +/* Return "&value". */ +static PyObject * +valpy_get_address (PyObject *self, void *closure) +{ + struct value *res_val = NULL; /* Initialize to appease gcc warning. */ + value_object *val_obj = (value_object *) self; + volatile struct gdb_exception except; + + if (!val_obj->address) + { + TRY_CATCH (except, RETURN_MASK_ALL) + { + res_val = value_addr (val_obj->value); + } + if (except.reason < 0) + { + val_obj->address = Py_None; + Py_INCREF (Py_None); + } + else + val_obj->address = value_to_value_object (res_val); + } + + Py_INCREF (val_obj->address); + + return val_obj->address; +} + +/* Return type of the value. */ +static PyObject * +valpy_get_type (PyObject *self, void *closure) +{ + value_object *obj = (value_object *) self; + if (!obj->type) + { + obj->type = type_to_type_object (value_type (obj->value)); + if (!obj->type) + { + obj->type = Py_None; + Py_INCREF (obj->type); + } + } + Py_INCREF (obj->type); + return obj->type; +} + +/* Implementation of gdb.Value.lazy_string ([encoding] [, length]) -> + string. Return a PyObject representing a lazy_string_object type. + A lazy string is a pointer to a string with an optional encoding and + length. If ENCODING is not given, encoding is set to None. If an + ENCODING is provided the encoding parameter is set to ENCODING, but + the string is not encoded. If LENGTH is provided then the length + parameter is set to LENGTH, otherwise length will be set to -1 (first + null of appropriate with). */ +static PyObject * +valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw) +{ + int length = -1; + struct value *value = ((value_object *) self)->value; + const char *user_encoding = NULL; + static char *keywords[] = { "encoding", "length", NULL }; + PyObject *str_obj; + + if (!PyArg_ParseTupleAndKeywords (args, kw, "|si", keywords, + &user_encoding, &length)) + return NULL; + + if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR) + value = value_ind (value); + + str_obj = gdbpy_create_lazy_string_object (value_address (value), length, + user_encoding, value_type (value)); + + return (PyObject *) str_obj; +} + +/* Implementation of gdb.Value.string ([encoding] [, errors] + [, length]) -> string. Return Unicode string with value contents. + If ENCODING is not given, the string is assumed to be encoded in + the target's charset. If LENGTH is provided, only fetch string to + the length provided. */ + +static PyObject * +valpy_string (PyObject *self, PyObject *args, PyObject *kw) +{ + int length = -1, ret = 0; + gdb_byte *buffer; + struct value *value = ((value_object *) self)->value; + volatile struct gdb_exception except; + PyObject *unicode; + const char *encoding = NULL; + const char *errors = NULL; + const char *user_encoding = NULL; + const char *la_encoding = NULL; + struct type *char_type; + static char *keywords[] = { "encoding", "errors", "length", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kw, "|ssi", keywords, + &user_encoding, &errors, &length)) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + LA_GET_STRING (value, &buffer, &length, &char_type, &la_encoding); + } + GDB_PY_HANDLE_EXCEPTION (except); + + encoding = (user_encoding && *user_encoding) ? user_encoding : la_encoding; + unicode = PyUnicode_Decode (buffer, length * TYPE_LENGTH (char_type), + encoding, errors); + xfree (buffer); + + return unicode; +} + +/* Cast a value to a given type. */ +static PyObject * +valpy_cast (PyObject *self, PyObject *args) +{ + PyObject *type_obj; + struct type *type; + struct value *res_val = NULL; /* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "O", &type_obj)) + return NULL; + + type = type_object_to_type (type_obj); + if (! type) + { + PyErr_SetString (PyExc_RuntimeError, "argument must be a Type"); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + res_val = value_cast (type, ((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (res_val); +} + +static Py_ssize_t +valpy_length (PyObject *self) +{ + /* We don't support getting the number of elements in a struct / class. */ + PyErr_SetString (PyExc_NotImplementedError, + "Invalid operation on gdb.Value."); + return -1; +} + +/* Given string name of an element inside structure, return its value + object. */ +static PyObject * +valpy_getitem (PyObject *self, PyObject *key) +{ + value_object *self_value = (value_object *) self; + char *field = NULL; + struct value *res_val = NULL; + volatile struct gdb_exception except; + + 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; + + 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) + { + /* Check the value's type is something that can be accessed via + a subscript. */ + struct type *type; + tmp = coerce_ref (tmp); + type = check_typedef (value_type (tmp)); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_PTR) + error( _("Cannot subscript requested type")); + else + res_val = value_subscript (tmp, value_as_long (idx)); + } + } + } + + xfree (field); + GDB_PY_HANDLE_EXCEPTION (except); + + return res_val ? value_to_value_object (res_val) : NULL; +} + +static int +valpy_setitem (PyObject *self, PyObject *key, PyObject *value) +{ + PyErr_Format (PyExc_NotImplementedError, + _("Setting of struct elements is not currently supported.")); + return -1; +} + +/* Called by the Python interpreter to obtain string representation + of the object. */ +static PyObject * +valpy_str (PyObject *self) +{ + char *s = NULL; + struct ui_file *stb; + struct cleanup *old_chain; + PyObject *result; + struct value_print_options opts; + volatile struct gdb_exception except; + + get_user_print_options (&opts); + opts.deref_ref = 0; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + common_val_print (((value_object *) self)->value, stb, 0, + &opts, python_language); + s = ui_file_xstrdup (stb, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + do_cleanups (old_chain); + + result = PyUnicode_Decode (s, strlen (s), host_charset (), NULL); + xfree (s); + + return result; +} + +/* Implements gdb.Value.is_optimized_out. */ +static PyObject * +valpy_get_is_optimized_out (PyObject *self, void *closure) +{ + struct value *value = ((value_object *) self)->value; + + if (value_optimized_out (value)) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +enum valpy_opcode +{ + VALPY_ADD, + VALPY_SUB, + VALPY_MUL, + VALPY_DIV, + VALPY_REM, + VALPY_POW, + VALPY_LSH, + VALPY_RSH, + VALPY_BITAND, + VALPY_BITOR, + VALPY_BITXOR +}; + +/* If TYPE is a reference, return the target; otherwise return TYPE. */ +#define STRIP_REFERENCE(TYPE) \ + ((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE)) + +/* Returns a value object which is the result of applying the operation + specified by OPCODE to the given arguments. */ +static PyObject * +valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) +{ + struct value *res_val = NULL; /* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct value *arg1, *arg2; + + /* If the gdb.Value object is the second operand, then it will be passed + to us as the OTHER argument, and SELF will be an entirely different + 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) + break; + + arg2 = convert_value_from_python (other); + if (arg2 == NULL) + break; + + switch (opcode) + { + case VALPY_ADD: + { + struct type *ltype = value_type (arg1); + struct type *rtype = value_type (arg2); + + CHECK_TYPEDEF (ltype); + ltype = STRIP_REFERENCE (ltype); + CHECK_TYPEDEF (rtype); + rtype = STRIP_REFERENCE (rtype); + + if (TYPE_CODE (ltype) == TYPE_CODE_PTR + && is_integral_type (rtype)) + res_val = value_ptradd (arg1, value_as_long (arg2)); + else if (TYPE_CODE (rtype) == TYPE_CODE_PTR + && is_integral_type (ltype)) + res_val = value_ptradd (arg2, value_as_long (arg1)); + else + res_val = value_binop (arg1, arg2, BINOP_ADD); + } + break; + case VALPY_SUB: + { + struct type *ltype = value_type (arg1); + struct type *rtype = value_type (arg2); + + CHECK_TYPEDEF (ltype); + ltype = STRIP_REFERENCE (ltype); + CHECK_TYPEDEF (rtype); + rtype = STRIP_REFERENCE (rtype); + + if (TYPE_CODE (ltype) == TYPE_CODE_PTR + && TYPE_CODE (rtype) == TYPE_CODE_PTR) + /* A ptrdiff_t for the target would be preferable here. */ + res_val = value_from_longest (builtin_type_pyint, + value_ptrdiff (arg1, arg2)); + else if (TYPE_CODE (ltype) == TYPE_CODE_PTR + && is_integral_type (rtype)) + res_val = value_ptradd (arg1, - value_as_long (arg2)); + else + res_val = value_binop (arg1, arg2, BINOP_SUB); + } + break; + case VALPY_MUL: + res_val = value_binop (arg1, arg2, BINOP_MUL); + break; + case VALPY_DIV: + res_val = value_binop (arg1, arg2, BINOP_DIV); + break; + case VALPY_REM: + res_val = value_binop (arg1, arg2, BINOP_REM); + break; + 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); + + return res_val ? value_to_value_object (res_val) : NULL; +} + +static PyObject * +valpy_add (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_ADD, self, other); +} + +static PyObject * +valpy_subtract (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_SUB, self, other); +} + +static PyObject * +valpy_multiply (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_MUL, self, other); +} + +static PyObject * +valpy_divide (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_DIV, self, other); +} + +static PyObject * +valpy_remainder (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_REM, self, other); +} + +static PyObject * +valpy_power (PyObject *self, PyObject *other, PyObject *unused) +{ + /* We don't support the ternary form of pow. I don't know how to express + that, so let's just throw NotImplementedError to at least do something + about it. */ + if (unused != Py_None) + { + PyErr_SetString (PyExc_NotImplementedError, + "Invalid operation on gdb.Value."); + return NULL; + } + + return valpy_binop (VALPY_POW, self, other); +} + +static PyObject * +valpy_negative (PyObject *self) +{ + struct value *val = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + val = value_neg (((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (val); +} + +static PyObject * +valpy_positive (PyObject *self) +{ + return value_to_value_object (((value_object *) self)->value); +} + +static PyObject * +valpy_absolute (PyObject *self) +{ + struct value *value = ((value_object *) self)->value; + if (value_less (value, value_zero (value_type (value), not_lval))) + return valpy_negative (self); + else + return valpy_positive (self); +} + +/* Implements boolean evaluation of gdb.Value. */ +static int +valpy_nonzero (PyObject *self) +{ + value_object *self_value = (value_object *) self; + struct type *type; + + type = check_typedef (value_type (self_value->value)); + + if (is_integral_type (type) || TYPE_CODE (type) == TYPE_CODE_PTR) + return !!value_as_long (self_value->value); + else if (TYPE_CODE (type) == TYPE_CODE_FLT) + return value_as_double (self_value->value) != 0; + else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + return !decimal_is_zero (value_contents (self_value->value), + TYPE_LENGTH (type), + gdbarch_byte_order (get_type_arch (type))); + else + { + PyErr_SetString (PyExc_TypeError, _("Attempted truth testing on invalid " + "gdb.Value type.")); + return 0; + } +} + +/* Implements ~ for value objects. */ +static PyObject * +valpy_invert (PyObject *self) +{ + struct value *val = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + val = value_complement (((value_object *) self)->value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (val); +} + +/* Implements left shift for value objects. */ +static PyObject * +valpy_lsh (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_LSH, self, other); +} + +/* Implements right shift for value objects. */ +static PyObject * +valpy_rsh (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_RSH, self, other); +} + +/* Implements bitwise and for value objects. */ +static PyObject * +valpy_and (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_BITAND, self, other); +} + +/* 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) { + case Py_LT: + case Py_LE: + case Py_EQ: + Py_RETURN_FALSE; + case Py_NE: + case Py_GT: + case Py_GE: + Py_RETURN_TRUE; + default: + /* Can't happen. */ + PyErr_SetString (PyExc_NotImplementedError, + "Invalid operation on gdb.Value."); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + value_other = convert_value_from_python (other); + if (value_other == NULL) + { + result = -1; + break; + } + + switch (op) { + case Py_LT: + result = value_less (((value_object *) self)->value, value_other); + break; + case Py_LE: + result = value_less (((value_object *) self)->value, value_other) + || value_equal (((value_object *) self)->value, value_other); + break; + case Py_EQ: + result = value_equal (((value_object *) self)->value, value_other); + break; + case Py_NE: + result = !value_equal (((value_object *) self)->value, value_other); + break; + case Py_GT: + result = value_less (value_other, ((value_object *) self)->value); + break; + case Py_GE: + result = value_less (value_other, ((value_object *) self)->value) + || value_equal (((value_object *) self)->value, value_other); + break; + default: + /* Can't happen. */ + PyErr_SetString (PyExc_NotImplementedError, + "Invalid operation on gdb.Value."); + result = -1; + break; + } + } + GDB_PY_HANDLE_EXCEPTION (except); + + /* In this case, the Python exception has already been set. */ + if (result < 0) + return NULL; + + if (result == 1) + Py_RETURN_TRUE; + + 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); + +#ifdef HAVE_LONG_LONG /* Defined by Python. */ + /* If we have 'long long', and the value overflows a 'long', use a + Python Long; otherwise use a Python Int. */ + if (sizeof (l) > sizeof (long) && (l > PyInt_GetMax () + || l < (- (LONGEST) PyInt_GetMax ()) - 1)) + return PyLong_FromLongLong (l); +#endif + 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); + +#ifdef HAVE_LONG_LONG /* Defined by Python. */ + return PyLong_FromLongLong (l); +#else + return PyLong_FromLong (l); +#endif +} + +/* 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 * +value_to_value_object (struct value *val) +{ + value_object *val_obj; + + val_obj = PyObject_New (value_object, &value_object_type); + if (val_obj != NULL) + { + val_obj->value = val; + value_incref (val); + val_obj->address = NULL; + val_obj->type = NULL; + note_value (val_obj); + } + + return (PyObject *) val_obj; +} + +/* Returns a borrowed reference to the struct value corresponding to + the given value object. */ +struct value * +value_object_to_value (PyObject *self) +{ + value_object *real; + if (! PyObject_TypeCheck (self, &value_object_type)) + return NULL; + real = (value_object *) self; + return real->value; +} + +/* Try to convert a Python value to a gdb value. If the value cannot + be converted, set a Python exception and return NULL. Returns a + reference to a new value on the all_values chain. */ + +struct value * +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; + + gdb_assert (obj != NULL); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + 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); + + 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 (gdbpy_is_string (obj)) + { + char *s; + + s = python_string_to_target_string (obj); + if (s != NULL) + { + old = make_cleanup (xfree, s); + value = value_cstring (s, strlen (s), builtin_type_pychar); + do_cleanups (old); + } + } + else if (PyObject_TypeCheck (obj, &value_object_type)) + value = value_copy (((value_object *) obj)->value); + else if (gdbpy_is_lazy_string (obj)) + { + PyObject *result; + PyObject *function = PyString_FromString ("value"); + result = PyObject_CallMethodObjArgs (obj, function, NULL); + value = value_copy (((value_object *) result)->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_history (PyObject *self, PyObject *args) +{ + int i; + struct value *res_val = NULL; /* Initialize to appease gcc warning. */ + volatile struct gdb_exception except; + + if (!PyArg_ParseTuple (args, "i", &i)) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + res_val = access_value_history (i); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (res_val); +} + +void +gdbpy_initialize_values (void) +{ + if (PyType_Ready (&value_object_type) < 0) + return; + + Py_INCREF (&value_object_type); + PyModule_AddObject (gdb_module, "Value", (PyObject *) &value_object_type); + + values_in_python = NULL; +} + + + +static PyGetSetDef value_object_getset[] = { + { "address", valpy_get_address, NULL, "The address of the value.", + NULL }, + { "is_optimized_out", valpy_get_is_optimized_out, NULL, + "Boolean telling whether the value is optimized out (i.e., not available).", + NULL }, + { "type", valpy_get_type, NULL, "Type of the value.", NULL }, + {NULL} /* Sentinel */ +}; + +static PyMethodDef value_object_methods[] = { + { "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." }, + { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." }, + { "lazy_string", (PyCFunction) valpy_lazy_string, METH_VARARGS | METH_KEYWORDS, + "lazy_string ([encoding] [, length]) -> lazy_string\n\ +Return a lazy string representation of the value." }, + { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS, + "string ([encoding] [, errors] [, length]) -> string\n\ +Return Unicode string representation of the value." }, + {NULL} /* Sentinel */ +}; + +static PyNumberMethods value_object_as_number = { + valpy_add, + valpy_subtract, + valpy_multiply, + valpy_divide, + valpy_remainder, + NULL, /* nb_divmod */ + valpy_power, /* nb_power */ + valpy_negative, /* nb_negative */ + valpy_positive, /* nb_positive */ + valpy_absolute, /* nb_absolute */ + 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 = { + valpy_length, + valpy_getitem, + valpy_setitem +}; + +PyTypeObject value_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Value", /*tp_name*/ + sizeof (value_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + valpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + &value_object_as_number, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + &value_object_as_mapping, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + valpy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + "GDB value object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + valpy_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + value_object_methods, /* tp_methods */ + 0, /* tp_members */ + value_object_getset, /* 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 */ +}; + +#else + +void +preserve_python_values (struct objfile *objfile, htab_t copied_types) +{ + /* Nothing. */ +} + +#endif /* HAVE_PYTHON */
py-value.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-utils.c =================================================================== --- py-utils.c (nonexistent) +++ py-utils.c (revision 842) @@ -0,0 +1,221 @@ +/* General utility routines for GDB/Python. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "charset.h" +#include "python-internal.h" + + +/* This is a cleanup function which decrements the refcount on a + Python object. */ + +static void +py_decref (void *p) +{ + PyObject *py = p; + /* Note that we need the extra braces in this 'if' to avoid a + warning from gcc. */ + if (py) + { + Py_DECREF (py); + } +} + +/* Return a new cleanup which will decrement the Python object's + refcount when run. */ + +struct cleanup * +make_cleanup_py_decref (PyObject *py) +{ + return make_cleanup (py_decref, (void *) py); +} + +/* Converts a Python 8-bit string to a unicode string object. Assumes the + 8-bit string is in the host charset. If an error occurs during conversion, + returns NULL with a python exception set. + + As an added bonus, the functions accepts a unicode string and returns it + right away, so callers don't need to check which kind of string they've + got. + + If the given object is not one of the mentioned string types, NULL is + returned, with the TypeError python exception set. */ +PyObject * +python_string_to_unicode (PyObject *obj) +{ + PyObject *unicode_str; + + /* If obj is already a unicode string, just return it. + I wish life was always that simple... */ + if (PyUnicode_Check (obj)) + { + unicode_str = obj; + Py_INCREF (obj); + } + + else if (PyString_Check (obj)) + unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL); + else + { + PyErr_SetString (PyExc_TypeError, + _("Expected a string or unicode object.")); + unicode_str = NULL; + } + + return unicode_str; +} + +/* Returns a newly allocated string with the contents of the given unicode + 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. */ +static char * +unicode_to_encoded_string (PyObject *unicode_str, const char *charset) +{ + char *result; + PyObject *string; + + /* Translate string to named charset. */ + string = PyUnicode_AsEncodedString (unicode_str, charset, NULL); + if (string == NULL) + return NULL; + + result = xstrdup (PyString_AsString (string)); + + Py_DECREF (string); + + return result; +} + +/* Returns a PyObject with the contents of the given unicode 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. */ +static PyObject * +unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset) +{ + PyObject *string; + + /* Translate string to named charset. */ + string = PyUnicode_AsEncodedString (unicode_str, charset, NULL); + if (string == NULL) + return NULL; + + return string; +} + +/* 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 ()); +} + +/* Returns a PyObject 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. */ +PyObject * +unicode_to_target_python_string (PyObject *unicode_str) +{ + return unicode_to_encoded_python_string (unicode_str, target_charset ()); +} + +/* Converts a python string (8-bit or unicode) to a target string in + the target's charset. Returns NULL on error, with a python exception set. + + The caller is responsible for xfree'ing the string. */ +char * +python_string_to_target_string (PyObject *obj) +{ + PyObject *str; + char *result; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + result = unicode_to_target_string (str); + Py_DECREF (str); + return result; +} + +/* Converts a python string (8-bit or unicode) to a target string in the + target's charset. Returns NULL on error, with a python exception + set. */ +PyObject * +python_string_to_target_python_string (PyObject *obj) +{ + PyObject *str; + PyObject *result; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + result = unicode_to_target_python_string (str); + Py_DECREF (str); + return result; +} + +/* 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; + char *result; + + str = python_string_to_unicode (obj); + if (str == NULL) + return NULL; + + result = unicode_to_encoded_string (str, host_charset ()); + Py_DECREF (str); + return result; +} + +/* Converts a target string of LENGTH bytes in the target's charset to a + Python Unicode string. If LENGTH is -1, convert until a null byte is found. + + Returns NULL on error, with a python exception set. */ +PyObject * +target_string_to_unicode (const gdb_byte *str, int length) +{ + if (length == -1) + length = strlen (str); + + return PyUnicode_Decode (str, length, target_charset (), NULL); +} + +/* 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); +}
py-utils.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: python.h =================================================================== --- python.h (nonexistent) +++ python.h (revision 842) @@ -0,0 +1,37 @@ +/* Python/gdb header for generic use in gdb + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef GDB_PYTHON_H +#define GDB_PYTHON_H + +#include "value.h" + +void eval_python_from_control_command (struct command_line *); + +void source_python_script (FILE *stream, char *file); + +int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value_print_options *options, + const struct language_defn *language); + +void preserve_python_values (struct objfile *objfile, htab_t copied_types); + +#endif /* GDB_PYTHON_H */
python.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-type.c =================================================================== --- py-type.c (nonexistent) +++ py-type.c (revision 842) @@ -0,0 +1,875 @@ +/* Python interface to types. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "gdbtypes.h" +#include "cp-support.h" +#include "demangle.h" +#include "objfiles.h" +#include "language.h" + +typedef struct pyty_type_object +{ + PyObject_HEAD + struct type *type; + + /* If a Type object is associated with an objfile, it is kept on a + doubly-linked list, rooted in the objfile. This lets us copy the + underlying struct type when the objfile is deleted. */ + struct pyty_type_object *prev; + struct pyty_type_object *next; +} type_object; + +static PyTypeObject type_object_type; + +/* A Field object. */ +typedef struct pyty_field_object +{ + PyObject_HEAD + + /* Dictionary holding our attributes. */ + PyObject *dict; +} field_object; + +static PyTypeObject field_object_type; + +/* This is used to initialize various gdb.TYPE_ constants. */ +struct pyty_code +{ + /* The code. */ + enum type_code code; + /* The name. */ + const char *name; +}; + +#define ENTRY(X) { X, #X } + +static struct pyty_code pyty_codes[] = +{ + ENTRY (TYPE_CODE_PTR), + ENTRY (TYPE_CODE_ARRAY), + ENTRY (TYPE_CODE_STRUCT), + ENTRY (TYPE_CODE_UNION), + ENTRY (TYPE_CODE_ENUM), + ENTRY (TYPE_CODE_FLAGS), + ENTRY (TYPE_CODE_FUNC), + ENTRY (TYPE_CODE_INT), + ENTRY (TYPE_CODE_FLT), + ENTRY (TYPE_CODE_VOID), + ENTRY (TYPE_CODE_SET), + ENTRY (TYPE_CODE_RANGE), + ENTRY (TYPE_CODE_STRING), + ENTRY (TYPE_CODE_BITSTRING), + ENTRY (TYPE_CODE_ERROR), + ENTRY (TYPE_CODE_METHOD), + ENTRY (TYPE_CODE_METHODPTR), + ENTRY (TYPE_CODE_MEMBERPTR), + ENTRY (TYPE_CODE_REF), + ENTRY (TYPE_CODE_CHAR), + ENTRY (TYPE_CODE_BOOL), + ENTRY (TYPE_CODE_COMPLEX), + ENTRY (TYPE_CODE_TYPEDEF), + ENTRY (TYPE_CODE_NAMESPACE), + ENTRY (TYPE_CODE_DECFLOAT), + ENTRY (TYPE_CODE_INTERNAL_FUNCTION), + { TYPE_CODE_UNDEF, NULL } +}; + + + +static void +field_dealloc (PyObject *obj) +{ + field_object *f = (field_object *) obj; + Py_XDECREF (f->dict); + f->ob_type->tp_free (obj); +} + +static PyObject * +field_new (void) +{ + field_object *result = PyObject_New (field_object, &field_object_type); + if (result) + { + result->dict = PyDict_New (); + if (!result->dict) + { + Py_DECREF (result); + result = NULL; + } + } + return (PyObject *) result; +} + + + +/* Return the code for this type. */ +static PyObject * +typy_get_code (PyObject *self, void *closure) +{ + struct type *type = ((type_object *) self)->type; + return PyInt_FromLong (TYPE_CODE (type)); +} + +/* Helper function for typy_fields which converts a single field to a + dictionary. Returns NULL on error. */ +static PyObject * +convert_field (struct type *type, int field) +{ + PyObject *result = field_new (); + PyObject *arg; + + if (!result) + return NULL; + + if (!field_is_static (&TYPE_FIELD (type, field))) + { + arg = PyLong_FromLong (TYPE_FIELD_BITPOS (type, field)); + if (!arg) + goto fail; + + if (PyObject_SetAttrString (result, "bitpos", arg) < 0) + goto failarg; + } + + if (TYPE_FIELD_NAME (type, field)) + arg = PyString_FromString (TYPE_FIELD_NAME (type, field)); + else + { + arg = Py_None; + Py_INCREF (arg); + } + if (!arg) + goto fail; + if (PyObject_SetAttrString (result, "name", arg) < 0) + goto failarg; + + arg = TYPE_FIELD_ARTIFICIAL (type, field) ? Py_True : Py_False; + Py_INCREF (arg); + if (PyObject_SetAttrString (result, "artificial", arg) < 0) + goto failarg; + + if (TYPE_CODE (type) == TYPE_CODE_CLASS) + arg = field < TYPE_N_BASECLASSES (type) ? Py_True : Py_False; + else + arg = Py_False; + Py_INCREF (arg); + if (PyObject_SetAttrString (result, "is_base_class", arg) < 0) + goto failarg; + + arg = PyLong_FromLong (TYPE_FIELD_BITSIZE (type, field)); + if (!arg) + goto fail; + if (PyObject_SetAttrString (result, "bitsize", arg) < 0) + goto failarg; + + /* A field can have a NULL type in some situations. */ + if (TYPE_FIELD_TYPE (type, field) == NULL) + { + arg = Py_None; + Py_INCREF (arg); + } + else + arg = type_to_type_object (TYPE_FIELD_TYPE (type, field)); + if (!arg) + goto fail; + if (PyObject_SetAttrString (result, "type", arg) < 0) + goto failarg; + + return result; + + failarg: + Py_DECREF (arg); + fail: + Py_DECREF (result); + return NULL; +} + +/* Return a sequence of all fields. Each field is a dictionary with + some pre-defined keys. */ +static PyObject * +typy_fields (PyObject *self, PyObject *args) +{ + PyObject *result; + int i; + struct type *type = ((type_object *) self)->type; + + /* We would like to make a tuple here, make fields immutable, and + then memoize the result (and perhaps make Field.type() lazy). + However, that can lead to cycles. */ + result = PyList_New (0); + + for (i = 0; i < TYPE_NFIELDS (type); ++i) + { + PyObject *dict = convert_field (type, i); + if (!dict) + { + Py_DECREF (result); + return NULL; + } + if (PyList_Append (result, dict)) + { + Py_DECREF (dict); + Py_DECREF (result); + return NULL; + } + } + + return result; +} + +/* Return the type's tag, or None. */ +static PyObject * +typy_get_tag (PyObject *self, void *closure) +{ + struct type *type = ((type_object *) self)->type; + if (!TYPE_TAG_NAME (type)) + Py_RETURN_NONE; + return PyString_FromString (TYPE_TAG_NAME (type)); +} + +/* Return the type, stripped of typedefs. */ +static PyObject * +typy_strip_typedefs (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + + return type_to_type_object (check_typedef (type)); +} + +/* Return a Type object which represents a pointer to SELF. */ +static PyObject * +typy_pointer (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = lookup_pointer_type (type); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return the range of a type represented by SELF. The return type is + a tuple. The first element of the tuple contains the low bound, + while the second element of the tuple contains the high bound. */ +static PyObject * +typy_range (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + PyObject *result; + PyObject *low_bound = NULL, *high_bound = NULL; + /* Initialize these to appease GCC warnings. */ + LONGEST low = 0, high = 0; + + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_STRING + && TYPE_CODE (type) != TYPE_CODE_RANGE) + { + PyErr_SetString (PyExc_RuntimeError, + "This type does not have a range."); + return NULL; + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + case TYPE_CODE_STRING: + low = TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)); + high = TYPE_HIGH_BOUND (TYPE_INDEX_TYPE (type)); + break; + case TYPE_CODE_RANGE: + low = TYPE_LOW_BOUND (type); + high = TYPE_HIGH_BOUND (type); + break; + } + + low_bound = PyLong_FromLong (low); + if (!low_bound) + goto failarg; + + high_bound = PyLong_FromLong (high); + if (!high_bound) + goto failarg; + + result = PyTuple_New (2); + if (!result) + goto failarg; + + if (PyTuple_SetItem (result, 0, low_bound) != 0) + { + Py_DECREF (result); + goto failarg; + } + if (PyTuple_SetItem (result, 1, high_bound) != 0) + { + Py_DECREF (high_bound); + Py_DECREF (result); + return NULL; + } + return result; + + failarg: + Py_XDECREF (high_bound); + Py_XDECREF (low_bound); + return NULL; +} + +/* Return a Type object which represents a reference to SELF. */ +static PyObject * +typy_reference (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = lookup_reference_type (type); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return a Type object which represents the target type of SELF. */ +static PyObject * +typy_target (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + + if (!TYPE_TARGET_TYPE (type)) + { + PyErr_SetString (PyExc_RuntimeError, "type does not have a target"); + return NULL; + } + + return type_to_type_object (TYPE_TARGET_TYPE (type)); +} + +/* Return a const-qualified type variant. */ +static PyObject * +typy_const (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = make_cv_type (1, 0, type, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return a volatile-qualified type variant. */ +static PyObject * +typy_volatile (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = make_cv_type (0, 1, type, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return an unqualified type variant. */ +static PyObject * +typy_unqualified (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = make_cv_type (0, 0, type, NULL); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return type_to_type_object (type); +} + +/* Return the size of the type represented by SELF, in bytes. */ +static PyObject * +typy_get_sizeof (PyObject *self, void *closure) +{ + struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + check_typedef (type); + } + /* Ignore exceptions. */ + + return PyLong_FromLong (TYPE_LENGTH (type)); +} + +static struct type * +typy_lookup_typename (char *type_name) +{ + struct type *type = NULL; + volatile struct gdb_exception except; + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (!strncmp (type_name, "struct ", 7)) + type = lookup_struct (type_name + 7, NULL); + else if (!strncmp (type_name, "union ", 6)) + type = lookup_union (type_name + 6, NULL); + else if (!strncmp (type_name, "enum ", 5)) + type = lookup_enum (type_name + 5, NULL); + else + type = lookup_typename (python_language, python_gdbarch, + type_name, NULL, 0); + } + if (except.reason < 0) + { + PyErr_Format (except.reason == RETURN_QUIT + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, + "%s", except.message); + return NULL; + } + + return type; +} + +static struct type * +typy_lookup_type (struct demangle_component *demangled) +{ + struct type *type; + char *type_name; + enum demangle_component_type demangled_type; + + /* Save the type: typy_lookup_type() may (indirectly) overwrite + memory pointed by demangled. */ + demangled_type = demangled->type; + + if (demangled_type == DEMANGLE_COMPONENT_POINTER + || demangled_type == DEMANGLE_COMPONENT_REFERENCE + || demangled_type == DEMANGLE_COMPONENT_CONST + || demangled_type == DEMANGLE_COMPONENT_VOLATILE) + { + type = typy_lookup_type (demangled->u.s_binary.left); + if (! type) + return NULL; + + switch (demangled_type) + { + case DEMANGLE_COMPONENT_REFERENCE: + return lookup_reference_type (type); + case DEMANGLE_COMPONENT_POINTER: + return lookup_pointer_type (type); + case DEMANGLE_COMPONENT_CONST: + return make_cv_type (1, 0, type, NULL); + case DEMANGLE_COMPONENT_VOLATILE: + return make_cv_type (0, 1, type, NULL); + } + } + + type_name = cp_comp_to_string (demangled, 10); + type = typy_lookup_typename (type_name); + xfree (type_name); + + return type; +} + +static PyObject * +typy_template_argument (PyObject *self, PyObject *args) +{ + int i, argno, n_pointers; + struct type *type = ((type_object *) self)->type; + struct demangle_component *demangled; + const char *err; + struct type *argtype; + + if (! PyArg_ParseTuple (args, "i", &argno)) + return NULL; + + type = check_typedef (type); + if (TYPE_CODE (type) == TYPE_CODE_REF) + type = check_typedef (TYPE_TARGET_TYPE (type)); + + if (TYPE_NAME (type) == NULL) + { + PyErr_SetString (PyExc_RuntimeError, "null type name"); + return NULL; + } + + /* Note -- this is not thread-safe. */ + demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err); + if (! demangled) + { + PyErr_SetString (PyExc_RuntimeError, err); + return NULL; + } + + /* Strip off component names. */ + while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME + || demangled->type == DEMANGLE_COMPONENT_LOCAL_NAME) + demangled = demangled->u.s_binary.right; + + if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE) + { + PyErr_SetString (PyExc_RuntimeError, "type is not a template"); + return NULL; + } + + /* Skip from the template to the arguments. */ + demangled = demangled->u.s_binary.right; + + for (i = 0; demangled && i < argno; ++i) + demangled = demangled->u.s_binary.right; + + if (! demangled) + { + PyErr_Format (PyExc_RuntimeError, "no argument %d in template", + argno); + return NULL; + } + + argtype = typy_lookup_type (demangled->u.s_binary.left); + if (! argtype) + return NULL; + + return type_to_type_object (argtype); +} + +static PyObject * +typy_str (PyObject *self) +{ + volatile struct gdb_exception except; + char *thetype = NULL; + long length = 0; + PyObject *result; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct cleanup *old_chain; + struct ui_file *stb; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + type_print (type_object_to_type (self), "", stb, -1); + + thetype = ui_file_xstrdup (stb, &length); + do_cleanups (old_chain); + } + if (except.reason < 0) + { + xfree (thetype); + GDB_PY_HANDLE_EXCEPTION (except); + } + + result = PyUnicode_Decode (thetype, length, host_charset (), NULL); + xfree (thetype); + + return result; +} + + + +static const struct objfile_data *typy_objfile_data_key; + +static void +save_objfile_types (struct objfile *objfile, void *datum) +{ + type_object *obj = datum; + htab_t copied_types; + struct cleanup *cleanup; + + /* This prevents another thread from freeing the objects we're + operating on. */ + cleanup = ensure_python_env (get_objfile_arch (objfile), current_language); + + copied_types = create_copied_types_hash (objfile); + + while (obj) + { + type_object *next = obj->next; + + htab_empty (copied_types); + + obj->type = copy_type_recursive (objfile, obj->type, copied_types); + + obj->next = NULL; + obj->prev = NULL; + + obj = next; + } + + htab_delete (copied_types); + + do_cleanups (cleanup); +} + +static void +set_type (type_object *obj, struct type *type) +{ + obj->type = type; + obj->prev = NULL; + if (type && TYPE_OBJFILE (type)) + { + struct objfile *objfile = TYPE_OBJFILE (type); + + obj->next = objfile_data (objfile, typy_objfile_data_key); + if (obj->next) + obj->next->prev = obj; + set_objfile_data (objfile, typy_objfile_data_key, obj); + } + else + obj->next = NULL; +} + +static void +typy_dealloc (PyObject *obj) +{ + type_object *type = (type_object *) obj; + + if (type->prev) + type->prev->next = type->next; + else if (type->type && TYPE_OBJFILE (type->type)) + { + /* Must reset head of list. */ + struct objfile *objfile = TYPE_OBJFILE (type->type); + if (objfile) + set_objfile_data (objfile, typy_objfile_data_key, type->next); + } + if (type->next) + type->next->prev = type->prev; + + type->ob_type->tp_free (type); +} + +/* Create a new Type referring to TYPE. */ +PyObject * +type_to_type_object (struct type *type) +{ + type_object *type_obj; + + type_obj = PyObject_New (type_object, &type_object_type); + if (type_obj) + set_type (type_obj, type); + + return (PyObject *) type_obj; +} + +struct type * +type_object_to_type (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &type_object_type)) + return NULL; + return ((type_object *) obj)->type; +} + + + +/* Implementation of gdb.lookup_type. */ +PyObject * +gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw) +{ + static char *keywords[] = { "name", NULL }; + char *type_name = NULL; + struct type *type = NULL; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &type_name)) + return NULL; + + type = typy_lookup_typename (type_name); + if (! type) + return NULL; + + return (PyObject *) type_to_type_object (type); +} + +void +gdbpy_initialize_types (void) +{ + int i; + + typy_objfile_data_key + = register_objfile_data_with_cleanup (save_objfile_types, NULL); + + if (PyType_Ready (&type_object_type) < 0) + return; + if (PyType_Ready (&field_object_type) < 0) + return; + + for (i = 0; pyty_codes[i].name; ++i) + { + if (PyModule_AddIntConstant (gdb_module, + /* Cast needed for Python 2.4. */ + (char *) pyty_codes[i].name, + pyty_codes[i].code) < 0) + return; + } + + Py_INCREF (&type_object_type); + PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type); + + Py_INCREF (&field_object_type); + PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type); +} + + + +static PyGetSetDef type_object_getset[] = +{ + { "code", typy_get_code, NULL, + "The code for this type.", NULL }, + { "sizeof", typy_get_sizeof, NULL, + "The size of this type, in bytes.", NULL }, + { "tag", typy_get_tag, NULL, + "The tag name for this type, or None.", NULL }, + { NULL } +}; + +static PyMethodDef type_object_methods[] = +{ + { "const", typy_const, METH_NOARGS, + "const () -> Type\n\ +Return a const variant of this type." }, + { "fields", typy_fields, METH_NOARGS, + "field () -> list\n\ +Return a sequence holding all the fields of this type.\n\ +Each field is a dictionary." }, + { "pointer", typy_pointer, METH_NOARGS, + "pointer () -> Type\n\ +Return a type of pointer to this type." }, + { "range", typy_range, METH_NOARGS, + "range () -> tuple\n\ +Return a tuple containing the lower and upper range for this type."}, + { "reference", typy_reference, METH_NOARGS, + "reference () -> Type\n\ +Return a type of reference to this type." }, + { "strip_typedefs", typy_strip_typedefs, METH_NOARGS, + "strip_typedefs () -> Type\n\ +Return a type formed by stripping this type of all typedefs."}, + { "target", typy_target, METH_NOARGS, + "target () -> Type\n\ +Return the target type of this type." }, + { "template_argument", typy_template_argument, METH_VARARGS, + "template_argument (arg) -> Type\n\ +Return the type of a template argument." }, + { "unqualified", typy_unqualified, METH_NOARGS, + "unqualified () -> Type\n\ +Return a variant of this type without const or volatile attributes." }, + { "volatile", typy_volatile, METH_NOARGS, + "volatile () -> Type\n\ +Return a volatile variant of this type" }, + { NULL } +}; + +static PyTypeObject type_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Type", /*tp_name*/ + sizeof (type_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + typy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + typy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB type object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + type_object_methods, /* tp_methods */ + 0, /* tp_members */ + type_object_getset, /* 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 */ + 0, /* tp_new */ +}; + +static PyTypeObject field_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Field", /*tp_name*/ + sizeof (field_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + field_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB field object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof (field_object, dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +};
py-type.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-cmd.c =================================================================== --- py-cmd.c (nonexistent) +++ py-cmd.c (revision 842) @@ -0,0 +1,585 @@ +/* gdb commands implemented in Python + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include "defs.h" +#include "arch-utils.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "gdbcmd.h" +#include "cli/cli-decode.h" +#include "completer.h" +#include "language.h" + +/* Struct representing built-in completion types. */ +struct cmdpy_completer +{ + /* Python symbol name. */ + char *name; + /* Completion function. */ + char **(*completer) (struct cmd_list_element *, char *, char *); +}; + +static struct cmdpy_completer completers[] = +{ + { "COMPLETE_NONE", noop_completer }, + { "COMPLETE_FILENAME", filename_completer }, + { "COMPLETE_LOCATION", location_completer }, + { "COMPLETE_COMMAND", command_completer }, + { "COMPLETE_SYMBOL", make_symbol_completion_list_fn }, +}; + +#define N_COMPLETERS (sizeof (completers) / sizeof (completers[0])) + +/* A gdb command. For the time being only ordinary commands (not + set/show commands) are allowed. */ +struct cmdpy_object +{ + PyObject_HEAD + + /* The corresponding gdb command object, or NULL if the command is + no longer installed. */ + struct cmd_list_element *command; + + /* A prefix command requires storage for a list of its sub-commands. + A pointer to this is passed to add_prefix_command, and to add_cmd + for sub-commands of that prefix. If this Command is not a prefix + command, then this field is unused. */ + struct cmd_list_element *sub_list; +}; + +typedef struct cmdpy_object cmdpy_object; + +static PyTypeObject cmdpy_object_type; + + +/* Constants used by this module. */ +static PyObject *invoke_cst; +static PyObject *complete_cst; + + + +/* Python function which wraps dont_repeat. */ +static PyObject * +cmdpy_dont_repeat (PyObject *self, PyObject *args) +{ + dont_repeat (); + Py_RETURN_NONE; +} + + + +/* Called if the gdb cmd_list_element is destroyed. */ +static void +cmdpy_destroyer (struct cmd_list_element *self, void *context) +{ + cmdpy_object *cmd; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + /* Release our hold on the command object. */ + cmd = (cmdpy_object *) context; + cmd->command = NULL; + Py_DECREF (cmd); + + /* We allocated the name, doc string, and perhaps the prefix + name. */ + xfree (self->name); + xfree (self->doc); + xfree (self->prefixname); + + do_cleanups (cleanup); +} + +/* Called by gdb to invoke the command. */ +static void +cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) +{ + cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command); + PyObject *argobj, *ttyobj, *result; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (! obj) + error (_("Invalid invocation of Python command object.")); + if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst)) + { + if (obj->command->prefixname) + { + /* A prefix command does not need an invoke method. */ + do_cleanups (cleanup); + return; + } + error (_("Python command object missing 'invoke' method.")); + } + + if (! args) + args = ""; + argobj = PyUnicode_Decode (args, strlen (args), host_charset (), NULL); + if (! argobj) + error (_("Could not convert arguments to Python string.")); + + ttyobj = from_tty ? Py_True : Py_False; + Py_INCREF (ttyobj); + result = PyObject_CallMethodObjArgs ((PyObject *) obj, invoke_cst, argobj, + ttyobj, NULL); + Py_DECREF (argobj); + Py_DECREF (ttyobj); + if (! result) + { + PyObject *ptype, *pvalue, *ptraceback; + char *s, *str; + + PyErr_Fetch (&ptype, &pvalue, &ptraceback); + + if (pvalue && PyString_Check (pvalue)) + { + /* Make a temporary copy of the string data. */ + char *s = PyString_AsString (pvalue); + char *copy = alloca (strlen (s) + 1); + strcpy (copy, s); + + PyErr_Restore (ptype, pvalue, ptraceback); + gdbpy_print_stack (); + error (_("Error occurred in Python command: %s"), copy); + } + else + { + PyErr_Restore (ptype, pvalue, ptraceback); + gdbpy_print_stack (); + error (_("Error occurred in Python command.")); + } + } + Py_DECREF (result); + do_cleanups (cleanup); +} + +/* Called by gdb for command completion. */ +static char ** +cmdpy_completer (struct cmd_list_element *command, char *text, char *word) +{ + cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command); + PyObject *textobj, *wordobj, *resultobj = NULL; + char **result = NULL; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (! obj) + error (_("Invalid invocation of Python command object.")); + if (! PyObject_HasAttr ((PyObject *) obj, complete_cst)) + { + /* If there is no complete method, don't error -- instead, just + say that there are no completions. */ + goto done; + } + + textobj = PyUnicode_Decode (text, strlen (text), host_charset (), NULL); + if (! textobj) + error (_("Could not convert argument to Python string.")); + wordobj = PyUnicode_Decode (word, strlen (word), host_charset (), NULL); + if (! wordobj) + error (_("Could not convert argument to Python string.")); + + resultobj = PyObject_CallMethodObjArgs ((PyObject *) obj, complete_cst, + textobj, wordobj, NULL); + Py_DECREF (textobj); + Py_DECREF (wordobj); + if (! resultobj) + { + /* Just swallow errors here. */ + PyErr_Clear (); + goto done; + } + make_cleanup_py_decref (resultobj); + + result = NULL; + if (PySequence_Check (resultobj)) + { + Py_ssize_t i, len = PySequence_Size (resultobj); + Py_ssize_t out; + if (len < 0) + goto done; + + result = (char **) xmalloc ((len + 1) * sizeof (char *)); + for (i = out = 0; i < len; ++i) + { + int l; + PyObject *elt = PySequence_GetItem (resultobj, i); + if (elt == NULL || ! gdbpy_is_string (elt)) + { + /* Skip problem elements. */ + PyErr_Clear (); + continue; + } + result[out] = python_string_to_host_string (elt); + ++out; + } + result[out] = NULL; + } + else if (PyInt_Check (resultobj)) + { + /* User code may also return one of the completion constants, + thus requesting that sort of completion. */ + long value = PyInt_AsLong (resultobj); + if (value >= 0 && value < (long) N_COMPLETERS) + result = completers[value].completer (command, text, word); + } + + done: + + do_cleanups (cleanup); + + return result; +} + +/* Helper for cmdpy_init which locates the command list to use and + pulls out the command name. + + TEXT is the command name list. The final word in the list is the + name of the new command. All earlier words must be existing prefix + commands. + + *BASE_LIST is set to the final prefix command's list of + *sub-commands. + + This function returns the xmalloc()d name of the new command. On + error sets the Python error and returns NULL. */ +static char * +parse_command_name (char *text, struct cmd_list_element ***base_list) +{ + struct cmd_list_element *elt; + int len = strlen (text); + int i, lastchar; + char *prefix_text; + char *result; + + /* Skip trailing whitespace. */ + for (i = len - 1; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + ; + if (i < 0) + { + PyErr_SetString (PyExc_RuntimeError, _("no command name found")); + return NULL; + } + lastchar = i; + + /* Find first character of the final word. */ + for (; i > 0 && (isalnum (text[i - 1]) + || text[i - 1] == '-' + || text[i - 1] == '_'); + --i) + ; + result = xmalloc (lastchar - i + 2); + memcpy (result, &text[i], lastchar - i + 1); + result[lastchar - i + 1] = '\0'; + + /* Skip whitespace again. */ + for (--i; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + ; + if (i < 0) + { + *base_list = &cmdlist; + return result; + } + + prefix_text = xmalloc (i + 2); + memcpy (prefix_text, text, i + 1); + prefix_text[i + 1] = '\0'; + + text = prefix_text; + elt = lookup_cmd_1 (&text, cmdlist, NULL, 1); + if (!elt || elt == (struct cmd_list_element *) -1) + { + PyErr_Format (PyExc_RuntimeError, _("could not find command prefix %s"), + prefix_text); + xfree (prefix_text); + xfree (result); + return NULL; + } + + if (elt->prefixlist) + { + xfree (prefix_text); + *base_list = elt->prefixlist; + return result; + } + + PyErr_Format (PyExc_RuntimeError, _("'%s' is not a prefix command"), + prefix_text); + xfree (prefix_text); + xfree (result); + return NULL; +} + +/* Object initializer; sets up gdb-side structures for command. + + Use: __init__(NAME, COMMAND_CLASS [, COMPLETER_CLASS][, PREFIX]]). + + NAME is the name of the command. It may consist of multiple words, + in which case the final word is the name of the new command, and + earlier words must be prefix commands. + + COMMAND_CLASS is the kind of command. It should be one of the COMMAND_* + constants defined in the gdb module. + + COMPLETER_CLASS is the kind of completer. If not given, the + "complete" method will be used. Otherwise, it should be one of the + COMPLETE_* constants defined in the gdb module. + + If PREFIX is True, then this command is a prefix command. + + The documentation for the command is taken from the doc string for + the python class. + +*/ +static int +cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) +{ + cmdpy_object *obj = (cmdpy_object *) self; + char *name; + int cmdtype; + int completetype = -1; + char *docstring = NULL; + volatile struct gdb_exception except; + struct cmd_list_element **cmd_list; + char *cmd_name, *pfx_name; + static char *keywords[] = { "name", "command_class", "completer_class", + "prefix", NULL }; + PyObject *is_prefix = NULL; + int cmp; + + if (obj->command) + { + /* Note: this is apparently not documented in Python. We return + 0 for success, -1 for failure. */ + PyErr_Format (PyExc_RuntimeError, + _("command object already initialized")); + return -1; + } + + if (! PyArg_ParseTupleAndKeywords (args, kw, "si|iO", keywords, &name, &cmdtype, + &completetype, &is_prefix)) + return -1; + + if (cmdtype != no_class && cmdtype != class_run + && cmdtype != class_vars && cmdtype != class_stack + && cmdtype != class_files && cmdtype != class_support + && cmdtype != class_info && cmdtype != class_breakpoint + && cmdtype != class_trace && cmdtype != class_obscure + && cmdtype != class_maintenance) + { + PyErr_Format (PyExc_RuntimeError, _("invalid command class argument")); + return -1; + } + + if (completetype < -1 || completetype >= (int) N_COMPLETERS) + { + PyErr_Format (PyExc_RuntimeError, _("invalid completion type argument")); + return -1; + } + + cmd_name = parse_command_name (name, &cmd_list); + if (! cmd_name) + return -1; + + pfx_name = NULL; + if (is_prefix != NULL) + { + cmp = PyObject_IsTrue (is_prefix); + if (cmp == 1) + { + int i, out; + + /* Make a normalized form of the command name. */ + pfx_name = xmalloc (strlen (name) + 2); + + i = 0; + out = 0; + while (name[i]) + { + /* Skip whitespace. */ + while (name[i] == ' ' || name[i] == '\t') + ++i; + /* Copy non-whitespace characters. */ + while (name[i] && name[i] != ' ' && name[i] != '\t') + pfx_name[out++] = name[i++]; + /* Add a single space after each word -- including the final + word. */ + pfx_name[out++] = ' '; + } + pfx_name[out] = '\0'; + } + else if (cmp < 0) + return -1; + } + if (PyObject_HasAttr (self, gdbpy_doc_cst)) + { + PyObject *ds_obj = PyObject_GetAttr (self, gdbpy_doc_cst); + if (ds_obj && gdbpy_is_string (ds_obj)) + docstring = python_string_to_host_string (ds_obj); + } + if (! docstring) + docstring = xstrdup (_("This command is not documented.")); + + Py_INCREF (self); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct cmd_list_element *cmd; + + if (pfx_name) + { + int allow_unknown; + + /* If we have our own "invoke" method, then allow unknown + sub-commands. */ + allow_unknown = PyObject_HasAttr (self, invoke_cst); + cmd = add_prefix_cmd (cmd_name, (enum command_class) cmdtype, + NULL, docstring, &obj->sub_list, + pfx_name, allow_unknown, cmd_list); + } + else + cmd = add_cmd (cmd_name, (enum command_class) cmdtype, NULL, + docstring, cmd_list); + + /* There appears to be no API to set this. */ + cmd->func = cmdpy_function; + cmd->destroyer = cmdpy_destroyer; + + obj->command = cmd; + set_cmd_context (cmd, self); + set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer + : completers[completetype].completer)); + } + if (except.reason < 0) + { + xfree (cmd_name); + xfree (docstring); + xfree (pfx_name); + Py_DECREF (self); + PyErr_Format (except.reason == RETURN_QUIT + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, + "%s", except.message); + return -1; + } + return 0; +} + + + +/* Initialize the 'commands' code. */ +void +gdbpy_initialize_commands (void) +{ + int i; + + if (PyType_Ready (&cmdpy_object_type) < 0) + return; + + /* Note: alias and user are special; pseudo appears to be unused, + and there is no reason to expose tui or xdb, I think. */ + if (PyModule_AddIntConstant (gdb_module, "COMMAND_NONE", no_class) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_RUNNING", class_run) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_DATA", class_vars) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_STACK", class_stack) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_FILES", class_files) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_SUPPORT", + class_support) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_STATUS", class_info) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_BREAKPOINTS", + class_breakpoint) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_TRACEPOINTS", + class_trace) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_OBSCURE", + class_obscure) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_MAINTENANCE", + class_maintenance) < 0) + return; + + for (i = 0; i < N_COMPLETERS; ++i) + { + if (PyModule_AddIntConstant (gdb_module, completers[i].name, i) < 0) + return; + } + + Py_INCREF (&cmdpy_object_type); + PyModule_AddObject (gdb_module, "Command", + (PyObject *) &cmdpy_object_type); + + invoke_cst = PyString_FromString ("invoke"); + complete_cst = PyString_FromString ("complete"); +} + + + +static PyMethodDef cmdpy_object_methods[] = +{ + { "dont_repeat", cmdpy_dont_repeat, METH_NOARGS, + "Prevent command repetition when user enters empty line." }, + + { 0 } +}; + +static PyTypeObject cmdpy_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Command", /*tp_name*/ + sizeof (cmdpy_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "GDB command object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + cmdpy_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 */ + cmdpy_init, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +};
py-cmd.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-lazy-string.c =================================================================== --- py-lazy-string.c (nonexistent) +++ py-lazy-string.c (revision 842) @@ -0,0 +1,291 @@ +/* Python interface to lazy strings. + + Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "python-internal.h" +#include "charset.h" +#include "value.h" +#include "exceptions.h" +#include "valprint.h" +#include "language.h" + +typedef struct { + PyObject_HEAD + /* Holds the address of the lazy string. */ + CORE_ADDR address; + + /* Holds the encoding that will be applied to the string + when the string is printed by GDB. If the encoding is set + to None then GDB will select the most appropriate + encoding when the sting is printed. */ + char *encoding; + + /* Holds the length of the string in characters. If the + length is -1, then the string will be fetched and encoded up to + the first null of appropriate width. */ + long length; + + /* This attribute holds the type that is represented by the lazy + string's type. */ + struct type *type; +} lazy_string_object; + +static PyTypeObject lazy_string_object_type; + +static PyObject * +stpy_get_address (PyObject *self, void *closure) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + return PyLong_FromUnsignedLongLong (self_string->address); +} + +static PyObject * +stpy_get_encoding (PyObject *self, void *closure) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + PyObject *result; + + /* An encoding can be set to NULL by the user, so check before + attempting a Python FromString call. If NULL return Py_None. */ + if (self_string->encoding) + result = PyString_FromString (self_string->encoding); + else + { + result = Py_None; + Py_INCREF (result); + } + + return result; +} + +static PyObject * +stpy_get_length (PyObject *self, void *closure) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + return PyLong_FromLong (self_string->length); +} + +PyObject * +stpy_get_type (PyObject *self, void *closure) +{ + lazy_string_object *str_obj = (lazy_string_object *) self; + return type_to_type_object (str_obj->type); +} + +static PyObject * +stpy_convert_to_value (PyObject *self, PyObject *args) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + struct value *val; + + val = value_at_lazy (self_string->type, self_string->address); + return value_to_value_object (val); +} + +static void +stpy_dealloc (PyObject *self) +{ + lazy_string_object *self_string = (lazy_string_object *) self; + xfree (self_string->encoding); +} + +PyObject * +gdbpy_create_lazy_string_object (CORE_ADDR address, long length, + const char *encoding, struct type *type) +{ + lazy_string_object *str_obj = NULL; + + if (address == 0) + { + PyErr_SetString (PyExc_MemoryError, + "Cannot create a lazy string from a GDB-side string."); + return NULL; + } + + if (!type) + { + PyErr_SetString (PyExc_RuntimeError, + "A lazy string's type cannot be NULL."); + return NULL; + } + + str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type); + if (!str_obj) + return NULL; + + str_obj->address = address; + str_obj->length = length; + if (encoding == NULL || !strcmp (encoding, "")) + str_obj->encoding = NULL; + else + str_obj->encoding = xstrdup (encoding); + str_obj->type = type; + + return (PyObject *) str_obj; +} + +void +gdbpy_initialize_lazy_string (void) +{ + if (PyType_Ready (&lazy_string_object_type) < 0) + return; + + Py_INCREF (&lazy_string_object_type); +} + +/* Determine whether the printer object pointed to by OBJ is a + Python lazy string. */ +int +gdbpy_is_lazy_string (PyObject *result) +{ + return PyObject_TypeCheck (result, &lazy_string_object_type); +} + +/* Extract and return the actual string from the lazy string object + STRING. Addtionally, the string type is written to *STR_TYPE, the + string length is written to *LENGTH, and the string encoding is + written to *ENCODING. On error, NULL is returned. The caller is + responsible for freeing the returned buffer. */ +gdb_byte * +gdbpy_extract_lazy_string (PyObject *string, struct type **str_type, + long *length, char **encoding) +{ + int width; + int bytes_read; + gdb_byte *buffer = NULL; + int errcode = 0; + CORE_ADDR addr; + struct gdbarch *gdbarch; + enum bfd_endian byte_order; + PyObject *py_len = NULL, *py_encoding = NULL; + PyObject *py_addr = NULL, *py_type = NULL; + volatile struct gdb_exception except; + + py_len = PyObject_GetAttrString (string, "length"); + py_encoding = PyObject_GetAttrString (string, "encoding"); + py_addr = PyObject_GetAttrString (string, "address"); + py_type = PyObject_GetAttrString (string, "type"); + + /* A NULL encoding, length, address or type is not ok. */ + if (!py_len || !py_encoding || !py_addr || !py_type) + goto error; + + *length = PyLong_AsLong (py_len); + addr = PyLong_AsUnsignedLongLong (py_addr); + + /* If the user supplies Py_None an encoding, set encoding to NULL. + This will trigger the resulting LA_PRINT_CALL to automatically + select an encoding. */ + if (py_encoding == Py_None) + *encoding = NULL; + else + *encoding = xstrdup (PyString_AsString (py_encoding)); + + *str_type = type_object_to_type (py_type); + gdbarch = get_type_arch (*str_type); + byte_order = gdbarch_byte_order (gdbarch); + width = TYPE_LENGTH (*str_type); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + errcode = read_string (addr, *length, width, + *length, byte_order, &buffer, + &bytes_read); + } + if (except.reason < 0) + { + PyErr_Format (except.reason == RETURN_QUIT \ + ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \ + "%s", except.message); \ + goto error; + + } + + if (errcode) + goto error; + + *length = bytes_read / width; + + Py_DECREF (py_encoding); + Py_DECREF (py_len); + Py_DECREF (py_addr); + Py_DECREF (py_type); + return buffer; + + error: + Py_XDECREF (py_encoding); + Py_XDECREF (py_len); + Py_XDECREF (py_addr); + Py_XDECREF (py_type); + xfree (buffer); + *length = 0; + *str_type = NULL; + return NULL; +} + + + +static PyMethodDef lazy_string_object_methods[] = { + { "value", stpy_convert_to_value, METH_NOARGS, + "Create a (lazy) value that contains a pointer to the string." }, + {NULL} /* Sentinel */ +}; + + +static PyGetSetDef lazy_string_object_getset[] = { + { "address", stpy_get_address, NULL, "Address of the string.", NULL }, + { "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL }, + { "length", stpy_get_length, NULL, "Length of the string.", NULL }, + { "type", stpy_get_type, NULL, "Type associated with the string.", NULL }, + { NULL } /* Sentinel */ +}; + +static PyTypeObject lazy_string_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.LazyString", /*tp_name*/ + sizeof (lazy_string_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + stpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB lazy string object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + lazy_string_object_methods, /* tp_methods */ + 0, /* tp_members */ + lazy_string_object_getset /* tp_getset */ +};
py-lazy-string.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-prettyprint.c =================================================================== --- py-prettyprint.c (nonexistent) +++ py-prettyprint.c (revision 842) @@ -0,0 +1,661 @@ +/* Python pretty-printing + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "exceptions.h" +#include "objfiles.h" +#include "symtab.h" +#include "language.h" +#include "valprint.h" + +#include "python.h" + +#ifdef HAVE_PYTHON +#include "python-internal.h" + + +/* Helper function for find_pretty_printer which iterates over a list, + calls each function and inspects output. This will return a + printer object if one recognizes VALUE. If no printer is found, it + will return None. On error, it will set the Python error and + return NULL. */ +static PyObject * +search_pp_list (PyObject *list, PyObject *value) +{ + Py_ssize_t pp_list_size, list_index; + PyObject *function, *printer = NULL; + + pp_list_size = PyList_Size (list); + for (list_index = 0; list_index < pp_list_size; list_index++) + { + function = PyList_GetItem (list, list_index); + if (! function) + return NULL; + + printer = PyObject_CallFunctionObjArgs (function, value, NULL); + if (! printer) + return NULL; + else if (printer != Py_None) + return printer; + + Py_DECREF (printer); + } + + Py_RETURN_NONE; +} + +/* Find the pretty-printing constructor function for VALUE. If no + pretty-printer exists, return None. If one exists, return a new + reference. On error, set the Python error and return NULL. */ +static PyObject * +find_pretty_printer (PyObject *value) +{ + PyObject *pp_list = NULL; + PyObject *function = NULL; + struct objfile *obj; + volatile struct gdb_exception except; + + /* Look at the pretty-printer dictionary for each objfile. */ + ALL_OBJFILES (obj) + { + PyObject *objf = objfile_to_objfile_object (obj); + if (!objf) + { + /* Ignore the error and continue. */ + PyErr_Clear (); + continue; + } + + pp_list = objfpy_get_printers (objf, NULL); + function = search_pp_list (pp_list, value); + + /* If there is an error in any objfile list, abort the search and + exit. */ + if (! function) + { + Py_XDECREF (pp_list); + return NULL; + } + + if (function != Py_None) + goto done; + + Py_DECREF (function); + Py_XDECREF (pp_list); + } + + pp_list = NULL; + /* Fetch the global pretty printer dictionary. */ + if (! PyObject_HasAttrString (gdb_module, "pretty_printers")) + { + function = Py_None; + Py_INCREF (function); + goto done; + } + pp_list = PyObject_GetAttrString (gdb_module, "pretty_printers"); + if (! pp_list) + goto done; + if (! PyList_Check (pp_list)) + goto done; + + function = search_pp_list (pp_list, value); + + done: + Py_XDECREF (pp_list); + + return function; +} + + +/* Pretty-print a single value, via the printer object PRINTER. + If the function returns a string, a PyObject containing the string + is returned. Otherwise, if the function returns a value, + *OUT_VALUE is set to the value, and NULL is returned. On error, + *OUT_VALUE is set to NULL, and NULL is returned. */ +static PyObject * +pretty_print_one_value (PyObject *printer, struct value **out_value) +{ + volatile struct gdb_exception except; + PyObject *result = NULL; + + *out_value = NULL; + TRY_CATCH (except, RETURN_MASK_ALL) + { + result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL); + if (result) + { + if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result)) + { + *out_value = convert_value_from_python (result); + if (PyErr_Occurred ()) + *out_value = NULL; + Py_DECREF (result); + result = NULL; + } + } + } + + return result; +} + +/* Return the display hint for the object printer, PRINTER. Return + NULL if there is no display_hint method, or if the method did not + return a string. On error, print stack trace and return NULL. On + success, return an xmalloc()d string. */ +char * +gdbpy_get_display_hint (PyObject *printer) +{ + PyObject *hint; + char *result = NULL; + + if (! PyObject_HasAttr (printer, gdbpy_display_hint_cst)) + return NULL; + + hint = PyObject_CallMethodObjArgs (printer, gdbpy_display_hint_cst, NULL); + if (gdbpy_is_string (hint)) + result = python_string_to_host_string (hint); + if (hint) + Py_DECREF (hint); + else + gdbpy_print_stack (); + + return result; +} + +/* Helper for apply_val_pretty_printer which calls to_string and + formats the result. */ +static void +print_string_repr (PyObject *printer, const char *hint, + struct ui_file *stream, int recurse, + const struct value_print_options *options, + const struct language_defn *language, + struct gdbarch *gdbarch) +{ + struct value *replacement = NULL; + PyObject *py_str = NULL; + + py_str = pretty_print_one_value (printer, &replacement); + if (py_str) + { + gdb_byte *output = NULL; + long length; + struct type *type; + char *encoding = NULL; + PyObject *string = NULL; + int is_lazy; + + is_lazy = gdbpy_is_lazy_string (py_str); + if (is_lazy) + output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding); + else + { + string = python_string_to_target_python_string (py_str); + if (string) + { + output = PyString_AsString (string); + length = PyString_Size (string); + type = builtin_type (gdbarch)->builtin_char; + } + else + gdbpy_print_stack (); + + } + + if (output) + { + if (is_lazy || (hint && !strcmp (hint, "string"))) + LA_PRINT_STRING (stream, type, output, length, encoding, + 0, options); + else + fputs_filtered (output, stream); + } + else + gdbpy_print_stack (); + + if (string) + Py_DECREF (string); + else + xfree (output); + + xfree (encoding); + Py_DECREF (py_str); + } + else if (replacement) + { + struct value_print_options opts = *options; + + opts.addressprint = 0; + common_val_print (replacement, stream, recurse, &opts, language); + } + else + gdbpy_print_stack (); +} + +static void +py_restore_tstate (void *p) +{ + PyFrameObject *frame = p; + PyThreadState *tstate = PyThreadState_GET (); + tstate->frame = frame; +} + +/* Create a dummy PyFrameObject, needed to work around + a Python-2.4 bug with generators. */ +static PyObject * +push_dummy_python_frame () +{ + PyObject *empty_string, *null_tuple, *globals; + PyCodeObject *code; + PyFrameObject *frame; + PyThreadState *tstate; + + empty_string = PyString_FromString (""); + if (!empty_string) + return NULL; + + null_tuple = PyTuple_New (0); + if (!null_tuple) + { + Py_DECREF (empty_string); + return NULL; + } + + code = PyCode_New (0, /* argcount */ + 0, /* nlocals */ + 0, /* stacksize */ + 0, /* flags */ + empty_string, /* code */ + null_tuple, /* consts */ + null_tuple, /* names */ + null_tuple, /* varnames */ +#if PYTHON_API_VERSION >= 1010 + null_tuple, /* freevars */ + null_tuple, /* cellvars */ +#endif + empty_string, /* filename */ + empty_string, /* name */ + 1, /* firstlineno */ + empty_string /* lnotab */ + ); + + Py_DECREF (empty_string); + Py_DECREF (null_tuple); + + if (!code) + return NULL; + + globals = PyDict_New (); + if (!globals) + { + Py_DECREF (code); + return NULL; + } + + tstate = PyThreadState_GET (); + + frame = PyFrame_New (tstate, code, globals, NULL); + + Py_DECREF (globals); + Py_DECREF (code); + + if (!frame) + return NULL; + + tstate->frame = frame; + make_cleanup (py_restore_tstate, frame->f_back); + return (PyObject *) frame; +} + +/* Helper for apply_val_pretty_printer that formats children of the + printer, if any exist. */ +static void +print_children (PyObject *printer, const char *hint, + struct ui_file *stream, int recurse, + const struct value_print_options *options, + const struct language_defn *language) +{ + int is_map, is_array, done_flag, pretty; + unsigned int i; + PyObject *children, *iter, *frame; + struct cleanup *cleanups; + + if (! PyObject_HasAttr (printer, gdbpy_children_cst)) + return; + + /* If we are printing a map or an array, we want some special + formatting. */ + is_map = hint && ! strcmp (hint, "map"); + is_array = hint && ! strcmp (hint, "array"); + + children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, + NULL); + if (! children) + { + gdbpy_print_stack (); + return; + } + + cleanups = make_cleanup_py_decref (children); + + iter = PyObject_GetIter (children); + if (!iter) + { + gdbpy_print_stack (); + goto done; + } + make_cleanup_py_decref (iter); + + /* Use the prettyprint_arrays option if we are printing an array, + and the pretty option otherwise. */ + pretty = is_array ? options->prettyprint_arrays : options->pretty; + + /* Manufacture a dummy Python frame to work around Python 2.4 bug, + where it insists on having a non-NULL tstate->frame when + a generator is called. */ + frame = push_dummy_python_frame (); + if (!frame) + { + gdbpy_print_stack (); + goto done; + } + make_cleanup_py_decref (frame); + + done_flag = 0; + for (i = 0; i < options->print_max; ++i) + { + PyObject *py_v, *item = PyIter_Next (iter); + char *name; + struct cleanup *inner_cleanup; + + if (! item) + { + if (PyErr_Occurred ()) + gdbpy_print_stack (); + /* Set a flag so we can know whether we printed all the + available elements. */ + else + done_flag = 1; + break; + } + + if (! PyArg_ParseTuple (item, "sO", &name, &py_v)) + { + gdbpy_print_stack (); + Py_DECREF (item); + continue; + } + inner_cleanup = make_cleanup_py_decref (item); + + /* Print initial "{". For other elements, there are three + cases: + 1. Maps. Print a "," after each value element. + 2. Arrays. Always print a ",". + 3. Other. Always print a ",". */ + if (i == 0) + fputs_filtered (" = {", stream); + else if (! is_map || i % 2 == 0) + fputs_filtered (pretty ? "," : ", ", stream); + + /* In summary mode, we just want to print "= {...}" if there is + a value. */ + if (options->summary) + { + /* This increment tricks the post-loop logic to print what + we want. */ + ++i; + /* Likewise. */ + pretty = 0; + break; + } + + if (! is_map || i % 2 == 0) + { + if (pretty) + { + fputs_filtered ("\n", stream); + print_spaces_filtered (2 + 2 * recurse, stream); + } + else + wrap_here (n_spaces (2 + 2 *recurse)); + } + + if (is_map && i % 2 == 0) + fputs_filtered ("[", stream); + else if (is_array) + { + /* We print the index, not whatever the child method + returned as the name. */ + if (options->print_array_indexes) + fprintf_filtered (stream, "[%d] = ", i); + } + else if (! is_map) + { + fputs_filtered (name, stream); + fputs_filtered (" = ", stream); + } + + if (gdbpy_is_lazy_string (py_v) || gdbpy_is_string (py_v)) + { + gdb_byte *output = NULL; + + if (gdbpy_is_lazy_string (py_v)) + { + struct type *type; + long length; + char *encoding = NULL; + + output = gdbpy_extract_lazy_string (py_v, &type, + &length, &encoding); + if (!output) + gdbpy_print_stack (); + LA_PRINT_STRING (stream, type, output, length, encoding, + 0, options); + xfree (encoding); + xfree (output); + } + else + { + output = python_string_to_host_string (py_v); + fputs_filtered (output, stream); + xfree (output); + } + } + else + { + struct value *value = convert_value_from_python (py_v); + + if (value == NULL) + { + gdbpy_print_stack (); + error (_("Error while executing Python code.")); + } + else + common_val_print (value, stream, recurse + 1, options, language); + } + + if (is_map && i % 2 == 0) + fputs_filtered ("] = ", stream); + + do_cleanups (inner_cleanup); + } + + if (i) + { + if (!done_flag) + { + if (pretty) + { + fputs_filtered ("\n", stream); + print_spaces_filtered (2 + 2 * recurse, stream); + } + fputs_filtered ("...", stream); + } + if (pretty) + { + fputs_filtered ("\n", stream); + print_spaces_filtered (2 * recurse, stream); + } + fputs_filtered ("}", stream); + } + + done: + do_cleanups (cleanups); +} + +int +apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value_print_options *options, + const struct language_defn *language) +{ + struct gdbarch *gdbarch = get_type_arch (type); + PyObject *printer = NULL; + PyObject *val_obj = NULL; + struct value *value; + char *hint = NULL; + struct cleanup *cleanups; + int result = 0; + + cleanups = ensure_python_env (gdbarch, language); + + /* Instantiate the printer. */ + if (valaddr) + valaddr += embedded_offset; + value = value_from_contents_and_address (type, valaddr, + address + embedded_offset); + + val_obj = value_to_value_object (value); + if (! val_obj) + goto done; + + /* Find the constructor. */ + printer = find_pretty_printer (val_obj); + Py_DECREF (val_obj); + make_cleanup_py_decref (printer); + if (! printer || printer == Py_None) + goto done; + + /* If we are printing a map, we want some special formatting. */ + hint = gdbpy_get_display_hint (printer); + make_cleanup (free_current_contents, &hint); + + /* Print the section */ + print_string_repr (printer, hint, stream, recurse, options, language, + gdbarch); + print_children (printer, hint, stream, recurse, options, language); + result = 1; + + + done: + if (PyErr_Occurred ()) + gdbpy_print_stack (); + do_cleanups (cleanups); + return result; +} + + +/* Apply a pretty-printer for the varobj code. PRINTER_OBJ is the + print object. It must have a 'to_string' method (but this is + checked by varobj, not here) which takes no arguments and + returns a string. The printer will return a value and in the case + of a Python string being returned, this function will return a + PyObject containing the string. For any other type, *REPLACEMENT is + set to the replacement value and this function returns NULL. On + error, *REPLACEMENT is set to NULL and this function also returns + NULL. */ +PyObject * +apply_varobj_pretty_printer (PyObject *printer_obj, + struct value **replacement) +{ + int size = 0; + PyObject *py_str = NULL; + + *replacement = NULL; + py_str = pretty_print_one_value (printer_obj, replacement); + + if (*replacement == NULL && py_str == NULL) + gdbpy_print_stack (); + + return py_str; +} + +/* Find a pretty-printer object for the varobj module. Returns a new + reference to the object if successful; returns NULL if not. VALUE + is the value for which a printer tests to determine if it + can pretty-print the value. */ +PyObject * +gdbpy_get_varobj_pretty_printer (struct value *value) +{ + PyObject *val_obj; + PyObject *pretty_printer = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + value = value_copy (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + val_obj = value_to_value_object (value); + if (! val_obj) + return NULL; + + pretty_printer = find_pretty_printer (val_obj); + Py_DECREF (val_obj); + return pretty_printer; +} + +/* A Python function which wraps find_pretty_printer and instantiates + the resulting class. This accepts a Value argument and returns a + pretty printer instance, or None. This function is useful as an + argument to the MI command -var-set-visualizer. */ +PyObject * +gdbpy_default_visualizer (PyObject *self, PyObject *args) +{ + PyObject *val_obj; + PyObject *cons, *printer = NULL; + struct value *value; + + if (! PyArg_ParseTuple (args, "O", &val_obj)) + return NULL; + value = value_object_to_value (val_obj); + if (! value) + { + PyErr_SetString (PyExc_TypeError, "argument must be a gdb.Value"); + return NULL; + } + + cons = find_pretty_printer (val_obj); + return cons; +} + +#else /* HAVE_PYTHON */ + +int +apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, int recurse, + const struct value_print_options *options, + const struct language_defn *language) +{ + return 0; +} + +#endif /* HAVE_PYTHON */
py-prettyprint.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: py-function.c =================================================================== --- py-function.c (nonexistent) +++ py-function.c (revision 842) @@ -0,0 +1,179 @@ +/* Convenience functions implemented in Python. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include "defs.h" +#include "value.h" +#include "exceptions.h" +#include "python-internal.h" +#include "charset.h" +#include "gdbcmd.h" +#include "cli/cli-decode.h" +#include "completer.h" +#include "expression.h" +#include "language.h" + +static PyTypeObject fnpy_object_type; + + + +static PyObject * +convert_values_to_python (int argc, struct value **argv) +{ + int i; + PyObject *result = PyTuple_New (argc); + for (i = 0; i < argc; ++i) + { + PyObject *elt = value_to_value_object (argv[i]); + if (! elt) + { + Py_DECREF (result); + error (_("Could not convert value to Python object.")); + } + PyTuple_SetItem (result, i, elt); + } + return result; +} + +/* Call a Python function object's invoke method. */ + +static struct value * +fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language, + void *cookie, int argc, struct value **argv) +{ + int i; + struct value *value = NULL; + PyObject *result, *callable, *args; + struct cleanup *cleanup; + + cleanup = ensure_python_env (gdbarch, language); + + args = convert_values_to_python (argc, argv); + + callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke"); + if (! callable) + { + Py_DECREF (args); + error (_("No method named 'invoke' in object.")); + } + + result = PyObject_Call (callable, args, NULL); + Py_DECREF (callable); + Py_DECREF (args); + + if (!result) + { + gdbpy_print_stack (); + error (_("Error while executing Python code.")); + } + + value = convert_value_from_python (result); + if (value == NULL) + { + Py_DECREF (result); + gdbpy_print_stack (); + error (_("Error while executing Python code.")); + } + + Py_DECREF (result); + do_cleanups (cleanup); + + return value; +} + +/* Initializer for a Function object. It takes one argument, the name + of the function. */ + +static int +fnpy_init (PyObject *self, PyObject *args, PyObject *kwds) +{ + char *name, *docstring = NULL; + if (! PyArg_ParseTuple (args, "s", &name)) + return -1; + Py_INCREF (self); + + if (PyObject_HasAttrString (self, "__doc__")) + { + PyObject *ds_obj = PyObject_GetAttrString (self, "__doc__"); + if (ds_obj && gdbpy_is_string (ds_obj)) + docstring = python_string_to_host_string (ds_obj); + } + if (! docstring) + docstring = xstrdup (_("This function is not documented.")); + + add_internal_function (name, docstring, fnpy_call, self); + return 0; +} + +/* Initialize internal function support. */ + +void +gdbpy_initialize_functions (void) +{ + if (PyType_Ready (&fnpy_object_type) < 0) + return; + + Py_INCREF (&fnpy_object_type); + PyModule_AddObject (gdb_module, "Function", (PyObject *) &fnpy_object_type); +} + + + +static PyTypeObject fnpy_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Function", /*tp_name*/ + sizeof (PyObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "GDB function object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* 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 */ + fnpy_init, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ +};
py-function.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.