Home | History | Annotate | Line # | Download | only in guile
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