]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gas/hash.c
"backtrace full/no-filters/hide" completer
[thirdparty/binutils-gdb.git] / gas / hash.c
index 85c6080625e7a73fcea037f4261f012be050dcfe..cfffede7e2e909648894c2aacafa28318b32b93b 100644 (file)
@@ -1,13 +1,11 @@
 /* hash.c -- gas hash table code
-   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
-   2000, 2001, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -17,8 +15,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 /* This version of the hash table code is a wholescale replacement of
    the old hash table code, which was fairly bad.  This is based on
 #include "safe-ctype.h"
 #include "obstack.h"
 
-/* The default number of entries to use when creating a hash table.  */
-
-#define DEFAULT_SIZE (4051)
-
 /* An entry in a hash table.  */
 
 struct hash_entry {
@@ -48,7 +42,7 @@ struct hash_entry {
      table.  */
   unsigned long hash;
   /* Pointer being stored in the hash table.  */
-  PTR data;
+  void *data;
 };
 
 /* A hash table.  */
@@ -72,18 +66,28 @@ struct hash_control {
 #endif /* HASH_STATISTICS */
 };
 
+/* The default number of entries to use when creating a hash table.
+   Note this value can be reduced to 4051 by using the command line
+   switch --reduce-memory-overheads, or set to other values by using
+   the --hash-size=<NUMBER> switch.  */
+
+static unsigned long gas_hash_table_size = 65537;
+
+void
+set_gas_hash_table_size (unsigned long size)
+{
+  gas_hash_table_size = bfd_hash_set_default_size (size);
+}
+
 /* Create a hash table.  This return a control block.  */
 
 struct hash_control *
-hash_new (void)
+hash_new_sized (unsigned long size)
 {
-  unsigned int size;
+  unsigned long alloc;
   struct hash_control *ret;
-  unsigned int alloc;
 
-  size = DEFAULT_SIZE;
-
-  ret = (struct hash_control *) xmalloc (sizeof *ret);
+  ret = XNEW (struct hash_control);
   obstack_begin (&ret->memory, chunksize);
   alloc = size * sizeof (struct hash_entry *);
   ret->table = (struct hash_entry **) obstack_alloc (&ret->memory, alloc);
@@ -102,6 +106,12 @@ hash_new (void)
   return ret;
 }
 
+struct hash_control *
+hash_new (void)
+{
+  return hash_new_sized (gas_hash_table_size);
+}
+
 /* Delete a hash table, freeing all allocated memory.  */
 
 void
@@ -120,20 +130,14 @@ hash_die (struct hash_control *table)
    Each time we look up a string, we move it to the start of the list
    for its hash code, to take advantage of referential locality.  */
 
-static struct hash_entry *hash_lookup (struct hash_control *,
-                                      const char *,
-                                      struct hash_entry ***,
-                                      unsigned long *);
-
 static struct hash_entry *
-hash_lookup (struct hash_control *table, const char *key,
+hash_lookup (struct hash_control *table, const char *key, size_t len,
             struct hash_entry ***plist, unsigned long *phash)
 {
-  register unsigned long hash;
-  unsigned int len;
-  register const unsigned char *s;
-  register unsigned int c;
-  unsigned int index;
+  unsigned long hash;
+  size_t n;
+  unsigned int c;
+  unsigned int hindex;
   struct hash_entry **list;
   struct hash_entry *p;
   struct hash_entry *prev;
@@ -143,13 +147,11 @@ hash_lookup (struct hash_control *table, const char *key,
 #endif
 
   hash = 0;
-  len = 0;
-  s = (const unsigned char *) key;
-  while ((c = *s++) != '\0')
+  for (n = 0; n < len; n++)
     {
+      c = key[n];
       hash += c + (c << 17);
       hash ^= hash >> 2;
-      ++len;
     }
   hash += len + (len << 17);
   hash ^= hash >> 2;
@@ -157,8 +159,8 @@ hash_lookup (struct hash_control *table, const char *key,
   if (phash != NULL)
     *phash = hash;
 
-  index = hash % table->size;
-  list = table->table + index;
+  hindex = hash % table->size;
+  list = table->table + hindex;
 
   if (plist != NULL)
     *plist = list;
@@ -176,7 +178,7 @@ hash_lookup (struct hash_control *table, const char *key,
          ++table->string_compares;
 #endif
 
-         if (strcmp (p->string, key) == 0)
+         if (strncmp (p->string, key, len) == 0 && p->string[len] == '\0')
            {
              if (prev != NULL)
                {
@@ -201,13 +203,13 @@ hash_lookup (struct hash_control *table, const char *key,
    hash table.  */
 
 const char *
-hash_insert (struct hash_control *table, const char *key, PTR value)
+hash_insert (struct hash_control *table, const char *key, void *val)
 {
   struct hash_entry *p;
   struct hash_entry **list;
   unsigned long hash;
 
-  p = hash_lookup (table, key, &list, &hash);
+  p = hash_lookup (table, key, strlen (key), &list, &hash);
   if (p != NULL)
     return "exists";
 
@@ -218,7 +220,7 @@ hash_insert (struct hash_control *table, const char *key, PTR value)
   p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p));
   p->string = key;
   p->hash = hash;
-  p->data = value;
+  p->data = val;
 
   p->next = *list;
   *list = p;
@@ -231,20 +233,20 @@ hash_insert (struct hash_control *table, const char *key, PTR value)
    error.  If an entry already exists, its value is replaced.  */
 
 const char *
-hash_jam (struct hash_control *table, const char *key, PTR value)
+hash_jam (struct hash_control *table, const char *key, void *val)
 {
   struct hash_entry *p;
   struct hash_entry **list;
   unsigned long hash;
 
-  p = hash_lookup (table, key, &list, &hash);
+  p = hash_lookup (table, key, strlen (key), &list, &hash);
   if (p != NULL)
     {
 #ifdef HASH_STATISTICS
       ++table->replacements;
 #endif
 
-      p->data = value;
+      p->data = val;
     }
   else
     {
@@ -255,7 +257,7 @@ hash_jam (struct hash_control *table, const char *key, PTR value)
       p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p));
       p->string = key;
       p->hash = hash;
-      p->data = value;
+      p->data = val;
 
       p->next = *list;
       *list = p;
@@ -268,13 +270,13 @@ hash_jam (struct hash_control *table, const char *key, PTR value)
    value stored for the entry.  If the entry is not found in the hash
    table, this does nothing and returns NULL.  */
 
-PTR
-hash_replace (struct hash_control *table, const char *key, PTR value)
+void *
+hash_replace (struct hash_control *table, const char *key, void *value)
 {
   struct hash_entry *p;
-  PTR ret;
+  void *ret;
 
-  p = hash_lookup (table, key, NULL, NULL);
+  p = hash_lookup (table, key, strlen (key), NULL, NULL);
   if (p == NULL)
     return NULL;
 
@@ -292,12 +294,27 @@ hash_replace (struct hash_control *table, const char *key, PTR value)
 /* Find an entry in a hash table, returning its value.  Returns NULL
    if the entry is not found.  */
 
-PTR
+void *
 hash_find (struct hash_control *table, const char *key)
 {
   struct hash_entry *p;
 
-  p = hash_lookup (table, key, NULL, NULL);
+  p = hash_lookup (table, key, strlen (key), NULL, NULL);
+  if (p == NULL)
+    return NULL;
+
+  return p->data;
+}
+
+/* As hash_find, but KEY is of length LEN and is not guaranteed to be
+   NUL-terminated.  */
+
+void *
+hash_find_n (struct hash_control *table, const char *key, size_t len)
+{
+  struct hash_entry *p;
+
+  p = hash_lookup (table, key, len, NULL, NULL);
   if (p == NULL)
     return NULL;
 
@@ -307,13 +324,13 @@ hash_find (struct hash_control *table, const char *key)
 /* Delete an entry from a hash table.  This returns the value stored
    for that entry, or NULL if there is no such entry.  */
 
-PTR
-hash_delete (struct hash_control *table, const char *key)
+void *
+hash_delete (struct hash_control *table, const char *key, int freeme)
 {
   struct hash_entry *p;
   struct hash_entry **list;
 
-  p = hash_lookup (table, key, &list, NULL);
+  p = hash_lookup (table, key, strlen (key), &list, NULL);
   if (p == NULL)
     return NULL;
 
@@ -326,9 +343,8 @@ hash_delete (struct hash_control *table, const char *key)
 
   *list = p->next;
 
-  /* Note that we never reclaim the memory for this entry.  If gas
-     ever starts deleting hash table entries in a big way, this will
-     have to change.  */
+  if (freeme)
+    obstack_free (&table->memory, p);
 
   return p->data;
 }
@@ -338,7 +354,7 @@ hash_delete (struct hash_control *table, const char *key)
 
 void
 hash_traverse (struct hash_control *table,
-              void (*pfn) (const char *key, PTR value))
+              void (*pfn) (const char *key, void *value))
 {
   unsigned int i;