1 /* $NetBSD: hash.c,v 1.30 2025/05/24 07:38:59 rillig Exp $ */ 2 3 /* 4 * Copyright (c) 1994, 1995 Jochen Pohl 5 * All Rights Reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jochen Pohl for 18 * The NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #if HAVE_NBTOOL_CONFIG_H 35 #include "nbtool_config.h" 36 #endif 37 38 #include <sys/cdefs.h> 39 #if defined(__RCSID) 40 __RCSID("$NetBSD: hash.c,v 1.30 2025/05/24 07:38:59 rillig Exp $"); 41 #endif 42 43 #include <limits.h> 44 #include <stddef.h> 45 #include <stdlib.h> 46 #include <string.h> 47 48 #include "lint2.h" 49 50 #define HTAB_BUCKETS 1009 51 52 static hte_t **htab; 53 54 hte_t ** 55 htab_new(void) 56 { 57 return xcalloc(HTAB_BUCKETS, sizeof(*htab_new())); 58 } 59 60 static unsigned int 61 hash(const char *s) 62 { 63 unsigned int v; 64 const char *p; 65 66 v = 0; 67 for (p = s; *p != '\0'; p++) { 68 v = (v << 4) + (unsigned char)*p; 69 v ^= v >> 28; 70 } 71 return v % HTAB_BUCKETS; 72 } 73 74 /* 75 * Look for a hash table entry. If no hash table entry for the 76 * given name exists and mknew is set, create a new one. 77 */ 78 hte_t * 79 hash_search(hte_t **table, const char *s, bool mknew) 80 { 81 unsigned int h; 82 hte_t *hte; 83 84 if (table == NULL) 85 table = htab; 86 87 h = hash(s); 88 for (hte = table[h]; hte != NULL; hte = hte->h_link) { 89 if (strcmp(hte->h_name, s) == 0) 90 break; 91 } 92 93 if (hte != NULL || !mknew) 94 return hte; 95 96 /* create a new hte */ 97 hte = xmalloc(sizeof(*hte)); 98 hte->h_name = xstrdup(s); 99 hte->h_used = false; 100 hte->h_def = false; 101 hte->h_static = false; 102 hte->h_syms = NULL; 103 hte->h_lsym = &hte->h_syms; 104 hte->h_calls = NULL; 105 hte->h_lcall = &hte->h_calls; 106 hte->h_usyms = NULL; 107 hte->h_lusym = &hte->h_usyms; 108 hte->h_link = table[h]; 109 hte->h_hte = NULL; 110 table[h] = hte; 111 112 return hte; 113 } 114 115 struct hte_list { 116 hte_t **items; 117 size_t len; 118 size_t cap; 119 }; 120 121 static void 122 hte_list_add(struct hte_list *list, hte_t *item) 123 { 124 if (list->len >= list->cap) { 125 list->cap = list->cap == 0 ? 1024 : 2 * list->cap; 126 list->items = xrealloc(list->items, 127 sizeof(list->items[0]) * list->cap); 128 } 129 list->items[list->len++] = item; 130 } 131 132 static int 133 hte_by_name(const void *va, const void *vb) 134 { 135 const hte_t *a = *((const hte_t *const *)va); 136 const hte_t *b = *((const hte_t *const *)vb); 137 138 return strcmp(a->h_name, b->h_name); 139 } 140 141 void 142 symtab_init(void) 143 { 144 htab = htab_new(); 145 } 146 147 /* 148 * Call the action for each name in the hash table. 149 */ 150 void 151 symtab_forall(void (*action)(hte_t *)) 152 { 153 int i; 154 hte_t *hte; 155 hte_t **table = htab; 156 157 for (i = 0; i < HTAB_BUCKETS; i++) { 158 for (hte = table[i]; hte != NULL; hte = hte->h_link) 159 action(hte); 160 } 161 } 162 163 /* Run the action for each name in the symbol table, in alphabetic order. */ 164 void 165 symtab_forall_sorted(void (*action)(const hte_t *)) 166 { 167 hte_t *hte; 168 struct hte_list sorted = { NULL, 0, 0 }; 169 size_t i; 170 hte_t **table = htab; 171 172 for (i = 0; i < HTAB_BUCKETS; i++) 173 for (hte = table[i]; hte != NULL; hte = hte->h_link) 174 hte_list_add(&sorted, hte); 175 176 qsort(sorted.items, sorted.len, sizeof(sorted.items[0]), hte_by_name); 177 178 for (i = 0; i < sorted.len; i++) 179 action(sorted.items[i]); 180 181 free(sorted.items); 182 } 183 184 /* 185 * Free all contents of the hash table that this module allocated. 186 */ 187 void 188 hash_free(hte_t **table) 189 { 190 int i; 191 hte_t *hte, *nexthte; 192 193 for (i = 0; i < HTAB_BUCKETS; i++) { 194 for (hte = table[i]; hte != NULL; hte = nexthte) { 195 free(__UNCONST(hte->h_name)); 196 nexthte = hte->h_link; 197 free(hte); 198 } 199 } 200 free(table); 201 } 202