diff options
Diffstat (limited to 'gdb/python/py-cmd.c')
-rw-r--r-- | gdb/python/py-cmd.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c index f9a4130..2cff4ba 100644 --- a/gdb/python/py-cmd.c +++ b/gdb/python/py-cmd.c @@ -88,6 +88,7 @@ cmdpy_dont_repeat (PyObject *self, PyObject *args) /* Called if the gdb cmd_list_element is destroyed. */ + static void cmdpy_destroyer (struct cmd_list_element *self, void *context) { @@ -111,6 +112,7 @@ cmdpy_destroyer (struct cmd_list_element *self, void *context) } /* Called by gdb to invoke the command. */ + static void cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) { @@ -145,30 +147,51 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) ttyobj, NULL); Py_DECREF (argobj); Py_DECREF (ttyobj); + if (! result) { PyObject *ptype, *pvalue, *ptraceback; + char *msg; 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); + /* Try to fetch an error message contained within ptype, pvalue. + When fetching the error message we need to make our own copy, + we no longer own ptype, pvalue after the call to PyErr_Restore. */ - strcpy (copy, s); - PyErr_Restore (ptype, pvalue, ptraceback); + msg = gdbpy_exception_to_string (ptype, pvalue); + make_cleanup (xfree, msg); + + if (msg == NULL) + { + /* An error occurred computing the string representation of the + error message. This is rare, but we should inform the user. */ + printf_filtered (_("An error occurred in a Python command\n" + "and then another occurred computing the error message.\n")); gdbpy_print_stack (); - error (_("Error occurred in Python command: %s"), copy); } - else + + /* Don't print the stack for gdb.GdbError exceptions. + It is generally used to flag user errors. + + We also don't want to print "Error occurred in Python command" + for user errors. However, a missing message for gdb.GdbError + exceptions is arguably a bug, so we flag it as such. */ + + if (! PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc) + || msg == NULL || *msg == '\0') { PyErr_Restore (ptype, pvalue, ptraceback); gdbpy_print_stack (); - error (_("Error occurred in Python command.")); + if (msg != NULL && *msg != '\0') + error (_("Error occurred in Python command: %s"), msg); + else + error (_("Error occurred in Python command.")); } + else + error ("%s", msg); } + Py_DECREF (result); do_cleanups (cleanup); } @@ -589,3 +612,55 @@ static PyTypeObject cmdpy_object_type = 0, /* tp_alloc */ PyType_GenericNew /* tp_new */ }; + + + +/* Utility to build a buildargv-like result from ARGS. + This intentionally parses arguments the way libiberty/argv.c:buildargv + does. It splits up arguments in a reasonable way, and we want a standard + way of parsing arguments. Several gdb commands use buildargv to parse their + arguments. Plus we want to be able to write compatible python + implementations of gdb commands. */ + +PyObject * +gdbpy_string_to_argv (PyObject *self, PyObject *args) +{ + PyObject *py_argv; + char *input; + + if (!PyArg_ParseTuple (args, "s", &input)) + return NULL; + + py_argv = PyList_New (0); + + /* buildargv uses NULL to represent an empty argument list, but we can't use + that in Python. Instead, if ARGS is "" then return an empty list. + This undoes the NULL -> "" conversion that cmdpy_function does. */ + + if (*input != '\0') + { + char **c_argv = gdb_buildargv (input); + int i; + + for (i = 0; c_argv[i] != NULL; ++i) + { + PyObject *argp = PyString_FromString (c_argv[i]); + + if (argp == NULL + || PyList_Append (py_argv, argp) < 0) + { + if (argp != NULL) + { + Py_DECREF (argp); + } + Py_DECREF (py_argv); + freeargv (c_argv); + return NULL; + } + } + + freeargv (c_argv); + } + + return py_argv; +} |