X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fpython%2Fpy-cmd.c;h=b9f60377bd60218547968f30ae737b6d8322d11e;hb=eb3ff9a55175dcdac8328b558d54951a14d719b1;hp=c24bca77e152bbd0f1228d937ce6feb00b9862e8;hpb=ecd75fc8eed3bde86036141228074a20e55dcfc9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c index c24bca77e1..b9f60377bd 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-2014 Free Software Foundation, Inc. + Copyright (C) 2008-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -21,30 +21,30 @@ #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. */ 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_SYMBOL", symbol_completer }, { "COMPLETE_EXPRESSION", expression_completer }, }; @@ -69,7 +69,7 @@ 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. */ @@ -93,35 +93,29 @@ cmdpy_dont_repeat (PyObject *self, PyObject *args) 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 ((char *) self->name); - xfree (self->doc); - xfree (self->prefixname); - - do_cleanups (cleanup); + 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.")); @@ -130,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.")); @@ -138,24 +131,23 @@ 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) + 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.")); } - 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); + 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) + if (result == NULL) { PyObject *ptype, *pvalue, *ptraceback; - char *msg; PyErr_Fetch (&ptype, &pvalue, &ptraceback); @@ -163,8 +155,8 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) When fetching the error message we need to make our own copy, we no longer own ptype, pvalue after the call to PyErr_Restore. */ - msg = gdbpy_exception_to_string (ptype, pvalue); - make_cleanup (xfree, msg); + gdb::unique_xmalloc_ptr + msg (gdbpy_exception_to_string (ptype, pvalue)); if (msg == NULL) { @@ -189,7 +181,7 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) PyErr_Restore (ptype, pvalue, ptraceback); gdbpy_print_stack (); if (msg != NULL && *msg != '\0') - error (_("Error occurred in Python command: %s"), msg); + error (_("Error occurred in Python command: %s"), msg.get ()); else error (_("Error occurred in Python command.")); } @@ -198,112 +190,201 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) Py_XDECREF (ptype); Py_XDECREF (pvalue); Py_XDECREF (ptraceback); - error ("%s", msg); + error ("%s", msg.get ()); } } - - Py_DECREF (result); - 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. + + 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 VEC (char_ptr) * -cmdpy_completer (struct cmd_list_element *command, - const char *text, const char *word) +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; - VEC (char_ptr) *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) - error (_("Could not convert argument to Python string.")); - wordobj = PyUnicode_Decode (word, strlen (word), host_charset (), NULL); - if (! wordobj) + gdbpy_ref<> textobj (PyUnicode_Decode (text, strlen (text), host_charset (), + NULL)); + if (textobj == 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<> wordobj; + if (word == NULL) + { + /* "brkchars" phase. */ + wordobj.reset (Py_None); + Py_INCREF (Py_None); + } + else + { + wordobj.reset (PyUnicode_Decode (word, strlen (word), host_charset (), + NULL)); + if (wordobj == NULL) + error (_("Could not convert argument to Python string.")); + } + + 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; } - result = NULL; - if (PyInt_Check (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, + completion_tracker &tracker, + 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) + { + completer_handle_brkchars_ftype *brkchars_fn; + + /* This is the core of this function. Depending on which + completer type the Python function returns, we have to + adjust the break characters accordingly. */ + brkchars_fn = (completer_handle_brkchars_func_for_completer + (completers[value].completer)); + brkchars_fn (command, tracker, text, word); + } + } +} + +/* Called by gdb for command completion. */ + +static void +cmdpy_completer (struct cmd_list_element *command, + completion_tracker &tracker, + 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)); + + /* If the result object of calling the Python function is NULL, it + means that there was an error. In this case, just give up. */ + 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. */ long value; - if (! gdb_py_int_as_long (resultobj, &value)) + 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); + completers[value].completer (command, tracker, text, word); } else { - PyObject *iter = PyObject_GetIter (resultobj); - PyObject *elt; + gdbpy_ref<> iter (PyObject_GetIter (resultobj.get ())); if (iter == NULL) - goto done; + return; - while ((elt = PyIter_Next (iter)) != NULL) + bool got_matches = false; + while (true) { - char *item; + gdbpy_ref<> elt (PyIter_Next (iter.get ())); + if (elt == NULL) + break; - if (! gdbpy_is_string (elt)) + if (! gdbpy_is_string (elt.get ())) { /* Skip problem elements. */ - Py_DECREF (elt); continue; } - item = python_string_to_host_string (elt); - Py_DECREF (elt); + gdb::unique_xmalloc_ptr + item (python_string_to_host_string (elt.get ())); if (item == NULL) { /* Skip problem elements. */ PyErr_Clear (); continue; } - VEC_safe_push (char_ptr, result, item); + tracker.add_completion (std::move (item)); + got_matches = true; } - Py_DECREF (iter); - /* If we got some results, ignore problems. Otherwise, report the problem. */ - if (result != NULL && PyErr_Occurred ()) + if (got_matches && PyErr_Occurred ()) PyErr_Clear (); } - - done: - - Py_XDECREF (resultobj); - do_cleanups (cleanup); - - return result; } /* Helper for cmdpy_init which locates the command list to use and @@ -349,7 +430,7 @@ gdbpy_parse_command_name (const char *name, || name[i - 1] == '_'); --i) ; - result = xmalloc (lastchar - i + 2); + result = (char *) xmalloc (lastchar - i + 2); memcpy (result, &name[i], lastchar - i + 1); result[lastchar - i + 1] = '\0'; @@ -362,13 +443,13 @@ gdbpy_parse_command_name (const char *name, return result; } - prefix_text = xmalloc (i + 2); + prefix_text = (char *) xmalloc (i + 2); memcpy (prefix_text, name, i + 1); prefix_text[i + 1] = '\0'; 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); @@ -419,11 +500,10 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) 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; @@ -436,9 +516,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 @@ -472,7 +552,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) 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; @@ -498,28 +578,25 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) } 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)) + if (ds_obj != NULL && gdbpy_is_string (ds_obj.get ())) { - docstring = python_string_to_host_string (ds_obj); + docstring = python_string_to_host_string (ds_obj.get ()).release (); if (docstring == NULL) { 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.")); Py_INCREF (self); - TRY_CATCH (except, RETURN_MASK_ALL) + TRY { struct cmd_list_element *cmd; @@ -546,8 +623,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); @@ -558,6 +638,8 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) "%s", except.message); return -1; } + END_CATCH + return 0; } @@ -575,7 +657,7 @@ gdbpy_initialize_commands (void) 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 @@ -625,7 +707,7 @@ static PyMethodDef cmdpy_object_methods[] = { 0 } }; -static PyTypeObject cmdpy_object_type = +PyTypeObject cmdpy_object_type = { PyVarObject_HEAD_INIT (NULL, 0) "gdb.Command", /*tp_name*/ @@ -678,13 +760,12 @@ static PyTypeObject cmdpy_object_type = PyObject * gdbpy_string_to_argv (PyObject *self, PyObject *args) { - PyObject *py_argv; const char *input; if (!PyArg_ParseTuple (args, "s", &input)) return NULL; - py_argv = PyList_New (0); + gdbpy_ref<> py_argv (PyList_New (0)); if (py_argv == NULL) return NULL; @@ -699,21 +780,18 @@ gdbpy_string_to_argv (PyObject *self, PyObject *args) for (i = 0; c_argv[i] != NULL; ++i) { - PyObject *argp = PyString_FromString (c_argv[i]); + gdbpy_ref<> argp (PyString_FromString (c_argv[i])); if (argp == NULL - || PyList_Append (py_argv, argp) < 0) + || PyList_Append (py_argv.get (), argp.get ()) < 0) { - Py_XDECREF (argp); - Py_DECREF (py_argv); freeargv (c_argv); return NULL; } - Py_DECREF (argp); } freeargv (c_argv); } - return py_argv; + return py_argv.release (); }