Fix "set" handling of Python parameters
[deliverable/binutils-gdb.git] / gdb / python / py-param.c
index dcc110f002409c91b27d6e7f0b3d666735377e2b..ef5c91b9ba13d76823346f946ea05cc60e8d3570 100644 (file)
@@ -1,6 +1,6 @@
 /* GDB parameters implemented in Python
 
-   Copyright (C) 2008-2015 Free Software Foundation, Inc.
+   Copyright (C) 2008-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "completer.h"
 #include "language.h"
 #include "arch-utils.h"
+#include "py-ref.h"
 
 /* Parameter constants and their values.  */
 struct parm_constant
 {
-  char *name;
+  const char *name;
   int value;
 };
 
@@ -46,6 +47,8 @@ struct parm_constant parm_constants[] =
   { "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 }
 };
@@ -148,21 +151,19 @@ set_parameter_value (parmpy_object *self, PyObject *value)
        }
       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))
          {
@@ -171,13 +172,13 @@ set_parameter_value (parmpy_object *self, PyObject *value)
            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,
@@ -226,6 +227,8 @@ set_parameter_value (parmpy_object *self, PyObject *value)
     case var_integer:
     case var_zinteger:
     case var_uinteger:
+    case var_zuinteger:
+    case var_zuinteger_unlimited:
       {
        long l;
        int ok;
@@ -240,20 +243,33 @@ set_parameter_value (parmpy_object *self, PyObject *value)
        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)
          {
@@ -262,7 +278,10 @@ set_parameter_value (parmpy_object *self, PyObject *value)
            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;
       }
 
@@ -301,25 +320,24 @@ set_attr (PyObject *obj, PyObject *attr_name, PyObject *val)
 /* 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;
 }
 
@@ -327,19 +345,18 @@ get_doc_string (PyObject *object, PyObject *attr)
    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;
     }
@@ -347,7 +364,6 @@ call_doc_function (PyObject *obj, PyObject *method, PyObject *arg)
     {
       PyErr_SetString (PyExc_RuntimeError,
                       _("Parameter must return a string value."));
-      Py_DECREF (result);
       return NULL;
     }
 
@@ -361,44 +377,34 @@ call_doc_function (PyObject *obj, PyObject *method, PyObject *arg)
    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_print_stack ();
+         return;
+       }
     }
 
-  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
@@ -413,29 +419,36 @@ get_show_value (struct ui_file *file, int from_tty,
                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
     {
@@ -443,19 +456,8 @@ get_show_value (struct ui_file *file, int from_tty,
         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
 
@@ -539,6 +541,21 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
                                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,
@@ -568,7 +585,6 @@ static int
 compute_enum_values (parmpy_object *self, PyObject *enum_values)
 {
   Py_ssize_t size, i;
-  struct cleanup *back_to;
 
   if (! enum_values)
     {
@@ -594,37 +610,27 @@ compute_enum_values (parmpy_object *self, PyObject *enum_values)
       return 0;
     }
 
-  self->enumeration = XCNEWVEC (const char *, size + 1);
-  back_to = make_cleanup (free_current_contents, &self->enumeration);
+  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,
                           _("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;
 }
 
@@ -682,7 +688,8 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
       && 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."));
@@ -716,9 +723,9 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
   if (! cmd_name)
     return -1;
 
-  set_doc = get_doc_string (self, set_doc_cst);
-  show_doc = get_doc_string (self, show_doc_cst);
-  doc = get_doc_string (self, gdbpy_doc_cst);
+  set_doc = get_doc_string (self, set_doc_cst).release ();
+  show_doc = get_doc_string (self, show_doc_cst).release ();
+  doc = get_doc_string (self, gdbpy_doc_cst).release ();
 
   Py_INCREF (self);
 
This page took 0.031638 seconds and 4 git commands to generate.