X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fpython%2Fpy-cmd.c;h=62032115b0c7963d0b190b15c220b5a2fa662754;hb=a121b7c1ac76833018f4fc3adaeddc3147272dd0;hp=f9a4130f26db37730f4154d8f2ff856d48aeba84;hpb=d59b6f6c38a3e9c229dae40bd6c668be47fe8e48;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c index f9a4130f26..62032115b0 100644 --- a/gdb/python/py-cmd.c +++ b/gdb/python/py-cmd.c @@ -1,6 +1,6 @@ /* gdb commands implemented in Python - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -21,30 +21,31 @@ #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" +#include "py-ref.h" /* Struct representing built-in completion types. */ struct cmdpy_completer { /* Python symbol name. */ - char *name; + const char *name; /* Completion function. */ - char **(*completer) (struct cmd_list_element *, char *, char *); + completer_ftype *completer; }; -static struct cmdpy_completer completers[] = +static const 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 }, + { "COMPLETE_EXPRESSION", expression_completer }, }; #define N_COMPLETERS (sizeof (completers) / sizeof (completers[0])) @@ -68,8 +69,8 @@ struct cmdpy_object typedef struct cmdpy_object cmdpy_object; -static PyTypeObject cmdpy_object_type; - +extern PyTypeObject cmdpy_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("cmdpy_object"); /* Constants used by this module. */ static PyObject *invoke_cst; @@ -88,37 +89,33 @@ 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) { - cmdpy_object *cmd; - struct cleanup *cleanup; - - cleanup = ensure_python_env (get_current_arch (), current_language); + gdbpy_enter enter_py (get_current_arch (), current_language); /* Release our hold on the command object. */ - cmd = (cmdpy_object *) context; + gdbpy_ref 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); + xfree ((char *) self->name); + xfree ((char *) self->doc); + xfree ((char *) self->prefixname); } /* Called by gdb to invoke the command. */ + static void -cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) +cmdpy_function (struct cmd_list_element *command, + char *args_entry, int from_tty) { + const char *args = args_entry; 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); + gdbpy_enter enter_py (get_current_arch (), current_language); if (! obj) error (_("Invalid invocation of Python command object.")); @@ -127,7 +124,6 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) if (obj->command->prefixname) { /* A prefix command does not need an invoke method. */ - do_cleanups (cleanup); return; } error (_("Python command object missing 'invoke' method.")); @@ -135,152 +131,279 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) 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) + gdbpy_ref<> argobj (PyUnicode_Decode (args, strlen (args), host_charset (), + NULL)); + if (argobj == NULL) + { + gdbpy_print_stack (); + error (_("Could not convert arguments to Python string.")); + } + + gdbpy_ref<> ttyobj (from_tty ? Py_True : Py_False); + Py_INCREF (ttyobj.get ()); + gdbpy_ref<> result (PyObject_CallMethodObjArgs ((PyObject *) obj, invoke_cst, + argobj.get (), ttyobj.get (), + NULL)); + + if (result == NULL) { PyObject *ptype, *pvalue, *ptraceback; PyErr_Fetch (&ptype, &pvalue, &ptraceback); - if (pvalue && PyString_Check (pvalue)) + /* 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. */ + + gdb::unique_xmalloc_ptr + msg (gdbpy_exception_to_string (ptype, pvalue)); + + if (msg == NULL) { - /* Make a temporary copy of the string data. */ - char *s = PyString_AsString (pvalue); - char *copy = alloca (strlen (s) + 1); + /* 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 (); + } + + /* Don't print the stack for gdb.GdbError exceptions. + It is generally used to flag user errors. - strcpy (copy, s); + 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: %s"), copy); + if (msg != NULL && *msg != '\0') + error (_("Error occurred in Python command: %s"), msg.get ()); + else + error (_("Error occurred in Python command.")); } else { - PyErr_Restore (ptype, pvalue, ptraceback); - gdbpy_print_stack (); - error (_("Error occurred in Python command.")); + Py_XDECREF (ptype); + Py_XDECREF (pvalue); + Py_XDECREF (ptraceback); + error ("%s", msg.get ()); } } - 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) +/* Helper function for the Python command completers (both "pure" + completer and brkchar handler). This function takes COMMAND, TEXT + and WORD and tries to call the Python method for completion with + these arguments. + + This function is usually called twice: once when we are figuring out + the break characters to be used, and another to perform the real + completion itself. The reason for this two step dance is that we + need to know the set of "brkchars" to use early on, before we + actually try to perform the completion. But if a Python command + supplies a "complete" method then we have to call that method + first: it may return as its result the kind of completion to + perform and that will in turn specify which brkchars to use. IOW, + we need the result of the "complete" method before we actually + perform the completion. The only situation when this function is + not called twice is when the user uses the "complete" command: in + this scenario, there is no call to determine the "brkchars". + + Ideally, it would be nice to cache the result of the first call (to + determine the "brkchars") and return this value directly in the + second call (to perform the actual completion). However, due to + the peculiarity of the "complete" command mentioned above, it is + possible to put GDB in a bad state if you perform a TAB-completion + and then a "complete"-completion sequentially. Therefore, we just + recalculate everything twice for TAB-completions. + + This function returns the PyObject representing the Python method + call. */ + +static PyObject * +cmdpy_completer_helper (struct cmd_list_element *command, + const char *text, const 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) + if (obj == NULL) error (_("Invalid invocation of Python command object.")); - if (! PyObject_HasAttr ((PyObject *) obj, complete_cst)) + 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; + /* If there is no complete method, don't error. */ + return NULL; } - textobj = PyUnicode_Decode (text, strlen (text), host_charset (), NULL); - if (! textobj) + gdbpy_ref<> textobj (PyUnicode_Decode (text, strlen (text), host_charset (), + NULL)); + if (textobj == NULL) error (_("Could not convert argument to Python string.")); - wordobj = PyUnicode_Decode (word, strlen (word), host_charset (), NULL); - if (! wordobj) + gdbpy_ref<> wordobj (PyUnicode_Decode (word, strlen (word), host_charset (), + NULL)); + if (wordobj == NULL) 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) + gdbpy_ref<> resultobj (PyObject_CallMethodObjArgs ((PyObject *) obj, + complete_cst, + textobj.get (), + wordobj.get (), NULL)); + if (resultobj == NULL) { /* Just swallow errors here. */ PyErr_Clear (); - goto done; } - make_cleanup_py_decref (resultobj); + + return resultobj.release (); +} + +/* Python function called to determine the break characters of a + certain completer. We are only interested in knowing if the + completer registered by the user will return one of the integer + codes (see COMPLETER_* symbols). */ + +static void +cmdpy_completer_handle_brkchars (struct cmd_list_element *command, + const char *text, const char *word) +{ + gdbpy_enter enter_py (get_current_arch (), current_language); + + /* Calling our helper to obtain the PyObject of the Python + function. */ + gdbpy_ref<> resultobj (cmdpy_completer_helper (command, text, word)); + + /* Check if there was an error. */ + if (resultobj == NULL) + return; + + if (PyInt_Check (resultobj.get ())) + { + /* User code may also return one of the completion constants, + thus requesting that sort of completion. We are only + interested in this kind of return. */ + long value; + + if (!gdb_py_int_as_long (resultobj.get (), &value)) + { + /* Ignore. */ + PyErr_Clear (); + } + else if (value >= 0 && value < (long) N_COMPLETERS) + { + /* This is the core of this function. Depending on which + completer type the Python function returns, we have to + adjust the break characters accordingly. */ + set_gdb_completion_word_break_characters + (completers[value].completer); + } + } +} + +/* Called by gdb for command completion. */ + +static VEC (char_ptr) * +cmdpy_completer (struct cmd_list_element *command, + const char *text, const char *word) +{ + VEC (char_ptr) *result = NULL; + + gdbpy_enter enter_py (get_current_arch (), current_language); + + /* Calling our helper to obtain the PyObject of the Python + function. */ + gdbpy_ref<> resultobj (cmdpy_completer_helper (command, text, word)); + + /* If the result object of calling the Python function is NULL, it + means that there was an error. In this case, just give up and + return NULL. */ + if (resultobj == NULL) + return NULL; result = NULL; - if (PySequence_Check (resultobj)) + if (PyInt_Check (resultobj.get ())) { - Py_ssize_t i, len = PySequence_Size (resultobj); - Py_ssize_t out; + /* User code may also return one of the completion constants, + thus requesting that sort of completion. */ + long value; - if (len < 0) - goto done; + if (! gdb_py_int_as_long (resultobj.get (), &value)) + { + /* Ignore. */ + PyErr_Clear (); + } + else if (value >= 0 && value < (long) N_COMPLETERS) + result = completers[value].completer (command, text, word); + } + else + { + gdbpy_ref<> iter (PyObject_GetIter (resultobj.get ())); + + if (iter == NULL) + return NULL; - result = (char **) xmalloc ((len + 1) * sizeof (char *)); - for (i = out = 0; i < len; ++i) + while (true) { - PyObject *elt = PySequence_GetItem (resultobj, i); + gdbpy_ref<> elt (PyIter_Next (iter.get ())); + if (elt == NULL) + break; - if (elt == NULL || ! gdbpy_is_string (elt)) + if (! gdbpy_is_string (elt.get ())) + { + /* Skip problem elements. */ + continue; + } + gdb::unique_xmalloc_ptr + item (python_string_to_host_string (elt.get ())); + if (item == NULL) { /* Skip problem elements. */ PyErr_Clear (); continue; } - result[out] = python_string_to_host_string (elt); - ++out; + VEC_safe_push (char_ptr, result, item.release ()); } - 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); + /* If we got some results, ignore problems. Otherwise, report + the problem. */ + if (result != NULL && PyErr_Occurred ()) + PyErr_Clear (); } - 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 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. - + START_LIST is the list in which the search starts. This function returns the xmalloc()d name of the new command. On error sets the Python error and returns NULL. */ + char * -gdbpy_parse_command_name (char *text, +gdbpy_parse_command_name (const char *name, struct cmd_list_element ***base_list, struct cmd_list_element **start_list) { struct cmd_list_element *elt; - int len = strlen (text); + int len = strlen (name); int i, lastchar; char *prefix_text; + const char *prefix_text2; char *result; /* Skip trailing whitespace. */ - for (i = len - 1; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i) ; if (i < 0) { @@ -290,17 +413,17 @@ gdbpy_parse_command_name (char *text, lastchar = i; /* Find first character of the final word. */ - for (; i > 0 && (isalnum (text[i - 1]) - || text[i - 1] == '-' - || text[i - 1] == '_'); + for (; i > 0 && (isalnum (name[i - 1]) + || name[i - 1] == '-' + || name[i - 1] == '_'); --i) ; - result = xmalloc (lastchar - i + 2); - memcpy (result, &text[i], lastchar - i + 1); + result = (char *) xmalloc (lastchar - i + 2); + memcpy (result, &name[i], lastchar - i + 1); result[lastchar - i + 1] = '\0'; /* Skip whitespace again. */ - for (--i; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + for (--i; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i) ; if (i < 0) { @@ -308,13 +431,13 @@ gdbpy_parse_command_name (char *text, return result; } - prefix_text = xmalloc (i + 2); - memcpy (prefix_text, text, i + 1); + prefix_text = (char *) xmalloc (i + 2); + memcpy (prefix_text, name, i + 1); prefix_text[i + 1] = '\0'; - text = prefix_text; - elt = lookup_cmd_1 (&text, *start_list, NULL, 1); - if (!elt || elt == (struct cmd_list_element *) -1) + prefix_text2 = prefix_text; + elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, 1); + if (elt == NULL || elt == CMD_LIST_AMBIGUOUS) { PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."), prefix_text); @@ -355,22 +478,20 @@ gdbpy_parse_command_name (char *text, 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. - -*/ + the python class. */ + static int cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) { cmdpy_object *obj = (cmdpy_object *) self; - char *name; + const 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 }; + static const char *keywords[] = { "name", "command_class", "completer_class", + "prefix", NULL }; PyObject *is_prefix = NULL; int cmp; @@ -383,8 +504,9 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) return -1; } - if (! PyArg_ParseTupleAndKeywords (args, kw, "si|iO", keywords, &name, &cmdtype, - &completetype, &is_prefix)) + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "si|iO", + keywords, &name, &cmdtype, + &completetype, &is_prefix)) return -1; if (cmdtype != no_class && cmdtype != class_run @@ -392,7 +514,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) && cmdtype != class_files && cmdtype != class_support && cmdtype != class_info && cmdtype != class_breakpoint && cmdtype != class_trace && cmdtype != class_obscure - && cmdtype != class_maintenance) + && cmdtype != class_maintenance && cmdtype != class_user) { PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument.")); return -1; @@ -400,7 +522,8 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) if (completetype < -1 || completetype >= (int) N_COMPLETERS) { - PyErr_Format (PyExc_RuntimeError, _("Invalid completion type argument.")); + PyErr_Format (PyExc_RuntimeError, + _("Invalid completion type argument.")); return -1; } @@ -409,16 +532,16 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) return -1; pfx_name = NULL; - if (is_prefix != 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); - + pfx_name = (char *) xmalloc (strlen (name) + 2); + i = 0; out = 0; while (name[i]) @@ -436,21 +559,32 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) pfx_name[out] = '\0'; } else if (cmp < 0) + { + xfree (cmd_name); return -1; + } } if (PyObject_HasAttr (self, gdbpy_doc_cst)) { - PyObject *ds_obj = PyObject_GetAttr (self, gdbpy_doc_cst); + gdbpy_ref<> 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 (ds_obj != NULL && gdbpy_is_string (ds_obj.get ())) + { + docstring = python_string_to_host_string (ds_obj.get ()).release (); + if (docstring == NULL) + { + xfree (cmd_name); + xfree (pfx_name); + return -1; + } + } } if (! docstring) docstring = xstrdup (_("This command is not documented.")); Py_INCREF (self); - TRY_CATCH (except, RETURN_MASK_ALL) + TRY { struct cmd_list_element *cmd; @@ -477,8 +611,11 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) set_cmd_context (cmd, self); set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer : completers[completetype].completer)); + if (completetype == -1) + set_cmd_completer_handle_brkchars (cmd, + cmdpy_completer_handle_brkchars); } - if (except.reason < 0) + CATCH (except, RETURN_MASK_ALL) { xfree (cmd_name); xfree (docstring); @@ -489,22 +626,26 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) "%s", except.message); return -1; } + END_CATCH + return 0; } /* Initialize the 'commands' code. */ -void + +int gdbpy_initialize_commands (void) { int i; + cmdpy_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&cmdpy_object_type) < 0) - return; + return -1; /* Note: alias and user are special; pseudo appears to be unused, - and there is no reason to expose tui or xdb, I think. */ + and there is no reason to expose tui, 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 @@ -520,21 +661,28 @@ gdbpy_initialize_commands (void) || PyModule_AddIntConstant (gdb_module, "COMMAND_OBSCURE", class_obscure) < 0 || PyModule_AddIntConstant (gdb_module, "COMMAND_MAINTENANCE", - class_maintenance) < 0) - return; + class_maintenance) < 0 + || PyModule_AddIntConstant (gdb_module, "COMMAND_USER", class_user) < 0) + return -1; for (i = 0; i < N_COMPLETERS; ++i) { if (PyModule_AddIntConstant (gdb_module, completers[i].name, i) < 0) - return; + return -1; } - Py_INCREF (&cmdpy_object_type); - PyModule_AddObject (gdb_module, "Command", - (PyObject *) &cmdpy_object_type); + if (gdb_pymodule_addobject (gdb_module, "Command", + (PyObject *) &cmdpy_object_type) < 0) + return -1; invoke_cst = PyString_FromString ("invoke"); + if (invoke_cst == NULL) + return -1; complete_cst = PyString_FromString ("complete"); + if (complete_cst == NULL) + return -1; + + return 0; } @@ -547,10 +695,9 @@ static PyMethodDef cmdpy_object_methods[] = { 0 } }; -static PyTypeObject cmdpy_object_type = +PyTypeObject cmdpy_object_type = { - PyObject_HEAD_INIT (NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT (NULL, 0) "gdb.Command", /*tp_name*/ sizeof (cmdpy_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -587,5 +734,52 @@ static PyTypeObject cmdpy_object_type = 0, /* tp_dictoffset */ cmdpy_init, /* tp_init */ 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) +{ + const char *input; + + if (!PyArg_ParseTuple (args, "s", &input)) + return NULL; + + gdbpy_ref<> py_argv (PyList_New (0)); + if (py_argv == NULL) + return NULL; + + /* 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) + { + gdbpy_ref<> argp (PyString_FromString (c_argv[i])); + + if (argp == NULL + || PyList_Append (py_argv.get (), argp.get ()) < 0) + { + freeargv (c_argv); + return NULL; + } + } + + freeargv (c_argv); + } + + return py_argv.release (); +}