aboutsummaryrefslogtreecommitdiff
path: root/gdb/registry.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/registry.h')
-rw-r--r--gdb/registry.h187
1 files changed, 187 insertions, 0 deletions
diff --git a/gdb/registry.h b/gdb/registry.h
new file mode 100644
index 0000000..d696781
--- /dev/null
+++ b/gdb/registry.h
@@ -0,0 +1,187 @@
+/* Macros for general registry objects.
+
+ Copyright (C) 2011, 2012
+ Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef REGISTRY_H
+#define REGISTRY_H
+
+/* The macros here implement a template type and functions for
+ associating some user data with a container object.
+
+ The API user requests a key from a registry during gdb
+ initialization. Later this key can be used to associate some
+ module-specific data with a specific container object.
+
+ A registry is associated with a struct tag name.
+
+ The exported API is best used via the wrapper macros:
+
+ - register_TAG_data(TAG)
+ Get a new key for the container type TAG.
+
+ - register_TAG_data_with_cleanup(TAG, SAVE, FREE)
+ Get a new key for the container type TAG.
+ SAVE and FREE are defined as void (*) (struct TAG *, void *)
+ When the container is destroyed, first all registered SAVE
+ functions are called.
+ Then all FREE functions are called.
+ Either or both may be NULL.
+
+ - clear_TAG_data(TAG, OBJECT)
+ Clear all the data associated with OBJECT. Should be called by the
+ container implementation when a container object is destroyed.
+
+ - set_TAG_data(TAG, OBJECT, KEY, DATA)
+ Set the data on an object.
+
+ - TAG_data(TAG, OBJECT, KEY)
+ Fetch the data for an object; returns NULL if it has not been set.
+*/
+
+/* This macro is used in a container struct definition to define the
+ fields used by the registry code. */
+
+#define REGISTRY_FIELDS \
+ void **data; \
+ unsigned num_data
+
+/* Define a new registry implementation. */
+
+#define DEFINE_REGISTRY(TAG) \
+struct TAG ## _data \
+{ \
+ unsigned index; \
+ void (*save) (struct TAG *, void *); \
+ void (*free) (struct TAG *, void *); \
+}; \
+ \
+struct TAG ## _data_registration \
+{ \
+ struct TAG ## _data *data; \
+ struct TAG ## _data_registration *next; \
+}; \
+ \
+struct TAG ## _data_registry \
+{ \
+ struct TAG ## _data_registration *registrations; \
+ unsigned num_registrations; \
+}; \
+ \
+struct TAG ## _data_registry TAG ## _data_registry = { NULL, 0 }; \
+ \
+const struct TAG ## _data * \
+register_ ## TAG ## _data_with_cleanup (void (*save) (struct TAG *, void *), \
+ void (*free) (struct TAG *, void *)) \
+{ \
+ struct TAG ## _data_registration **curr; \
+ \
+ /* Append new registration. */ \
+ for (curr = &TAG ## _data_registry.registrations; \
+ *curr != NULL; curr = &(*curr)->next); \
+ \
+ *curr = XMALLOC (struct TAG ## _data_registration); \
+ (*curr)->next = NULL; \
+ (*curr)->data = XMALLOC (struct TAG ## _data); \
+ (*curr)->data->index = TAG ## _data_registry.num_registrations++; \
+ (*curr)->data->save = save; \
+ (*curr)->data->free = free; \
+ \
+ return (*curr)->data; \
+} \
+ \
+const struct TAG ## _data * \
+register_ ## TAG ## _data (void) \
+{ \
+ return register_ ## TAG ## _data_with_cleanup (NULL, NULL); \
+} \
+ \
+static void \
+TAG ## _alloc_data (struct TAG *container) \
+{ \
+ gdb_assert (container->data == NULL); \
+ container->num_data = TAG ## _data_registry.num_registrations; \
+ container->data = XCALLOC (container->num_data, void *); \
+} \
+ \
+void \
+clear_ ## TAG ## _data (struct TAG *container) \
+{ \
+ struct TAG ## _data_registration *registration; \
+ int i; \
+ \
+ gdb_assert (container->data != NULL); \
+ \
+ /* Process all the save handlers. */ \
+ \
+ for (registration = TAG ## _data_registry.registrations, i = 0; \
+ i < container->num_data; \
+ registration = registration->next, i++) \
+ if (container->data[i] != NULL && registration->data->save != NULL) \
+ registration->data->save (container, container->data[i]); \
+ \
+ /* Now process all the free handlers. */ \
+ \
+ for (registration = TAG ## _data_registry.registrations, i = 0; \
+ i < container->num_data; \
+ registration = registration->next, i++) \
+ if (container->data[i] != NULL && registration->data->free != NULL) \
+ registration->data->free (container, container->data[i]); \
+ \
+ memset (container->data, 0, container->num_data * sizeof (void *)); \
+} \
+ \
+static void \
+TAG ## _free_data (struct TAG *container) \
+{ \
+ void ***rdata = &container->data; \
+ gdb_assert (*rdata != NULL); \
+ clear_ ## TAG ## _data (container); \
+ xfree (*rdata); \
+ *rdata = NULL; \
+} \
+ \
+void \
+set_ ## TAG ## _data (struct TAG *container, const struct TAG ## _data *data, \
+ void *value) \
+{ \
+ gdb_assert (data->index < container->num_data); \
+ container->data[data->index] = value; \
+} \
+ \
+void * \
+TAG ## _data (struct TAG *container, const struct TAG ## _data *data) \
+{ \
+ gdb_assert (data->index < container->num_data); \
+ return container->data[data->index]; \
+}
+
+
+/* External declarations for the registry functions. */
+
+#define DECLARE_REGISTRY(TAG) \
+extern const struct TAG ## _data *register_ ## TAG ## _data (void); \
+extern const struct TAG ## _data *register_ ## TAG ## _data_with_cleanup \
+ (void (*save) (struct TAG *, void *), void (*free) (struct TAG *, void *)); \
+extern void clear_ ## TAG ## _data (struct TAG *); \
+extern void set_ ## TAG ## _data (struct TAG *, \
+ const struct TAG ## _data *data, void *value); \
+extern void *TAG ## _data (struct TAG *, \
+ const struct TAG ## _data *data);
+
+#endif /* REGISTRY_H */