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