/* GDB parameters implemented in Python
- Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Copyright (C) 2008-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "value.h"
-#include "exceptions.h"
#include "python-internal.h"
#include "charset.h"
#include "gdbcmd.h"
/* Parameter constants and their values. */
struct parm_constant
{
- char *name;
+ const char *name;
int value;
};
{ "PARAM_OPTIONAL_FILENAME", var_optional_filename },
{ "PARAM_FILENAME", var_filename },
{ "PARAM_ZINTEGER", var_zinteger },
+ { "PARAM_ZUINTEGER", var_zuinteger },
+ { "PARAM_ZUINTEGER_UNLIMITED", var_zuinteger_unlimited },
{ "PARAM_ENUM", var_enum },
{ NULL, 0 }
};
/* A union that can hold anything described by enum var_types. */
union parmpy_variable
{
- /* Hold an integer value, for boolean and integer types. */
+ /* Hold a boolean value. */
+ bool boolval;
+
+ /* Hold an integer value. */
int intval;
/* Hold an auto_boolean. */
typedef struct parmpy_object parmpy_object;
-static PyTypeObject parmpy_object_type
+extern PyTypeObject parmpy_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("parmpy_object");
/* Some handy string constants. */
&& (self->type == var_filename
|| value != Py_None))
{
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("String required for filename."));
return -1;
}
else
{
- char *string;
-
- string = python_string_to_host_string (value);
+ gdb::unique_xmalloc_ptr<char>
+ string (python_string_to_host_string (value));
if (string == NULL)
return -1;
xfree (self->value.stringval);
- self->value.stringval = string;
+ self->value.stringval = string.release ();
}
break;
case var_enum:
{
int i;
- char *str;
if (! gdbpy_is_string (value))
{
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("ENUM arguments must be a string."));
return -1;
}
- str = python_string_to_host_string (value);
+ gdb::unique_xmalloc_ptr<char>
+ str (python_string_to_host_string (value));
if (str == NULL)
return -1;
for (i = 0; self->enumeration[i]; ++i)
- if (! strcmp (self->enumeration[i], str))
+ if (! strcmp (self->enumeration[i], str.get ()))
break;
- xfree (str);
if (! self->enumeration[i])
{
PyErr_SetString (PyExc_RuntimeError,
case var_boolean:
if (! PyBool_Check (value))
{
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("A boolean argument is required."));
return -1;
}
cmp = PyObject_IsTrue (value);
- if (cmp < 0)
+ if (cmp < 0)
return -1;
- self->value.intval = cmp;
+ self->value.boolval = cmp;
break;
case var_auto_boolean:
{
cmp = PyObject_IsTrue (value);
if (cmp < 0 )
- return -1;
+ return -1;
if (cmp == 1)
self->value.autoboolval = AUTO_BOOLEAN_TRUE;
- else
+ else
self->value.autoboolval = AUTO_BOOLEAN_FALSE;
}
break;
case var_integer:
case var_zinteger:
case var_uinteger:
+ case var_zuinteger:
+ case var_zuinteger_unlimited:
{
long l;
int ok;
if (! PyInt_Check (value))
{
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("The value must be integer."));
return -1;
}
if (! gdb_py_int_as_long (value, &l))
return -1;
- if (self->type == var_uinteger)
+ switch (self->type)
{
- ok = (l >= 0 && l <= UINT_MAX);
+ case var_uinteger:
if (l == 0)
l = UINT_MAX;
- }
- else if (self->type == var_integer)
- {
+ /* Fall through. */
+ case var_zuinteger:
+ ok = (l >= 0 && l <= UINT_MAX);
+ break;
+
+ case var_zuinteger_unlimited:
+ ok = (l >= -1 && l <= INT_MAX);
+ break;
+
+ case var_integer:
ok = (l >= INT_MIN && l <= INT_MAX);
if (l == 0)
l = INT_MAX;
+ break;
+
+ case var_zinteger:
+ ok = (l >= INT_MIN && l <= INT_MAX);
+ break;
+
+ default:
+ gdb_assert_not_reached ("unknown var_ constant");
}
- else
- ok = (l >= INT_MIN && l <= INT_MAX);
if (! ok)
{
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("Range exceeded."));
return -1;
}
- self->value.intval = (int) l;
+ if (self->type == var_uinteger || self->type == var_zuinteger)
+ self->value.uintval = (unsigned) l;
+ else
+ self->value.intval = (int) l;
break;
}
default:
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("Unhandled type in parameter value."));
return -1;
}
/* A helper function which returns a documentation string for an
object. */
-static char *
+static gdb::unique_xmalloc_ptr<char>
get_doc_string (PyObject *object, PyObject *attr)
{
- char *result = NULL;
+ gdb::unique_xmalloc_ptr<char> result;
if (PyObject_HasAttr (object, attr))
{
- PyObject *ds_obj = PyObject_GetAttr (object, attr);
+ gdbpy_ref<> ds_obj (PyObject_GetAttr (object, attr));
- if (ds_obj && gdbpy_is_string (ds_obj))
+ if (ds_obj != NULL && gdbpy_is_string (ds_obj.get ()))
{
- result = python_string_to_host_string (ds_obj);
+ result = python_string_to_host_string (ds_obj.get ());
if (result == NULL)
gdbpy_print_stack ();
}
- Py_XDECREF (ds_obj);
}
if (! result)
- result = xstrdup (_("This command is not documented."));
+ result.reset (xstrdup (_("This command is not documented.")));
return result;
}
argument ARG. ARG can be NULL. METHOD should return a Python
string. If this function returns NULL, there has been an error and
the appropriate exception set. */
-static char *
+static gdb::unique_xmalloc_ptr<char>
call_doc_function (PyObject *obj, PyObject *method, PyObject *arg)
{
- char *data = NULL;
- PyObject *result = PyObject_CallMethodObjArgs (obj, method, arg, NULL);
+ gdb::unique_xmalloc_ptr<char> data;
+ gdbpy_ref<> result (PyObject_CallMethodObjArgs (obj, method, arg, NULL));
- if (! result)
+ if (result == NULL)
return NULL;
- if (gdbpy_is_string (result))
+ if (gdbpy_is_string (result.get ()))
{
- data = python_string_to_host_string (result);
- Py_DECREF (result);
+ data = python_string_to_host_string (result.get ());
if (! data)
return NULL;
}
{
PyErr_SetString (PyExc_RuntimeError,
_("Parameter must return a string value."));
- Py_DECREF (result);
return NULL;
}
neither exist, insert a string indicating the Parameter is not
documented. */
static void
-get_set_value (char *args, int from_tty,
+get_set_value (const char *args, int from_tty,
struct cmd_list_element *c)
{
PyObject *obj = (PyObject *) get_cmd_context (c);
- char *set_doc_string;
- struct cleanup *cleanup = ensure_python_env (get_current_arch (),
- current_language);
- PyObject *set_doc_func = PyString_FromString ("get_set_string");
+ gdb::unique_xmalloc_ptr<char> set_doc_string;
- if (! set_doc_func)
- goto error;
+ gdbpy_enter enter_py (get_current_arch (), current_language);
+ gdbpy_ref<> set_doc_func (PyString_FromString ("get_set_string"));
- if (PyObject_HasAttr (obj, set_doc_func))
+ if (set_doc_func == NULL)
{
- set_doc_string = call_doc_function (obj, set_doc_func, NULL);
- if (! set_doc_string)
- goto error;
+ gdbpy_print_stack ();
+ return;
}
- else
+
+ if (PyObject_HasAttr (obj, set_doc_func.get ()))
{
- /* We have to preserve the existing < GDB 7.3 API. If a
- callback function does not exist, then attempt to read the
- set_doc attribute. */
- set_doc_string = get_doc_string (obj, set_doc_cst);
+ set_doc_string = call_doc_function (obj, set_doc_func.get (), NULL);
+ if (! set_doc_string)
+ gdbpy_handle_exception ();
}
- make_cleanup (xfree, set_doc_string);
- fprintf_filtered (gdb_stdout, "%s\n", set_doc_string);
-
- Py_XDECREF (set_doc_func);
- do_cleanups (cleanup);
- return;
-
- error:
- Py_XDECREF (set_doc_func);
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- return;
+ const char *str = set_doc_string.get ();
+ if (str != nullptr && str[0] != '\0')
+ fprintf_filtered (gdb_stdout, "%s\n", str);
}
/* A callback function that is registered against the respective
const char *value)
{
PyObject *obj = (PyObject *) get_cmd_context (c);
- char *show_doc_string = NULL;
- struct cleanup *cleanup = ensure_python_env (get_current_arch (),
- current_language);
- PyObject *show_doc_func = PyString_FromString ("get_show_string");
+ gdb::unique_xmalloc_ptr<char> show_doc_string;
- if (! show_doc_func)
- goto error;
+ gdbpy_enter enter_py (get_current_arch (), current_language);
+ gdbpy_ref<> show_doc_func (PyString_FromString ("get_show_string"));
- if (PyObject_HasAttr (obj, show_doc_func))
+ if (show_doc_func == NULL)
{
- PyObject *val_obj = PyString_FromString (value);
+ gdbpy_print_stack ();
+ return;
+ }
- if (! val_obj)
- goto error;
+ if (PyObject_HasAttr (obj, show_doc_func.get ()))
+ {
+ gdbpy_ref<> val_obj (PyString_FromString (value));
- show_doc_string = call_doc_function (obj, show_doc_func, val_obj);
- Py_DECREF (val_obj);
- if (! show_doc_string)
- goto error;
+ if (val_obj == NULL)
+ {
+ gdbpy_print_stack ();
+ return;
+ }
- make_cleanup (xfree, show_doc_string);
+ show_doc_string = call_doc_function (obj, show_doc_func.get (),
+ val_obj.get ());
+ if (! show_doc_string)
+ {
+ gdbpy_print_stack ();
+ return;
+ }
- fprintf_filtered (file, "%s\n", show_doc_string);
+ fprintf_filtered (file, "%s\n", show_doc_string.get ());
}
else
{
callback function does not exist, then attempt to read the
show_doc attribute. */
show_doc_string = get_doc_string (obj, show_doc_cst);
- make_cleanup (xfree, show_doc_string);
- fprintf_filtered (file, "%s %s\n", show_doc_string, value);
+ fprintf_filtered (file, "%s %s\n", show_doc_string.get (), value);
}
-
- Py_XDECREF (show_doc_func);
- do_cleanups (cleanup);
- return;
-
- error:
- Py_XDECREF (show_doc_func);
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- return;
}
\f
function. */
static void
add_setshow_generic (int parmclass, enum command_class cmdclass,
- char *cmd_name, parmpy_object *self,
- char *set_doc, char *show_doc, char *help_doc,
+ const char *cmd_name, parmpy_object *self,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
struct cmd_list_element **set_list,
struct cmd_list_element **show_list)
{
case var_boolean:
add_setshow_boolean_cmd (cmd_name, cmdclass,
- &self->value.intval, set_doc, show_doc,
+ &self->value.boolval, set_doc, show_doc,
help_doc, get_set_value, get_show_value,
set_list, show_list);
set_list, show_list);
break;
+ case var_zuinteger:
+ add_setshow_zuinteger_cmd (cmd_name, cmdclass,
+ &self->value.uintval, set_doc, show_doc,
+ help_doc, get_set_value, get_show_value,
+ set_list, show_list);
+ break;
+
+ case var_zuinteger_unlimited:
+ add_setshow_zuinteger_unlimited_cmd (cmd_name, cmdclass,
+ &self->value.intval, set_doc,
+ show_doc, help_doc, get_set_value,
+ get_show_value,
+ set_list, show_list);
+ break;
+
case var_enum:
add_setshow_enum_cmd (cmd_name, cmdclass, self->enumeration,
&self->value.cstringval, set_doc, show_doc,
compute_enum_values (parmpy_object *self, PyObject *enum_values)
{
Py_ssize_t size, i;
- struct cleanup *back_to;
if (! enum_values)
{
if (! PySequence_Check (enum_values))
{
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("The enumeration is not a sequence."));
return 0;
}
return 0;
if (size == 0)
{
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("The enumeration is empty."));
return 0;
}
- self->enumeration = xmalloc ((size + 1) * sizeof (char *));
- back_to = make_cleanup (free_current_contents, &self->enumeration);
- memset (self->enumeration, 0, (size + 1) * sizeof (char *));
+ gdb_argv holder (XCNEWVEC (char *, size + 1));
+ char **enumeration = holder.get ();
for (i = 0; i < size; ++i)
{
- PyObject *item = PySequence_GetItem (enum_values, i);
+ gdbpy_ref<> item (PySequence_GetItem (enum_values, i));
- if (! item)
+ if (item == NULL)
+ return 0;
+ if (! gdbpy_is_string (item.get ()))
{
- do_cleanups (back_to);
- return 0;
- }
- if (! gdbpy_is_string (item))
- {
- Py_DECREF (item);
- do_cleanups (back_to);
- PyErr_SetString (PyExc_RuntimeError,
+ PyErr_SetString (PyExc_RuntimeError,
_("The enumeration item not a string."));
return 0;
}
- self->enumeration[i] = python_string_to_host_string (item);
- Py_DECREF (item);
- if (self->enumeration[i] == NULL)
- {
- do_cleanups (back_to);
- return 0;
- }
- make_cleanup (xfree, (char *) self->enumeration[i]);
+ enumeration[i] = python_string_to_host_string (item.get ()).release ();
+ if (enumeration[i] == NULL)
+ return 0;
}
- discard_cleanups (back_to);
+ self->enumeration = const_cast<const char**> (holder.release ());
return 1;
}
{
parmpy_object *obj = (parmpy_object *) self;
const char *name;
- char *set_doc, *show_doc, *doc;
+ gdb::unique_xmalloc_ptr<char> set_doc, show_doc, doc;
char *cmd_name;
int parmclass, cmdtype;
PyObject *enum_values = NULL;
struct cmd_list_element **set_list, **show_list;
- volatile struct gdb_exception except;
if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass,
&enum_values))
&& parmclass != var_uinteger && parmclass != var_integer
&& parmclass != var_string && parmclass != var_string_noescape
&& parmclass != var_optional_filename && parmclass != var_filename
- && parmclass != var_zinteger && parmclass != var_enum)
+ && parmclass != var_zinteger && parmclass != var_zuinteger
+ && parmclass != var_zuinteger_unlimited && parmclass != var_enum)
{
PyErr_SetString (PyExc_RuntimeError,
_("Invalid parameter class argument."));
Py_INCREF (self);
- TRY_CATCH (except, RETURN_MASK_ALL)
+ try
{
add_setshow_generic (parmclass, (enum command_class) cmdtype,
cmd_name, obj,
- set_doc, show_doc,
- doc, set_list, show_list);
+ set_doc.get (), show_doc.get (),
+ doc.get (), set_list, show_list);
}
- if (except.reason < 0)
+ catch (const gdb_exception &except)
{
xfree (cmd_name);
- xfree (set_doc);
- xfree (show_doc);
- xfree (doc);
Py_DECREF (self);
- PyErr_Format (except.reason == RETURN_QUIT
- ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
- "%s", except.message);
+ gdbpy_convert_exception (except);
return -1;
}
+
return 0;
}
\f
-static PyTypeObject parmpy_object_type =
+PyTypeObject parmpy_object_type =
{
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.Parameter", /*tp_name*/