X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fpython%2Fpy-cmd.c;h=a5e96d645ad7dfb25d502fb19359e15469ca2a67;hb=e36122e9;hp=aad1ab466cdc3cf7e0f29b6295be14b5c0ba7fc1;hpb=0b30217134add051e159a192066a1e568ebd837f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c index aad1ab466c..a5e96d645a 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-2012 Free Software Foundation, Inc. + Copyright (C) 2008-2015 Free Software Foundation, Inc. This file is part of GDB. @@ -21,7 +21,6 @@ #include "defs.h" #include "arch-utils.h" #include "value.h" -#include "exceptions.h" #include "python-internal.h" #include "charset.h" #include "gdbcmd.h" @@ -32,19 +31,22 @@ /* Struct representing built-in completion types. */ struct cmdpy_completer { - /* Python symbol name. */ + /* Python symbol name. + This isn't a const char * for Python 2.4's sake. + PyModule_AddIntConstant only takes a char *, sigh. */ 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,7 +70,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; @@ -103,9 +106,9 @@ cmdpy_destroyer (struct cmd_list_element *self, void *context) /* We allocated the name, doc string, and perhaps the prefix name. */ - xfree (self->name); - xfree (self->doc); - xfree (self->prefixname); + xfree ((char *) self->name); + xfree ((char *) self->doc); + xfree ((char *) self->prefixname); do_cleanups (cleanup); } @@ -204,90 +207,214 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) do_cleanups (cleanup); } -/* Called by gdb for command completion. */ +/* 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. It also takes HANDLE_BRKCHARS_P, an argument to + identify whether it is being called from the brkchar handler or + from the "pure" completer. In the first case, it effectively calls + the Python method for completion, and records the PyObject in a + static variable (used as a "cache"). In the second case, it just + returns that variable, without actually calling the Python method + again. This saves us one Python method call. + + 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. + + It is important to mention that this function is built on the + assumption that the calls to cmdpy_completer_handle_brkchars and + cmdpy_completer will be subsequent with nothing intervening. This + is true for our completer mechanism. + + This function returns the PyObject representing the Python method + call. */ -static char ** -cmdpy_completer (struct cmd_list_element *command, char *text, char *word) +static PyObject * +cmdpy_completer_helper (struct cmd_list_element *command, + const char *text, const char *word, + int handle_brkchars_p) { cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command); - PyObject *textobj, *wordobj, *resultobj = NULL; - char **result = NULL; + PyObject *textobj, *wordobj; + /* This static variable will server as a "cache" for us, in order to + store the PyObject that results from calling the Python + function. */ + static PyObject *resultobj = NULL; + + if (handle_brkchars_p) + { + /* If we were called to handle brkchars, it means this is the + first function call of two that will happen in a row. + Therefore, we need to call the completer ourselves, and cache + the return value in the static variable RESULTOBJ. Then, in + the second call, we can just use the value of RESULTOBJ to do + our job. */ + if (resultobj != NULL) + Py_DECREF (resultobj); + + resultobj = NULL; + if (obj == NULL) + error (_("Invalid invocation of Python command object.")); + if (!PyObject_HasAttr ((PyObject *) obj, complete_cst)) + { + /* If there is no complete method, don't error. */ + return NULL; + } + + textobj = PyUnicode_Decode (text, strlen (text), host_charset (), NULL); + if (textobj == NULL) + error (_("Could not convert argument to Python string.")); + wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL); + if (wordobj == NULL) + { + Py_DECREF (textobj); + 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 (); + } + + Py_XINCREF (resultobj); + } + + return resultobj; +} + +/* 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) +{ + PyObject *resultobj = 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; - } + /* Calling our helper to obtain the PyObject of the Python + function. */ + resultobj = cmdpy_completer_helper (command, text, word, 1); - 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) + /* Check if there was an error. */ + if (resultobj == NULL) + goto done; + + if (PyInt_Check (resultobj)) { - /* Just swallow errors here. */ - PyErr_Clear (); - goto done; + /* 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, &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); + } } - make_cleanup_py_decref (resultobj); + + done: + + /* We do not call Py_XDECREF here because RESULTOBJ will be used in + the subsequent call to cmdpy_completer function. */ + do_cleanups (cleanup); +} + +/* Called by gdb for command completion. */ + +static VEC (char_ptr) * +cmdpy_completer (struct cmd_list_element *command, + const char *text, const char *word) +{ + PyObject *resultobj = NULL; + VEC (char_ptr) *result = NULL; + struct cleanup *cleanup; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + /* Calling our helper to obtain the PyObject of the Python + function. */ + resultobj = cmdpy_completer_helper (command, text, word, 0); + + /* 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) + goto done; result = NULL; - if (PySequence_Check (resultobj)) + if (PyInt_Check (resultobj)) + { + /* User code may also return one of the completion constants, + thus requesting that sort of completion. */ + long value; + + if (! gdb_py_int_as_long (resultobj, &value)) + { + /* Ignore. */ + PyErr_Clear (); + } + else if (value >= 0 && value < (long) N_COMPLETERS) + result = completers[value].completer (command, text, word); + } + else { - Py_ssize_t i, len = PySequence_Size (resultobj); - Py_ssize_t out; + PyObject *iter = PyObject_GetIter (resultobj); + PyObject *elt; - if (len < 0) + if (iter == NULL) goto done; - result = (char **) xmalloc ((len + 1) * sizeof (char *)); - for (i = out = 0; i < len; ++i) + while ((elt = PyIter_Next (iter)) != NULL) { - PyObject *elt = PySequence_GetItem (resultobj, i); + char *item; - if (elt == NULL || ! gdbpy_is_string (elt)) + if (! gdbpy_is_string (elt)) { /* Skip problem elements. */ - PyErr_Clear (); + Py_DECREF (elt); continue; } - result[out] = python_string_to_host_string (elt); - if (result[out] == NULL) + item = python_string_to_host_string (elt); + Py_DECREF (elt); + if (item == NULL) { /* Skip problem elements. */ PyErr_Clear (); continue; } - ++out; + VEC_safe_push (char_ptr, result, item); } - 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; - if (! gdb_py_int_as_long (resultobj, &value)) - { - /* Ignore. */ - PyErr_Clear (); - } - else if (value >= 0 && value < (long) N_COMPLETERS) - result = completers[value].completer (command, text, word); + Py_DECREF (iter); + + /* If we got some results, ignore problems. Otherwise, report + the problem. */ + if (result != NULL && PyErr_Occurred ()) + PyErr_Clear (); } done: @@ -299,14 +426,14 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word) /* Helper for cmdpy_init which locates the command list to use and pulls out the command name. - + 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 @@ -320,7 +447,8 @@ gdbpy_parse_command_name (const char *name, struct cmd_list_element *elt; int len = strlen (name); int i, lastchar; - char *prefix_text, *prefix_text2; + char *prefix_text; + const char *prefix_text2; char *result; /* Skip trailing whitespace. */ @@ -358,7 +486,7 @@ gdbpy_parse_command_name (const char *name, prefix_text2 = prefix_text; elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, 1); - if (!elt || elt == (struct cmd_list_element *) -1) + if (elt == NULL || elt == CMD_LIST_AMBIGUOUS) { PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."), prefix_text); @@ -436,7 +564,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; @@ -454,16 +582,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); - + i = 0; out = 0; while (name[i]) @@ -497,9 +625,12 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) { xfree (cmd_name); xfree (pfx_name); + Py_DECREF (ds_obj); return -1; } } + + Py_XDECREF (ds_obj); } if (! docstring) docstring = xstrdup (_("This command is not documented.")); @@ -533,6 +664,9 @@ 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) { @@ -552,14 +686,14 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) /* 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. */ @@ -578,21 +712,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; } @@ -605,10 +746,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*/ @@ -666,6 +806,8 @@ gdbpy_string_to_argv (PyObject *self, PyObject *args) return NULL; 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.