Commit | Line | Data |
---|---|---|
8e260fc0 TT |
1 | /* Macros for general registry objects. |
2 | ||
3 | Copyright (C) 2011, 2012 | |
4 | Free Software Foundation, Inc. | |
5 | ||
6 | This file is part of GDB. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #ifndef REGISTRY_H | |
22 | #define REGISTRY_H | |
23 | ||
24 | /* The macros here implement a template type and functions for | |
25 | associating some user data with a container object. | |
26 | ||
6b81941e TT |
27 | A registry is associated with a struct tag name. To attach a |
28 | registry to a structure, use DEFINE_REGISTRY. This takes the | |
29 | structure tag and an access method as arguments. In the usual | |
30 | case, where the registry fields appear directly in the struct, you | |
31 | can use the 'REGISTRY_FIELDS' macro to declare the fields in the | |
32 | struct definition, and you can pass 'REGISTRY_ACCESS_FIELD' as the | |
33 | access argument to DEFINE_REGISTRY. In other cases, use | |
34 | REGISTRY_FIELDS to define the fields in the appropriate spot, and | |
35 | then define your own accessor to find the registry field structure | |
36 | given an instance of your type. | |
37 | ||
8e260fc0 TT |
38 | The API user requests a key from a registry during gdb |
39 | initialization. Later this key can be used to associate some | |
40 | module-specific data with a specific container object. | |
41 | ||
8e260fc0 TT |
42 | The exported API is best used via the wrapper macros: |
43 | ||
44 | - register_TAG_data(TAG) | |
45 | Get a new key for the container type TAG. | |
46 | ||
47 | - register_TAG_data_with_cleanup(TAG, SAVE, FREE) | |
48 | Get a new key for the container type TAG. | |
49 | SAVE and FREE are defined as void (*) (struct TAG *, void *) | |
50 | When the container is destroyed, first all registered SAVE | |
51 | functions are called. | |
52 | Then all FREE functions are called. | |
53 | Either or both may be NULL. | |
54 | ||
55 | - clear_TAG_data(TAG, OBJECT) | |
56 | Clear all the data associated with OBJECT. Should be called by the | |
57 | container implementation when a container object is destroyed. | |
58 | ||
59 | - set_TAG_data(TAG, OBJECT, KEY, DATA) | |
60 | Set the data on an object. | |
61 | ||
62 | - TAG_data(TAG, OBJECT, KEY) | |
63 | Fetch the data for an object; returns NULL if it has not been set. | |
64 | */ | |
65 | ||
6b81941e TT |
66 | /* This structure is used in a container to hold the data that the |
67 | registry uses. */ | |
68 | ||
69 | struct registry_fields | |
70 | { | |
71 | void **data; | |
72 | unsigned num_data; | |
73 | }; | |
74 | ||
8e260fc0 TT |
75 | /* This macro is used in a container struct definition to define the |
76 | fields used by the registry code. */ | |
77 | ||
78 | #define REGISTRY_FIELDS \ | |
6b81941e TT |
79 | struct registry_fields registry_data |
80 | ||
81 | /* A convenience macro for the typical case where the registry data is | |
82 | kept as fields of the object. This can be passed as the ACCESS | |
83 | method to DEFINE_REGISTRY. */ | |
84 | ||
85 | #define REGISTRY_ACCESS_FIELD(CONTAINER) \ | |
86 | (CONTAINER) | |
8e260fc0 TT |
87 | |
88 | /* Define a new registry implementation. */ | |
89 | ||
6b81941e | 90 | #define DEFINE_REGISTRY(TAG, ACCESS) \ |
8e260fc0 TT |
91 | struct TAG ## _data \ |
92 | { \ | |
93 | unsigned index; \ | |
94 | void (*save) (struct TAG *, void *); \ | |
95 | void (*free) (struct TAG *, void *); \ | |
96 | }; \ | |
97 | \ | |
98 | struct TAG ## _data_registration \ | |
99 | { \ | |
100 | struct TAG ## _data *data; \ | |
101 | struct TAG ## _data_registration *next; \ | |
102 | }; \ | |
103 | \ | |
104 | struct TAG ## _data_registry \ | |
105 | { \ | |
106 | struct TAG ## _data_registration *registrations; \ | |
107 | unsigned num_registrations; \ | |
108 | }; \ | |
109 | \ | |
110 | struct TAG ## _data_registry TAG ## _data_registry = { NULL, 0 }; \ | |
111 | \ | |
112 | const struct TAG ## _data * \ | |
113 | register_ ## TAG ## _data_with_cleanup (void (*save) (struct TAG *, void *), \ | |
114 | void (*free) (struct TAG *, void *)) \ | |
115 | { \ | |
116 | struct TAG ## _data_registration **curr; \ | |
117 | \ | |
118 | /* Append new registration. */ \ | |
119 | for (curr = &TAG ## _data_registry.registrations; \ | |
120 | *curr != NULL; curr = &(*curr)->next); \ | |
121 | \ | |
122 | *curr = XMALLOC (struct TAG ## _data_registration); \ | |
123 | (*curr)->next = NULL; \ | |
124 | (*curr)->data = XMALLOC (struct TAG ## _data); \ | |
125 | (*curr)->data->index = TAG ## _data_registry.num_registrations++; \ | |
126 | (*curr)->data->save = save; \ | |
127 | (*curr)->data->free = free; \ | |
128 | \ | |
129 | return (*curr)->data; \ | |
130 | } \ | |
131 | \ | |
132 | const struct TAG ## _data * \ | |
133 | register_ ## TAG ## _data (void) \ | |
134 | { \ | |
135 | return register_ ## TAG ## _data_with_cleanup (NULL, NULL); \ | |
136 | } \ | |
137 | \ | |
138 | static void \ | |
139 | TAG ## _alloc_data (struct TAG *container) \ | |
140 | { \ | |
6b81941e TT |
141 | struct registry_fields *rdata = &ACCESS (container)->registry_data; \ |
142 | gdb_assert (rdata->data == NULL); \ | |
143 | rdata->num_data = TAG ## _data_registry.num_registrations; \ | |
144 | rdata->data = XCALLOC (rdata->num_data, void *); \ | |
8e260fc0 TT |
145 | } \ |
146 | \ | |
147 | void \ | |
148 | clear_ ## TAG ## _data (struct TAG *container) \ | |
149 | { \ | |
6b81941e | 150 | struct registry_fields *rdata = &ACCESS (container)->registry_data; \ |
8e260fc0 TT |
151 | struct TAG ## _data_registration *registration; \ |
152 | int i; \ | |
153 | \ | |
6b81941e | 154 | gdb_assert (rdata->data != NULL); \ |
8e260fc0 TT |
155 | \ |
156 | /* Process all the save handlers. */ \ | |
157 | \ | |
158 | for (registration = TAG ## _data_registry.registrations, i = 0; \ | |
6b81941e | 159 | i < rdata->num_data; \ |
8e260fc0 | 160 | registration = registration->next, i++) \ |
6b81941e TT |
161 | if (rdata->data[i] != NULL && registration->data->save != NULL) \ |
162 | registration->data->save (container, rdata->data[i]); \ | |
8e260fc0 TT |
163 | \ |
164 | /* Now process all the free handlers. */ \ | |
165 | \ | |
166 | for (registration = TAG ## _data_registry.registrations, i = 0; \ | |
6b81941e | 167 | i < rdata->num_data; \ |
8e260fc0 | 168 | registration = registration->next, i++) \ |
6b81941e TT |
169 | if (rdata->data[i] != NULL && registration->data->free != NULL) \ |
170 | registration->data->free (container, rdata->data[i]); \ | |
8e260fc0 | 171 | \ |
6b81941e | 172 | memset (rdata->data, 0, rdata->num_data * sizeof (void *)); \ |
8e260fc0 TT |
173 | } \ |
174 | \ | |
175 | static void \ | |
176 | TAG ## _free_data (struct TAG *container) \ | |
177 | { \ | |
6b81941e TT |
178 | struct registry_fields *rdata = &ACCESS (container)->registry_data; \ |
179 | gdb_assert (rdata->data != NULL); \ | |
8e260fc0 | 180 | clear_ ## TAG ## _data (container); \ |
6b81941e TT |
181 | xfree (rdata->data); \ |
182 | rdata->data = NULL; \ | |
8e260fc0 TT |
183 | } \ |
184 | \ | |
185 | void \ | |
186 | set_ ## TAG ## _data (struct TAG *container, const struct TAG ## _data *data, \ | |
187 | void *value) \ | |
188 | { \ | |
6b81941e TT |
189 | struct registry_fields *rdata = &ACCESS (container)->registry_data; \ |
190 | gdb_assert (data->index < rdata->num_data); \ | |
191 | rdata->data[data->index] = value; \ | |
8e260fc0 TT |
192 | } \ |
193 | \ | |
194 | void * \ | |
195 | TAG ## _data (struct TAG *container, const struct TAG ## _data *data) \ | |
196 | { \ | |
6b81941e TT |
197 | struct registry_fields *rdata = &ACCESS (container)->registry_data; \ |
198 | gdb_assert (data->index < rdata->num_data); \ | |
199 | return rdata->data[data->index]; \ | |
8e260fc0 TT |
200 | } |
201 | ||
202 | ||
203 | /* External declarations for the registry functions. */ | |
204 | ||
205 | #define DECLARE_REGISTRY(TAG) \ | |
206 | extern const struct TAG ## _data *register_ ## TAG ## _data (void); \ | |
207 | extern const struct TAG ## _data *register_ ## TAG ## _data_with_cleanup \ | |
208 | (void (*save) (struct TAG *, void *), void (*free) (struct TAG *, void *)); \ | |
209 | extern void clear_ ## TAG ## _data (struct TAG *); \ | |
210 | extern void set_ ## TAG ## _data (struct TAG *, \ | |
211 | const struct TAG ## _data *data, void *value); \ | |
212 | extern void *TAG ## _data (struct TAG *, \ | |
213 | const struct TAG ## _data *data); | |
214 | ||
215 | #endif /* REGISTRY_H */ |