more 8+3 friendly.
gdb/
* Makefile.in (py-cmd.o): Renamed from python-cmd.o. Updated
references.
(py-frame.o): Renamed from python-frame.o. Updated references.
(py-function.o): Renamed from python-function.o. Updated references.
(py-objfile.o): Renamed from python-objfile.o. Updated references.
(py-prettyprint.o): Renamed from python-prettyprint.o. Updated
+references.
(py-type.o): Renamed from python-type.o. Updated references.
(py-utils.o): Renamed from python-utils.o. Updated references.
(py-value.o): Renamed from python-value.o. Updated references.
* py-cmd.o: Renamed from python-cmd.o.
* py-frame.o: Renamed from python-frame.o.
* py-function.o: Renamed from python-function.o.
* py-objfile.o: Renamed from python-objfile.o.
* py-prettyprint.o: Renamed from python-prettyprint.o.
* py-type.o: Renamed from python-type.o.
* py-utils.o: Renamed from python-utils.o.
* py-value.o: Renamed from python-value.o.
gdb/testsuite/
* gdb.python/Makefile.in (EXECUTABLES): Adjust to new executable
names, add missing ones.
* gdb.python/py-cmd.exp: Rename from python-cmd.exp.
* gdb.python/py-frame.c: Rename from python-frame.c.
* gdb.python/py-frame.exp: Rename from python-frame.exp. Adjust
testfile name.
* gdb.python/py-function.exp: Rename from python-function.exp.
* gdb.python/py-mi.exp: Rename from python-mi.exp. Adjust
testfile name.
* gdb.python/py-prettyprint.c: Rename from python-prettyprint.c.
* gdb.python/py-prettyprint.exp: Rename from python-prettyprint.exp.
Adjust testfile name.
* gdb.python/py-prettyprint.py: Rename from python-prettyprint.py.
* gdb.python/py-template.cc: Rename from python-template.cc.
* gdb.python/py-template.exp: Rename from python-template.exp.
Adjust testfile name.
* gdb.python/py-value.c: Rename from python-value.c.
* gdb.python/py-value.exp: Rename from python-value.exp. Adjust
testfile name.
+2009-09-08 Thiago Jung Bauermann <thiago.bauermann@gmail.com>
+
+ * Makefile.in (py-cmd.o): Renamed from python-cmd.o. Updated
+ references.
+ (py-frame.o): Renamed from python-frame.o. Updated references.
+ (py-function.o): Renamed from python-function.o. Updated references.
+ (py-objfile.o): Renamed from python-objfile.o. Updated references.
+ (py-prettyprint.o): Renamed from python-prettyprint.o. Updated
+ references.
+ (py-type.o): Renamed from python-type.o. Updated references.
+ (py-utils.o): Renamed from python-utils.o. Updated references.
+ (py-value.o): Renamed from python-value.o. Updated references.
+ * py-cmd.c: Renamed from python-cmd.c.
+ * py-frame.c: Renamed from python-frame.c.
+ * py-function.c: Renamed from python-function.c.
+ * py-objfile.c: Renamed from python-objfile.c.
+ * py-prettyprint.c: Renamed from python-prettyprint.c.
+ * py-type.c: Renamed from python-type.c.
+ * py-utils.c: Renamed from python-utils.c.
+ * py-value.c: Renamed from python-value.c.
+
2009-09-08 Joel Brobecker <brobecker@adacore.com>
Avoid quadratic behavior when computing the value of a register.
#
SUBDIR_PYTHON_OBS = \
python.o \
- python-cmd.o \
- python-frame.o \
- python-function.o \
- python-objfile.o \
- python-prettyprint.o \
- python-type.o \
- python-utils.o \
- python-value.o
+ py-cmd.o \
+ py-frame.o \
+ py-function.o \
+ py-objfile.o \
+ py-prettyprint.o \
+ py-type.o \
+ py-utils.o \
+ py-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
- python/python-cmd.c \
- python/python-frame.c \
- python/python-function.c \
- python/python-objfile.c \
- python/python-prettyprint.c \
- python/python-type.c \
- python/python-utils.c \
- python/python-value.c
+ python/py-cmd.c \
+ python/py-frame.c \
+ python/py-function.c \
+ python/py-objfile.c \
+ python/py-prettyprint.c \
+ python/py-type.c \
+ python/py-utils.c \
+ python/py-value.c
SUBDIR_PYTHON_DEPS =
SUBDIR_PYTHON_LDFLAGS=
SUBDIR_PYTHON_CFLAGS=
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
$(POSTCOMPILE)
-python-cmd.o: $(srcdir)/python/python-cmd.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-cmd.c
+py-cmd.o: $(srcdir)/python/py-cmd.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-cmd.c
$(POSTCOMPILE)
-python-frame.o: $(srcdir)/python/python-frame.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-frame.c
+py-frame.o: $(srcdir)/python/py-frame.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-frame.c
$(POSTCOMPILE)
-python-function.o: $(srcdir)/python/python-function.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-function.c
+py-function.o: $(srcdir)/python/py-function.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
$(POSTCOMPILE)
-python-objfile.o: $(srcdir)/python/python-objfile.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-objfile.c
+py-objfile.o: $(srcdir)/python/py-objfile.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c
$(POSTCOMPILE)
-python-prettyprint.o: $(srcdir)/python/python-prettyprint.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-prettyprint.c
+py-prettyprint.o: $(srcdir)/python/py-prettyprint.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-prettyprint.c
$(POSTCOMPILE)
-python-type.o: $(srcdir)/python/python-type.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-type.c
+py-type.o: $(srcdir)/python/py-type.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-type.c
$(POSTCOMPILE)
-python-utils.o: $(srcdir)/python/python-utils.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c
+py-utils.o: $(srcdir)/python/py-utils.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-utils.c
$(POSTCOMPILE)
-python-value.o: $(srcdir)/python/python-value.c
- $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-value.c
+py-value.o: $(srcdir)/python/py-value.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-value.c
$(POSTCOMPILE)
#
--- /dev/null
+/* gdb commands implemented in Python
+
+ Copyright (C) 2008, 2009 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 "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;
+
+\f
+
+/* Python function which wraps dont_repeat. */
+static PyObject *
+cmdpy_dont_repeat (PyObject *self, PyObject *args)
+{
+ dont_repeat ();
+ Py_RETURN_NONE;
+}
+
+\f
+
+/* 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;
+}
+
+\f
+
+/* 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");
+}
+
+\f
+
+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 */
+};
--- /dev/null
+/* Python interface to stack frames
+
+ Copyright (C) 2008, 2009 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);
+}
+
+\f
+
+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 */
+};
--- /dev/null
+/* Convenience functions implemented in Python.
+
+ Copyright (C) 2008, 2009 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 "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;
+
+\f
+
+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))
+ /* Nothing ever frees this. */
+ docstring = python_string_to_host_string (ds_obj);
+ }
+ if (! docstring)
+ docstring = _("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);
+}
+
+\f
+
+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 */
+};
--- /dev/null
+/* Python interface to objfiles.
+
+ Copyright (C) 2008, 2009 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 "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;
+
+\f
+
+/* 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;
+}
+
+\f
+
+/* Clear the OBJFILE pointer in an Objfile object and remove the
+ reference. */
+static void
+clean_up_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 (clean_up_objfile);
+
+ if (PyType_Ready (&objfile_object_type) < 0)
+ return;
+
+ Py_INCREF (&objfile_object_type);
+ PyModule_AddObject (gdb_module, "Objfile", (PyObject *) &objfile_object_type);
+}
+
+\f
+
+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 */
+};
--- /dev/null
+/* Python pretty-printing
+
+ Copyright (C) 2008, 2009 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 "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))
+ {
+ *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)
+ {
+ PyObject *string = python_string_to_target_python_string (py_str);
+ if (string)
+ {
+ gdb_byte *output = PyString_AsString (string);
+ int len = PyString_Size (string);
+
+ if (hint && !strcmp (hint, "string"))
+ LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
+ output, len, 0, options);
+ else
+ fputs_filtered (output, stream);
+ Py_DECREF (string);
+ }
+ else
+ gdbpy_print_stack ();
+ Py_DECREF (py_str);
+ }
+ else if (replacement)
+ common_val_print (replacement, stream, recurse, options, 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_string (py_v))
+ {
+ char *text = python_string_to_host_string (py_v);
+ if (! text)
+ gdbpy_print_stack ();
+ else
+ {
+ fputs_filtered (text, stream);
+ xfree (text);
+ }
+ }
+ 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);
+
+ 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 */
--- /dev/null
+/* Python interface to types.
+
+ Copyright (C) 2008, 2009 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 "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 }
+};
+
+\f
+
+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;
+}
+
+\f
+
+/* 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;
+
+ 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 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;
+}
+
+\f
+
+static const struct objfile_data *typy_objfile_data_key;
+
+static void
+clean_up_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;
+}
+
+\f
+
+/* 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 (clean_up_objfile_types);
+
+ 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);
+}
+
+\f
+
+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." },
+ { "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 */
+};
--- /dev/null
+/* General utility routines for GDB/Python.
+
+ Copyright (C) 2008, 2009 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 "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);
+}
--- /dev/null
+/* Python interface to values.
+
+ Copyright (C) 2008, 2009 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 "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.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;
+ static char *keywords[] = { "encoding", "errors", "length" };
+
+ 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, &la_encoding);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ encoding = (user_encoding && *user_encoding) ? user_encoding : la_encoding;
+ unicode = PyUnicode_Decode (buffer, length, 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)
+ 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);
+
+ return PyInt_FromLong (l);
+}
+
+/* Implements conversion to long. */
+static PyObject *
+valpy_long (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ LONGEST l = 0;
+ volatile struct gdb_exception except;
+
+ if (!is_intlike (type, 1))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to long");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ l = value_as_long (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromLong (l);
+}
+
+/* Implements conversion to float. */
+static PyObject *
+valpy_float (PyObject *self)
+{
+ struct value *value = ((value_object *) self)->value;
+ struct type *type = value_type (value);
+ double d = 0;
+ volatile struct gdb_exception except;
+
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) != TYPE_CODE_FLT)
+ {
+ PyErr_SetString (PyExc_RuntimeError, "cannot convert value to float");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ d = value_as_double (value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyFloat_FromDouble (d);
+}
+
+/* Returns an object for a value which is released from the all_values chain,
+ so its lifetime is not bound to the execution of a command. */
+PyObject *
+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
+ 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;
+}
+
+\f
+
+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." },
+ { "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 */
+++ /dev/null
-/* gdb commands implemented in Python
-
- Copyright (C) 2008, 2009 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 "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;
-
-\f
-
-/* Python function which wraps dont_repeat. */
-static PyObject *
-cmdpy_dont_repeat (PyObject *self, PyObject *args)
-{
- dont_repeat ();
- Py_RETURN_NONE;
-}
-
-\f
-
-/* 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;
-}
-
-\f
-
-/* 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");
-}
-
-\f
-
-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 */
-};
+++ /dev/null
-/* Python interface to stack frames
-
- Copyright (C) 2008, 2009 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);
-}
-
-\f
-
-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 */
-};
+++ /dev/null
-/* Convenience functions implemented in Python.
-
- Copyright (C) 2008, 2009 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 "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;
-
-\f
-
-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))
- /* Nothing ever frees this. */
- docstring = python_string_to_host_string (ds_obj);
- }
- if (! docstring)
- docstring = _("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);
-}
-
-\f
-
-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 */
-};
+++ /dev/null
-/* Python interface to objfiles.
-
- Copyright (C) 2008, 2009 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 "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;
-
-\f
-
-/* 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;
-}
-
-\f
-
-/* Clear the OBJFILE pointer in an Objfile object and remove the
- reference. */
-static void
-clean_up_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 (clean_up_objfile);
-
- if (PyType_Ready (&objfile_object_type) < 0)
- return;
-
- Py_INCREF (&objfile_object_type);
- PyModule_AddObject (gdb_module, "Objfile", (PyObject *) &objfile_object_type);
-}
-
-\f
-
-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 */
-};
+++ /dev/null
-/* Python pretty-printing
-
- Copyright (C) 2008, 2009 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 "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))
- {
- *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)
- {
- PyObject *string = python_string_to_target_python_string (py_str);
- if (string)
- {
- gdb_byte *output = PyString_AsString (string);
- int len = PyString_Size (string);
-
- if (hint && !strcmp (hint, "string"))
- LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
- output, len, 0, options);
- else
- fputs_filtered (output, stream);
- Py_DECREF (string);
- }
- else
- gdbpy_print_stack ();
- Py_DECREF (py_str);
- }
- else if (replacement)
- common_val_print (replacement, stream, recurse, options, 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_string (py_v))
- {
- char *text = python_string_to_host_string (py_v);
- if (! text)
- gdbpy_print_stack ();
- else
- {
- fputs_filtered (text, stream);
- xfree (text);
- }
- }
- 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);
-
- 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 */
+++ /dev/null
-/* Python interface to types.
-
- Copyright (C) 2008, 2009 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 "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 }
-};
-
-\f
-
-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;
-}
-
-\f
-
-/* 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;
-
- 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 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;
-}
-
-\f
-
-static const struct objfile_data *typy_objfile_data_key;
-
-static void
-clean_up_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;
-}
-
-\f
-
-/* 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 (clean_up_objfile_types);
-
- 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);
-}
-
-\f
-
-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." },
- { "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 */
-};
+++ /dev/null
-/* General utility routines for GDB/Python.
-
- Copyright (C) 2008, 2009 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 "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);
-}
+++ /dev/null
-/* Python interface to values.
-
- Copyright (C) 2008, 2009 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 "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.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;
- static char *keywords[] = { "encoding", "errors", "length" };
-
- 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, &la_encoding);
- }
- GDB_PY_HANDLE_EXCEPTION (except);
-
- encoding = (user_encoding && *user_encoding) ? user_encoding : la_encoding;
- unicode = PyUnicode_Decode (buffer, length, 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)
- 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);
-
- return PyInt_FromLong (l);
-}
-
-/* Implements conversion to long. */
-static PyObject *
-valpy_long (PyObject *self)
-{
- struct value *value = ((value_object *) self)->value;
- struct type *type = value_type (value);
- LONGEST l = 0;
- volatile struct gdb_exception except;
-
- if (!is_intlike (type, 1))
- {
- PyErr_SetString (PyExc_RuntimeError, "cannot convert value to long");
- return NULL;
- }
-
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- l = value_as_long (value);
- }
- GDB_PY_HANDLE_EXCEPTION (except);
-
- return PyLong_FromLong (l);
-}
-
-/* Implements conversion to float. */
-static PyObject *
-valpy_float (PyObject *self)
-{
- struct value *value = ((value_object *) self)->value;
- struct type *type = value_type (value);
- double d = 0;
- volatile struct gdb_exception except;
-
- CHECK_TYPEDEF (type);
- if (TYPE_CODE (type) != TYPE_CODE_FLT)
- {
- PyErr_SetString (PyExc_RuntimeError, "cannot convert value to float");
- return NULL;
- }
-
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- d = value_as_double (value);
- }
- GDB_PY_HANDLE_EXCEPTION (except);
-
- return PyFloat_FromDouble (d);
-}
-
-/* Returns an object for a value which is released from the all_values chain,
- so its lifetime is not bound to the execution of a command. */
-PyObject *
-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
- 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;
-}
-
-\f
-
-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." },
- { "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 */
+2009-09-08 Thiago Jung Bauermann <thiago.bauermann@gmail.com>
+
+ * gdb.python/Makefile.in (EXECUTABLES): Adjust to new executable
+ names, add missing ones.
+ * gdb.python/py-cmd.exp: Rename from python-cmd.exp.
+ * gdb.python/py-frame.c: Rename from python-frame.c.
+ * gdb.python/py-frame.exp: Rename from python-frame.exp. Adjust
+ testfile name.
+ * gdb.python/py-function.exp: Rename from python-function.exp.
+ * gdb.python/py-mi.exp: Rename from python-mi.exp. Adjust
+ testfile name.
+ * gdb.python/py-prettyprint.c: Rename from python-prettyprint.c.
+ * gdb.python/py-prettyprint.exp: Rename from python-prettyprint.exp.
+ Adjust testfile name.
+ * gdb.python/py-prettyprint.py: Rename from python-prettyprint.py.
+ * gdb.python/py-template.cc: Rename from python-template.cc.
+ * gdb.python/py-template.exp: Rename from python-template.exp.
+ Adjust testfile name.
+ * gdb.python/py-value.c: Rename from python-value.c.
+ * gdb.python/py-value.exp: Rename from python-value.exp. Adjust
+ testfile name.
+
2009-09-08 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.base/breakpoint-shadow.exp (Second breakpoint placed): Initialize
VPATH = @srcdir@
srcdir = @srcdir@
-EXECUTABLES = python-value
+EXECUTABLES = py-value py-prettyprint py-template
all info install-info dvi install uninstall installcheck check:
@echo "Nothing to be done for $@..."
--- /dev/null
+# Copyright (C) 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# for defining new GDB commands in Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+ global gdb_prompt
+ foreach {input result} $args {
+ if {[gdb_test_multiple $input "$name - $input" {
+ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+ pass "$name - $input"
+ }
+ }]} {
+ return 1
+ }
+ }
+ return 0
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+# Test a simple command.
+
+gdb_py_test_multiple "input simple command" \
+ "python" "" \
+ "class test_cmd (gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super (test_cmd, self).__init__ (\"test_cmd\", gdb.COMMAND_OBSCURE)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print \"test_cmd output, arg = %s\" % arg" "" \
+ "test_cmd ()" "" \
+ "end" ""
+
+gdb_test "test_cmd ugh" "test_cmd output, arg = ugh" "call simple command"
+
+# Test a prefix command, and a subcommand within it.
+
+gdb_py_test_multiple "input prefix command" \
+ "python" "" \
+ "class prefix_cmd (gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super (prefix_cmd, self).__init__ (\"prefix_cmd\", gdb.COMMAND_OBSCURE, gdb.COMPLETE_NONE, True)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print \"prefix_cmd output, arg = %s\" % arg" "" \
+ "prefix_cmd ()" "" \
+ "end" ""
+
+gdb_test "prefix_cmd ugh" "prefix_cmd output, arg = ugh" "call prefix command"
+
+gdb_py_test_multiple "input subcommand" \
+ "python" "" \
+ "class subcmd (gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super (subcmd, self).__init__ (\"prefix_cmd subcmd\", gdb.COMMAND_OBSCURE)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print \"subcmd output, arg = %s\" % arg" "" \
+ "subcmd ()" "" \
+ "end" ""
+
+gdb_test "prefix_cmd subcmd ugh" "subcmd output, arg = ugh" "call subcmd"
+
+# Test prefix command using keyword arguments.
+
+gdb_py_test_multiple "input prefix command, keyword arguments" \
+ "python" "" \
+ "class prefix_cmd2 (gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super (prefix_cmd2, self).__init__ (\"prefix_cmd2\", gdb.COMMAND_OBSCURE, prefix = True, completer_class = gdb.COMPLETE_FILENAME)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print \"prefix_cmd2 output, arg = %s\" % arg" "" \
+ "prefix_cmd2 ()" "" \
+ "end" ""
+
+gdb_test "prefix_cmd2 argh" "prefix_cmd2 output, arg = argh" "call prefix command, keyword arguments"
+
+gdb_py_test_multiple "input subcommand under prefix_cmd2" \
+ "python" "" \
+ "class subcmd (gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super (subcmd, self).__init__ (\"prefix_cmd2 subcmd\", gdb.COMMAND_OBSCURE)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print \"subcmd output, arg = %s\" % arg" "" \
+ "subcmd ()" "" \
+ "end" ""
+
+gdb_test "prefix_cmd2 subcmd ugh" "subcmd output, arg = ugh" "call subcmd under prefix_cmd2"
+
+# Test a subcommand in an existing GDB prefix.
+
+gdb_py_test_multiple "input new subcommand" \
+ "python" "" \
+ "class newsubcmd (gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super (newsubcmd, self).__init__ (\"info newsubcmd\", gdb.COMMAND_OBSCURE)" "" \
+ " def invoke (self, arg, from_tty):" "" \
+ " print \"newsubcmd output, arg = %s\" % arg" "" \
+ "newsubcmd ()" "" \
+ "end" ""
+
+gdb_test "info newsubcmd ugh" "newsubcmd output, arg = ugh" "call newsubcmd"
--- /dev/null
+int f2 (int a)
+{
+ return ++a;
+}
+
+int f1 (int a, int b)
+{
+ return f2(a) + b;
+}
+
+int main (int argc, char *argv[])
+{
+ return f1 (1, 2);
+}
--- /dev/null
+# Copyright (C) 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "py-frame"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Run a command in GDB, and report a failure if a Python exception is thrown.
+# If report_pass is true, report a pass if no exception is thrown.
+proc gdb_py_test_silent_cmd {cmd name report_pass} {
+ global gdb_prompt
+
+ gdb_test_multiple $cmd $name {
+ -re "Traceback.*$gdb_prompt $" { fail $name }
+ -re "$gdb_prompt $" { if $report_pass { pass $name } }
+ }
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+# The following tests require execution.
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+gdb_breakpoint "f2"
+gdb_continue_to_breakpoint "breakpoint at f2"
+gdb_test "up" "" ""
+
+gdb_py_test_silent_cmd "python f1 = gdb.selected_frame ()" "get second frame" 0
+gdb_py_test_silent_cmd "python f0 = f1.newer ()" "get first frame" 0
+
+gdb_test "python print 'result =', f0 == f1" " = False" "test equality comparison (false)"
+gdb_test "python print 'result =', f0 == f0" " = True" "test equality comparison (true)"
+gdb_test "python print 'result =', f0 != f1" " = True" "test inequality comparison (true)"
+gdb_test "python print 'result =', f0 != f0" " = False" "test inequality comparison (false)"
+gdb_test "python print 'result =', f0.is_valid ()" " = True" "test Frame.is_valid"
+gdb_test "python print 'result =', f0.name ()" " = f2" "test Frame.name"
+gdb_test "python print 'result =', f0.type () == gdb.NORMAL_FRAME" " = True" "test Frame.type"
+gdb_test "python print 'result =', f0.unwind_stop_reason () == gdb.FRAME_UNWIND_NO_REASON" " = True" "test Frame.type"
+gdb_test "python print 'result =', gdb.frame_stop_reason_string (gdb.FRAME_UNWIND_INNER_ID)" " = previous frame inner to this frame \\(corrupt stack\\?\\)" "test gdb.frame_stop_reason_string"
+gdb_test "python print 'result =', f0.pc ()" " = \[0-9\]+" "test Frame.pc"
+gdb_test "python print 'result =', f0.older () == f1" " = True" "test Frame.older"
+gdb_test "python print 'result =', f1.newer () == f0" " = True" "test Frame.newer"
+gdb_test "python print 'result =', f0.read_var ('variable_which_surely_doesnt_exist')" \
+ "ValueError: variable 'variable_which_surely_doesnt_exist' not found.*Error while executing Python code." \
+ "test Frame.read_var - error"
+gdb_test "python print 'result =', f0.read_var ('a')" " = 1" "test Frame.read_var - success"
+
+gdb_test "python print 'result =', gdb.selected_frame () == f1" " = True" "test gdb.selected_frame"
--- /dev/null
+# Copyright (C) 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing convenience functions to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+ global gdb_prompt
+ foreach {input result} $args {
+ if {[gdb_test_multiple $input "$name - $input" {
+ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+ pass "$name - $input"
+ }
+ }]} {
+ return 1
+ }
+ }
+ return 0
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+gdb_py_test_multiple "input convenience function" \
+ "python" "" \
+ "class test_func (gdb.Function):" "" \
+ " def __init__ (self):" "" \
+ " super (test_func, self).__init__ (\"test_func\")" "" \
+ " def invoke (self, arg):" "" \
+ " return \"test_func output, arg = %s\" % arg.string ()" "" \
+ "test_func ()" "" \
+ "end" ""
+
+gdb_test "print \$test_func (\"ugh\")" "= \"test_func output, arg = ugh\"" "call function"
+
+# Test returning a gdb.Value from the function. This segfaulted GDB at one point.
+
+gdb_py_test_multiple "input value-returning convenience function" \
+ "python" "" \
+ "class Double (gdb.Function):" "" \
+ " def __init__ (self):" "" \
+ " super (Double, self).__init__ (\"double\")" "" \
+ " def invoke (self, n):" "" \
+ " return n*2" "" \
+ "Double ()" "" \
+ "end" ""
+
+gdb_test "print \$double (1)" "= 2" "call value-returning function"
--- /dev/null
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests Python-based
+# pretty-printing for MI.
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi2"
+
+gdb_exit
+if [mi_gdb_start] {
+ continue
+}
+
+set testfile "py-prettyprint"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DMI}] != "" } {
+ untested mi2-var-child.exp
+ return -1
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+if {[lsearch -exact [mi_get_features] python] < 0} {
+ unsupported "python support is disabled"
+ return -1
+}
+
+mi_runto main
+
+mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
+
+mi_continue_to_line [gdb_get_line_number {MI breakpoint here} ${testfile}.c] \
+ "step to breakpoint"
+
+mi_create_floating_varobj container c "create container varobj"
+
+mi_list_varobj_children container {
+} "examine container children=0"
+
+mi_next "next over update 1"
+
+mi_varobj_update_dynamic container {
+ { {container.\[0\]} {\[0\]} 0 int }
+} "varobj update 1"
+
+mi_next "next over update 2"
+
+mi_varobj_update_dynamic container {
+ { {container.\[0\]} {\[0\]} 0 int }
+ { {container.\[1\]} {\[1\]} 0 int }
+} "varobj update 2"
+
+mi_gdb_test "-var-set-visualizer container None" \
+ "\\^done" \
+ "clear visualizer"
+
+mi_gdb_test "-var-update container" \
+ "\\^done,changelist=\\\[\\\]" \
+ "varobj update after clearing"
+
+mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \
+ "\\^done" \
+ "choose default visualizer"
+
+mi_varobj_update_dynamic container {
+ { {container.\[0\]} {\[0\]} 0 int }
+ { {container.\[1\]} {\[1\]} 0 int }
+} "varobj update after choosing default"
+
+mi_gdb_test "-var-set-visualizer container ContainerPrinter" \
+ "\\^done" \
+ "choose visualizer using expression"
+
+mi_varobj_update_dynamic container {
+ { {container.\[0\]} {\[0\]} 0 int }
+ { {container.\[1\]} {\[1\]} 0 int }
+} "varobj update after choosing via expression"
+
+mi_continue_to_line \
+ [gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \
+ "step to second breakpoint"
+
+mi_varobj_update_with_type_change container int 0 "update after type change"
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2008, 2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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/>. */
+
+struct s
+{
+ int a;
+ int *b;
+};
+
+struct ss
+{
+ struct s a;
+ struct s b;
+};
+
+struct ns {
+ const char *null_str;
+ int length;
+};
+
+#ifdef __cplusplus
+struct S : public s {
+ int zs;
+};
+
+struct SS {
+ int zss;
+ S s;
+};
+
+struct SSS
+{
+ SSS (int x, const S& r);
+ int a;
+ const S &b;
+};
+SSS::SSS (int x, const S& r) : a(x), b(r) { }
+
+class VirtualTest
+{
+ private:
+ int value;
+
+ public:
+ VirtualTest ()
+ {
+ value = 1;
+ }
+};
+
+class Vbase1 : public virtual VirtualTest { };
+class Vbase2 : public virtual VirtualTest { };
+class Vbase3 : public virtual VirtualTest { };
+
+class Derived : public Vbase1, public Vbase2, public Vbase3
+{
+ private:
+ int value;
+
+ public:
+ Derived ()
+ {
+ value = 2;
+ }
+};
+
+#endif
+
+typedef struct string_repr
+{
+ struct whybother
+ {
+ const char *contents;
+ } whybother;
+} string;
+
+/* This lets us avoid malloc. */
+int array[100];
+
+struct container
+{
+ string name;
+ int len;
+ int *elements;
+};
+
+typedef struct container zzz_type;
+
+string
+make_string (const char *s)
+{
+ string result;
+ result.whybother.contents = s;
+ return result;
+}
+
+zzz_type
+make_container (const char *s)
+{
+ zzz_type result;
+
+ result.name = make_string (s);
+ result.len = 0;
+ result.elements = 0;
+
+ return result;
+}
+
+void
+add_item (zzz_type *c, int val)
+{
+ if (c->len == 0)
+ c->elements = array;
+ c->elements[c->len] = val;
+ ++c->len;
+}
+
+void init_s(struct s *s, int a)
+{
+ s->a = a;
+ s->b = &s->a;
+}
+
+void init_ss(struct ss *s, int a, int b)
+{
+ init_s(&s->a, a);
+ init_s(&s->b, b);
+}
+
+void do_nothing(void)
+{
+ int c;
+
+ c = 23; /* Another MI breakpoint */
+}
+
+int
+main ()
+{
+ struct ss ss;
+ struct ss ssa[2];
+ string x = make_string ("this is x");
+ zzz_type c = make_container ("container");
+ const struct string_repr cstring = { { "const string" } };
+
+ init_ss(&ss, 1, 2);
+ init_ss(ssa+0, 3, 4);
+ init_ss(ssa+1, 5, 6);
+
+ struct ns ns;
+ ns.null_str = "embedded\0null\0string";
+ ns.length = 20;
+
+#ifdef __cplusplus
+ S cps;
+
+ cps.zs = 7;
+ init_s(&cps, 8);
+
+ SS cpss;
+ cpss.zss = 9;
+ init_s(&cpss.s, 10);
+
+ SS cpssa[2];
+ cpssa[0].zss = 11;
+ init_s(&cpssa[0].s, 12);
+ cpssa[1].zss = 13;
+ init_s(&cpssa[1].s, 14);
+
+ SSS sss(15, cps);
+
+ SSS& ref (sss);
+
+ Derived derived;
+
+#endif
+
+ add_item (&c, 23); /* MI breakpoint here */
+ add_item (&c, 72);
+
+#ifdef MI
+ do_nothing ();
+#endif
+
+ return 0; /* break to inspect struct and union */
+}
--- /dev/null
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests Python-based
+# pretty-printing for the CLI.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "py-prettyprint"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+proc run_lang_tests {lang} {
+ global srcdir subdir srcfile binfile testfile hex
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug $lang"] != "" } {
+ untested "Couldn't compile ${srcfile} in $lang mode"
+ return -1
+ }
+
+ set nl "\[\r\n\]+"
+
+ # Start with a fresh gdb.
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+
+
+ if ![runto_main ] then {
+ perror "couldn't run to breakpoint"
+ return
+ }
+
+ gdb_test "set print pretty on" ""
+
+ gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \
+ ".*Breakpoint.*"
+ gdb_test "continue" ".*Breakpoint.*"
+
+ gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
+
+ gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>"
+ gdb_test "print ssa\[1\]" " = a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>"
+ gdb_test "print ssa" " = {a=< a=<3> b=<$hex>> b=< a=<4> b=<$hex>>, a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>}"
+
+ if {$lang == "c++"} {
+ gdb_test "print cps" "= a=<8> b=<$hex>"
+ gdb_test "print cpss" " = {$nl *zss = 9, *$nl *s = a=<10> b=<$hex>$nl}"
+ gdb_test "print cpssa\[0\]" " = {$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl}"
+ gdb_test "print cpssa\[1\]" " = {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl}"
+ gdb_test "print cpssa" " = {{$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl *}, {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl *}}"
+ gdb_test "print sss" "= a=<15> b=< a=<8> b=<$hex>>"
+ gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
+ gdb_test "print derived" \
+ " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
+ gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
+ }
+
+ gdb_test "print x" " = $hex \"this is x\""
+ gdb_test "print cstring" " = $hex \"const string\""
+
+ gdb_test "print c" " = container $hex \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}"
+
+ gdb_test "continue" "Program exited normally\."
+}
+
+run_lang_tests "c"
+run_lang_tests "c++"
--- /dev/null
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests python pretty
+# printers.
+
+import re
+
+# Test returning a Value from a printer.
+class string_print:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return self.val['whybother']['contents']
+
+# Test a class-based printer.
+class ContainerPrinter:
+ class _iterator:
+ def __init__ (self, pointer, len):
+ self.start = pointer
+ self.pointer = pointer
+ self.end = pointer + len
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if self.pointer == self.end:
+ raise StopIteration
+ result = self.pointer
+ self.pointer = self.pointer + 1
+ return ('[%d]' % int (result - self.start), result.dereference())
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return 'container %s with %d elements' % (self.val['name'], self.val['len'])
+
+ def children(self):
+ return self._iterator(self.val['elements'], self.val['len'])
+
+class pp_s:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ a = self.val["a"]
+ b = self.val["b"]
+ if a.address != b:
+ raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b)))
+ return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
+
+class pp_ss:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
+
+class pp_sss:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">"
+
+class pp_multiple_virtual:
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ return "pp value variable is: " + str (self.val['value'])
+
+class pp_vbase1:
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ return "pp class name: " + self.val.type.tag
+
+class pp_ns:
+ "Print a std::basic_string of some kind"
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ len = self.val['length']
+ return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len)
+
+ def display_hint (self):
+ return 'string'
+
+def lookup_function (val):
+ "Look-up and return a pretty-printer that can print val."
+
+ # Get the type.
+ type = val.type;
+
+ # If it points to a reference, get the reference.
+ if type.code == gdb.TYPE_CODE_REF:
+ type = type.target ()
+
+ # Get the unqualified type, stripped of typedefs.
+ type = type.unqualified ().strip_typedefs ()
+
+ # Get the type name.
+ typename = type.tag
+
+ if typename == None:
+ return None
+
+ # Iterate over local dictionary of types to determine
+ # if a printer is registered for that type. Return an
+ # instantiation of the printer if found.
+ for function in pretty_printers_dict:
+ if function.match (typename):
+ return pretty_printers_dict[function] (val)
+
+ # Cannot find a pretty printer. Return None.
+
+ return None
+
+
+def register_pretty_printers ():
+ pretty_printers_dict[re.compile ('^struct s$')] = pp_s
+ pretty_printers_dict[re.compile ('^s$')] = pp_s
+ pretty_printers_dict[re.compile ('^S$')] = pp_s
+
+ pretty_printers_dict[re.compile ('^struct ss$')] = pp_ss
+ pretty_printers_dict[re.compile ('^ss$')] = pp_ss
+ pretty_printers_dict[re.compile ('^const S &$')] = pp_s
+ pretty_printers_dict[re.compile ('^SSS$')] = pp_sss
+
+ pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual
+ pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1
+
+ # Note that we purposely omit the typedef names here.
+ # Printer lookup is based on canonical name.
+ # However, we do need both tagged and untagged variants, to handle
+ # both the C and C++ cases.
+ pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print
+ pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter
+ pretty_printers_dict[re.compile ('^string_repr$')] = string_print
+ pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
+
+ pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
+ pretty_printers_dict[re.compile ('^ns$')] = pp_ns
+pretty_printers_dict = {}
+
+register_pretty_printers ()
+gdb.pretty_printers.append (lookup_function)
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2008 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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/>. */
+
+template <typename T>
+struct Foo {
+};
+
+#ifndef TYPE
+#define TYPE int
+#endif
+
+int main()
+{
+ Foo<TYPE> foo;
+ return 0; // break here
+}
--- /dev/null
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "py-template"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ {debug c++}] != "" } {
+ untested "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+proc test_template_arg {type} {
+ global testfile srcdir subdir srcfile binfile
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+ executable \
+ [list debug c++ additional_flags="-DTYPE=$type"]] != "" } {
+ untested $type
+ return -1
+ }
+ gdb_load ${binfile}
+ if ![runto_main ] then {
+ perror "couldn't run to breakpoint"
+ return
+ }
+ # There is no executable code in main(), so we are where we want to be
+ gdb_test "print foo" ""
+ gdb_test "python foo = gdb.history(0)" ""
+
+ # Replace '*' with '\*' in regex.
+ regsub -all {\*} $type {\*} t
+ gdb_test "python print foo.type.template_argument(0)" $t $type
+}
+
+test_template_arg "const int"
+test_template_arg "volatile int"
+test_template_arg "const int &"
+test_template_arg "volatile int &"
+test_template_arg "volatile int * const"
+test_template_arg "volatile int * const *"
+test_template_arg "const int * volatile"
+test_template_arg "const int * volatile * const * volatile *"
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2008, 2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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/>. */
+
+struct s
+{
+ int a;
+ int b;
+};
+
+union u
+{
+ int a;
+ float b;
+};
+
+enum e
+ {
+ ONE = 1,
+ TWO = 2
+ };
+
+typedef struct s *PTR;
+
+enum e evalue = TWO;
+
+int
+main (int argc, char *argv[])
+{
+ char *cp = argv[0]; /* Prevent gcc from optimizing argv[] out. */
+ struct s s;
+ union u u;
+ PTR x = &s;
+ char st[17] = "divide et impera";
+ char nullst[17] = "divide\0et\0impera";
+
+ s.a = 3;
+ s.b = 5;
+ u.a = 7;
+
+ return 0; /* break to inspect struct and union */
+}
--- /dev/null
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set testfile "py-value"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+ global gdb_prompt
+ foreach {input result} $args {
+ if {[gdb_test_multiple $input "$name - $input" {
+ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+ pass "$name - $input"
+ }
+ }]} {
+ return 1
+ }
+ }
+ return 0
+}
+
+# Run a command in GDB, and report a failure if a Python exception is thrown.
+# If report_pass is true, report a pass if no exception is thrown.
+proc gdb_py_test_silent_cmd {cmd name report_pass} {
+ global gdb_prompt
+
+ gdb_test_multiple $cmd $name {
+ -re "Traceback.*$gdb_prompt $" { fail $name }
+ -re "$gdb_prompt $" { if $report_pass { pass $name } }
+ }
+}
+
+proc test_value_creation {} {
+ global gdb_prompt
+
+ gdb_py_test_silent_cmd "python i = gdb.Value (True)" "create boolean value" 1
+ gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create integer value" 1
+ gdb_py_test_silent_cmd "python i = gdb.Value (5L)" "create long value" 1
+ gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create double value" 1
+ gdb_py_test_silent_cmd "python a = gdb.Value ('string test')" "create 8-bit string value" 1
+ gdb_test "python print a" "\"string test\"" "print 8-bit string"
+ gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of 8-bit string"
+ gdb_py_test_silent_cmd "python a = gdb.Value (u'unicode test')" "create unicode value" 1
+ gdb_test "python print a" "\"unicode test\"" "print Unicode string"
+ gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of unicode string"
+
+ # Test address attribute is None in a non-addressable value
+ gdb_test "python print 'result =', i.address" "= None" "Test address attribute in non-addressable value"
+}
+
+proc test_value_numeric_ops {} {
+ global gdb_prompt
+
+ gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create first integer value" 0
+ gdb_py_test_silent_cmd "python j = gdb.Value (2)" "create second integer value" 0
+ gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create first double value" 0
+ gdb_py_test_silent_cmd "python g = gdb.Value (2.5)" "create second double value" 0
+ gdb_test "python print 'result = ' + str(i+j)" " = 7" "add two integer values"
+ gdb_test "python print (i+j).__class__" "<type 'gdb.Value'>" "verify type of integer add result"
+
+ gdb_test "python print 'result = ' + str(f+g)" " = 3.75" "add two double values"
+ gdb_test "python print 'result = ' + str(i-j)" " = 3" "subtract two integer values"
+ gdb_test "python print 'result = ' + str(f-g)" " = -1.25" "subtract two double values"
+ gdb_test "python print 'result = ' + str(i*j)" " = 10" "multiply two integer values"
+ gdb_test "python print 'result = ' + str(f*g)" " = 3.125" "multiply two double values"
+ gdb_test "python print 'result = ' + str(i/j)" " = 2" "divide two integer values"
+ gdb_test "python print 'result = ' + str(f/g)" " = 0.5" "divide two double values"
+ gdb_test "python print 'result = ' + str(i%j)" " = 1" "take remainder of two integer values"
+ # Remainder of float is implemented in Python but not in GDB's value system.
+
+ gdb_test "python print 'result = ' + str(i**j)" " = 25" "integer value raised to the power of another integer value"
+ gdb_test "python print 'result = ' + str(g**j)" " = 6.25" "double value raised to the power of integer value"
+
+ gdb_test "python print 'result = ' + str(-i)" " = -5" "negated integer value"
+ gdb_test "python print 'result = ' + str(+i)" " = 5" "positive integer value"
+ gdb_test "python print 'result = ' + str(-f)" " = -1.25" "negated double value"
+ gdb_test "python print 'result = ' + str(+f)" " = 1.25" "positive double value"
+ gdb_test "python print 'result = ' + str(abs(j-i))" " = 3" "absolute of integer value"
+ gdb_test "python print 'result = ' + str(abs(f-g))" " = 1.25" "absolute of double value"
+
+ # Test gdb.Value mixed with Python types.
+
+ gdb_test "python print 'result = ' + str(i-1)" " = 4" "subtract integer value from python integer"
+ gdb_test "python print (i-1).__class__" "<type 'gdb.Value'>" "verify type of mixed integer subtraction result"
+ gdb_test "python print 'result = ' + str(f+1.5)" " = 2.75" "add double value with python float"
+
+ gdb_test "python print 'result = ' + str(1-i)" " = -4" "subtract python integer from integer value"
+ gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value"
+
+ # Conversion test.
+ gdb_test "print evalue" " = TWO"
+ gdb_test "python evalue = gdb.history (0)" ""
+ gdb_test "python print int (evalue)" "2"
+
+ # Test pointer arithmethic
+
+ # First, obtain the pointers
+ gdb_test "print (void *) 2" "" ""
+ gdb_test "python a = gdb.history (0)" "" ""
+ gdb_test "print (void *) 5" "" ""
+ gdb_test "python b = gdb.history (0)" "" ""
+
+ gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer"
+ gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value"
+ gdb_test "python print 'result = ' + str(b-a)" " = 3" "subtract two pointer values"
+
+ # Test some invalid operations.
+
+ gdb_test_multiple "python print 'result = ' + str(i+'foo')" "catch error in python type conversion" {
+ -re "Argument to arithmetic operation not a number or boolean.*$gdb_prompt $" {pass "catch error in python type conversion"}
+ -re "result = .*$gdb_prompt $" {fail "catch error in python type conversion"}
+ -re "$gdb_prompt $" {fail "catch error in python type conversion"}
+ }
+
+ gdb_test_multiple "python print 'result = ' + str(i+gdb.Value('foo'))" "catch throw of GDB error" {
+ -re "Traceback.*$gdb_prompt $" {pass "catch throw of GDB error"}
+ -re "result = .*$gdb_prompt $" {fail "catch throw of GDB error"}
+ -re "$gdb_prompt $" {fail "catch throw of GDB error"}
+ }
+}
+
+proc test_value_boolean {} {
+ # First, define a useful function to test booleans.
+ gdb_py_test_multiple "define function to test booleans" \
+ "python" "" \
+ "def test_bool (val):" "" \
+ " if val:" "" \
+ " print 'yay'" "" \
+ " else:" "" \
+ " print 'nay'" "" \
+ "end" ""
+
+ gdb_test "py test_bool (gdb.Value (True))" "yay" "check evaluation of true boolean value in expression"
+
+ gdb_test "py test_bool (gdb.Value (False))" "nay" "check evaluation of false boolean value in expression"
+
+ gdb_test "py test_bool (gdb.Value (5))" "yay" "check evaluation of true integer value in expression"
+
+ gdb_test "py test_bool (gdb.Value (0))" "nay" "check evaluation of false integer value in expression"
+
+ gdb_test "py test_bool (gdb.Value (5.2))" "yay" "check evaluation of true integer value in expression"
+
+ gdb_test "py test_bool (gdb.Value (0.0))" "nay" "check evaluation of false integer value in expression"
+}
+
+proc test_value_compare {} {
+ gdb_test "py print gdb.Value (1) < gdb.Value (1)" "False" "less than, equal"
+ gdb_test "py print gdb.Value (1) < gdb.Value (2)" "True" "less than, less"
+ gdb_test "py print gdb.Value (2) < gdb.Value (1)" "False" "less than, greater"
+ gdb_test "py print gdb.Value (2) < None" "False" "less than, None"
+
+ gdb_test "py print gdb.Value (1) <= gdb.Value (1)" "True" "less or equal, equal"
+ gdb_test "py print gdb.Value (1) <= gdb.Value (2)" "True" "less or equal, less"
+ gdb_test "py print gdb.Value (2) <= gdb.Value (1)" "False" "less or equal, greater"
+ gdb_test "py print gdb.Value (2) <= None" "False" "less or equal, None"
+
+ gdb_test "py print gdb.Value (1) == gdb.Value (1)" "True" "equality of gdb.Values"
+ gdb_test "py print gdb.Value (1) == gdb.Value (2)" "False" "inequality of gdb.Values"
+ gdb_test "py print gdb.Value (1) == 1.0" "True" "equality of gdb.Value with Python value"
+ gdb_test "py print gdb.Value (1) == 2" "False" "inequality of gdb.Value with Python value"
+ gdb_test "py print gdb.Value (1) == None" "False" "inequality of gdb.Value with None"
+
+ gdb_test "py print gdb.Value (1) != gdb.Value (1)" "False" "inequality, false"
+ gdb_test "py print gdb.Value (1) != gdb.Value (2)" "True" "inequality, true"
+ gdb_test "py print gdb.Value (1) != None" "True" "inequality, None"
+
+ gdb_test "py print gdb.Value (1) > gdb.Value (1)" "False" "greater than, equal"
+ gdb_test "py print gdb.Value (1) > gdb.Value (2)" "False" "greater than, less"
+ gdb_test "py print gdb.Value (2) > gdb.Value (1)" "True" "greater than, greater"
+ gdb_test "py print gdb.Value (2) > None" "True" "greater than, None"
+
+ gdb_test "py print gdb.Value (1) >= gdb.Value (1)" "True" "greater or equal, equal"
+ gdb_test "py print gdb.Value (1) >= gdb.Value (2)" "False" "greater or equal, less"
+ gdb_test "py print gdb.Value (2) >= gdb.Value (1)" "True" "greater or equal, greater"
+ gdb_test "py print gdb.Value (2) >= None" "True" "greater or equal, None"
+}
+
+proc test_value_in_inferior {} {
+ global gdb_prompt
+ global testfile
+
+ gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"]
+
+ gdb_continue_to_breakpoint "break to inspect struct and union"
+
+ # Just get inferior variable s in the value history, available to python.
+ gdb_test "print s" " = {a = 3, b = 5}" ""
+
+ gdb_py_test_silent_cmd "python s = gdb.history (0)" "get value from history" 1
+
+ gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name"
+ gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name"
+
+ # Test dereferencing the argv pointer
+
+ # Just get inferior variable argv the value history, available to python.
+ gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" ""
+
+ gdb_py_test_silent_cmd "python argv = gdb.history (0)" "" 0
+ gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1
+
+ # Check that the dereferenced value is sane
+ gdb_test "python print arg0" "0x.*$testfile\"" "verify dereferenced value"
+
+ # Smoke-test is_optimized_out attribute
+ gdb_test "python print 'result =', arg0.is_optimized_out" "= False" "Test is_optimized_out attribute"
+
+ # Test address attribute
+ gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
+
+ # Test string fetches, both partial and whole.
+ gdb_test "print st" "\"divide et impera\""
+ gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value from history" 1
+ gdb_test "python print st.string ()" "divide et impera" "Test string with no length"
+ gdb_test "python print st.string (length = -1)" "divide et impera" "Test string (length = -1) is all of the string"
+ gdb_test "python print st.string (length = 6)" "divide"
+ gdb_test "python print \"---\"+st.string (length = 0)+\"---\"" "------" "Test string (length = 0) is empty"
+ gdb_test "python print len(st.string (length = 0))" "0" "Test length is 0"
+
+
+ # Fetch a string that has embedded nulls.
+ gdb_test "print nullst" "\"divide\\\\000et\\\\000impera\".*"
+ gdb_py_test_silent_cmd "python nullst = gdb.history (0)" "get value from history" 1
+ gdb_test "python print nullst.string ()" "divide" "Test string to first null"
+ # Python cannot print strings that contain the null (\0) character.
+ # For the purposes of this test, use repr()
+ gdb_py_test_silent_cmd "python nullst = nullst.string (length = 9)" "get string beyond null" 1
+ gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
+}
+
+# A few objfile tests.
+proc test_objfiles {} {
+ gdb_test "python\nok=False\nfor file in gdb.objfiles():\n if 'py-value' in file.filename:\n ok=True\nprint ok\nend" "True"
+
+ gdb_test "python print gdb.objfiles()\[0\].pretty_printers" "\\\[\\\]"
+
+ gdb_test "python gdb.objfiles()\[0\].pretty_printers = 0" \
+ "pretty_printers attribute must be a list.*Error while executing Python code."
+}
+
+proc test_value_after_death {} {
+ # Construct a type while the inferior is still running.
+ gdb_py_test_silent_cmd "python ptrtype = gdb.lookup_type('PTR')" \
+ "create PTR type" 1
+
+ # Kill the inferior and remove the symbols.
+ gdb_test "kill" "" "kill the inferior" \
+ "Kill the program being debugged. .y or n. $" \
+ "y"
+ gdb_test "file" "" "Discard the symbols" \
+ "Discard symbol table from.*y or n. $" \
+ "y"
+
+ # Now create a value using that type. Relies on arg0, created by
+ # test_value_in_inferior.
+ gdb_py_test_silent_cmd "python castval = arg0.cast(ptrtype.pointer())" \
+ "cast arg0 to PTR" 1
+
+ # Make sure the type is deleted.
+ gdb_py_test_silent_cmd "python ptrtype = None" \
+ "delete PTR type" 1
+
+ # Now see if the value's type is still valid.
+ gdb_test "python print castval.type" "PTR ." \
+ "print value's type"
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+test_value_creation
+test_value_numeric_ops
+test_value_boolean
+test_value_compare
+test_objfiles
+
+# The following tests require execution.
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+test_value_in_inferior
+test_value_after_death
+++ /dev/null
-# Copyright (C) 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests the mechanism
-# for defining new GDB commands in Python.
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
-# Run a test named NAME, consisting of multiple lines of input.
-# After each input line INPUT, search for result line RESULT.
-# Succeed if all results are seen; fail otherwise.
-proc gdb_py_test_multiple {name args} {
- global gdb_prompt
- foreach {input result} $args {
- if {[gdb_test_multiple $input "$name - $input" {
- -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
- pass "$name - $input"
- }
- }]} {
- return 1
- }
- }
- return 0
-}
-
-# Start with a fresh gdb.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
- -re "not supported.*$gdb_prompt $" {
- unsupported "python support is disabled"
- return -1
- }
- -re "$gdb_prompt $" {}
-}
-
-# Test a simple command.
-
-gdb_py_test_multiple "input simple command" \
- "python" "" \
- "class test_cmd (gdb.Command):" "" \
- " def __init__ (self):" "" \
- " super (test_cmd, self).__init__ (\"test_cmd\", gdb.COMMAND_OBSCURE)" "" \
- " def invoke (self, arg, from_tty):" "" \
- " print \"test_cmd output, arg = %s\" % arg" "" \
- "test_cmd ()" "" \
- "end" ""
-
-gdb_test "test_cmd ugh" "test_cmd output, arg = ugh" "call simple command"
-
-# Test a prefix command, and a subcommand within it.
-
-gdb_py_test_multiple "input prefix command" \
- "python" "" \
- "class prefix_cmd (gdb.Command):" "" \
- " def __init__ (self):" "" \
- " super (prefix_cmd, self).__init__ (\"prefix_cmd\", gdb.COMMAND_OBSCURE, gdb.COMPLETE_NONE, True)" "" \
- " def invoke (self, arg, from_tty):" "" \
- " print \"prefix_cmd output, arg = %s\" % arg" "" \
- "prefix_cmd ()" "" \
- "end" ""
-
-gdb_test "prefix_cmd ugh" "prefix_cmd output, arg = ugh" "call prefix command"
-
-gdb_py_test_multiple "input subcommand" \
- "python" "" \
- "class subcmd (gdb.Command):" "" \
- " def __init__ (self):" "" \
- " super (subcmd, self).__init__ (\"prefix_cmd subcmd\", gdb.COMMAND_OBSCURE)" "" \
- " def invoke (self, arg, from_tty):" "" \
- " print \"subcmd output, arg = %s\" % arg" "" \
- "subcmd ()" "" \
- "end" ""
-
-gdb_test "prefix_cmd subcmd ugh" "subcmd output, arg = ugh" "call subcmd"
-
-# Test prefix command using keyword arguments.
-
-gdb_py_test_multiple "input prefix command, keyword arguments" \
- "python" "" \
- "class prefix_cmd2 (gdb.Command):" "" \
- " def __init__ (self):" "" \
- " super (prefix_cmd2, self).__init__ (\"prefix_cmd2\", gdb.COMMAND_OBSCURE, prefix = True, completer_class = gdb.COMPLETE_FILENAME)" "" \
- " def invoke (self, arg, from_tty):" "" \
- " print \"prefix_cmd2 output, arg = %s\" % arg" "" \
- "prefix_cmd2 ()" "" \
- "end" ""
-
-gdb_test "prefix_cmd2 argh" "prefix_cmd2 output, arg = argh" "call prefix command, keyword arguments"
-
-gdb_py_test_multiple "input subcommand under prefix_cmd2" \
- "python" "" \
- "class subcmd (gdb.Command):" "" \
- " def __init__ (self):" "" \
- " super (subcmd, self).__init__ (\"prefix_cmd2 subcmd\", gdb.COMMAND_OBSCURE)" "" \
- " def invoke (self, arg, from_tty):" "" \
- " print \"subcmd output, arg = %s\" % arg" "" \
- "subcmd ()" "" \
- "end" ""
-
-gdb_test "prefix_cmd2 subcmd ugh" "subcmd output, arg = ugh" "call subcmd under prefix_cmd2"
-
-# Test a subcommand in an existing GDB prefix.
-
-gdb_py_test_multiple "input new subcommand" \
- "python" "" \
- "class newsubcmd (gdb.Command):" "" \
- " def __init__ (self):" "" \
- " super (newsubcmd, self).__init__ (\"info newsubcmd\", gdb.COMMAND_OBSCURE)" "" \
- " def invoke (self, arg, from_tty):" "" \
- " print \"newsubcmd output, arg = %s\" % arg" "" \
- "newsubcmd ()" "" \
- "end" ""
-
-gdb_test "info newsubcmd ugh" "newsubcmd output, arg = ugh" "call newsubcmd"
+++ /dev/null
-int f2 (int a)
-{
- return ++a;
-}
-
-int f1 (int a, int b)
-{
- return f2(a) + b;
-}
-
-int main (int argc, char *argv[])
-{
- return f1 (1, 2);
-}
+++ /dev/null
-# Copyright (C) 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests the mechanism
-# exposing values to Python.
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-set testfile "python-frame"
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
- untested "Couldn't compile ${srcfile}"
- return -1
-}
-
-# Run a command in GDB, and report a failure if a Python exception is thrown.
-# If report_pass is true, report a pass if no exception is thrown.
-proc gdb_py_test_silent_cmd {cmd name report_pass} {
- global gdb_prompt
-
- gdb_test_multiple $cmd $name {
- -re "Traceback.*$gdb_prompt $" { fail $name }
- -re "$gdb_prompt $" { if $report_pass { pass $name } }
- }
-}
-
-# Start with a fresh gdb.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
- -re "not supported.*$gdb_prompt $" {
- unsupported "python support is disabled"
- return -1
- }
- -re "$gdb_prompt $" {}
-}
-
-# The following tests require execution.
-
-if ![runto_main] then {
- fail "Can't run to main"
- return 0
-}
-
-gdb_breakpoint "f2"
-gdb_continue_to_breakpoint "breakpoint at f2"
-gdb_test "up" "" ""
-
-gdb_py_test_silent_cmd "python f1 = gdb.selected_frame ()" "get second frame" 0
-gdb_py_test_silent_cmd "python f0 = f1.newer ()" "get first frame" 0
-
-gdb_test "python print 'result =', f0 == f1" " = False" "test equality comparison (false)"
-gdb_test "python print 'result =', f0 == f0" " = True" "test equality comparison (true)"
-gdb_test "python print 'result =', f0 != f1" " = True" "test inequality comparison (true)"
-gdb_test "python print 'result =', f0 != f0" " = False" "test inequality comparison (false)"
-gdb_test "python print 'result =', f0.is_valid ()" " = True" "test Frame.is_valid"
-gdb_test "python print 'result =', f0.name ()" " = f2" "test Frame.name"
-gdb_test "python print 'result =', f0.type () == gdb.NORMAL_FRAME" " = True" "test Frame.type"
-gdb_test "python print 'result =', f0.unwind_stop_reason () == gdb.FRAME_UNWIND_NO_REASON" " = True" "test Frame.type"
-gdb_test "python print 'result =', gdb.frame_stop_reason_string (gdb.FRAME_UNWIND_INNER_ID)" " = previous frame inner to this frame \\(corrupt stack\\?\\)" "test gdb.frame_stop_reason_string"
-gdb_test "python print 'result =', f0.pc ()" " = \[0-9\]+" "test Frame.pc"
-gdb_test "python print 'result =', f0.older () == f1" " = True" "test Frame.older"
-gdb_test "python print 'result =', f1.newer () == f0" " = True" "test Frame.newer"
-gdb_test "python print 'result =', f0.read_var ('variable_which_surely_doesnt_exist')" \
- "ValueError: variable 'variable_which_surely_doesnt_exist' not found.*Error while executing Python code." \
- "test Frame.read_var - error"
-gdb_test "python print 'result =', f0.read_var ('a')" " = 1" "test Frame.read_var - success"
-
-gdb_test "python print 'result =', gdb.selected_frame () == f1" " = True" "test gdb.selected_frame"
+++ /dev/null
-# Copyright (C) 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests the mechanism
-# exposing convenience functions to Python.
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
-# Run a test named NAME, consisting of multiple lines of input.
-# After each input line INPUT, search for result line RESULT.
-# Succeed if all results are seen; fail otherwise.
-proc gdb_py_test_multiple {name args} {
- global gdb_prompt
- foreach {input result} $args {
- if {[gdb_test_multiple $input "$name - $input" {
- -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
- pass "$name - $input"
- }
- }]} {
- return 1
- }
- }
- return 0
-}
-
-# Start with a fresh gdb.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
- -re "not supported.*$gdb_prompt $" {
- unsupported "python support is disabled"
- return -1
- }
- -re "$gdb_prompt $" {}
-}
-
-gdb_py_test_multiple "input convenience function" \
- "python" "" \
- "class test_func (gdb.Function):" "" \
- " def __init__ (self):" "" \
- " super (test_func, self).__init__ (\"test_func\")" "" \
- " def invoke (self, arg):" "" \
- " return \"test_func output, arg = %s\" % arg.string ()" "" \
- "test_func ()" "" \
- "end" ""
-
-gdb_test "print \$test_func (\"ugh\")" "= \"test_func output, arg = ugh\"" "call function"
-
-# Test returning a gdb.Value from the function. This segfaulted GDB at one point.
-
-gdb_py_test_multiple "input value-returning convenience function" \
- "python" "" \
- "class Double (gdb.Function):" "" \
- " def __init__ (self):" "" \
- " super (Double, self).__init__ (\"double\")" "" \
- " def invoke (self, n):" "" \
- " return n*2" "" \
- "Double ()" "" \
- "end" ""
-
-gdb_test "print \$double (1)" "= 2" "call value-returning function"
+++ /dev/null
-# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests Python-based
-# pretty-printing for MI.
-
-load_lib mi-support.exp
-set MIFLAGS "-i=mi2"
-
-gdb_exit
-if [mi_gdb_start] {
- continue
-}
-
-set testfile "python-prettyprint"
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DMI}] != "" } {
- untested mi2-var-child.exp
- return -1
-}
-
-mi_delete_breakpoints
-mi_gdb_reinitialize_dir $srcdir/$subdir
-mi_gdb_load ${binfile}
-
-if {[lsearch -exact [mi_get_features] python] < 0} {
- unsupported "python support is disabled"
- return -1
-}
-
-mi_runto main
-
-mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
-
-mi_continue_to_line [gdb_get_line_number {MI breakpoint here} ${testfile}.c] \
- "step to breakpoint"
-
-mi_create_floating_varobj container c "create container varobj"
-
-mi_list_varobj_children container {
-} "examine container children=0"
-
-mi_next "next over update 1"
-
-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
-} "varobj update 1"
-
-mi_next "next over update 2"
-
-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
- { {container.\[1\]} {\[1\]} 0 int }
-} "varobj update 2"
-
-mi_gdb_test "-var-set-visualizer container None" \
- "\\^done" \
- "clear visualizer"
-
-mi_gdb_test "-var-update container" \
- "\\^done,changelist=\\\[\\\]" \
- "varobj update after clearing"
-
-mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \
- "\\^done" \
- "choose default visualizer"
-
-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
- { {container.\[1\]} {\[1\]} 0 int }
-} "varobj update after choosing default"
-
-mi_gdb_test "-var-set-visualizer container ContainerPrinter" \
- "\\^done" \
- "choose visualizer using expression"
-
-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
- { {container.\[1\]} {\[1\]} 0 int }
-} "varobj update after choosing via expression"
-
-mi_continue_to_line \
- [gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \
- "step to second breakpoint"
-
-mi_varobj_update_with_type_change container int 0 "update after type change"
+++ /dev/null
-/* This testcase is part of GDB, the GNU debugger.
-
- Copyright 2008, 2009 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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/>. */
-
-struct s
-{
- int a;
- int *b;
-};
-
-struct ss
-{
- struct s a;
- struct s b;
-};
-
-struct ns {
- const char *null_str;
- int length;
-};
-
-#ifdef __cplusplus
-struct S : public s {
- int zs;
-};
-
-struct SS {
- int zss;
- S s;
-};
-
-struct SSS
-{
- SSS (int x, const S& r);
- int a;
- const S &b;
-};
-SSS::SSS (int x, const S& r) : a(x), b(r) { }
-
-class VirtualTest
-{
- private:
- int value;
-
- public:
- VirtualTest ()
- {
- value = 1;
- }
-};
-
-class Vbase1 : public virtual VirtualTest { };
-class Vbase2 : public virtual VirtualTest { };
-class Vbase3 : public virtual VirtualTest { };
-
-class Derived : public Vbase1, public Vbase2, public Vbase3
-{
- private:
- int value;
-
- public:
- Derived ()
- {
- value = 2;
- }
-};
-
-#endif
-
-typedef struct string_repr
-{
- struct whybother
- {
- const char *contents;
- } whybother;
-} string;
-
-/* This lets us avoid malloc. */
-int array[100];
-
-struct container
-{
- string name;
- int len;
- int *elements;
-};
-
-typedef struct container zzz_type;
-
-string
-make_string (const char *s)
-{
- string result;
- result.whybother.contents = s;
- return result;
-}
-
-zzz_type
-make_container (const char *s)
-{
- zzz_type result;
-
- result.name = make_string (s);
- result.len = 0;
- result.elements = 0;
-
- return result;
-}
-
-void
-add_item (zzz_type *c, int val)
-{
- if (c->len == 0)
- c->elements = array;
- c->elements[c->len] = val;
- ++c->len;
-}
-
-void init_s(struct s *s, int a)
-{
- s->a = a;
- s->b = &s->a;
-}
-
-void init_ss(struct ss *s, int a, int b)
-{
- init_s(&s->a, a);
- init_s(&s->b, b);
-}
-
-void do_nothing(void)
-{
- int c;
-
- c = 23; /* Another MI breakpoint */
-}
-
-int
-main ()
-{
- struct ss ss;
- struct ss ssa[2];
- string x = make_string ("this is x");
- zzz_type c = make_container ("container");
- const struct string_repr cstring = { { "const string" } };
-
- init_ss(&ss, 1, 2);
- init_ss(ssa+0, 3, 4);
- init_ss(ssa+1, 5, 6);
-
- struct ns ns;
- ns.null_str = "embedded\0null\0string";
- ns.length = 20;
-
-#ifdef __cplusplus
- S cps;
-
- cps.zs = 7;
- init_s(&cps, 8);
-
- SS cpss;
- cpss.zss = 9;
- init_s(&cpss.s, 10);
-
- SS cpssa[2];
- cpssa[0].zss = 11;
- init_s(&cpssa[0].s, 12);
- cpssa[1].zss = 13;
- init_s(&cpssa[1].s, 14);
-
- SSS sss(15, cps);
-
- SSS& ref (sss);
-
- Derived derived;
-
-#endif
-
- add_item (&c, 23); /* MI breakpoint here */
- add_item (&c, 72);
-
-#ifdef MI
- do_nothing ();
-#endif
-
- return 0; /* break to inspect struct and union */
-}
+++ /dev/null
-# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests Python-based
-# pretty-printing for the CLI.
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-set testfile "python-prettyprint"
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}
-
-# Start with a fresh gdb.
-gdb_exit
-gdb_start
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
- -re "not supported.*$gdb_prompt $" {
- unsupported "python support is disabled"
- return -1
- }
- -re "$gdb_prompt $" {}
-}
-
-proc run_lang_tests {lang} {
- global srcdir subdir srcfile binfile testfile hex
- if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug $lang"] != "" } {
- untested "Couldn't compile ${srcfile} in $lang mode"
- return -1
- }
-
- set nl "\[\r\n\]+"
-
- # Start with a fresh gdb.
- gdb_exit
- gdb_start
- gdb_reinitialize_dir $srcdir/$subdir
- gdb_load ${binfile}
-
-
- if ![runto_main ] then {
- perror "couldn't run to breakpoint"
- return
- }
-
- gdb_test "set print pretty on" ""
-
- gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \
- ".*Breakpoint.*"
- gdb_test "continue" ".*Breakpoint.*"
-
- gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
-
- gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>"
- gdb_test "print ssa\[1\]" " = a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>"
- gdb_test "print ssa" " = {a=< a=<3> b=<$hex>> b=< a=<4> b=<$hex>>, a=< a=<5> b=<$hex>> b=< a=<6> b=<$hex>>}"
-
- if {$lang == "c++"} {
- gdb_test "print cps" "= a=<8> b=<$hex>"
- gdb_test "print cpss" " = {$nl *zss = 9, *$nl *s = a=<10> b=<$hex>$nl}"
- gdb_test "print cpssa\[0\]" " = {$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl}"
- gdb_test "print cpssa\[1\]" " = {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl}"
- gdb_test "print cpssa" " = {{$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl *}, {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl *}}"
- gdb_test "print sss" "= a=<15> b=< a=<8> b=<$hex>>"
- gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
- gdb_test "print derived" \
- " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
- gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
- }
-
- gdb_test "print x" " = $hex \"this is x\""
- gdb_test "print cstring" " = $hex \"const string\""
-
- gdb_test "print c" " = container $hex \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}"
-
- gdb_test "continue" "Program exited normally\."
-}
-
-run_lang_tests "c"
-run_lang_tests "c++"
+++ /dev/null
-# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests python pretty
-# printers.
-
-import re
-
-# Test returning a Value from a printer.
-class string_print:
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return self.val['whybother']['contents']
-
-# Test a class-based printer.
-class ContainerPrinter:
- class _iterator:
- def __init__ (self, pointer, len):
- self.start = pointer
- self.pointer = pointer
- self.end = pointer + len
-
- def __iter__(self):
- return self
-
- def next(self):
- if self.pointer == self.end:
- raise StopIteration
- result = self.pointer
- self.pointer = self.pointer + 1
- return ('[%d]' % int (result - self.start), result.dereference())
-
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return 'container %s with %d elements' % (self.val['name'], self.val['len'])
-
- def children(self):
- return self._iterator(self.val['elements'], self.val['len'])
-
-class pp_s:
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- a = self.val["a"]
- b = self.val["b"]
- if a.address != b:
- raise Exception("&a(%s) != b(%s)" % (str(a.address), str(b)))
- return " a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
-
-class pp_ss:
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return "a=<" + str(self.val["a"]) + "> b=<" + str(self.val["b"]) + ">"
-
-class pp_sss:
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- return "a=<" + str(self.val['a']) + "> b=<" + str(self.val["b"]) + ">"
-
-class pp_multiple_virtual:
- def __init__ (self, val):
- self.val = val
-
- def to_string (self):
- return "pp value variable is: " + str (self.val['value'])
-
-class pp_vbase1:
- def __init__ (self, val):
- self.val = val
-
- def to_string (self):
- return "pp class name: " + self.val.type.tag
-
-class pp_ns:
- "Print a std::basic_string of some kind"
-
- def __init__(self, val):
- self.val = val
-
- def to_string(self):
- len = self.val['length']
- return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len)
-
- def display_hint (self):
- return 'string'
-
-def lookup_function (val):
- "Look-up and return a pretty-printer that can print val."
-
- # Get the type.
- type = val.type;
-
- # If it points to a reference, get the reference.
- if type.code == gdb.TYPE_CODE_REF:
- type = type.target ()
-
- # Get the unqualified type, stripped of typedefs.
- type = type.unqualified ().strip_typedefs ()
-
- # Get the type name.
- typename = type.tag
-
- if typename == None:
- return None
-
- # Iterate over local dictionary of types to determine
- # if a printer is registered for that type. Return an
- # instantiation of the printer if found.
- for function in pretty_printers_dict:
- if function.match (typename):
- return pretty_printers_dict[function] (val)
-
- # Cannot find a pretty printer. Return None.
-
- return None
-
-
-def register_pretty_printers ():
- pretty_printers_dict[re.compile ('^struct s$')] = pp_s
- pretty_printers_dict[re.compile ('^s$')] = pp_s
- pretty_printers_dict[re.compile ('^S$')] = pp_s
-
- pretty_printers_dict[re.compile ('^struct ss$')] = pp_ss
- pretty_printers_dict[re.compile ('^ss$')] = pp_ss
- pretty_printers_dict[re.compile ('^const S &$')] = pp_s
- pretty_printers_dict[re.compile ('^SSS$')] = pp_sss
-
- pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual
- pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1
-
- # Note that we purposely omit the typedef names here.
- # Printer lookup is based on canonical name.
- # However, we do need both tagged and untagged variants, to handle
- # both the C and C++ cases.
- pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print
- pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter
- pretty_printers_dict[re.compile ('^string_repr$')] = string_print
- pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
-
- pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
- pretty_printers_dict[re.compile ('^ns$')] = pp_ns
-pretty_printers_dict = {}
-
-register_pretty_printers ()
-gdb.pretty_printers.append (lookup_function)
+++ /dev/null
-/* This testcase is part of GDB, the GNU debugger.
-
- Copyright 2008 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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/>. */
-
-template <typename T>
-struct Foo {
-};
-
-#ifndef TYPE
-#define TYPE int
-#endif
-
-int main()
-{
- Foo<TYPE> foo;
- return 0; // break here
-}
+++ /dev/null
-# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests the mechanism
-# exposing values to Python.
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-set testfile "python-template"
-set srcfile ${testfile}.cc
-set binfile ${objdir}/${subdir}/${testfile}
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
- {debug c++}] != "" } {
- untested "Couldn't compile ${srcfile}"
- return -1
-}
-
-# Start with a fresh gdb.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-
-gdb_test_multiple "python print 23" "verify python support" {
- -re "not supported.*$gdb_prompt $" {
- unsupported "python support is disabled"
- return -1
- }
- -re "$gdb_prompt $" {}
-}
-
-proc test_template_arg {type} {
- global testfile srcdir subdir srcfile binfile
- if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
- executable \
- [list debug c++ additional_flags="-DTYPE=$type"]] != "" } {
- untested $type
- return -1
- }
- gdb_load ${binfile}
- if ![runto_main ] then {
- perror "couldn't run to breakpoint"
- return
- }
- # There is no executable code in main(), so we are where we want to be
- gdb_test "print foo" ""
- gdb_test "python foo = gdb.history(0)" ""
-
- # Replace '*' with '\*' in regex.
- regsub -all {\*} $type {\*} t
- gdb_test "python print foo.type.template_argument(0)" $t $type
-}
-
-test_template_arg "const int"
-test_template_arg "volatile int"
-test_template_arg "const int &"
-test_template_arg "volatile int &"
-test_template_arg "volatile int * const"
-test_template_arg "volatile int * const *"
-test_template_arg "const int * volatile"
-test_template_arg "const int * volatile * const * volatile *"
+++ /dev/null
-/* This testcase is part of GDB, the GNU debugger.
-
- Copyright 2008, 2009 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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/>. */
-
-struct s
-{
- int a;
- int b;
-};
-
-union u
-{
- int a;
- float b;
-};
-
-enum e
- {
- ONE = 1,
- TWO = 2
- };
-
-typedef struct s *PTR;
-
-enum e evalue = TWO;
-
-int
-main (int argc, char *argv[])
-{
- char *cp = argv[0]; /* Prevent gcc from optimizing argv[] out. */
- struct s s;
- union u u;
- PTR x = &s;
- char st[17] = "divide et impera";
- char nullst[17] = "divide\0et\0impera";
-
- s.a = 3;
- s.b = 5;
- u.a = 7;
-
- return 0; /* break to inspect struct and union */
-}
+++ /dev/null
-# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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/>.
-
-# This file is part of the GDB testsuite. It tests the mechanism
-# exposing values to Python.
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-set testfile "python-value"
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
- untested "Couldn't compile ${srcfile}"
- return -1
-}
-
-# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
-# Run a test named NAME, consisting of multiple lines of input.
-# After each input line INPUT, search for result line RESULT.
-# Succeed if all results are seen; fail otherwise.
-proc gdb_py_test_multiple {name args} {
- global gdb_prompt
- foreach {input result} $args {
- if {[gdb_test_multiple $input "$name - $input" {
- -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
- pass "$name - $input"
- }
- }]} {
- return 1
- }
- }
- return 0
-}
-
-# Run a command in GDB, and report a failure if a Python exception is thrown.
-# If report_pass is true, report a pass if no exception is thrown.
-proc gdb_py_test_silent_cmd {cmd name report_pass} {
- global gdb_prompt
-
- gdb_test_multiple $cmd $name {
- -re "Traceback.*$gdb_prompt $" { fail $name }
- -re "$gdb_prompt $" { if $report_pass { pass $name } }
- }
-}
-
-proc test_value_creation {} {
- global gdb_prompt
-
- gdb_py_test_silent_cmd "python i = gdb.Value (True)" "create boolean value" 1
- gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create integer value" 1
- gdb_py_test_silent_cmd "python i = gdb.Value (5L)" "create long value" 1
- gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create double value" 1
- gdb_py_test_silent_cmd "python a = gdb.Value ('string test')" "create 8-bit string value" 1
- gdb_test "python print a" "\"string test\"" "print 8-bit string"
- gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of 8-bit string"
- gdb_py_test_silent_cmd "python a = gdb.Value (u'unicode test')" "create unicode value" 1
- gdb_test "python print a" "\"unicode test\"" "print Unicode string"
- gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of unicode string"
-
- # Test address attribute is None in a non-addressable value
- gdb_test "python print 'result =', i.address" "= None" "Test address attribute in non-addressable value"
-}
-
-proc test_value_numeric_ops {} {
- global gdb_prompt
-
- gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create first integer value" 0
- gdb_py_test_silent_cmd "python j = gdb.Value (2)" "create second integer value" 0
- gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create first double value" 0
- gdb_py_test_silent_cmd "python g = gdb.Value (2.5)" "create second double value" 0
- gdb_test "python print 'result = ' + str(i+j)" " = 7" "add two integer values"
- gdb_test "python print (i+j).__class__" "<type 'gdb.Value'>" "verify type of integer add result"
-
- gdb_test "python print 'result = ' + str(f+g)" " = 3.75" "add two double values"
- gdb_test "python print 'result = ' + str(i-j)" " = 3" "subtract two integer values"
- gdb_test "python print 'result = ' + str(f-g)" " = -1.25" "subtract two double values"
- gdb_test "python print 'result = ' + str(i*j)" " = 10" "multiply two integer values"
- gdb_test "python print 'result = ' + str(f*g)" " = 3.125" "multiply two double values"
- gdb_test "python print 'result = ' + str(i/j)" " = 2" "divide two integer values"
- gdb_test "python print 'result = ' + str(f/g)" " = 0.5" "divide two double values"
- gdb_test "python print 'result = ' + str(i%j)" " = 1" "take remainder of two integer values"
- # Remainder of float is implemented in Python but not in GDB's value system.
-
- gdb_test "python print 'result = ' + str(i**j)" " = 25" "integer value raised to the power of another integer value"
- gdb_test "python print 'result = ' + str(g**j)" " = 6.25" "double value raised to the power of integer value"
-
- gdb_test "python print 'result = ' + str(-i)" " = -5" "negated integer value"
- gdb_test "python print 'result = ' + str(+i)" " = 5" "positive integer value"
- gdb_test "python print 'result = ' + str(-f)" " = -1.25" "negated double value"
- gdb_test "python print 'result = ' + str(+f)" " = 1.25" "positive double value"
- gdb_test "python print 'result = ' + str(abs(j-i))" " = 3" "absolute of integer value"
- gdb_test "python print 'result = ' + str(abs(f-g))" " = 1.25" "absolute of double value"
-
- # Test gdb.Value mixed with Python types.
-
- gdb_test "python print 'result = ' + str(i-1)" " = 4" "subtract integer value from python integer"
- gdb_test "python print (i-1).__class__" "<type 'gdb.Value'>" "verify type of mixed integer subtraction result"
- gdb_test "python print 'result = ' + str(f+1.5)" " = 2.75" "add double value with python float"
-
- gdb_test "python print 'result = ' + str(1-i)" " = -4" "subtract python integer from integer value"
- gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value"
-
- # Conversion test.
- gdb_test "print evalue" " = TWO"
- gdb_test "python evalue = gdb.history (0)" ""
- gdb_test "python print int (evalue)" "2"
-
- # Test pointer arithmethic
-
- # First, obtain the pointers
- gdb_test "print (void *) 2" "" ""
- gdb_test "python a = gdb.history (0)" "" ""
- gdb_test "print (void *) 5" "" ""
- gdb_test "python b = gdb.history (0)" "" ""
-
- gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer"
- gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value"
- gdb_test "python print 'result = ' + str(b-a)" " = 3" "subtract two pointer values"
-
- # Test some invalid operations.
-
- gdb_test_multiple "python print 'result = ' + str(i+'foo')" "catch error in python type conversion" {
- -re "Argument to arithmetic operation not a number or boolean.*$gdb_prompt $" {pass "catch error in python type conversion"}
- -re "result = .*$gdb_prompt $" {fail "catch error in python type conversion"}
- -re "$gdb_prompt $" {fail "catch error in python type conversion"}
- }
-
- gdb_test_multiple "python print 'result = ' + str(i+gdb.Value('foo'))" "catch throw of GDB error" {
- -re "Traceback.*$gdb_prompt $" {pass "catch throw of GDB error"}
- -re "result = .*$gdb_prompt $" {fail "catch throw of GDB error"}
- -re "$gdb_prompt $" {fail "catch throw of GDB error"}
- }
-}
-
-proc test_value_boolean {} {
- # First, define a useful function to test booleans.
- gdb_py_test_multiple "define function to test booleans" \
- "python" "" \
- "def test_bool (val):" "" \
- " if val:" "" \
- " print 'yay'" "" \
- " else:" "" \
- " print 'nay'" "" \
- "end" ""
-
- gdb_test "py test_bool (gdb.Value (True))" "yay" "check evaluation of true boolean value in expression"
-
- gdb_test "py test_bool (gdb.Value (False))" "nay" "check evaluation of false boolean value in expression"
-
- gdb_test "py test_bool (gdb.Value (5))" "yay" "check evaluation of true integer value in expression"
-
- gdb_test "py test_bool (gdb.Value (0))" "nay" "check evaluation of false integer value in expression"
-
- gdb_test "py test_bool (gdb.Value (5.2))" "yay" "check evaluation of true integer value in expression"
-
- gdb_test "py test_bool (gdb.Value (0.0))" "nay" "check evaluation of false integer value in expression"
-}
-
-proc test_value_compare {} {
- gdb_test "py print gdb.Value (1) < gdb.Value (1)" "False" "less than, equal"
- gdb_test "py print gdb.Value (1) < gdb.Value (2)" "True" "less than, less"
- gdb_test "py print gdb.Value (2) < gdb.Value (1)" "False" "less than, greater"
- gdb_test "py print gdb.Value (2) < None" "False" "less than, None"
-
- gdb_test "py print gdb.Value (1) <= gdb.Value (1)" "True" "less or equal, equal"
- gdb_test "py print gdb.Value (1) <= gdb.Value (2)" "True" "less or equal, less"
- gdb_test "py print gdb.Value (2) <= gdb.Value (1)" "False" "less or equal, greater"
- gdb_test "py print gdb.Value (2) <= None" "False" "less or equal, None"
-
- gdb_test "py print gdb.Value (1) == gdb.Value (1)" "True" "equality of gdb.Values"
- gdb_test "py print gdb.Value (1) == gdb.Value (2)" "False" "inequality of gdb.Values"
- gdb_test "py print gdb.Value (1) == 1.0" "True" "equality of gdb.Value with Python value"
- gdb_test "py print gdb.Value (1) == 2" "False" "inequality of gdb.Value with Python value"
- gdb_test "py print gdb.Value (1) == None" "False" "inequality of gdb.Value with None"
-
- gdb_test "py print gdb.Value (1) != gdb.Value (1)" "False" "inequality, false"
- gdb_test "py print gdb.Value (1) != gdb.Value (2)" "True" "inequality, true"
- gdb_test "py print gdb.Value (1) != None" "True" "inequality, None"
-
- gdb_test "py print gdb.Value (1) > gdb.Value (1)" "False" "greater than, equal"
- gdb_test "py print gdb.Value (1) > gdb.Value (2)" "False" "greater than, less"
- gdb_test "py print gdb.Value (2) > gdb.Value (1)" "True" "greater than, greater"
- gdb_test "py print gdb.Value (2) > None" "True" "greater than, None"
-
- gdb_test "py print gdb.Value (1) >= gdb.Value (1)" "True" "greater or equal, equal"
- gdb_test "py print gdb.Value (1) >= gdb.Value (2)" "False" "greater or equal, less"
- gdb_test "py print gdb.Value (2) >= gdb.Value (1)" "True" "greater or equal, greater"
- gdb_test "py print gdb.Value (2) >= None" "True" "greater or equal, None"
-}
-
-proc test_value_in_inferior {} {
- global gdb_prompt
- global testfile
-
- gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"]
-
- gdb_continue_to_breakpoint "break to inspect struct and union"
-
- # Just get inferior variable s in the value history, available to python.
- gdb_test "print s" " = {a = 3, b = 5}" ""
-
- gdb_py_test_silent_cmd "python s = gdb.history (0)" "get value from history" 1
-
- gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name"
- gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name"
-
- # Test dereferencing the argv pointer
-
- # Just get inferior variable argv the value history, available to python.
- gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" ""
-
- gdb_py_test_silent_cmd "python argv = gdb.history (0)" "" 0
- gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1
-
- # Check that the dereferenced value is sane
- gdb_test "python print arg0" "0x.*$testfile\"" "verify dereferenced value"
-
- # Smoke-test is_optimized_out attribute
- gdb_test "python print 'result =', arg0.is_optimized_out" "= False" "Test is_optimized_out attribute"
-
- # Test address attribute
- gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
-
- # Test string fetches, both partial and whole.
- gdb_test "print st" "\"divide et impera\""
- gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value from history" 1
- gdb_test "python print st.string ()" "divide et impera" "Test string with no length"
- gdb_test "python print st.string (length = -1)" "divide et impera" "Test string (length = -1) is all of the string"
- gdb_test "python print st.string (length = 6)" "divide"
- gdb_test "python print \"---\"+st.string (length = 0)+\"---\"" "------" "Test string (length = 0) is empty"
- gdb_test "python print len(st.string (length = 0))" "0" "Test length is 0"
-
-
- # Fetch a string that has embedded nulls.
- gdb_test "print nullst" "\"divide\\\\000et\\\\000impera\".*"
- gdb_py_test_silent_cmd "python nullst = gdb.history (0)" "get value from history" 1
- gdb_test "python print nullst.string ()" "divide" "Test string to first null"
- # Python cannot print strings that contain the null (\0) character.
- # For the purposes of this test, use repr()
- gdb_py_test_silent_cmd "python nullst = nullst.string (length = 9)" "get string beyond null" 1
- gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
-}
-
-# A few objfile tests.
-proc test_objfiles {} {
- gdb_test "python\nok=False\nfor file in gdb.objfiles():\n if 'python-value' in file.filename:\n ok=True\nprint ok\nend" "True"
-
- gdb_test "python print gdb.objfiles()\[0\].pretty_printers" "\\\[\\\]"
-
- gdb_test "python gdb.objfiles()\[0\].pretty_printers = 0" \
- "pretty_printers attribute must be a list.*Error while executing Python code."
-}
-
-proc test_value_after_death {} {
- # Construct a type while the inferior is still running.
- gdb_py_test_silent_cmd "python ptrtype = gdb.lookup_type('PTR')" \
- "create PTR type" 1
-
- # Kill the inferior and remove the symbols.
- gdb_test "kill" "" "kill the inferior" \
- "Kill the program being debugged. .y or n. $" \
- "y"
- gdb_test "file" "" "Discard the symbols" \
- "Discard symbol table from.*y or n. $" \
- "y"
-
- # Now create a value using that type. Relies on arg0, created by
- # test_value_in_inferior.
- gdb_py_test_silent_cmd "python castval = arg0.cast(ptrtype.pointer())" \
- "cast arg0 to PTR" 1
-
- # Make sure the type is deleted.
- gdb_py_test_silent_cmd "python ptrtype = None" \
- "delete PTR type" 1
-
- # Now see if the value's type is still valid.
- gdb_test "python print castval.type" "PTR ." \
- "print value's type"
-}
-
-# Start with a fresh gdb.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
- -re "not supported.*$gdb_prompt $" {
- unsupported "python support is disabled"
- return -1
- }
- -re "$gdb_prompt $" {}
-}
-
-test_value_creation
-test_value_numeric_ops
-test_value_boolean
-test_value_compare
-test_objfiles
-
-# The following tests require execution.
-
-if ![runto_main] then {
- fail "Can't run to main"
- return 0
-}
-
-test_value_in_inferior
-test_value_after_death