gdb: remove BLOCK_FUNCTION macro
[binutils-gdb.git] / gdb / reggroups.c
index 01dbe34cd0f8ab641bfcc677beb92438215e8f98..1a13cb2fba0b9fbd39cc1de939d8d089dc9da451 100644 (file)
@@ -1,7 +1,6 @@
 /* Register groupings for GDB, the GNU debugger.
 
-   Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2002-2022 Free Software Foundation, Inc.
 
    Contributed by Red Hat.
 
 #include "arch-utils.h"
 #include "reggroups.h"
 #include "gdbtypes.h"
-#include "gdb_assert.h"
 #include "regcache.h"
 #include "command.h"
 #include "gdbcmd.h"            /* For maintenanceprintlist.  */
+#include "gdbsupport/gdb_obstack.h"
 
-/* Individual register groups.  */
+/* See reggroups.h.  */
 
-struct reggroup
-{
-  const char *name;
-  enum reggroup_type type;
-};
-
-struct reggroup *
+const reggroup *
 reggroup_new (const char *name, enum reggroup_type type)
 {
-  struct reggroup *group = XMALLOC (struct reggroup);
-  group->name = name;
-  group->type = type;
-  return group;
+  return new reggroup (name, type);
 }
 
-/* Register group attributes.  */
+/* See reggroups.h.  */
 
-const char *
-reggroup_name (struct reggroup *group)
+const reggroup *
+reggroup_gdbarch_new (struct gdbarch *gdbarch, const char *name,
+                     enum reggroup_type type)
 {
-  return group->name;
+  name = gdbarch_obstack_strdup (gdbarch, name);
+  return obstack_new<struct reggroup> (gdbarch_obstack (gdbarch),
+                                      name, type);
 }
 
-enum reggroup_type
-reggroup_type (struct reggroup *group)
+/* A container holding all the register groups for a particular
+   architecture.  */
+
+struct reggroups
 {
-  return group->type;
-}
+  /* Add GROUP to the list of register groups.  */
 
-/* A linked list of groups for the given architecture.  */
+  void add (const reggroup *group)
+  {
+    gdb_assert (group != nullptr);
+    gdb_assert (std::find (m_groups.begin(), m_groups.end(), group)
+               == m_groups.end());
 
-struct reggroup_el
-{
-  struct reggroup *group;
-  struct reggroup_el *next;
-};
+    m_groups.push_back (group);
+  }
 
-struct reggroups
-{
-  struct reggroup_el *first;
-  struct reggroup_el **last;
-};
+  /* The number of register groups.  */
 
-static struct gdbarch_data *reggroups_data;
+  std::vector<struct reggroup *>::size_type
+  size () const
+  {
+    return m_groups.size ();
+  }
 
-static void *
-reggroups_init (struct gdbarch *gdbarch)
-{
-  struct reggroups *groups = GDBARCH_OBSTACK_ZALLOC (gdbarch,
-                                                    struct reggroups);
-  groups->last = &groups->first;
-  return groups;
-}
+  /* Return a reference to the list of all groups.  */
 
-/* Add a register group (with attribute values) to the pre-defined
-   list.  */
+  const std::vector<const struct reggroup *> &
+  groups () const
+  {
+    return m_groups;
+  }
 
-static void
-add_group (struct reggroups *groups, struct reggroup *group,
-          struct reggroup_el *el)
-{
-  gdb_assert (group != NULL);
-  el->group = group;
-  el->next = NULL;
-  (*groups->last) = el;
-  groups->last = &el->next;
-}
+private:
+  /* The register groups.  */
+  std::vector<const struct reggroup *> m_groups;
+};
+
+/* Key used to lookup register group data from a gdbarch.  */
+
+static struct gdbarch_data *reggroups_data;
+
+/* See reggroups.h.  */
 
 void
-reggroup_add (struct gdbarch *gdbarch, struct reggroup *group)
+reggroup_add (struct gdbarch *gdbarch, const reggroup *group)
 {
-  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  struct reggroups *groups
+    = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
 
-  if (groups == NULL)
-    {
-      /* ULGH, called during architecture initialization.  Patch
-         things up.  */
-      groups = reggroups_init (gdbarch);
-      deprecated_set_gdbarch_data (gdbarch, reggroups_data, groups);
-    }
-  add_group (groups, group,
-            GDBARCH_OBSTACK_ZALLOC (gdbarch, struct reggroup_el));
+  gdb_assert (groups != nullptr);
+  gdb_assert (group != nullptr);
+
+  groups->add (group);
 }
 
-/* The default register groups for an architecture.  */
+/* Called to initialize the per-gdbarch register group information.  */
 
-static struct reggroups default_groups = { NULL, &default_groups.first };
+static void *
+reggroups_init (struct obstack *obstack)
+{
+  struct reggroups *groups = obstack_new<struct reggroups> (obstack);
 
-/* A register group iterator.  */
+  /* Add the default groups.  */
+  groups->add (general_reggroup);
+  groups->add (float_reggroup);
+  groups->add (system_reggroup);
+  groups->add (vector_reggroup);
+  groups->add (all_reggroup);
+  groups->add (save_reggroup);
+  groups->add (restore_reggroup);
 
-struct reggroup *
-reggroup_next (struct gdbarch *gdbarch, struct reggroup *last)
+  return groups;
+}
+
+/* See reggroups.h.  */
+const std::vector<const reggroup *> &
+gdbarch_reggroups (struct gdbarch *gdbarch)
 {
-  struct reggroups *groups;
-  struct reggroup_el *el;
-
-  /* Don't allow this function to be called during architecture
-     creation.  If there are no groups, use the default groups list.  */
-  groups = gdbarch_data (gdbarch, reggroups_data);
-  gdb_assert (groups != NULL);
-  if (groups->first == NULL)
-    groups = &default_groups;
-
-  /* Return the first/next reggroup.  */
-  if (last == NULL)
-    return groups->first->group;
-  for (el = groups->first; el != NULL; el = el->next)
-    {
-      if (el->group == last)
-       {
-         if (el->next != NULL)
-           return el->next->group;
-         else
-           return NULL;
-       }
-    }
-  return NULL;
+  struct reggroups *groups
+    = (struct reggroups *) gdbarch_data (gdbarch, reggroups_data);
+  gdb_assert (groups != nullptr);
+  gdb_assert (groups->size () > 0);
+  return groups->groups ();
 }
 
-/* Is REGNUM a member of REGGROUP?  */
+/* See reggroups.h.  */
+
 int
 default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
-                            struct reggroup *group)
+                            const struct reggroup *group)
 {
   int vector_p;
   int float_p;
@@ -164,8 +147,10 @@ default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return 0;
   if (group == all_reggroup)
     return 1;
-  vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
-  float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
+  vector_p = register_type (gdbarch, regnum)->is_vector ();
+  float_p = (register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT
+            || (register_type (gdbarch, regnum)->code ()
+                == TYPE_CODE_DECFLOAT));
   raw_p = regnum < gdbarch_num_regs (gdbarch);
   if (group == float_reggroup)
     return float_p;
@@ -175,7 +160,20 @@ default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return (!vector_p && !float_p);
   if (group == save_reggroup || group == restore_reggroup)
     return raw_p;
-  return 0;   
+  return 0;
+}
+
+/* See reggroups.h.  */
+
+const reggroup *
+reggroup_find (struct gdbarch *gdbarch, const char *name)
+{
+  for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
+    {
+      if (strcmp (name, group->name ()) == 0)
+       return group;
+    }
+  return NULL;
 }
 
 /* Dump out a table of register groups for the current architecture.  */
@@ -183,54 +181,41 @@ default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
 static void
 reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
 {
-  struct reggroup *group = NULL;
+  static constexpr const char *fmt = " %-10s %-10s\n";
+
+  gdb_printf (file, fmt, "Group", "Type");
 
-  do
+  for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
     {
       /* Group name.  */
-      {
-       const char *name;
-       if (group == NULL)
-         name = "Group";
-       else
-         name = reggroup_name (group);
-       fprintf_unfiltered (file, " %-10s", name);
-      }
-      
+      const char *name = group->name ();
+
       /* Group type.  */
-      {
-       const char *type;
-       if (group == NULL)
-         type = "Type";
-       else
-         {
-           switch (reggroup_type (group))
-             {
-             case USER_REGGROUP:
-               type = "user";
-               break;
-             case INTERNAL_REGGROUP:
-               type = "internal";
-               break;
-             default:
-               internal_error (__FILE__, __LINE__, _("bad switch"));
-             }
-         }
-       fprintf_unfiltered (file, " %-10s", type);
-      }
+      const char *type;
+
+      switch (group->type ())
+       {
+       case USER_REGGROUP:
+         type = "user";
+         break;
+       case INTERNAL_REGGROUP:
+         type = "internal";
+         break;
+       default:
+         internal_error (__FILE__, __LINE__, _("bad switch"));
+       }
 
       /* Note: If you change this, be sure to also update the
-         documentation.  */
-      
-      fprintf_unfiltered (file, "\n");
+        documentation.  */
 
-      group = reggroup_next (gdbarch, group);
+      gdb_printf (file, fmt, name, type);
     }
-  while (group != NULL);
 }
 
+/* Implement 'maintenance print reggroups' command.  */
+
 static void
-maintenance_print_reggroups (char *args, int from_tty)
+maintenance_print_reggroups (const char *args, int from_tty)
 {
   struct gdbarch *gdbarch = get_current_arch ();
 
@@ -238,48 +223,36 @@ maintenance_print_reggroups (char *args, int from_tty)
     reggroups_dump (gdbarch, gdb_stdout);
   else
     {
-      struct cleanup *cleanups;
-      struct ui_file *file = gdb_fopen (args, "w");
-      if (file == NULL)
+      stdio_file file;
+
+      if (!file.open (args, "w"))
        perror_with_name (_("maintenance print reggroups"));
-      cleanups = make_cleanup_ui_file_delete (file);
-      reggroups_dump (gdbarch, file);
-      do_cleanups (cleanups);
+      reggroups_dump (gdbarch, &file);
     }
 }
 
 /* Pre-defined register groups.  */
-static struct reggroup general_group = { "general", USER_REGGROUP };
-static struct reggroup float_group = { "float", USER_REGGROUP };
-static struct reggroup system_group = { "system", USER_REGGROUP };
-static struct reggroup vector_group = { "vector", USER_REGGROUP };
-static struct reggroup all_group = { "all", USER_REGGROUP };
-static struct reggroup save_group = { "save", INTERNAL_REGGROUP };
-static struct reggroup restore_group = { "restore", INTERNAL_REGGROUP };
-
-struct reggroup *const general_reggroup = &general_group;
-struct reggroup *const float_reggroup = &float_group;
-struct reggroup *const system_reggroup = &system_group;
-struct reggroup *const vector_reggroup = &vector_group;
-struct reggroup *const all_reggroup = &all_group;
-struct reggroup *const save_reggroup = &save_group;
-struct reggroup *const restore_reggroup = &restore_group;
-
-extern initialize_file_ftype _initialize_reggroup; /* -Wmissing-prototypes */
-
+static const reggroup general_group = { "general", USER_REGGROUP };
+static const reggroup float_group = { "float", USER_REGGROUP };
+static const reggroup system_group = { "system", USER_REGGROUP };
+static const reggroup vector_group = { "vector", USER_REGGROUP };
+static const reggroup all_group = { "all", USER_REGGROUP };
+static const reggroup save_group = { "save", INTERNAL_REGGROUP };
+static const reggroup restore_group = { "restore", INTERNAL_REGGROUP };
+
+const reggroup *const general_reggroup = &general_group;
+const reggroup *const float_reggroup = &float_group;
+const reggroup *const system_reggroup = &system_group;
+const reggroup *const vector_reggroup = &vector_group;
+const reggroup *const all_reggroup = &all_group;
+const reggroup *const save_reggroup = &save_group;
+const reggroup *const restore_reggroup = &restore_group;
+
+void _initialize_reggroup ();
 void
-_initialize_reggroup (void)
+_initialize_reggroup ()
 {
-  reggroups_data = gdbarch_data_register_post_init (reggroups_init);
-
-  /* The pre-defined list of groups.  */
-  add_group (&default_groups, general_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, float_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, system_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, vector_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, all_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, save_reggroup, XMALLOC (struct reggroup_el));
-  add_group (&default_groups, restore_reggroup, XMALLOC (struct reggroup_el));
+  reggroups_data = gdbarch_data_register_pre_init (reggroups_init);
 
   add_cmd ("reggroups", class_maintenance,
           maintenance_print_reggroups, _("\