Home | History | Annotate | Line # | Download | only in libctf
      1 /* Interface to hashtable implementations.
      2    Copyright (C) 2006-2025 Free Software Foundation, Inc.
      3 
      4    This file is part of libctf.
      5 
      6    libctf is free software; you can redistribute it and/or modify it under
      7    the terms of the GNU General Public License as published by the Free
      8    Software Foundation; either version 3, or (at your option) any later
      9    version.
     10 
     11    This program is distributed in the hope that it will be useful, but
     12    WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     14    See the GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; see the file COPYING.  If not see
     18    <http://www.gnu.org/licenses/>.  */
     19 
     20 #include <ctf-impl.h>
     21 #include <string.h>
     22 #include "libiberty.h"
     23 #include "hashtab.h"
     24 
     25 /* We have two hashtable implementations:
     26 
     27    - ctf_dynhash_* is an interface to a dynamically-expanding hash with
     28      unknown size that should support addition of large numbers of items,
     29      and removal as well, and is used only at type-insertion time and during
     30      linking.  It can be constructed with an expected initial number of
     31      elements, but need not be.
     32 
     33    - ctf_dynset_* is an interface to a dynamically-expanding hash that contains
     34      only keys: no values.
     35 
     36    These can be implemented by the same underlying hashmap if you wish.  */
     37 
     38 /* The helem is used for general key/value mappings in the ctf_dynhash: the
     39    owner may not have space allocated for it, and will be garbage (not
     40    NULL!) in that case.  */
     41 
     42 typedef struct ctf_helem
     43 {
     44   void *key;			 /* Either a pointer, or a coerced ctf_id_t.  */
     45   void *value;			 /* The value (possibly a coerced int).  */
     46   ctf_dynhash_t *owner;          /* The hash that owns us.  */
     47 } ctf_helem_t;
     48 
     49 /* Equally, the key_free and value_free may not exist.  */
     50 
     51 struct ctf_dynhash
     52 {
     53   struct htab *htab;
     54   ctf_hash_free_fun key_free;
     55   ctf_hash_free_fun value_free;
     56 };
     57 
     58 /* Hash and eq functions for the dynhash and hash. */
     59 
     60 unsigned int
     61 ctf_hash_integer (const void *ptr)
     62 {
     63   ctf_helem_t *hep = (ctf_helem_t *) ptr;
     64 
     65   return htab_hash_pointer (hep->key);
     66 }
     67 
     68 int
     69 ctf_hash_eq_integer (const void *a, const void *b)
     70 {
     71   ctf_helem_t *hep_a = (ctf_helem_t *) a;
     72   ctf_helem_t *hep_b = (ctf_helem_t *) b;
     73 
     74   return htab_eq_pointer (hep_a->key, hep_b->key);
     75 }
     76 
     77 unsigned int
     78 ctf_hash_string (const void *ptr)
     79 {
     80   ctf_helem_t *hep = (ctf_helem_t *) ptr;
     81 
     82   return htab_hash_string (hep->key);
     83 }
     84 
     85 int
     86 ctf_hash_eq_string (const void *a, const void *b)
     87 {
     88   ctf_helem_t *hep_a = (ctf_helem_t *) a;
     89   ctf_helem_t *hep_b = (ctf_helem_t *) b;
     90 
     91   return !strcmp((const char *) hep_a->key, (const char *) hep_b->key);
     92 }
     93 
     94 /* Hash a type_key.  */
     95 unsigned int
     96 ctf_hash_type_key (const void *ptr)
     97 {
     98   ctf_helem_t *hep = (ctf_helem_t *) ptr;
     99   ctf_link_type_key_t *k = (ctf_link_type_key_t *) hep->key;
    100 
    101   return htab_hash_pointer (k->cltk_fp) + 59
    102     * htab_hash_pointer ((void *) (uintptr_t) k->cltk_idx);
    103 }
    104 
    105 int
    106 ctf_hash_eq_type_key (const void *a, const void *b)
    107 {
    108   ctf_helem_t *hep_a = (ctf_helem_t *) a;
    109   ctf_helem_t *hep_b = (ctf_helem_t *) b;
    110   ctf_link_type_key_t *key_a = (ctf_link_type_key_t *) hep_a->key;
    111   ctf_link_type_key_t *key_b = (ctf_link_type_key_t *) hep_b->key;
    112 
    113   return (key_a->cltk_fp == key_b->cltk_fp)
    114     && (key_a->cltk_idx == key_b->cltk_idx);
    115 }
    116 
    117 /* Hash a type_id_key.  */
    118 unsigned int
    119 ctf_hash_type_id_key (const void *ptr)
    120 {
    121   ctf_helem_t *hep = (ctf_helem_t *) ptr;
    122   ctf_type_id_key_t *k = (ctf_type_id_key_t *) hep->key;
    123 
    124   return htab_hash_pointer ((void *) (uintptr_t) k->ctii_input_num)
    125     + 59 * htab_hash_pointer ((void *) (uintptr_t) k->ctii_type);
    126 }
    127 
    128 int
    129 ctf_hash_eq_type_id_key (const void *a, const void *b)
    130 {
    131   ctf_helem_t *hep_a = (ctf_helem_t *) a;
    132   ctf_helem_t *hep_b = (ctf_helem_t *) b;
    133   ctf_type_id_key_t *key_a = (ctf_type_id_key_t *) hep_a->key;
    134   ctf_type_id_key_t *key_b = (ctf_type_id_key_t *) hep_b->key;
    135 
    136   return (key_a->ctii_input_num == key_b->ctii_input_num)
    137     && (key_a->ctii_type == key_b->ctii_type);
    138 }
    139 
    140 /* The dynhash, used for hashes whose size is not known at creation time. */
    141 
    142 /* Free a single ctf_helem with arbitrary key/value functions.  */
    143 
    144 static void
    145 ctf_dynhash_item_free (void *item)
    146 {
    147   ctf_helem_t *helem = item;
    148 
    149   if (helem->owner->key_free && helem->key)
    150     helem->owner->key_free (helem->key);
    151   if (helem->owner->value_free && helem->value)
    152     helem->owner->value_free (helem->value);
    153   free (helem);
    154 }
    155 
    156 ctf_dynhash_t *
    157 ctf_dynhash_create_sized (unsigned long nelems, ctf_hash_fun hash_fun,
    158 			  ctf_hash_eq_fun eq_fun, ctf_hash_free_fun key_free,
    159 			  ctf_hash_free_fun value_free)
    160 {
    161   ctf_dynhash_t *dynhash;
    162   htab_del del = ctf_dynhash_item_free;
    163 
    164   if (key_free || value_free)
    165     dynhash = malloc (sizeof (ctf_dynhash_t));
    166   else
    167     {
    168       void *p = malloc (offsetof (ctf_dynhash_t, key_free));
    169       dynhash = p;
    170     }
    171   if (!dynhash)
    172     return NULL;
    173 
    174   if (key_free == NULL && value_free == NULL)
    175     del = free;
    176 
    177   if ((dynhash->htab = htab_create_alloc (nelems, (htab_hash) hash_fun, eq_fun,
    178 					  del, xcalloc, free)) == NULL)
    179     {
    180       free (dynhash);
    181       return NULL;
    182     }
    183 
    184   if (key_free || value_free)
    185     {
    186       dynhash->key_free = key_free;
    187       dynhash->value_free = value_free;
    188     }
    189 
    190   return dynhash;
    191 }
    192 
    193 ctf_dynhash_t *
    194 ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
    195 		    ctf_hash_free_fun key_free, ctf_hash_free_fun value_free)
    196 {
    197   /* 7 is arbitrary and not benchmarked yet.  */
    198 
    199   return ctf_dynhash_create_sized (7, hash_fun, eq_fun, key_free, value_free);
    200 }
    201 
    202 static ctf_helem_t **
    203 ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert)
    204 {
    205   ctf_helem_t tmp = { .key = (void *) key };
    206   return (ctf_helem_t **) htab_find_slot (htab, &tmp, insert);
    207 }
    208 
    209 static ctf_helem_t *
    210 ctf_hashtab_insert (struct htab *htab, void *key, void *value,
    211 		    ctf_hash_free_fun key_free,
    212 		    ctf_hash_free_fun value_free)
    213 {
    214   ctf_helem_t **slot;
    215 
    216   slot = ctf_hashtab_lookup (htab, key, INSERT);
    217 
    218   if (!slot)
    219     {
    220       errno = ENOMEM;
    221       return NULL;
    222     }
    223 
    224   if (!*slot)
    225     {
    226       /* Only spend space on the owner if we're going to use it: if there is a
    227 	 key or value freeing function.  */
    228       if (key_free || value_free)
    229 	*slot = malloc (sizeof (ctf_helem_t));
    230       else
    231 	{
    232 	  void *p = malloc (offsetof (ctf_helem_t, owner));
    233 	  *slot = p;
    234 	}
    235       if (!*slot)
    236 	return NULL;
    237       (*slot)->key = key;
    238     }
    239   else
    240     {
    241       if (key_free)
    242 	  key_free (key);
    243       if (value_free)
    244 	  value_free ((*slot)->value);
    245     }
    246   (*slot)->value = value;
    247   return *slot;
    248 }
    249 
    250 int
    251 ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value)
    252 {
    253   ctf_helem_t *slot;
    254   ctf_hash_free_fun key_free = NULL, value_free = NULL;
    255 
    256   if (hp->htab->del_f == ctf_dynhash_item_free)
    257     {
    258       key_free = hp->key_free;
    259       value_free = hp->value_free;
    260     }
    261   slot = ctf_hashtab_insert (hp->htab, key, value,
    262 			     key_free, value_free);
    263 
    264   if (!slot)
    265     return -errno;
    266 
    267   /* Keep track of the owner, so that the del function can get at the key_free
    268      and value_free functions.  Only do this if one of those functions is set:
    269      if not, the owner is not even present in the helem.  */
    270 
    271   if (key_free || value_free)
    272     slot->owner = hp;
    273 
    274   return 0;
    275 }
    276 
    277 void
    278 ctf_dynhash_remove (ctf_dynhash_t *hp, const void *key)
    279 {
    280   ctf_helem_t hep = { (void *) key, NULL, NULL };
    281   htab_remove_elt (hp->htab, &hep);
    282 }
    283 
    284 void
    285 ctf_dynhash_empty (ctf_dynhash_t *hp)
    286 {
    287   htab_empty (hp->htab);
    288 }
    289 
    290 size_t
    291 ctf_dynhash_elements (ctf_dynhash_t *hp)
    292 {
    293   return htab_elements (hp->htab);
    294 }
    295 
    296 void *
    297 ctf_dynhash_lookup (ctf_dynhash_t *hp, const void *key)
    298 {
    299   ctf_helem_t **slot;
    300 
    301   slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT);
    302 
    303   if (slot)
    304     return (*slot)->value;
    305 
    306   return NULL;
    307 }
    308 
    309 /* TRUE/FALSE return.  */
    310 int
    311 ctf_dynhash_lookup_kv (ctf_dynhash_t *hp, const void *key,
    312 		       const void **orig_key, void **value)
    313 {
    314   ctf_helem_t **slot;
    315 
    316   slot = ctf_hashtab_lookup (hp->htab, key, NO_INSERT);
    317 
    318   if (slot)
    319     {
    320       if (orig_key)
    321 	*orig_key = (*slot)->key;
    322       if (value)
    323 	*value = (*slot)->value;
    324       return 1;
    325     }
    326   return 0;
    327 }
    328 
    329 typedef struct ctf_traverse_cb_arg
    330 {
    331   ctf_hash_iter_f fun;
    332   void *arg;
    333 } ctf_traverse_cb_arg_t;
    334 
    335 static int
    336 ctf_hashtab_traverse (void **slot, void *arg_)
    337 {
    338   ctf_helem_t *helem = *((ctf_helem_t **) slot);
    339   ctf_traverse_cb_arg_t *arg = (ctf_traverse_cb_arg_t *) arg_;
    340 
    341   arg->fun (helem->key, helem->value, arg->arg);
    342   return 1;
    343 }
    344 
    345 void
    346 ctf_dynhash_iter (ctf_dynhash_t *hp, ctf_hash_iter_f fun, void *arg_)
    347 {
    348   ctf_traverse_cb_arg_t arg = { fun, arg_ };
    349   htab_traverse (hp->htab, ctf_hashtab_traverse, &arg);
    350 }
    351 
    352 typedef struct ctf_traverse_find_cb_arg
    353 {
    354   ctf_hash_iter_find_f fun;
    355   void *arg;
    356   void *found_key;
    357 } ctf_traverse_find_cb_arg_t;
    358 
    359 static int
    360 ctf_hashtab_traverse_find (void **slot, void *arg_)
    361 {
    362   ctf_helem_t *helem = *((ctf_helem_t **) slot);
    363   ctf_traverse_find_cb_arg_t *arg = (ctf_traverse_find_cb_arg_t *) arg_;
    364 
    365   if (arg->fun (helem->key, helem->value, arg->arg))
    366     {
    367       arg->found_key = helem->key;
    368       return 0;
    369     }
    370   return 1;
    371 }
    372 
    373 void *
    374 ctf_dynhash_iter_find (ctf_dynhash_t *hp, ctf_hash_iter_find_f fun, void *arg_)
    375 {
    376   ctf_traverse_find_cb_arg_t arg = { fun, arg_, NULL };
    377   htab_traverse (hp->htab, ctf_hashtab_traverse_find, &arg);
    378   return arg.found_key;
    379 }
    380 
    381 typedef struct ctf_traverse_remove_cb_arg
    382 {
    383   struct htab *htab;
    384   ctf_hash_iter_remove_f fun;
    385   void *arg;
    386 } ctf_traverse_remove_cb_arg_t;
    387 
    388 static int
    389 ctf_hashtab_traverse_remove (void **slot, void *arg_)
    390 {
    391   ctf_helem_t *helem = *((ctf_helem_t **) slot);
    392   ctf_traverse_remove_cb_arg_t *arg = (ctf_traverse_remove_cb_arg_t *) arg_;
    393 
    394   if (arg->fun (helem->key, helem->value, arg->arg))
    395     htab_clear_slot (arg->htab, slot);
    396   return 1;
    397 }
    398 
    399 void
    400 ctf_dynhash_iter_remove (ctf_dynhash_t *hp, ctf_hash_iter_remove_f fun,
    401                          void *arg_)
    402 {
    403   ctf_traverse_remove_cb_arg_t arg = { hp->htab, fun, arg_ };
    404   htab_traverse (hp->htab, ctf_hashtab_traverse_remove, &arg);
    405 }
    406 
    407 /* Traverse a dynhash in arbitrary order, in _next iterator form.
    408 
    409    Adding entries to the dynhash while iterating is not supported (just as it
    410    isn't for htab_traverse).  Deleting is fine (see ctf_dynhash_next_remove,
    411    below).
    412 
    413    Note: unusually, this returns zero on success and a *positive* value on
    414    error, because it does not take an fp, taking an error pointer would be
    415    incredibly clunky, and nearly all error-handling ends up stuffing the result
    416    of this into some sort of errno or ctf_errno, which is invariably
    417    positive.  So doing this simplifies essentially all callers.  */
    418 int
    419 ctf_dynhash_next (ctf_dynhash_t *h, ctf_next_t **it, void **key, void **value)
    420 {
    421   ctf_next_t *i = *it;
    422   ctf_helem_t *slot;
    423 
    424   if (!i)
    425     {
    426       size_t size = htab_size (h->htab);
    427 
    428       /* If the table has too many entries to fit in an ssize_t, just give up.
    429 	 This might be spurious, but if any type-related hashtable has ever been
    430 	 nearly as large as that then something very odd is going on.  */
    431       if (((ssize_t) size) < 0)
    432 	return EDOM;
    433 
    434       if ((i = ctf_next_create ()) == NULL)
    435 	return ENOMEM;
    436 
    437       i->u.ctn_hash_slot = h->htab->entries;
    438       i->cu.ctn_h = h;
    439       i->ctn_n = 0;
    440       i->ctn_size = (ssize_t) size;
    441       i->ctn_iter_fun = (void (*) (void)) ctf_dynhash_next;
    442       *it = i;
    443     }
    444 
    445   if ((void (*) (void)) ctf_dynhash_next != i->ctn_iter_fun)
    446     return ECTF_NEXT_WRONGFUN;
    447 
    448   if (h != i->cu.ctn_h)
    449     return ECTF_NEXT_WRONGFP;
    450 
    451   if ((ssize_t) i->ctn_n == i->ctn_size)
    452     goto hash_end;
    453 
    454   while ((ssize_t) i->ctn_n < i->ctn_size
    455 	 && (*i->u.ctn_hash_slot == HTAB_EMPTY_ENTRY
    456 	     || *i->u.ctn_hash_slot == HTAB_DELETED_ENTRY))
    457     {
    458       i->u.ctn_hash_slot++;
    459       i->ctn_n++;
    460     }
    461 
    462   if ((ssize_t) i->ctn_n == i->ctn_size)
    463     goto hash_end;
    464 
    465   slot = *i->u.ctn_hash_slot;
    466 
    467   if (key)
    468     *key = slot->key;
    469   if (value)
    470     *value = slot->value;
    471 
    472   i->u.ctn_hash_slot++;
    473   i->ctn_n++;
    474 
    475   return 0;
    476 
    477  hash_end:
    478   ctf_next_destroy (i);
    479   *it = NULL;
    480   return ECTF_NEXT_END;
    481 }
    482 
    483 /* Remove the entry most recently returned by ctf_dynhash_next.
    484 
    485    Returns ECTF_NEXT_END if this is impossible (already removed, iterator not
    486    initialized, iterator off the end).  */
    487 
    488 int
    489 ctf_dynhash_next_remove (ctf_next_t * const *it)
    490 {
    491   ctf_next_t *i = *it;
    492 
    493   if ((void (*) (void)) ctf_dynhash_next != i->ctn_iter_fun)
    494     return ECTF_NEXT_WRONGFUN;
    495 
    496   if (!i)
    497     return ECTF_NEXT_END;
    498 
    499   if (i->ctn_n == 0)
    500     return ECTF_NEXT_END;
    501 
    502   htab_clear_slot (i->cu.ctn_h->htab, i->u.ctn_hash_slot - 1);
    503 
    504   return 0;
    505 }
    506 
    507 int
    508 ctf_dynhash_sort_by_name (const ctf_next_hkv_t *one, const ctf_next_hkv_t *two,
    509 			  void *unused _libctf_unused_)
    510 {
    511   return strcmp ((char *) one->hkv_key, (char *) two->hkv_key);
    512 }
    513 
    514 /* Traverse a sorted dynhash, in _next iterator form.
    515 
    516    See ctf_dynhash_next for notes on error returns, etc.
    517 
    518    Sort keys before iterating over them using the SORT_FUN and SORT_ARG.
    519 
    520    If SORT_FUN is null, thunks to ctf_dynhash_next.  */
    521 int
    522 ctf_dynhash_next_sorted (ctf_dynhash_t *h, ctf_next_t **it, void **key,
    523 			 void **value, ctf_hash_sort_f sort_fun, void *sort_arg)
    524 {
    525   ctf_next_t *i = *it;
    526 
    527   if (sort_fun == NULL)
    528     return ctf_dynhash_next (h, it, key, value);
    529 
    530   if (!i)
    531     {
    532       size_t els = ctf_dynhash_elements (h);
    533       ctf_next_t *accum_i = NULL;
    534       void *key, *value;
    535       int err;
    536       ctf_next_hkv_t *walk;
    537 
    538       if (((ssize_t) els) < 0)
    539 	return EDOM;
    540 
    541       if ((i = ctf_next_create ()) == NULL)
    542 	return ENOMEM;
    543 
    544       if ((i->u.ctn_sorted_hkv = calloc (els, sizeof (ctf_next_hkv_t))) == NULL)
    545 	{
    546 	  ctf_next_destroy (i);
    547 	  return ENOMEM;
    548 	}
    549       walk = i->u.ctn_sorted_hkv;
    550 
    551       i->cu.ctn_h = h;
    552 
    553       while ((err = ctf_dynhash_next (h, &accum_i, &key, &value)) == 0)
    554 	{
    555 	  walk->hkv_key = key;
    556 	  walk->hkv_value = value;
    557 	  walk++;
    558 	}
    559       if (err != ECTF_NEXT_END)
    560 	{
    561 	  ctf_next_destroy (i);
    562 	  return err;
    563 	}
    564 
    565       if (sort_fun)
    566 	  ctf_qsort_r (i->u.ctn_sorted_hkv, els, sizeof (ctf_next_hkv_t),
    567 		       (int (*) (const void *, const void *, void *)) sort_fun,
    568 		       sort_arg);
    569       i->ctn_n = 0;
    570       i->ctn_size = (ssize_t) els;
    571       i->ctn_iter_fun = (void (*) (void)) ctf_dynhash_next_sorted;
    572       *it = i;
    573     }
    574 
    575   if ((void (*) (void)) ctf_dynhash_next_sorted != i->ctn_iter_fun)
    576     return ECTF_NEXT_WRONGFUN;
    577 
    578   if (h != i->cu.ctn_h)
    579     return ECTF_NEXT_WRONGFP;
    580 
    581   if ((ssize_t) i->ctn_n == i->ctn_size)
    582     {
    583       ctf_next_destroy (i);
    584       *it = NULL;
    585       return ECTF_NEXT_END;
    586     }
    587 
    588   if (key)
    589     *key = i->u.ctn_sorted_hkv[i->ctn_n].hkv_key;
    590   if (value)
    591     *value = i->u.ctn_sorted_hkv[i->ctn_n].hkv_value;
    592   i->ctn_n++;
    593   return 0;
    594 }
    595 
    596 void
    597 ctf_dynhash_destroy (ctf_dynhash_t *hp)
    598 {
    599   if (hp != NULL)
    600     htab_delete (hp->htab);
    601   free (hp);
    602 }
    603 
    604 /* The dynset, used for sets of keys with no value.  The implementation of this
    605    can be much simpler, because without a value the slot can simply be the
    606    stored key, which means we don't need to store the freeing functions and the
    607    dynset itself is just a htab.  */
    608 
    609 ctf_dynset_t *
    610 ctf_dynset_create (htab_hash hash_fun, htab_eq eq_fun,
    611 		   ctf_hash_free_fun key_free)
    612 {
    613   /* 7 is arbitrary and untested for now.  */
    614   return (ctf_dynset_t *) htab_create_alloc (7, (htab_hash) hash_fun, eq_fun,
    615 					     key_free, xcalloc, free);
    616 }
    617 
    618 /* The dynset has one complexity: the underlying implementation reserves two
    619    values for internal hash table implementation details (empty versus deleted
    620    entries).  These values are otherwise very useful for pointers cast to ints,
    621    so transform the ctf_dynset_inserted value to allow for it.  (This
    622    introduces an ambiguity in that one can no longer store these two values in
    623    the dynset, but if we pick high enough values this is very unlikely to be a
    624    problem.)
    625 
    626    We leak this implementation detail to the freeing functions on the grounds
    627    that any use of these functions is overwhelmingly likely to be in sets using
    628    real pointers, which will be unaffected.  */
    629 
    630 #define DYNSET_EMPTY_ENTRY_REPLACEMENT ((void *) (uintptr_t) -64)
    631 #define DYNSET_DELETED_ENTRY_REPLACEMENT ((void *) (uintptr_t) -63)
    632 
    633 static void *
    634 key_to_internal (const void *key)
    635 {
    636   if (key == HTAB_EMPTY_ENTRY)
    637     return DYNSET_EMPTY_ENTRY_REPLACEMENT;
    638   else if (key == HTAB_DELETED_ENTRY)
    639     return DYNSET_DELETED_ENTRY_REPLACEMENT;
    640 
    641   return (void *) key;
    642 }
    643 
    644 static void *
    645 internal_to_key (const void *internal)
    646 {
    647   if (internal == DYNSET_EMPTY_ENTRY_REPLACEMENT)
    648     return HTAB_EMPTY_ENTRY;
    649   else if (internal == DYNSET_DELETED_ENTRY_REPLACEMENT)
    650     return HTAB_DELETED_ENTRY;
    651   return (void *) internal;
    652 }
    653 
    654 int
    655 ctf_dynset_insert (ctf_dynset_t *hp, void *key)
    656 {
    657   struct htab *htab = (struct htab *) hp;
    658   void **slot;
    659 
    660   slot = htab_find_slot (htab, key_to_internal (key), INSERT);
    661 
    662   if (!slot)
    663     {
    664       errno = ENOMEM;
    665       return -errno;
    666     }
    667 
    668   if (*slot)
    669     {
    670       if (htab->del_f)
    671 	(*htab->del_f) (*slot);
    672     }
    673 
    674   *slot = key_to_internal (key);
    675 
    676   return 0;
    677 }
    678 
    679 void
    680 ctf_dynset_remove (ctf_dynset_t *hp, const void *key)
    681 {
    682   htab_remove_elt ((struct htab *) hp, key_to_internal (key));
    683 }
    684 
    685 size_t
    686 ctf_dynset_elements (ctf_dynset_t *hp)
    687 {
    688   return htab_elements ((struct htab *) hp);
    689 }
    690 
    691 void
    692 ctf_dynset_destroy (ctf_dynset_t *hp)
    693 {
    694   if (hp != NULL)
    695     htab_delete ((struct htab *) hp);
    696 }
    697 
    698 void *
    699 ctf_dynset_lookup (ctf_dynset_t *hp, const void *key)
    700 {
    701   void **slot = htab_find_slot ((struct htab *) hp,
    702 				key_to_internal (key), NO_INSERT);
    703 
    704   if (slot)
    705     return internal_to_key (*slot);
    706   return NULL;
    707 }
    708 
    709 /* TRUE/FALSE return.  */
    710 int
    711 ctf_dynset_exists (ctf_dynset_t *hp, const void *key, const void **orig_key)
    712 {
    713   void **slot = htab_find_slot ((struct htab *) hp,
    714 				key_to_internal (key), NO_INSERT);
    715 
    716   if (orig_key && slot)
    717     *orig_key = internal_to_key (*slot);
    718   return (slot != NULL);
    719 }
    720 
    721 /* Look up a completely random value from the set, if any exist.
    722    Keys with value zero cannot be distinguished from a nonexistent key.  */
    723 void *
    724 ctf_dynset_lookup_any (ctf_dynset_t *hp)
    725 {
    726   struct htab *htab = (struct htab *) hp;
    727   void **slot = htab->entries;
    728   void **limit = slot + htab_size (htab);
    729 
    730   while (slot < limit
    731 	 && (*slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY))
    732       slot++;
    733 
    734   if (slot < limit)
    735     return internal_to_key (*slot);
    736   return NULL;
    737 }
    738 
    739 /* Traverse a dynset in arbitrary order, in _next iterator form.
    740 
    741    Otherwise, just like ctf_dynhash_next.  */
    742 int
    743 ctf_dynset_next (ctf_dynset_t *hp, ctf_next_t **it, void **key)
    744 {
    745   struct htab *htab = (struct htab *) hp;
    746   ctf_next_t *i = *it;
    747   void *slot;
    748 
    749   if (!i)
    750     {
    751       size_t size = htab_size (htab);
    752 
    753       /* If the table has too many entries to fit in an ssize_t, just give up.
    754 	 This might be spurious, but if any type-related hashtable has ever been
    755 	 nearly as large as that then somthing very odd is going on.  */
    756 
    757       if (((ssize_t) size) < 0)
    758 	return EDOM;
    759 
    760       if ((i = ctf_next_create ()) == NULL)
    761 	return ENOMEM;
    762 
    763       i->u.ctn_hash_slot = htab->entries;
    764       i->cu.ctn_s = hp;
    765       i->ctn_n = 0;
    766       i->ctn_size = (ssize_t) size;
    767       i->ctn_iter_fun = (void (*) (void)) ctf_dynset_next;
    768       *it = i;
    769     }
    770 
    771   if ((void (*) (void)) ctf_dynset_next != i->ctn_iter_fun)
    772     return ECTF_NEXT_WRONGFUN;
    773 
    774   if (hp != i->cu.ctn_s)
    775     return ECTF_NEXT_WRONGFP;
    776 
    777   if ((ssize_t) i->ctn_n == i->ctn_size)
    778     goto set_end;
    779 
    780   while ((ssize_t) i->ctn_n < i->ctn_size
    781 	 && (*i->u.ctn_hash_slot == HTAB_EMPTY_ENTRY
    782 	     || *i->u.ctn_hash_slot == HTAB_DELETED_ENTRY))
    783     {
    784       i->u.ctn_hash_slot++;
    785       i->ctn_n++;
    786     }
    787 
    788   if ((ssize_t) i->ctn_n == i->ctn_size)
    789     goto set_end;
    790 
    791   slot = *i->u.ctn_hash_slot;
    792 
    793   if (key)
    794     *key = internal_to_key (slot);
    795 
    796   i->u.ctn_hash_slot++;
    797   i->ctn_n++;
    798 
    799   return 0;
    800 
    801  set_end:
    802   ctf_next_destroy (i);
    803   *it = NULL;
    804   return ECTF_NEXT_END;
    805 }
    806 
    807 /* Helper functions for insertion/removal of types.  */
    808 
    809 int
    810 ctf_dynhash_insert_type (ctf_dict_t *fp, ctf_dynhash_t *hp, uint32_t type,
    811 			 uint32_t name)
    812 {
    813   const char *str;
    814   int err;
    815 
    816   if (type == 0)
    817     return EINVAL;
    818 
    819   if ((str = ctf_strptr_validate (fp, name)) == NULL)
    820     return ctf_errno (fp) * -1;
    821 
    822   if (str[0] == '\0')
    823     return 0;		   /* Just ignore empty strings on behalf of caller.  */
    824 
    825   if ((err = ctf_dynhash_insert (hp, (char *) str,
    826 				 (void *) (ptrdiff_t) type)) == 0)
    827     return 0;
    828 
    829   /* ctf_dynhash_insert returns a negative error value: negate it for
    830      ctf_set_errno.  */
    831   ctf_set_errno (fp, err * -1);
    832   return err;
    833 }
    834 
    835 ctf_id_t
    836 ctf_dynhash_lookup_type (ctf_dynhash_t *hp, const char *key)
    837 {
    838   void *value;
    839 
    840   if (ctf_dynhash_lookup_kv (hp, key, NULL, &value))
    841     return (ctf_id_t) (uintptr_t) value;
    842 
    843   return 0;
    844 }
    845