xref: /openbsd-src/gnu/usr.bin/binutils/bfd/hash.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* hash.c -- hash table routines for BFD
2*007c2a45Smiod    Copyright 1993, 1994, 1995, 1997, 1999, 2001, 2002, 2003
3b55d4692Sfgsch    Free Software Foundation, Inc.
42159047fSniklas    Written by Steve Chamberlain <sac@cygnus.com>
52159047fSniklas 
62159047fSniklas This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas 
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas 
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
202159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas #include "bfd.h"
232159047fSniklas #include "sysdep.h"
242159047fSniklas #include "libbfd.h"
25b305b0f1Sespie #include "objalloc.h"
262159047fSniklas 
272159047fSniklas /*
282159047fSniklas SECTION
292159047fSniklas 	Hash Tables
302159047fSniklas 
312159047fSniklas @cindex Hash tables
322159047fSniklas 	BFD provides a simple set of hash table functions.  Routines
332159047fSniklas 	are provided to initialize a hash table, to free a hash table,
342159047fSniklas 	to look up a string in a hash table and optionally create an
352159047fSniklas 	entry for it, and to traverse a hash table.  There is
362159047fSniklas 	currently no routine to delete an string from a hash table.
372159047fSniklas 
382159047fSniklas 	The basic hash table does not permit any data to be stored
392159047fSniklas 	with a string.  However, a hash table is designed to present a
402159047fSniklas 	base class from which other types of hash tables may be
412159047fSniklas 	derived.  These derived types may store additional information
422159047fSniklas 	with the string.  Hash tables were implemented in this way,
432159047fSniklas 	rather than simply providing a data pointer in a hash table
442159047fSniklas 	entry, because they were designed for use by the linker back
452159047fSniklas 	ends.  The linker may create thousands of hash table entries,
462159047fSniklas 	and the overhead of allocating private data and storing and
472159047fSniklas 	following pointers becomes noticeable.
482159047fSniklas 
492159047fSniklas 	The basic hash table code is in <<hash.c>>.
502159047fSniklas 
512159047fSniklas @menu
522159047fSniklas @* Creating and Freeing a Hash Table::
532159047fSniklas @* Looking Up or Entering a String::
542159047fSniklas @* Traversing a Hash Table::
552159047fSniklas @* Deriving a New Hash Table Type::
562159047fSniklas @end menu
572159047fSniklas 
582159047fSniklas INODE
592159047fSniklas Creating and Freeing a Hash Table, Looking Up or Entering a String, Hash Tables, Hash Tables
602159047fSniklas SUBSECTION
612159047fSniklas 	Creating and freeing a hash table
622159047fSniklas 
632159047fSniklas @findex bfd_hash_table_init
642159047fSniklas @findex bfd_hash_table_init_n
652159047fSniklas 	To create a hash table, create an instance of a <<struct
662159047fSniklas 	bfd_hash_table>> (defined in <<bfd.h>>) and call
672159047fSniklas 	<<bfd_hash_table_init>> (if you know approximately how many
682159047fSniklas 	entries you will need, the function <<bfd_hash_table_init_n>>,
692159047fSniklas 	which takes a @var{size} argument, may be used).
70c074d1c9Sdrahn 	<<bfd_hash_table_init>> returns <<FALSE>> if some sort of
712159047fSniklas 	error occurs.
722159047fSniklas 
732159047fSniklas @findex bfd_hash_newfunc
742159047fSniklas 	The function <<bfd_hash_table_init>> take as an argument a
752159047fSniklas 	function to use to create new entries.  For a basic hash
762159047fSniklas 	table, use the function <<bfd_hash_newfunc>>.  @xref{Deriving
77b305b0f1Sespie 	a New Hash Table Type}, for why you would want to use a
782159047fSniklas 	different value for this argument.
792159047fSniklas 
802159047fSniklas @findex bfd_hash_allocate
81b305b0f1Sespie 	<<bfd_hash_table_init>> will create an objalloc which will be
822159047fSniklas 	used to allocate new entries.  You may allocate memory on this
83b305b0f1Sespie 	objalloc using <<bfd_hash_allocate>>.
842159047fSniklas 
852159047fSniklas @findex bfd_hash_table_free
862159047fSniklas 	Use <<bfd_hash_table_free>> to free up all the memory that has
872159047fSniklas 	been allocated for a hash table.  This will not free up the
882159047fSniklas 	<<struct bfd_hash_table>> itself, which you must provide.
892159047fSniklas 
902159047fSniklas INODE
912159047fSniklas Looking Up or Entering a String, Traversing a Hash Table, Creating and Freeing a Hash Table, Hash Tables
922159047fSniklas SUBSECTION
932159047fSniklas 	Looking up or entering a string
942159047fSniklas 
952159047fSniklas @findex bfd_hash_lookup
962159047fSniklas 	The function <<bfd_hash_lookup>> is used both to look up a
972159047fSniklas 	string in the hash table and to create a new entry.
982159047fSniklas 
99c074d1c9Sdrahn 	If the @var{create} argument is <<FALSE>>, <<bfd_hash_lookup>>
1002159047fSniklas 	will look up a string.  If the string is found, it will
1012159047fSniklas 	returns a pointer to a <<struct bfd_hash_entry>>.  If the
1022159047fSniklas 	string is not found in the table <<bfd_hash_lookup>> will
1032159047fSniklas 	return <<NULL>>.  You should not modify any of the fields in
1042159047fSniklas 	the returns <<struct bfd_hash_entry>>.
1052159047fSniklas 
106c074d1c9Sdrahn 	If the @var{create} argument is <<TRUE>>, the string will be
1072159047fSniklas 	entered into the hash table if it is not already there.
1082159047fSniklas 	Either way a pointer to a <<struct bfd_hash_entry>> will be
1092159047fSniklas 	returned, either to the existing structure or to a newly
1102159047fSniklas 	created one.  In this case, a <<NULL>> return means that an
1112159047fSniklas 	error occurred.
1122159047fSniklas 
113c074d1c9Sdrahn 	If the @var{create} argument is <<TRUE>>, and a new entry is
1142159047fSniklas 	created, the @var{copy} argument is used to decide whether to
115b305b0f1Sespie 	copy the string onto the hash table objalloc or not.  If
116c074d1c9Sdrahn 	@var{copy} is passed as <<FALSE>>, you must be careful not to
1172159047fSniklas 	deallocate or modify the string as long as the hash table
1182159047fSniklas 	exists.
1192159047fSniklas 
1202159047fSniklas INODE
1212159047fSniklas Traversing a Hash Table, Deriving a New Hash Table Type, Looking Up or Entering a String, Hash Tables
1222159047fSniklas SUBSECTION
1232159047fSniklas 	Traversing a hash table
1242159047fSniklas 
1252159047fSniklas @findex bfd_hash_traverse
1262159047fSniklas 	The function <<bfd_hash_traverse>> may be used to traverse a
1272159047fSniklas 	hash table, calling a function on each element.  The traversal
1282159047fSniklas 	is done in a random order.
1292159047fSniklas 
1302159047fSniklas 	<<bfd_hash_traverse>> takes as arguments a function and a
1312159047fSniklas 	generic <<void *>> pointer.  The function is called with a
1322159047fSniklas 	hash table entry (a <<struct bfd_hash_entry *>>) and the
1332159047fSniklas 	generic pointer passed to <<bfd_hash_traverse>>.  The function
1342159047fSniklas 	must return a <<boolean>> value, which indicates whether to
1352159047fSniklas 	continue traversing the hash table.  If the function returns
136c074d1c9Sdrahn 	<<FALSE>>, <<bfd_hash_traverse>> will stop the traversal and
1372159047fSniklas 	return immediately.
1382159047fSniklas 
1392159047fSniklas INODE
1402159047fSniklas Deriving a New Hash Table Type, , Traversing a Hash Table, Hash Tables
1412159047fSniklas SUBSECTION
1422159047fSniklas 	Deriving a new hash table type
1432159047fSniklas 
1442159047fSniklas 	Many uses of hash tables want to store additional information
1452159047fSniklas 	which each entry in the hash table.  Some also find it
1462159047fSniklas 	convenient to store additional information with the hash table
1472159047fSniklas 	itself.  This may be done using a derived hash table.
1482159047fSniklas 
1492159047fSniklas 	Since C is not an object oriented language, creating a derived
1502159047fSniklas 	hash table requires sticking together some boilerplate
1512159047fSniklas 	routines with a few differences specific to the type of hash
1522159047fSniklas 	table you want to create.
1532159047fSniklas 
1542159047fSniklas 	An example of a derived hash table is the linker hash table.
1552159047fSniklas 	The structures for this are defined in <<bfdlink.h>>.  The
1562159047fSniklas 	functions are in <<linker.c>>.
1572159047fSniklas 
1582159047fSniklas 	You may also derive a hash table from an already derived hash
1592159047fSniklas 	table.  For example, the a.out linker backend code uses a hash
1602159047fSniklas 	table derived from the linker hash table.
1612159047fSniklas 
1622159047fSniklas @menu
1632159047fSniklas @* Define the Derived Structures::
1642159047fSniklas @* Write the Derived Creation Routine::
1652159047fSniklas @* Write Other Derived Routines::
1662159047fSniklas @end menu
1672159047fSniklas 
1682159047fSniklas INODE
1692159047fSniklas Define the Derived Structures, Write the Derived Creation Routine, Deriving a New Hash Table Type, Deriving a New Hash Table Type
1702159047fSniklas SUBSUBSECTION
1712159047fSniklas 	Define the derived structures
1722159047fSniklas 
1732159047fSniklas 	You must define a structure for an entry in the hash table,
1742159047fSniklas 	and a structure for the hash table itself.
1752159047fSniklas 
1762159047fSniklas 	The first field in the structure for an entry in the hash
1772159047fSniklas 	table must be of the type used for an entry in the hash table
1782159047fSniklas 	you are deriving from.  If you are deriving from a basic hash
1792159047fSniklas 	table this is <<struct bfd_hash_entry>>, which is defined in
1802159047fSniklas 	<<bfd.h>>.  The first field in the structure for the hash
1812159047fSniklas 	table itself must be of the type of the hash table you are
1822159047fSniklas 	deriving from itself.  If you are deriving from a basic hash
1832159047fSniklas 	table, this is <<struct bfd_hash_table>>.
1842159047fSniklas 
1852159047fSniklas 	For example, the linker hash table defines <<struct
1862159047fSniklas 	bfd_link_hash_entry>> (in <<bfdlink.h>>).  The first field,
1872159047fSniklas 	<<root>>, is of type <<struct bfd_hash_entry>>.  Similarly,
1882159047fSniklas 	the first field in <<struct bfd_link_hash_table>>, <<table>>,
1892159047fSniklas 	is of type <<struct bfd_hash_table>>.
1902159047fSniklas 
1912159047fSniklas INODE
1922159047fSniklas Write the Derived Creation Routine, Write Other Derived Routines, Define the Derived Structures, Deriving a New Hash Table Type
1932159047fSniklas SUBSUBSECTION
1942159047fSniklas 	Write the derived creation routine
1952159047fSniklas 
1962159047fSniklas 	You must write a routine which will create and initialize an
1972159047fSniklas 	entry in the hash table.  This routine is passed as the
1982159047fSniklas 	function argument to <<bfd_hash_table_init>>.
1992159047fSniklas 
2002159047fSniklas 	In order to permit other hash tables to be derived from the
2012159047fSniklas 	hash table you are creating, this routine must be written in a
2022159047fSniklas 	standard way.
2032159047fSniklas 
2042159047fSniklas 	The first argument to the creation routine is a pointer to a
2052159047fSniklas 	hash table entry.  This may be <<NULL>>, in which case the
2062159047fSniklas 	routine should allocate the right amount of space.  Otherwise
2072159047fSniklas 	the space has already been allocated by a hash table type
2082159047fSniklas 	derived from this one.
2092159047fSniklas 
2102159047fSniklas 	After allocating space, the creation routine must call the
2112159047fSniklas 	creation routine of the hash table type it is derived from,
2122159047fSniklas 	passing in a pointer to the space it just allocated.  This
2132159047fSniklas 	will initialize any fields used by the base hash table.
2142159047fSniklas 
2152159047fSniklas 	Finally the creation routine must initialize any local fields
2162159047fSniklas 	for the new hash table type.
2172159047fSniklas 
2182159047fSniklas 	Here is a boilerplate example of a creation routine.
2192159047fSniklas 	@var{function_name} is the name of the routine.
2202159047fSniklas 	@var{entry_type} is the type of an entry in the hash table you
2212159047fSniklas 	are creating.  @var{base_newfunc} is the name of the creation
2222159047fSniklas 	routine of the hash table type your hash table is derived
2232159047fSniklas 	from.
2242159047fSniklas 
2252159047fSniklas EXAMPLE
2262159047fSniklas 
2272159047fSniklas .struct bfd_hash_entry *
2282159047fSniklas .@var{function_name} (entry, table, string)
2292159047fSniklas .     struct bfd_hash_entry *entry;
2302159047fSniklas .     struct bfd_hash_table *table;
2312159047fSniklas .     const char *string;
2322159047fSniklas .{
2332159047fSniklas .  struct @var{entry_type} *ret = (@var{entry_type} *) entry;
2342159047fSniklas .
2352159047fSniklas . {* Allocate the structure if it has not already been allocated by a
2362159047fSniklas .    derived class.  *}
2372159047fSniklas .  if (ret == (@var{entry_type} *) NULL)
2382159047fSniklas .    {
2392159047fSniklas .      ret = ((@var{entry_type} *)
2402159047fSniklas .	      bfd_hash_allocate (table, sizeof (@var{entry_type})));
2412159047fSniklas .      if (ret == (@var{entry_type} *) NULL)
2422159047fSniklas .        return NULL;
2432159047fSniklas .    }
2442159047fSniklas .
2452159047fSniklas . {* Call the allocation method of the base class.  *}
2462159047fSniklas .  ret = ((@var{entry_type} *)
2472159047fSniklas .	 @var{base_newfunc} ((struct bfd_hash_entry *) ret, table, string));
2482159047fSniklas .
2492159047fSniklas . {* Initialize the local fields here.  *}
2502159047fSniklas .
2512159047fSniklas .  return (struct bfd_hash_entry *) ret;
2522159047fSniklas .}
2532159047fSniklas 
2542159047fSniklas DESCRIPTION
2552159047fSniklas 	The creation routine for the linker hash table, which is in
2562159047fSniklas 	<<linker.c>>, looks just like this example.
2572159047fSniklas 	@var{function_name} is <<_bfd_link_hash_newfunc>>.
2582159047fSniklas 	@var{entry_type} is <<struct bfd_link_hash_entry>>.
2592159047fSniklas 	@var{base_newfunc} is <<bfd_hash_newfunc>>, the creation
2602159047fSniklas 	routine for a basic hash table.
2612159047fSniklas 
2622159047fSniklas 	<<_bfd_link_hash_newfunc>> also initializes the local fields
2632159047fSniklas 	in a linker hash table entry: <<type>>, <<written>> and
2642159047fSniklas 	<<next>>.
2652159047fSniklas 
2662159047fSniklas INODE
2672159047fSniklas Write Other Derived Routines, , Write the Derived Creation Routine, Deriving a New Hash Table Type
2682159047fSniklas SUBSUBSECTION
2692159047fSniklas 	Write other derived routines
2702159047fSniklas 
2712159047fSniklas 	You will want to write other routines for your new hash table,
2722159047fSniklas 	as well.
2732159047fSniklas 
2742159047fSniklas 	You will want an initialization routine which calls the
2752159047fSniklas 	initialization routine of the hash table you are deriving from
2762159047fSniklas 	and initializes any other local fields.  For the linker hash
2772159047fSniklas 	table, this is <<_bfd_link_hash_table_init>> in <<linker.c>>.
2782159047fSniklas 
2792159047fSniklas 	You will want a lookup routine which calls the lookup routine
2802159047fSniklas 	of the hash table you are deriving from and casts the result.
2812159047fSniklas 	The linker hash table uses <<bfd_link_hash_lookup>> in
2822159047fSniklas 	<<linker.c>> (this actually takes an additional argument which
2832159047fSniklas 	it uses to decide how to return the looked up value).
2842159047fSniklas 
2852159047fSniklas 	You may want a traversal routine.  This should just call the
2862159047fSniklas 	traversal routine of the hash table you are deriving from with
2872159047fSniklas 	appropriate casts.  The linker hash table uses
2882159047fSniklas 	<<bfd_link_hash_traverse>> in <<linker.c>>.
2892159047fSniklas 
2902159047fSniklas 	These routines may simply be defined as macros.  For example,
2912159047fSniklas 	the a.out backend linker hash table, which is derived from the
2922159047fSniklas 	linker hash table, uses macros for the lookup and traversal
2932159047fSniklas 	routines.  These are <<aout_link_hash_lookup>> and
2942159047fSniklas 	<<aout_link_hash_traverse>> in aoutx.h.
2952159047fSniklas */
2962159047fSniklas 
2972159047fSniklas /* The default number of entries to use when creating a hash table.  */
2982159047fSniklas #define DEFAULT_SIZE (4051)
2992159047fSniklas 
3002159047fSniklas /* Create a new hash table, given a number of entries.  */
3012159047fSniklas 
302c074d1c9Sdrahn bfd_boolean
bfd_hash_table_init_n(table,newfunc,size)3032159047fSniklas bfd_hash_table_init_n (table, newfunc, size)
3042159047fSniklas      struct bfd_hash_table *table;
3052159047fSniklas      struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
3062159047fSniklas 						struct bfd_hash_table *,
3072159047fSniklas 						const char *));
3082159047fSniklas      unsigned int size;
3092159047fSniklas {
3102159047fSniklas   unsigned int alloc;
3112159047fSniklas 
3122159047fSniklas   alloc = size * sizeof (struct bfd_hash_entry *);
313b305b0f1Sespie 
314b305b0f1Sespie   table->memory = (PTR) objalloc_create ();
315b305b0f1Sespie   if (table->memory == NULL)
3162159047fSniklas     {
3172159047fSniklas       bfd_set_error (bfd_error_no_memory);
318c074d1c9Sdrahn       return FALSE;
3192159047fSniklas     }
3202159047fSniklas   table->table = ((struct bfd_hash_entry **)
321b305b0f1Sespie 		  objalloc_alloc ((struct objalloc *) table->memory, alloc));
322b305b0f1Sespie   if (table->table == NULL)
3232159047fSniklas     {
3242159047fSniklas       bfd_set_error (bfd_error_no_memory);
325c074d1c9Sdrahn       return FALSE;
3262159047fSniklas     }
3272159047fSniklas   memset ((PTR) table->table, 0, alloc);
3282159047fSniklas   table->size = size;
3292159047fSniklas   table->newfunc = newfunc;
330c074d1c9Sdrahn   return TRUE;
3312159047fSniklas }
3322159047fSniklas 
3332159047fSniklas /* Create a new hash table with the default number of entries.  */
3342159047fSniklas 
335c074d1c9Sdrahn bfd_boolean
bfd_hash_table_init(table,newfunc)3362159047fSniklas bfd_hash_table_init (table, newfunc)
3372159047fSniklas      struct bfd_hash_table *table;
3382159047fSniklas      struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
3392159047fSniklas 						struct bfd_hash_table *,
3402159047fSniklas 						const char *));
3412159047fSniklas {
3422159047fSniklas   return bfd_hash_table_init_n (table, newfunc, DEFAULT_SIZE);
3432159047fSniklas }
3442159047fSniklas 
3452159047fSniklas /* Free a hash table.  */
3462159047fSniklas 
3472159047fSniklas void
bfd_hash_table_free(table)3482159047fSniklas bfd_hash_table_free (table)
3492159047fSniklas      struct bfd_hash_table *table;
3502159047fSniklas {
351b305b0f1Sespie   objalloc_free ((struct objalloc *) table->memory);
352b305b0f1Sespie   table->memory = NULL;
3532159047fSniklas }
3542159047fSniklas 
3552159047fSniklas /* Look up a string in a hash table.  */
3562159047fSniklas 
3572159047fSniklas struct bfd_hash_entry *
bfd_hash_lookup(table,string,create,copy)3582159047fSniklas bfd_hash_lookup (table, string, create, copy)
3592159047fSniklas      struct bfd_hash_table *table;
3602159047fSniklas      const char *string;
361c074d1c9Sdrahn      bfd_boolean create;
362c074d1c9Sdrahn      bfd_boolean copy;
3632159047fSniklas {
3642159047fSniklas   register const unsigned char *s;
3652159047fSniklas   register unsigned long hash;
3662159047fSniklas   register unsigned int c;
3672159047fSniklas   struct bfd_hash_entry *hashp;
3682159047fSniklas   unsigned int len;
3692159047fSniklas   unsigned int index;
3702159047fSniklas 
3712159047fSniklas   hash = 0;
3722159047fSniklas   len = 0;
3732159047fSniklas   s = (const unsigned char *) string;
3742159047fSniklas   while ((c = *s++) != '\0')
3752159047fSniklas     {
3762159047fSniklas       hash += c + (c << 17);
3772159047fSniklas       hash ^= hash >> 2;
3782159047fSniklas     }
379c074d1c9Sdrahn   len = (s - (const unsigned char *) string) - 1;
3802159047fSniklas   hash += len + (len << 17);
3812159047fSniklas   hash ^= hash >> 2;
3822159047fSniklas 
3832159047fSniklas   index = hash % table->size;
3842159047fSniklas   for (hashp = table->table[index];
3852159047fSniklas        hashp != (struct bfd_hash_entry *) NULL;
3862159047fSniklas        hashp = hashp->next)
3872159047fSniklas     {
3882159047fSniklas       if (hashp->hash == hash
3892159047fSniklas 	  && strcmp (hashp->string, string) == 0)
3902159047fSniklas 	return hashp;
3912159047fSniklas     }
3922159047fSniklas 
3932159047fSniklas   if (! create)
3942159047fSniklas     return (struct bfd_hash_entry *) NULL;
3952159047fSniklas 
3962159047fSniklas   hashp = (*table->newfunc) ((struct bfd_hash_entry *) NULL, table, string);
3972159047fSniklas   if (hashp == (struct bfd_hash_entry *) NULL)
3982159047fSniklas     return (struct bfd_hash_entry *) NULL;
3992159047fSniklas   if (copy)
4002159047fSniklas     {
4012159047fSniklas       char *new;
4022159047fSniklas 
403b305b0f1Sespie       new = (char *) objalloc_alloc ((struct objalloc *) table->memory,
404b305b0f1Sespie 				     len + 1);
4052159047fSniklas       if (!new)
4062159047fSniklas 	{
4072159047fSniklas 	  bfd_set_error (bfd_error_no_memory);
4082159047fSniklas 	  return (struct bfd_hash_entry *) NULL;
4092159047fSniklas 	}
410c074d1c9Sdrahn       memcpy (new, string, len + 1);
4112159047fSniklas       string = new;
4122159047fSniklas     }
4132159047fSniklas   hashp->string = string;
4142159047fSniklas   hashp->hash = hash;
4152159047fSniklas   hashp->next = table->table[index];
4162159047fSniklas   table->table[index] = hashp;
4172159047fSniklas 
4182159047fSniklas   return hashp;
4192159047fSniklas }
4202159047fSniklas 
4212159047fSniklas /* Replace an entry in a hash table.  */
4222159047fSniklas 
4232159047fSniklas void
bfd_hash_replace(table,old,nw)4242159047fSniklas bfd_hash_replace (table, old, nw)
4252159047fSniklas      struct bfd_hash_table *table;
4262159047fSniklas      struct bfd_hash_entry *old;
4272159047fSniklas      struct bfd_hash_entry *nw;
4282159047fSniklas {
4292159047fSniklas   unsigned int index;
4302159047fSniklas   struct bfd_hash_entry **pph;
4312159047fSniklas 
4322159047fSniklas   index = old->hash % table->size;
4332159047fSniklas   for (pph = &table->table[index];
4342159047fSniklas        (*pph) != (struct bfd_hash_entry *) NULL;
4352159047fSniklas        pph = &(*pph)->next)
4362159047fSniklas     {
4372159047fSniklas       if (*pph == old)
4382159047fSniklas 	{
4392159047fSniklas 	  *pph = nw;
4402159047fSniklas 	  return;
4412159047fSniklas 	}
4422159047fSniklas     }
4432159047fSniklas 
4442159047fSniklas   abort ();
4452159047fSniklas }
4462159047fSniklas 
4472159047fSniklas /* Base method for creating a new hash table entry.  */
4482159047fSniklas 
4492159047fSniklas struct bfd_hash_entry *
bfd_hash_newfunc(entry,table,string)4502159047fSniklas bfd_hash_newfunc (entry, table, string)
4512159047fSniklas      struct bfd_hash_entry *entry;
4522159047fSniklas      struct bfd_hash_table *table;
453b305b0f1Sespie      const char *string ATTRIBUTE_UNUSED;
4542159047fSniklas {
4552159047fSniklas   if (entry == (struct bfd_hash_entry *) NULL)
4562159047fSniklas     entry = ((struct bfd_hash_entry *)
4572159047fSniklas 	     bfd_hash_allocate (table, sizeof (struct bfd_hash_entry)));
4582159047fSniklas   return entry;
4592159047fSniklas }
4602159047fSniklas 
4612159047fSniklas /* Allocate space in a hash table.  */
4622159047fSniklas 
4632159047fSniklas PTR
bfd_hash_allocate(table,size)4642159047fSniklas bfd_hash_allocate (table, size)
4652159047fSniklas      struct bfd_hash_table *table;
4662159047fSniklas      unsigned int size;
4672159047fSniklas {
4682159047fSniklas   PTR ret;
4692159047fSniklas 
470b305b0f1Sespie   ret = objalloc_alloc ((struct objalloc *) table->memory, size);
4712159047fSniklas   if (ret == NULL && size != 0)
4722159047fSniklas     bfd_set_error (bfd_error_no_memory);
4732159047fSniklas   return ret;
4742159047fSniklas }
4752159047fSniklas 
4762159047fSniklas /* Traverse a hash table.  */
4772159047fSniklas 
4782159047fSniklas void
bfd_hash_traverse(table,func,info)4792159047fSniklas bfd_hash_traverse (table, func, info)
4802159047fSniklas      struct bfd_hash_table *table;
481c074d1c9Sdrahn      bfd_boolean (*func) PARAMS ((struct bfd_hash_entry *, PTR));
4822159047fSniklas      PTR info;
4832159047fSniklas {
4842159047fSniklas   unsigned int i;
4852159047fSniklas 
4862159047fSniklas   for (i = 0; i < table->size; i++)
4872159047fSniklas     {
4882159047fSniklas       struct bfd_hash_entry *p;
4892159047fSniklas 
4902159047fSniklas       for (p = table->table[i]; p != NULL; p = p->next)
4912159047fSniklas 	{
4922159047fSniklas 	  if (! (*func) (p, info))
4932159047fSniklas 	    return;
4942159047fSniklas 	}
4952159047fSniklas     }
4962159047fSniklas }
4972159047fSniklas 
4982159047fSniklas /* A few different object file formats (a.out, COFF, ELF) use a string
4992159047fSniklas    table.  These functions support adding strings to a string table,
5002159047fSniklas    returning the byte offset, and writing out the table.
5012159047fSniklas 
5022159047fSniklas    Possible improvements:
5032159047fSniklas    + look for strings matching trailing substrings of other strings
5042159047fSniklas    + better data structures?  balanced trees?
5052159047fSniklas    + look at reducing memory use elsewhere -- maybe if we didn't have
5062159047fSniklas      to construct the entire symbol table at once, we could get by
5072159047fSniklas      with smaller amounts of VM?  (What effect does that have on the
5082159047fSniklas      string table reductions?)  */
5092159047fSniklas 
5102159047fSniklas /* An entry in the strtab hash table.  */
5112159047fSniklas 
5122159047fSniklas struct strtab_hash_entry
5132159047fSniklas {
5142159047fSniklas   struct bfd_hash_entry root;
5152159047fSniklas   /* Index in string table.  */
5162159047fSniklas   bfd_size_type index;
5172159047fSniklas   /* Next string in strtab.  */
5182159047fSniklas   struct strtab_hash_entry *next;
5192159047fSniklas };
5202159047fSniklas 
5212159047fSniklas /* The strtab hash table.  */
5222159047fSniklas 
5232159047fSniklas struct bfd_strtab_hash
5242159047fSniklas {
5252159047fSniklas   struct bfd_hash_table table;
5262159047fSniklas   /* Size of strtab--also next available index.  */
5272159047fSniklas   bfd_size_type size;
5282159047fSniklas   /* First string in strtab.  */
5292159047fSniklas   struct strtab_hash_entry *first;
5302159047fSniklas   /* Last string in strtab.  */
5312159047fSniklas   struct strtab_hash_entry *last;
5322159047fSniklas   /* Whether to precede strings with a two byte length, as in the
5332159047fSniklas      XCOFF .debug section.  */
534c074d1c9Sdrahn   bfd_boolean xcoff;
5352159047fSniklas };
5362159047fSniklas 
5372159047fSniklas static struct bfd_hash_entry *strtab_hash_newfunc
5382159047fSniklas   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
5392159047fSniklas 
5402159047fSniklas /* Routine to create an entry in a strtab.  */
5412159047fSniklas 
5422159047fSniklas static struct bfd_hash_entry *
strtab_hash_newfunc(entry,table,string)5432159047fSniklas strtab_hash_newfunc (entry, table, string)
5442159047fSniklas      struct bfd_hash_entry *entry;
5452159047fSniklas      struct bfd_hash_table *table;
5462159047fSniklas      const char *string;
5472159047fSniklas {
5482159047fSniklas   struct strtab_hash_entry *ret = (struct strtab_hash_entry *) entry;
5492159047fSniklas 
5502159047fSniklas   /* Allocate the structure if it has not already been allocated by a
5512159047fSniklas      subclass.  */
5522159047fSniklas   if (ret == (struct strtab_hash_entry *) NULL)
5532159047fSniklas     ret = ((struct strtab_hash_entry *)
5542159047fSniklas 	   bfd_hash_allocate (table, sizeof (struct strtab_hash_entry)));
5552159047fSniklas   if (ret == (struct strtab_hash_entry *) NULL)
5562159047fSniklas     return NULL;
5572159047fSniklas 
5582159047fSniklas   /* Call the allocation method of the superclass.  */
5592159047fSniklas   ret = ((struct strtab_hash_entry *)
5602159047fSniklas 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
5612159047fSniklas 
5622159047fSniklas   if (ret)
5632159047fSniklas     {
5642159047fSniklas       /* Initialize the local fields.  */
5652159047fSniklas       ret->index = (bfd_size_type) -1;
5662159047fSniklas       ret->next = NULL;
5672159047fSniklas     }
5682159047fSniklas 
5692159047fSniklas   return (struct bfd_hash_entry *) ret;
5702159047fSniklas }
5712159047fSniklas 
5722159047fSniklas /* Look up an entry in an strtab.  */
5732159047fSniklas 
5742159047fSniklas #define strtab_hash_lookup(t, string, create, copy) \
5752159047fSniklas   ((struct strtab_hash_entry *) \
5762159047fSniklas    bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
5772159047fSniklas 
5782159047fSniklas /* Create a new strtab.  */
5792159047fSniklas 
5802159047fSniklas struct bfd_strtab_hash *
_bfd_stringtab_init()5812159047fSniklas _bfd_stringtab_init ()
5822159047fSniklas {
5832159047fSniklas   struct bfd_strtab_hash *table;
584c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct bfd_strtab_hash);
5852159047fSniklas 
586c074d1c9Sdrahn   table = (struct bfd_strtab_hash *) bfd_malloc (amt);
5872159047fSniklas   if (table == NULL)
5882159047fSniklas     return NULL;
5892159047fSniklas 
5902159047fSniklas   if (! bfd_hash_table_init (&table->table, strtab_hash_newfunc))
5912159047fSniklas     {
5922159047fSniklas       free (table);
5932159047fSniklas       return NULL;
5942159047fSniklas     }
5952159047fSniklas 
5962159047fSniklas   table->size = 0;
5972159047fSniklas   table->first = NULL;
5982159047fSniklas   table->last = NULL;
599c074d1c9Sdrahn   table->xcoff = FALSE;
6002159047fSniklas 
6012159047fSniklas   return table;
6022159047fSniklas }
6032159047fSniklas 
6042159047fSniklas /* Create a new strtab in which the strings are output in the format
6052159047fSniklas    used in the XCOFF .debug section: a two byte length precedes each
6062159047fSniklas    string.  */
6072159047fSniklas 
6082159047fSniklas struct bfd_strtab_hash *
_bfd_xcoff_stringtab_init()6092159047fSniklas _bfd_xcoff_stringtab_init ()
6102159047fSniklas {
6112159047fSniklas   struct bfd_strtab_hash *ret;
6122159047fSniklas 
6132159047fSniklas   ret = _bfd_stringtab_init ();
6142159047fSniklas   if (ret != NULL)
615c074d1c9Sdrahn     ret->xcoff = TRUE;
6162159047fSniklas   return ret;
6172159047fSniklas }
6182159047fSniklas 
6192159047fSniklas /* Free a strtab.  */
6202159047fSniklas 
6212159047fSniklas void
_bfd_stringtab_free(table)6222159047fSniklas _bfd_stringtab_free (table)
6232159047fSniklas      struct bfd_strtab_hash *table;
6242159047fSniklas {
6252159047fSniklas   bfd_hash_table_free (&table->table);
6262159047fSniklas   free (table);
6272159047fSniklas }
6282159047fSniklas 
6292159047fSniklas /* Get the index of a string in a strtab, adding it if it is not
630c074d1c9Sdrahn    already present.  If HASH is FALSE, we don't really use the hash
6312159047fSniklas    table, and we don't eliminate duplicate strings.  */
6322159047fSniklas 
6332159047fSniklas bfd_size_type
_bfd_stringtab_add(tab,str,hash,copy)6342159047fSniklas _bfd_stringtab_add (tab, str, hash, copy)
6352159047fSniklas      struct bfd_strtab_hash *tab;
6362159047fSniklas      const char *str;
637c074d1c9Sdrahn      bfd_boolean hash;
638c074d1c9Sdrahn      bfd_boolean copy;
6392159047fSniklas {
6402159047fSniklas   register struct strtab_hash_entry *entry;
6412159047fSniklas 
6422159047fSniklas   if (hash)
6432159047fSniklas     {
644c074d1c9Sdrahn       entry = strtab_hash_lookup (tab, str, TRUE, copy);
6452159047fSniklas       if (entry == NULL)
6462159047fSniklas 	return (bfd_size_type) -1;
6472159047fSniklas     }
6482159047fSniklas   else
6492159047fSniklas     {
6502159047fSniklas       entry = ((struct strtab_hash_entry *)
6512159047fSniklas 	       bfd_hash_allocate (&tab->table,
6522159047fSniklas 				  sizeof (struct strtab_hash_entry)));
6532159047fSniklas       if (entry == NULL)
6542159047fSniklas 	return (bfd_size_type) -1;
6552159047fSniklas       if (! copy)
6562159047fSniklas 	entry->root.string = str;
6572159047fSniklas       else
6582159047fSniklas 	{
6592159047fSniklas 	  char *n;
6602159047fSniklas 
6612159047fSniklas 	  n = (char *) bfd_hash_allocate (&tab->table, strlen (str) + 1);
6622159047fSniklas 	  if (n == NULL)
6632159047fSniklas 	    return (bfd_size_type) -1;
6642159047fSniklas 	  entry->root.string = n;
6652159047fSniklas 	}
6662159047fSniklas       entry->index = (bfd_size_type) -1;
6672159047fSniklas       entry->next = NULL;
6682159047fSniklas     }
6692159047fSniklas 
6702159047fSniklas   if (entry->index == (bfd_size_type) -1)
6712159047fSniklas     {
6722159047fSniklas       entry->index = tab->size;
6732159047fSniklas       tab->size += strlen (str) + 1;
6742159047fSniklas       if (tab->xcoff)
6752159047fSniklas 	{
6762159047fSniklas 	  entry->index += 2;
6772159047fSniklas 	  tab->size += 2;
6782159047fSniklas 	}
6792159047fSniklas       if (tab->first == NULL)
6802159047fSniklas 	tab->first = entry;
6812159047fSniklas       else
6822159047fSniklas 	tab->last->next = entry;
6832159047fSniklas       tab->last = entry;
6842159047fSniklas     }
6852159047fSniklas 
6862159047fSniklas   return entry->index;
6872159047fSniklas }
6882159047fSniklas 
6892159047fSniklas /* Get the number of bytes in a strtab.  */
6902159047fSniklas 
6912159047fSniklas bfd_size_type
_bfd_stringtab_size(tab)6922159047fSniklas _bfd_stringtab_size (tab)
6932159047fSniklas      struct bfd_strtab_hash *tab;
6942159047fSniklas {
6952159047fSniklas   return tab->size;
6962159047fSniklas }
6972159047fSniklas 
6982159047fSniklas /* Write out a strtab.  ABFD must already be at the right location in
6992159047fSniklas    the file.  */
7002159047fSniklas 
701c074d1c9Sdrahn bfd_boolean
_bfd_stringtab_emit(abfd,tab)7022159047fSniklas _bfd_stringtab_emit (abfd, tab)
7032159047fSniklas      register bfd *abfd;
7042159047fSniklas      struct bfd_strtab_hash *tab;
7052159047fSniklas {
706c074d1c9Sdrahn   register bfd_boolean xcoff;
7072159047fSniklas   register struct strtab_hash_entry *entry;
7082159047fSniklas 
7092159047fSniklas   xcoff = tab->xcoff;
7102159047fSniklas 
7112159047fSniklas   for (entry = tab->first; entry != NULL; entry = entry->next)
7122159047fSniklas     {
713c074d1c9Sdrahn       const char *str;
714c074d1c9Sdrahn       size_t len;
7152159047fSniklas 
7162159047fSniklas       str = entry->root.string;
7172159047fSniklas       len = strlen (str) + 1;
7182159047fSniklas 
7192159047fSniklas       if (xcoff)
7202159047fSniklas 	{
7212159047fSniklas 	  bfd_byte buf[2];
7222159047fSniklas 
7232159047fSniklas 	  /* The output length includes the null byte.  */
724c074d1c9Sdrahn 	  bfd_put_16 (abfd, (bfd_vma) len, buf);
725c074d1c9Sdrahn 	  if (bfd_bwrite ((PTR) buf, (bfd_size_type) 2, abfd) != 2)
726c074d1c9Sdrahn 	    return FALSE;
7272159047fSniklas 	}
7282159047fSniklas 
729c074d1c9Sdrahn       if (bfd_bwrite ((PTR) str, (bfd_size_type) len, abfd) != len)
730c074d1c9Sdrahn 	return FALSE;
7312159047fSniklas     }
7322159047fSniklas 
733c074d1c9Sdrahn   return TRUE;
7342159047fSniklas }
735