/* gdb commands implemented in Python
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "cli/cli-decode.h"
#include "completer.h"
#include "language.h"
-#include "py-ref.h"
/* Struct representing built-in completion types. */
struct cmdpy_completer
gdbpy_ref<cmdpy_object> cmd ((cmdpy_object *) context);
cmd->command = NULL;
- /* We allocated the name, doc string, and perhaps the prefix
- name. */
- xfree ((char *) self->name);
- xfree ((char *) self->doc);
+ /* We may have allocated the prefix name. */
xfree ((char *) self->prefixname);
}
static void
cmdpy_function (struct cmd_list_element *command,
- char *args_entry, int from_tty)
+ const char *args, int from_tty)
{
- const char *args = args_entry;
cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
gdbpy_enter enter_py (get_current_arch (), current_language);
error (_("Could not convert arguments to Python string."));
}
- gdbpy_ref<> ttyobj (from_tty ? Py_True : Py_False);
- Py_INCREF (ttyobj.get ());
+ gdbpy_ref<> ttyobj
+ = gdbpy_ref<>::new_reference (from_tty ? Py_True : Py_False);
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);
-
- /* 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<char>
- msg (gdbpy_exception_to_string (ptype, pvalue));
-
- 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 ();
- }
-
- /* 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 ();
- if (msg != NULL && *msg != '\0')
- error (_("Error occurred in Python command: %s"), msg.get ());
- else
- error (_("Error occurred in Python command."));
- }
- else
- {
- Py_XDECREF (ptype);
- Py_XDECREF (pvalue);
- Py_XDECREF (ptraceback);
- error ("%s", msg.get ());
- }
- }
+ gdbpy_handle_exception ();
}
/* Helper function for the Python command completers (both "pure"
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. */
+ This function returns a reference to the PyObject representing the
+ Python method call. */
-static PyObject *
+static gdbpy_ref<>
cmdpy_completer_helper (struct cmd_list_element *command,
const char *text, const char *word)
{
if (word == NULL)
{
/* "brkchars" phase. */
- wordobj.reset (Py_None);
- Py_INCREF (Py_None);
+ wordobj = gdbpy_ref<>::new_reference (Py_None);
}
else
{
PyErr_Clear ();
}
- return resultobj.release ();
+ return resultobj;
}
/* Python function called to determine the break characters of a
{
gdbpy_enter enter_py (get_current_arch (), current_language);
- /* Calling our helper to obtain the PyObject of the Python
+ /* Calling our helper to obtain a reference to the PyObject of the Python
function. */
- gdbpy_ref<> resultobj (cmdpy_completer_helper (command, text, word));
+ gdbpy_ref<> resultobj = cmdpy_completer_helper (command, text, word);
/* Check if there was an error. */
if (resultobj == NULL)
{
gdbpy_enter enter_py (get_current_arch (), current_language);
- /* Calling our helper to obtain the PyObject of the Python
+ /* Calling our helper to obtain a reference to the PyObject of the Python
function. */
- gdbpy_ref<> resultobj (cmdpy_completer_helper (command, text, word));
+ 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. */
struct cmd_list_element *elt;
int len = strlen (name);
int i, lastchar;
- char *prefix_text;
const char *prefix_text2;
char *result;
lastchar = i;
/* Find first character of the final word. */
- for (; i > 0 && (isalnum (name[i - 1])
- || name[i - 1] == '-'
- || name[i - 1] == '_');
- --i)
+ for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
;
result = (char *) xmalloc (lastchar - i + 2);
memcpy (result, &name[i], lastchar - i + 1);
return result;
}
- prefix_text = (char *) xmalloc (i + 2);
- memcpy (prefix_text, name, i + 1);
- prefix_text[i + 1] = '\0';
+ std::string prefix_text (name, i + 1);
- prefix_text2 = prefix_text;
+ prefix_text2 = prefix_text.c_str ();
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);
- xfree (prefix_text);
+ prefix_text.c_str ());
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);
+ prefix_text.c_str ());
xfree (result);
return NULL;
}
&& cmdtype != class_files && cmdtype != class_support
&& cmdtype != class_info && cmdtype != class_breakpoint
&& cmdtype != class_trace && cmdtype != class_obscure
- && cmdtype != class_maintenance && cmdtype != class_user)
+ && cmdtype != class_maintenance && cmdtype != class_user
+ && cmdtype != class_tui)
{
PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument."));
return -1;
if (! docstring)
docstring = xstrdup (_("This command is not documented."));
- Py_INCREF (self);
+ gdbpy_ref<> self_ref = gdbpy_ref<>::new_reference (self);
- TRY
+ try
{
struct cmd_list_element *cmd;
pfx_name, allow_unknown, cmd_list);
}
else
- cmd = add_cmd (cmd_name, (enum command_class) cmdtype, NULL,
+ cmd = add_cmd (cmd_name, (enum command_class) cmdtype,
docstring, cmd_list);
/* There appears to be no API to set this. */
cmd->func = cmdpy_function;
cmd->destroyer = cmdpy_destroyer;
+ cmd->doc_allocated = 1;
+ cmd->name_allocated = 1;
obj->command = cmd;
- set_cmd_context (cmd, self);
+ set_cmd_context (cmd, self_ref.release ());
set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer
: completers[completetype].completer));
if (completetype == -1)
set_cmd_completer_handle_brkchars (cmd,
cmdpy_completer_handle_brkchars);
}
- CATCH (except, RETURN_MASK_ALL)
+ catch (const gdb_exception &except)
{
xfree (cmd_name);
xfree (docstring);
xfree (pfx_name);
- Py_DECREF (self);
- PyErr_Format (except.reason == RETURN_QUIT
- ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
- "%s", except.message);
+ gdbpy_convert_exception (except);
return -1;
}
- END_CATCH
return 0;
}
if (PyType_Ready (&cmdpy_object_type) < 0)
return -1;
- /* Note: alias and user are special; pseudo appears to be unused,
- and there is no reason to expose tui, I think. */
+ /* Note: alias and user are special. */
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
class_obscure) < 0
|| PyModule_AddIntConstant (gdb_module, "COMMAND_MAINTENANCE",
class_maintenance) < 0
- || PyModule_AddIntConstant (gdb_module, "COMMAND_USER", class_user) < 0)
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_USER", class_user) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_TUI", class_tui) < 0)
return -1;
for (i = 0; i < N_COMPLETERS; ++i)