scm-gsmob.c revision 1.3 1 1.1 christos /* GDB/Scheme smobs (gsmob is pronounced "jee smob")
2 1.1 christos
3 1.1 christos Copyright (C) 2014-2015 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos /* See README file in this directory for implementation notes, coding
21 1.1 christos conventions, et.al. */
22 1.1 christos
23 1.1 christos /* Smobs are Guile's "small object".
24 1.1 christos They are used to export C structs to Scheme.
25 1.1 christos
26 1.1 christos Note: There's only room in the encoding space for 256, and while we won't
27 1.1 christos come close to that, mixed with other libraries maybe someday we could.
28 1.1 christos We don't worry about it now, except to be aware of the issue.
29 1.1 christos We could allocate just a few smobs and use the unused smob flags field to
30 1.1 christos specify the gdb smob kind, that is left for another day if it ever is
31 1.1 christos needed.
32 1.1 christos
33 1.1 christos Some GDB smobs are "chained gsmobs". They are used to assist with life-time
34 1.1 christos tracking of GDB objects vs Scheme objects. Gsmobs can "subclass"
35 1.1 christos chained_gdb_smob, which contains a doubly-linked list to assist with
36 1.1 christos life-time tracking.
37 1.1 christos
38 1.1 christos Some other GDB smobs are "eqable gsmobs". Gsmob implementations can
39 1.1 christos "subclass" eqable_gdb_smob to make gsmobs eq?-able. This is done by
40 1.1 christos recording all gsmobs in a hash table and before creating a gsmob first
41 1.1 christos seeing if it's already in the table. Eqable gsmobs can also be used where
42 1.1 christos lifetime-tracking is required. */
43 1.1 christos
44 1.1 christos #include "defs.h"
45 1.1 christos #include "hashtab.h"
46 1.1 christos #include "objfiles.h"
47 1.1 christos #include "guile-internal.h"
48 1.1 christos
49 1.1 christos /* We need to call this. Undo our hack to prevent others from calling it. */
50 1.1 christos #undef scm_make_smob_type
51 1.1 christos
52 1.1 christos static htab_t registered_gsmobs;
53 1.1 christos
54 1.1 christos /* Hash function for registered_gsmobs hash table. */
55 1.1 christos
56 1.1 christos static hashval_t
57 1.1 christos hash_scm_t_bits (const void *item)
58 1.1 christos {
59 1.1 christos uintptr_t v = (uintptr_t) item;
60 1.1 christos
61 1.1 christos return v;
62 1.1 christos }
63 1.1 christos
64 1.1 christos /* Equality function for registered_gsmobs hash table. */
65 1.1 christos
66 1.1 christos static int
67 1.1 christos eq_scm_t_bits (const void *item_lhs, const void *item_rhs)
68 1.1 christos {
69 1.1 christos return item_lhs == item_rhs;
70 1.1 christos }
71 1.1 christos
72 1.1 christos /* Record GSMOB_CODE as being a gdb smob.
73 1.1 christos GSMOB_CODE is the result of scm_make_smob_type. */
74 1.1 christos
75 1.1 christos static void
76 1.1 christos register_gsmob (scm_t_bits gsmob_code)
77 1.1 christos {
78 1.1 christos void **slot;
79 1.1 christos
80 1.1 christos slot = htab_find_slot (registered_gsmobs, (void *) gsmob_code, INSERT);
81 1.1 christos gdb_assert (*slot == NULL);
82 1.1 christos *slot = (void *) gsmob_code;
83 1.1 christos }
84 1.1 christos
85 1.1 christos /* Return non-zero if SCM is any registered gdb smob object. */
86 1.1 christos
87 1.1 christos static int
88 1.1 christos gdbscm_is_gsmob (SCM scm)
89 1.1 christos {
90 1.1 christos void **slot;
91 1.1 christos
92 1.1 christos if (SCM_IMP (scm))
93 1.1 christos return 0;
94 1.1 christos slot = htab_find_slot (registered_gsmobs, (void *) SCM_TYP16 (scm),
95 1.1 christos NO_INSERT);
96 1.1 christos return slot != NULL;
97 1.1 christos }
98 1.1 christos
99 1.1 christos /* Call this to register a smob, instead of scm_make_smob_type. */
100 1.1 christos
101 1.1 christos scm_t_bits
102 1.1 christos gdbscm_make_smob_type (const char *name, size_t size)
103 1.1 christos {
104 1.1 christos scm_t_bits result = scm_make_smob_type (name, size);
105 1.1 christos
106 1.1 christos register_gsmob (result);
107 1.1 christos return result;
108 1.1 christos }
109 1.1 christos
110 1.1 christos /* Initialize a gsmob. */
111 1.1 christos
112 1.1 christos void
113 1.1 christos gdbscm_init_gsmob (gdb_smob *base)
114 1.1 christos {
115 1.1 christos base->empty_base_class = 0;
116 1.1 christos }
117 1.1 christos
118 1.1 christos /* Initialize a chained_gdb_smob.
119 1.1 christos This is the same as gdbscm_init_gsmob except that it also sets prev,next
120 1.1 christos to NULL. */
121 1.1 christos
122 1.1 christos void
123 1.1 christos gdbscm_init_chained_gsmob (chained_gdb_smob *base)
124 1.1 christos {
125 1.1 christos gdbscm_init_gsmob ((gdb_smob *) base);
126 1.1 christos base->prev = NULL;
127 1.1 christos base->next = NULL;
128 1.1 christos }
129 1.1 christos
130 1.1 christos /* Initialize an eqable_gdb_smob.
131 1.1 christos This is the same as gdbscm_init_gsmob except that it also sets
132 1.1 christos BASE->containing_scm to CONTAINING_SCM. */
133 1.1 christos
134 1.1 christos void
135 1.1 christos gdbscm_init_eqable_gsmob (eqable_gdb_smob *base, SCM containing_scm)
136 1.1 christos {
137 1.1 christos gdbscm_init_gsmob ((gdb_smob *) base);
138 1.1 christos base->containing_scm = containing_scm;
139 1.1 christos }
140 1.1 christos
141 1.1 christos
142 1.1 christos /* gsmob accessors */
144 1.1 christos
145 1.1 christos /* Return the gsmob in SELF.
146 1.1 christos Throws an exception if SELF is not a gsmob. */
147 1.1 christos
148 1.1 christos static SCM
149 1.1 christos gsscm_get_gsmob_arg_unsafe (SCM self, int arg_pos, const char *func_name)
150 1.1 christos {
151 1.1 christos SCM_ASSERT_TYPE (gdbscm_is_gsmob (self), self, arg_pos, func_name,
152 1.1 christos _("any gdb smob"));
153 1.1 christos
154 1.1 christos return self;
155 1.1 christos }
156 1.1 christos
157 1.1 christos /* (gdb-object-kind gsmob) -> symbol
158 1.1 christos
159 1.1 christos Note: While one might want to name this gdb-object-class-name, it is named
160 1.1 christos "-kind" because smobs aren't real GOOPS classes. */
161 1.1 christos
162 1.1 christos static SCM
163 1.1 christos gdbscm_gsmob_kind (SCM self)
164 1.1 christos {
165 1.1 christos SCM smob, result;
166 1.1 christos scm_t_bits smobnum;
167 1.1 christos const char *name;
168 1.1 christos char *kind;
169 1.1 christos
170 1.1 christos smob = gsscm_get_gsmob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
171 1.1 christos
172 1.1 christos smobnum = SCM_SMOBNUM (smob);
173 1.1 christos name = SCM_SMOBNAME (smobnum);
174 1.1 christos kind = xstrprintf ("<%s>", name);
175 1.1 christos result = scm_from_latin1_symbol (kind);
176 1.1 christos xfree (kind);
177 1.1 christos
178 1.1 christos return result;
179 1.1 christos }
180 1.1 christos
181 1.1 christos
182 1.1 christos /* When underlying gdb data structures are deleted, we need to update any
184 1.1 christos smobs with references to them. There are several smobs that reference
185 1.1 christos objfile-based data, so we provide helpers to manage this. */
186 1.1 christos
187 1.1 christos /* Add G_SMOB to the reference chain for OBJFILE specified by DATA_KEY.
188 1.1 christos OBJFILE may be NULL, in which case just set prev,next to NULL. */
189 1.1 christos
190 1.1 christos void
191 1.1 christos gdbscm_add_objfile_ref (struct objfile *objfile,
192 1.1 christos const struct objfile_data *data_key,
193 1.1 christos chained_gdb_smob *g_smob)
194 1.1 christos {
195 1.1 christos g_smob->prev = NULL;
196 1.1 christos if (objfile != NULL)
197 1.1 christos {
198 1.1 christos g_smob->next = objfile_data (objfile, data_key);
199 1.1 christos if (g_smob->next)
200 1.1 christos g_smob->next->prev = g_smob;
201 1.1 christos set_objfile_data (objfile, data_key, g_smob);
202 1.1 christos }
203 1.1 christos else
204 1.1 christos g_smob->next = NULL;
205 1.1 christos }
206 1.1 christos
207 1.1 christos /* Remove G_SMOB from the reference chain for OBJFILE specified
208 1.1 christos by DATA_KEY. OBJFILE may be NULL. */
209 1.1 christos
210 1.1 christos void
211 1.1 christos gdbscm_remove_objfile_ref (struct objfile *objfile,
212 1.1 christos const struct objfile_data *data_key,
213 1.1 christos chained_gdb_smob *g_smob)
214 1.1 christos {
215 1.1 christos if (g_smob->prev)
216 1.1 christos g_smob->prev->next = g_smob->next;
217 1.1 christos else if (objfile != NULL)
218 1.1 christos set_objfile_data (objfile, data_key, g_smob->next);
219 1.1 christos if (g_smob->next)
220 1.1 christos g_smob->next->prev = g_smob->prev;
221 1.1 christos }
222 1.1 christos
223 1.1 christos /* Create a hash table for mapping a pointer to a gdb data structure to the
224 1.1 christos gsmob that wraps it. */
225 1.1 christos
226 1.1 christos htab_t
227 1.1 christos gdbscm_create_eqable_gsmob_ptr_map (htab_hash hash_fn, htab_eq eq_fn)
228 1.1 christos {
229 1.1 christos htab_t htab = htab_create_alloc (7, hash_fn, eq_fn,
230 1.1 christos NULL, xcalloc, xfree);
231 1.1 christos
232 1.1 christos return htab;
233 1.1 christos }
234 1.1 christos
235 1.1 christos /* Return a pointer to the htab entry for the eq?-able gsmob BASE.
236 1.1 christos If the entry is found, *SLOT is non-NULL.
237 1.1 christos Otherwise *slot is NULL. */
238 1.1 christos
239 1.1 christos eqable_gdb_smob **
240 1.1 christos gdbscm_find_eqable_gsmob_ptr_slot (htab_t htab, eqable_gdb_smob *base)
241 1.1 christos {
242 1.1 christos void **slot = htab_find_slot (htab, base, INSERT);
243 1.1 christos
244 1.1 christos return (eqable_gdb_smob **) slot;
245 1.1 christos }
246 1.1 christos
247 1.1 christos /* Record BASE in SLOT. SLOT must be the result of calling
248 1.1 christos gdbscm_find_eqable_gsmob_ptr_slot on BASE (or equivalent for lookup). */
249 1.1 christos
250 1.1 christos void
251 1.1 christos gdbscm_fill_eqable_gsmob_ptr_slot (eqable_gdb_smob **slot,
252 1.1 christos eqable_gdb_smob *base)
253 1.1 christos {
254 1.1 christos *slot = base;
255 1.1 christos }
256 1.1 christos
257 1.1 christos /* Remove BASE from HTAB.
258 1.1 christos BASE is a pointer to a gsmob that wraps a pointer to a GDB datum.
259 1.1 christos This is used, for example, when an object is freed.
260 1.1 christos
261 1.1 christos It is an error to call this if PTR is not in HTAB (only because it allows
262 1.1 christos for some consistency checking). */
263 1.1 christos
264 1.1 christos void
265 1.1 christos gdbscm_clear_eqable_gsmob_ptr_slot (htab_t htab, eqable_gdb_smob *base)
266 1.1 christos {
267 1.1 christos void **slot = htab_find_slot (htab, base, NO_INSERT);
268 1.1 christos
269 1.1 christos gdb_assert (slot != NULL);
270 1.1 christos htab_clear_slot (htab, slot);
271 1.1 christos }
272 1.1 christos
273 1.1 christos /* Initialize the Scheme gsmobs code. */
275 1.1 christos
276 1.1 christos static const scheme_function gsmob_functions[] =
277 1.1 christos {
278 1.1 christos /* N.B. There is a general rule of not naming symbols in gdb-guile with a
279 1.1 christos "gdb" prefix. This symbol does not violate this rule because it is to
280 1.1 christos be read as "gdb-object-foo", not "gdb-foo". */
281 1.1 christos { "gdb-object-kind", 1, 0, 0, gdbscm_gsmob_kind,
282 1.1 christos "\
283 1.1 christos Return the kind of the GDB object, e.g., <gdb:breakpoint>, as a symbol." },
284 1.1 christos
285 1.1 christos END_FUNCTIONS
286 1.1 christos };
287 1.1 christos
288 1.1 christos void
289 1.1 christos gdbscm_initialize_smobs (void)
290 1.1 christos {
291 1.1 christos registered_gsmobs = htab_create_alloc (10,
292 1.1 christos hash_scm_t_bits, eq_scm_t_bits,
293 1.1 christos NULL, xcalloc, xfree);
294
295 gdbscm_define_functions (gsmob_functions, 1);
296 }
297