1 | @section Hash Tables
|
---|
2 | @cindex Hash tables
|
---|
3 | BFD provides a simple set of hash table functions. Routines
|
---|
4 | are provided to initialize a hash table, to free a hash table,
|
---|
5 | to look up a string in a hash table and optionally create an
|
---|
6 | entry for it, and to traverse a hash table. There is
|
---|
7 | currently no routine to delete an string from a hash table.
|
---|
8 |
|
---|
9 | The basic hash table does not permit any data to be stored
|
---|
10 | with a string. However, a hash table is designed to present a
|
---|
11 | base class from which other types of hash tables may be
|
---|
12 | derived. These derived types may store additional information
|
---|
13 | with the string. Hash tables were implemented in this way,
|
---|
14 | rather than simply providing a data pointer in a hash table
|
---|
15 | entry, because they were designed for use by the linker back
|
---|
16 | ends. The linker may create thousands of hash table entries,
|
---|
17 | and the overhead of allocating private data and storing and
|
---|
18 | following pointers becomes noticeable.
|
---|
19 |
|
---|
20 | The basic hash table code is in @code{hash.c}.
|
---|
21 |
|
---|
22 | @menu
|
---|
23 | * Creating and Freeing a Hash Table::
|
---|
24 | * Looking Up or Entering a String::
|
---|
25 | * Traversing a Hash Table::
|
---|
26 | * Deriving a New Hash Table Type::
|
---|
27 | @end menu
|
---|
28 |
|
---|
29 | @node Creating and Freeing a Hash Table, Looking Up or Entering a String, Hash Tables, Hash Tables
|
---|
30 | @subsection Creating and freeing a hash table
|
---|
31 | @findex bfd_hash_table_init
|
---|
32 | @findex bfd_hash_table_init_n
|
---|
33 | To create a hash table, create an instance of a @code{struct
|
---|
34 | bfd_hash_table} (defined in @code{bfd.h}) and call
|
---|
35 | @code{bfd_hash_table_init} (if you know approximately how many
|
---|
36 | entries you will need, the function @code{bfd_hash_table_init_n},
|
---|
37 | which takes a @var{size} argument, may be used).
|
---|
38 | @code{bfd_hash_table_init} returns @code{FALSE} if some sort of
|
---|
39 | error occurs.
|
---|
40 |
|
---|
41 | @findex bfd_hash_newfunc
|
---|
42 | The function @code{bfd_hash_table_init} take as an argument a
|
---|
43 | function to use to create new entries. For a basic hash
|
---|
44 | table, use the function @code{bfd_hash_newfunc}. @xref{Deriving
|
---|
45 | a New Hash Table Type}, for why you would want to use a
|
---|
46 | different value for this argument.
|
---|
47 |
|
---|
48 | @findex bfd_hash_allocate
|
---|
49 | @code{bfd_hash_table_init} will create an objalloc which will be
|
---|
50 | used to allocate new entries. You may allocate memory on this
|
---|
51 | objalloc using @code{bfd_hash_allocate}.
|
---|
52 |
|
---|
53 | @findex bfd_hash_table_free
|
---|
54 | Use @code{bfd_hash_table_free} to free up all the memory that has
|
---|
55 | been allocated for a hash table. This will not free up the
|
---|
56 | @code{struct bfd_hash_table} itself, which you must provide.
|
---|
57 |
|
---|
58 | @node Looking Up or Entering a String, Traversing a Hash Table, Creating and Freeing a Hash Table, Hash Tables
|
---|
59 | @subsection Looking up or entering a string
|
---|
60 | @findex bfd_hash_lookup
|
---|
61 | The function @code{bfd_hash_lookup} is used both to look up a
|
---|
62 | string in the hash table and to create a new entry.
|
---|
63 |
|
---|
64 | If the @var{create} argument is @code{FALSE}, @code{bfd_hash_lookup}
|
---|
65 | will look up a string. If the string is found, it will
|
---|
66 | returns a pointer to a @code{struct bfd_hash_entry}. If the
|
---|
67 | string is not found in the table @code{bfd_hash_lookup} will
|
---|
68 | return @code{NULL}. You should not modify any of the fields in
|
---|
69 | the returns @code{struct bfd_hash_entry}.
|
---|
70 |
|
---|
71 | If the @var{create} argument is @code{TRUE}, the string will be
|
---|
72 | entered into the hash table if it is not already there.
|
---|
73 | Either way a pointer to a @code{struct bfd_hash_entry} will be
|
---|
74 | returned, either to the existing structure or to a newly
|
---|
75 | created one. In this case, a @code{NULL} return means that an
|
---|
76 | error occurred.
|
---|
77 |
|
---|
78 | If the @var{create} argument is @code{TRUE}, and a new entry is
|
---|
79 | created, the @var{copy} argument is used to decide whether to
|
---|
80 | copy the string onto the hash table objalloc or not. If
|
---|
81 | @var{copy} is passed as @code{FALSE}, you must be careful not to
|
---|
82 | deallocate or modify the string as long as the hash table
|
---|
83 | exists.
|
---|
84 |
|
---|
85 | @node Traversing a Hash Table, Deriving a New Hash Table Type, Looking Up or Entering a String, Hash Tables
|
---|
86 | @subsection Traversing a hash table
|
---|
87 | @findex bfd_hash_traverse
|
---|
88 | The function @code{bfd_hash_traverse} may be used to traverse a
|
---|
89 | hash table, calling a function on each element. The traversal
|
---|
90 | is done in a random order.
|
---|
91 |
|
---|
92 | @code{bfd_hash_traverse} takes as arguments a function and a
|
---|
93 | generic @code{void *} pointer. The function is called with a
|
---|
94 | hash table entry (a @code{struct bfd_hash_entry *}) and the
|
---|
95 | generic pointer passed to @code{bfd_hash_traverse}. The function
|
---|
96 | must return a @code{boolean} value, which indicates whether to
|
---|
97 | continue traversing the hash table. If the function returns
|
---|
98 | @code{FALSE}, @code{bfd_hash_traverse} will stop the traversal and
|
---|
99 | return immediately.
|
---|
100 |
|
---|
101 | @node Deriving a New Hash Table Type, , Traversing a Hash Table, Hash Tables
|
---|
102 | @subsection Deriving a new hash table type
|
---|
103 | Many uses of hash tables want to store additional information
|
---|
104 | which each entry in the hash table. Some also find it
|
---|
105 | convenient to store additional information with the hash table
|
---|
106 | itself. This may be done using a derived hash table.
|
---|
107 |
|
---|
108 | Since C is not an object oriented language, creating a derived
|
---|
109 | hash table requires sticking together some boilerplate
|
---|
110 | routines with a few differences specific to the type of hash
|
---|
111 | table you want to create.
|
---|
112 |
|
---|
113 | An example of a derived hash table is the linker hash table.
|
---|
114 | The structures for this are defined in @code{bfdlink.h}. The
|
---|
115 | functions are in @code{linker.c}.
|
---|
116 |
|
---|
117 | You may also derive a hash table from an already derived hash
|
---|
118 | table. For example, the a.out linker backend code uses a hash
|
---|
119 | table derived from the linker hash table.
|
---|
120 |
|
---|
121 | @menu
|
---|
122 | * Define the Derived Structures::
|
---|
123 | * Write the Derived Creation Routine::
|
---|
124 | * Write Other Derived Routines::
|
---|
125 | @end menu
|
---|
126 |
|
---|
127 | @node Define the Derived Structures, Write the Derived Creation Routine, Deriving a New Hash Table Type, Deriving a New Hash Table Type
|
---|
128 | @subsubsection Define the derived structures
|
---|
129 | You must define a structure for an entry in the hash table,
|
---|
130 | and a structure for the hash table itself.
|
---|
131 |
|
---|
132 | The first field in the structure for an entry in the hash
|
---|
133 | table must be of the type used for an entry in the hash table
|
---|
134 | you are deriving from. If you are deriving from a basic hash
|
---|
135 | table this is @code{struct bfd_hash_entry}, which is defined in
|
---|
136 | @code{bfd.h}. The first field in the structure for the hash
|
---|
137 | table itself must be of the type of the hash table you are
|
---|
138 | deriving from itself. If you are deriving from a basic hash
|
---|
139 | table, this is @code{struct bfd_hash_table}.
|
---|
140 |
|
---|
141 | For example, the linker hash table defines @code{struct
|
---|
142 | bfd_link_hash_entry} (in @code{bfdlink.h}). The first field,
|
---|
143 | @code{root}, is of type @code{struct bfd_hash_entry}. Similarly,
|
---|
144 | the first field in @code{struct bfd_link_hash_table}, @code{table},
|
---|
145 | is of type @code{struct bfd_hash_table}.
|
---|
146 |
|
---|
147 | @node Write the Derived Creation Routine, Write Other Derived Routines, Define the Derived Structures, Deriving a New Hash Table Type
|
---|
148 | @subsubsection Write the derived creation routine
|
---|
149 | You must write a routine which will create and initialize an
|
---|
150 | entry in the hash table. This routine is passed as the
|
---|
151 | function argument to @code{bfd_hash_table_init}.
|
---|
152 |
|
---|
153 | In order to permit other hash tables to be derived from the
|
---|
154 | hash table you are creating, this routine must be written in a
|
---|
155 | standard way.
|
---|
156 |
|
---|
157 | The first argument to the creation routine is a pointer to a
|
---|
158 | hash table entry. This may be @code{NULL}, in which case the
|
---|
159 | routine should allocate the right amount of space. Otherwise
|
---|
160 | the space has already been allocated by a hash table type
|
---|
161 | derived from this one.
|
---|
162 |
|
---|
163 | After allocating space, the creation routine must call the
|
---|
164 | creation routine of the hash table type it is derived from,
|
---|
165 | passing in a pointer to the space it just allocated. This
|
---|
166 | will initialize any fields used by the base hash table.
|
---|
167 |
|
---|
168 | Finally the creation routine must initialize any local fields
|
---|
169 | for the new hash table type.
|
---|
170 |
|
---|
171 | Here is a boilerplate example of a creation routine.
|
---|
172 | @var{function_name} is the name of the routine.
|
---|
173 | @var{entry_type} is the type of an entry in the hash table you
|
---|
174 | are creating. @var{base_newfunc} is the name of the creation
|
---|
175 | routine of the hash table type your hash table is derived
|
---|
176 | from.
|
---|
177 |
|
---|
178 |
|
---|
179 | @example
|
---|
180 | struct bfd_hash_entry *
|
---|
181 | @var{function_name} (entry, table, string)
|
---|
182 | struct bfd_hash_entry *entry;
|
---|
183 | struct bfd_hash_table *table;
|
---|
184 | const char *string;
|
---|
185 | @{
|
---|
186 | struct @var{entry_type} *ret = (@var{entry_type} *) entry;
|
---|
187 |
|
---|
188 | /* Allocate the structure if it has not already been allocated by a
|
---|
189 | derived class. */
|
---|
190 | if (ret == (@var{entry_type} *) NULL)
|
---|
191 | @{
|
---|
192 | ret = ((@var{entry_type} *)
|
---|
193 | bfd_hash_allocate (table, sizeof (@var{entry_type})));
|
---|
194 | if (ret == (@var{entry_type} *) NULL)
|
---|
195 | return NULL;
|
---|
196 | @}
|
---|
197 |
|
---|
198 | /* Call the allocation method of the base class. */
|
---|
199 | ret = ((@var{entry_type} *)
|
---|
200 | @var{base_newfunc} ((struct bfd_hash_entry *) ret, table, string));
|
---|
201 |
|
---|
202 | /* Initialize the local fields here. */
|
---|
203 |
|
---|
204 | return (struct bfd_hash_entry *) ret;
|
---|
205 | @}
|
---|
206 | @end example
|
---|
207 | @strong{Description}@*
|
---|
208 | The creation routine for the linker hash table, which is in
|
---|
209 | @code{linker.c}, looks just like this example.
|
---|
210 | @var{function_name} is @code{_bfd_link_hash_newfunc}.
|
---|
211 | @var{entry_type} is @code{struct bfd_link_hash_entry}.
|
---|
212 | @var{base_newfunc} is @code{bfd_hash_newfunc}, the creation
|
---|
213 | routine for a basic hash table.
|
---|
214 |
|
---|
215 | @code{_bfd_link_hash_newfunc} also initializes the local fields
|
---|
216 | in a linker hash table entry: @code{type}, @code{written} and
|
---|
217 | @code{next}.
|
---|
218 |
|
---|
219 | @node Write Other Derived Routines, , Write the Derived Creation Routine, Deriving a New Hash Table Type
|
---|
220 | @subsubsection Write other derived routines
|
---|
221 | You will want to write other routines for your new hash table,
|
---|
222 | as well.
|
---|
223 |
|
---|
224 | You will want an initialization routine which calls the
|
---|
225 | initialization routine of the hash table you are deriving from
|
---|
226 | and initializes any other local fields. For the linker hash
|
---|
227 | table, this is @code{_bfd_link_hash_table_init} in @code{linker.c}.
|
---|
228 |
|
---|
229 | You will want a lookup routine which calls the lookup routine
|
---|
230 | of the hash table you are deriving from and casts the result.
|
---|
231 | The linker hash table uses @code{bfd_link_hash_lookup} in
|
---|
232 | @code{linker.c} (this actually takes an additional argument which
|
---|
233 | it uses to decide how to return the looked up value).
|
---|
234 |
|
---|
235 | You may want a traversal routine. This should just call the
|
---|
236 | traversal routine of the hash table you are deriving from with
|
---|
237 | appropriate casts. The linker hash table uses
|
---|
238 | @code{bfd_link_hash_traverse} in @code{linker.c}.
|
---|
239 |
|
---|
240 | These routines may simply be defined as macros. For example,
|
---|
241 | the a.out backend linker hash table, which is derived from the
|
---|
242 | linker hash table, uses macros for the lookup and traversal
|
---|
243 | routines. These are @code{aout_link_hash_lookup} and
|
---|
244 | @code{aout_link_hash_traverse} in aoutx.h.
|
---|
245 |
|
---|