diff options
author | Martin Liska <mliska@suse.cz> | 2020-08-18 14:24:41 +0200 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-08-20 10:57:52 +0930 |
commit | a0522545b6ef4dd43f976d6acb4fd2b0aa964b27 (patch) | |
tree | 719fe72e7b9174a60bfe4e2f32d895ccfe9f55b1 /gas | |
parent | 629310abec8811510177101f3c7992dfd4be24dd (diff) | |
download | binutils-a0522545b6ef4dd43f976d6acb4fd2b0aa964b27.zip binutils-a0522545b6ef4dd43f976d6acb4fd2b0aa964b27.tar.gz binutils-a0522545b6ef4dd43f976d6acb4fd2b0aa964b27.tar.bz2 |
Remove --reduce-memory-overheads and --hash-size arguments.
* NEWS: Mention --reduce-memory-overheads and --hash-size arguments
options.
* as.c: Remove the options from help.
* doc/as.texi: Remove options.
* doc/internals.texi: Remove hash from documentation.
* hash.c (struct hash_entry): Remove.
(struct hash_control): Likewise.
(set_gas_hash_table_size): Likewise.
(hash_new_sized): Likewise.
(hash_new): Likewise.
(hash_die): Likewise.
(hash_lookup): Likewise.
(hash_insert): Likewise.
(hash_jam): Likewise.
(hash_replace): Likewise.
(hash_find): Likewise.
(hash_find_n): Likewise.
(hash_delete): Likewise.
(hash_traverse): Likewise.
(hash_print_statistics): Likewise.
(TABLES): Likewise.
(STATBUFSIZE): Likewise.
(main): Likewise.
(what): Likewise.
(destroy): Likewise.
(applicatee): Likewise.
(whattable): Likewise.
* hash.h (struct hash_control): Likewise.
(set_gas_hash_table_size): Likewise.
(hash_new): Likewise.
(hash_new_sized): Likewise.
(hash_die): Likewise.
(hash_insert): Likewise.
(hash_jam): Likewise.
(hash_replace): Likewise.
(hash_find): Likewise.
(hash_find_n): Likewise.
(hash_delete): Likewise.
(hash_traverse): Likewise.
(hash_print_statistics): Likewise.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 43 | ||||
-rw-r--r-- | gas/NEWS | 3 | ||||
-rw-r--r-- | gas/as.c | 22 | ||||
-rw-r--r-- | gas/doc/as.texi | 13 | ||||
-rw-r--r-- | gas/doc/internals.texi | 32 | ||||
-rw-r--r-- | gas/hash.c | 574 | ||||
-rw-r--r-- | gas/hash.h | 64 |
7 files changed, 47 insertions, 704 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index b2c8b98..0ba47b8 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,48 @@ 2020-08-20 Martin Liska <mliska@suse.cz> + * NEWS: Mention --reduce-memory-overheads and --hash-size arguments + options. + * as.c: Remove the options from help. + * doc/as.texi: Remove options. + * doc/internals.texi: Remove hash from documentation. + * hash.c (struct hash_entry): Remove. + (struct hash_control): Likewise. + (set_gas_hash_table_size): Likewise. + (hash_new_sized): Likewise. + (hash_new): Likewise. + (hash_die): Likewise. + (hash_lookup): Likewise. + (hash_insert): Likewise. + (hash_jam): Likewise. + (hash_replace): Likewise. + (hash_find): Likewise. + (hash_find_n): Likewise. + (hash_delete): Likewise. + (hash_traverse): Likewise. + (hash_print_statistics): Likewise. + (TABLES): Likewise. + (STATBUFSIZE): Likewise. + (main): Likewise. + (what): Likewise. + (destroy): Likewise. + (applicatee): Likewise. + (whattable): Likewise. + * hash.h (struct hash_control): Likewise. + (set_gas_hash_table_size): Likewise. + (hash_new): Likewise. + (hash_new_sized): Likewise. + (hash_die): Likewise. + (hash_insert): Likewise. + (hash_jam): Likewise. + (hash_replace): Likewise. + (hash_find): Likewise. + (hash_find_n): Likewise. + (hash_delete): Likewise. + (hash_traverse): Likewise. + (hash_print_statistics): Likewise. + +2020-08-20 Martin Liska <mliska@suse.cz> + * config/obj-coff-seh.c (seh_hash_insert): Port to use new str_htab type. (seh_hash_find): Likewise. @@ -1,5 +1,8 @@ -*- text -*- +* Removed --reduce-memory-overheads and --hash-size as gas now + uses hash tables that can be expand and shrink automatically. + * Add {disp16} pseudo prefix to x86 assembler. * Add support for Intel AMX instructions. @@ -346,10 +346,6 @@ Options:\n\ fprintf (stream, _("\ --gdwarf-sections generate per-function section names for DWARF line information\n")); fprintf (stream, _("\ - --hash-size=<value> set the hash table size close to <value>\n")); - fprintf (stream, _("\ - --help show this message and exit\n")); - fprintf (stream, _("\ --target-help show target specific options\n")); fprintf (stream, _("\ -I DIR add DIR to search list for .include directives\n")); @@ -372,10 +368,6 @@ Options:\n\ fprintf (stream, _("\ -R fold data section into text section\n")); fprintf (stream, _("\ - --reduce-memory-overheads \n\ - prefer smaller memory use at the cost of longer\n\ - assembly times\n")); - fprintf (stream, _("\ --statistics print various measured statistics from execution\n")); fprintf (stream, _("\ --strip-local-absolute strip local absolute symbols\n")); @@ -1100,22 +1092,10 @@ This program has absolutely no warranty.\n")); break; case OPTION_REDUCE_MEMORY_OVERHEADS: - /* The only change we make at the moment is to reduce - the size of the hash tables that we use. */ - set_gas_hash_table_size (4051); break; case OPTION_HASH_TABLE_SIZE: - { - unsigned long new_size; - - new_size = strtoul (optarg, NULL, 0); - if (new_size) - set_gas_hash_table_size (new_size); - else - as_fatal (_("--hash-size needs a numeric argument")); - break; - } + break; } } diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 0dffb01..4f86e21 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -238,7 +238,6 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}. [@b{--listing-cont-lines}=@var{NUM}] [@b{--keep-locals}] [@b{--no-pad-sections}] [@b{-o} @var{objfile}] [@b{-R}] - [@b{--hash-size}=@var{NUM}] [@b{--reduce-memory-overheads}] [@b{--statistics}] [@b{-v}] [@b{-version}] [@b{--version}] [@b{-W}] [@b{--warn}] [@b{--fatal-warnings}] [@b{-w}] [@b{-x}] @@ -875,18 +874,6 @@ Name the object-file output from @command{@value{AS}} @var{objfile}. @item -R Fold the data section into the text section. -@item --hash-size=@var{number} -Set the default size of GAS's hash tables to a prime number close to -@var{number}. Increasing this value can reduce the length of time it takes the -assembler to perform its tasks, at the expense of increasing the assembler's -memory requirements. Similarly reducing this value can reduce the memory -requirements at the expense of speed. - -@item --reduce-memory-overheads -This option reduces GAS's memory requirements, at the expense of making the -assembly processes slower. Currently this switch is a synonym for -@samp{--hash-size=4051}, but in the future it may have other effects as well. - @ifset ELF @item --sectname-subst Honor substitution sequences in section names. diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi index 23520bd..a690d78 100644 --- a/gas/doc/internals.texi +++ b/gas/doc/internals.texi @@ -1915,38 +1915,6 @@ type is narrow enough, a decimal number will be produced; otherwise, it will be in hexadecimal. The value itself is not examined to make this determination. @end deftypefun -@node Hash tables -@subsection Hash tables -@cindex hash tables - -@deftypefun @{@} @{struct hash_control *@} hash_new (void) -Creates the hash table control structure. -@end deftypefun - -@deftypefun @{@} void hash_die (struct hash_control *) -Destroy a hash table. -@end deftypefun - -@deftypefun @{@} void *hash_delete (struct hash_control *, const char *, int) -Deletes entry from the hash table, returns the value it had. If the last -arg is non-zero, free memory allocated for this entry and all entries -allocated more recently than this entry. -@end deftypefun - -@deftypefun @{@} void *hash_replace (struct hash_control *, const char *, void *) -Updates the value for an entry already in the table, returning the old value. -If no entry was found, just returns NULL. -@end deftypefun - -@deftypefun @{@} @{const char *@} hash_insert (struct hash_control *, const char *, void *) -Inserting a value already in the table is an error. -Returns an error message or NULL. -@end deftypefun - -@deftypefun @{@} @{const char *@} hash_jam (struct hash_control *, const char *, void *) -Inserts if the value isn't already present, updates it if it is. -@end deftypefun - @node Test suite @section Test suite @cindex test suite @@ -18,395 +18,7 @@ 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 - the hash table code in BFD, but optimized slightly for the - assembler. The assembler does not need to derive structures that - are stored in the hash table. Instead, it always stores a pointer. - The assembler uses the hash table mostly to store symbols, and we - don't need to confuse the symbol structure with a hash table - structure. */ - #include "as.h" -#include "safe-ctype.h" -#include "obstack.h" - -/* An entry in a hash table. */ - -struct hash_entry { - /* Next entry for this hash code. */ - struct hash_entry *next; - /* String being hashed. */ - const char *string; - /* Hash code. This is the full hash code, not the index into the - table. */ - unsigned long hash; - /* Pointer being stored in the hash table. */ - void *data; -}; - -/* A hash table. */ - -struct hash_control { - /* The hash array. */ - struct hash_entry **table; - /* The number of slots in the hash table. */ - unsigned int size; - /* An obstack for this hash table. */ - struct obstack memory; - -#ifdef HASH_STATISTICS - /* Statistics. */ - unsigned long lookups; - unsigned long hash_compares; - unsigned long string_compares; - unsigned long insertions; - unsigned long replacements; - unsigned long deletions; -#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_sized (unsigned long size) -{ - unsigned long alloc; - struct hash_control *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); - memset (ret->table, 0, alloc); - ret->size = size; - -#ifdef HASH_STATISTICS - ret->lookups = 0; - ret->hash_compares = 0; - ret->string_compares = 0; - ret->insertions = 0; - ret->replacements = 0; - ret->deletions = 0; -#endif - - 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 -hash_die (struct hash_control *table) -{ - obstack_free (&table->memory, 0); - free (table); -} - -/* Look up a string in a hash table. This returns a pointer to the - hash_entry, or NULL if the string is not in the table. If PLIST is - not NULL, this sets *PLIST to point to the start of the list which - would hold this hash entry. If PHASH is not NULL, this sets *PHASH - to the hash code for KEY. - - 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 *table, const char *key, size_t len, - struct hash_entry ***plist, unsigned long *phash) -{ - unsigned long hash; - size_t n; - unsigned int c; - unsigned int hindex; - struct hash_entry **list; - struct hash_entry *p; - struct hash_entry *prev; - -#ifdef HASH_STATISTICS - ++table->lookups; -#endif - - hash = 0; - for (n = 0; n < len; n++) - { - c = key[n]; - hash += c + (c << 17); - hash ^= hash >> 2; - } - hash += len + (len << 17); - hash ^= hash >> 2; - - if (phash != NULL) - *phash = hash; - - hindex = hash % table->size; - list = table->table + hindex; - - if (plist != NULL) - *plist = list; - - prev = NULL; - for (p = *list; p != NULL; p = p->next) - { -#ifdef HASH_STATISTICS - ++table->hash_compares; -#endif - - if (p->hash == hash) - { -#ifdef HASH_STATISTICS - ++table->string_compares; -#endif - - if (strncmp (p->string, key, len) == 0 && p->string[len] == '\0') - { - if (prev != NULL) - { - prev->next = p->next; - p->next = *list; - *list = p; - } - - return p; - } - } - - prev = p; - } - - return NULL; -} - -/* Insert an entry into a hash table. This returns NULL on success. - On error, it returns a printable string indicating the error. It - is considered to be an error if the entry already exists in the - hash table. */ - -const char * -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, strlen (key), &list, &hash); - if (p != NULL) - return "exists"; - -#ifdef HASH_STATISTICS - ++table->insertions; -#endif - - p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p)); - p->string = key; - p->hash = hash; - p->data = val; - - p->next = *list; - *list = p; - - return NULL; -} - -/* Insert or replace an entry in a hash table. This returns NULL on - success. On error, it returns a printable string indicating the - error. If an entry already exists, its value is replaced. */ - -const char * -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, strlen (key), &list, &hash); - if (p != NULL) - { -#ifdef HASH_STATISTICS - ++table->replacements; -#endif - - p->data = val; - } - else - { -#ifdef HASH_STATISTICS - ++table->insertions; -#endif - - p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p)); - p->string = key; - p->hash = hash; - p->data = val; - - p->next = *list; - *list = p; - } - - return NULL; -} - -/* Replace an existing entry in a hash table. This returns the old - value stored for the entry. If the entry is not found in the hash - table, this does nothing and returns NULL. */ - -void * -hash_replace (struct hash_control *table, const char *key, void *value) -{ - struct hash_entry *p; - void *ret; - - p = hash_lookup (table, key, strlen (key), NULL, NULL); - if (p == NULL) - return NULL; - -#ifdef HASH_STATISTICS - ++table->replacements; -#endif - - ret = p->data; - - p->data = value; - - return ret; -} - -/* Find an entry in a hash table, returning its value. Returns NULL - if the entry is not found. */ - -void * -hash_find (struct hash_control *table, const char *key) -{ - struct hash_entry *p; - - 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; - - return p->data; -} - -/* Delete an entry from a hash table. This returns the value stored - for that entry, or NULL if there is no such entry. */ - -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, strlen (key), &list, NULL); - if (p == NULL) - return NULL; - - if (p != *list) - abort (); - -#ifdef HASH_STATISTICS - ++table->deletions; -#endif - - *list = p->next; - - if (freeme) - obstack_free (&table->memory, p); - - return p->data; -} - -/* Traverse a hash table. Call the function on every entry in the - hash table. */ - -void -hash_traverse (struct hash_control *table, - void (*pfn) (const char *key, void *value)) -{ - unsigned int i; - - for (i = 0; i < table->size; ++i) - { - struct hash_entry *p; - - for (p = table->table[i]; p != NULL; p = p->next) - (*pfn) (p->string, p->data); - } -} - -/* Print hash table statistics on the specified file. NAME is the - name of the hash table, used for printing a header. */ - -void -hash_print_statistics (FILE *f ATTRIBUTE_UNUSED, - const char *name ATTRIBUTE_UNUSED, - struct hash_control *table ATTRIBUTE_UNUSED) -{ -#ifdef HASH_STATISTICS - unsigned int i; - unsigned long total; - unsigned long empty; - - fprintf (f, "%s hash statistics:\n", name); - fprintf (f, "\t%lu lookups\n", table->lookups); - fprintf (f, "\t%lu hash comparisons\n", table->hash_compares); - fprintf (f, "\t%lu string comparisons\n", table->string_compares); - fprintf (f, "\t%lu insertions\n", table->insertions); - fprintf (f, "\t%lu replacements\n", table->replacements); - fprintf (f, "\t%lu deletions\n", table->deletions); - - total = 0; - empty = 0; - for (i = 0; i < table->size; ++i) - { - struct hash_entry *p; - - if (table->table[i] == NULL) - ++empty; - else - { - for (p = table->table[i]; p != NULL; p = p->next) - ++total; - } - } - - fprintf (f, "\t%g average chain length\n", (double) total / table->size); - fprintf (f, "\t%lu empty slots\n", empty); -#endif -} /* Insert ELEMENT into HTAB. If the element exists, it is overwritten. */ @@ -431,189 +43,3 @@ htab_print_statistics (FILE *f, const char *name, htab_t table) fprintf (f, "\t%lu elements\n", (unsigned long) htab_elements (table)); fprintf (f, "\t%lu table size\n", (unsigned long) htab_size (table)); } - -#ifdef TEST - -/* This test program is left over from the old hash table code. */ - -/* Number of hash tables to maintain (at once) in any testing. */ -#define TABLES (6) - -/* We can have 12 statistics. */ -#define STATBUFSIZE (12) - -/* Display statistics here. */ -int statbuf[STATBUFSIZE]; - -/* Human farts here. */ -char answer[100]; - -/* We test many hash tables at once. */ -char *hashtable[TABLES]; - -/* Points to current hash_control. */ -char *h; -char **pp; -char *p; -char *name; -char *value; -int size; -int used; -char command; - -/* Number 0:TABLES-1 of current hashed symbol table. */ -int number; - -int -main () -{ - void applicatee (); - void destroy (); - char *what (); - int *ip; - - number = 0; - h = 0; - printf ("type h <RETURN> for help\n"); - for (;;) - { - printf ("hash_test command: "); - gets (answer); - command = answer[0]; - command = TOLOWER (command); /* Ecch! */ - switch (command) - { - case '#': - printf ("old hash table #=%d.\n", number); - whattable (); - break; - case '?': - for (pp = hashtable; pp < hashtable + TABLES; pp++) - { - printf ("address of hash table #%d control block is %xx\n", - pp - hashtable, *pp); - } - break; - case 'a': - hash_traverse (h, applicatee); - break; - case 'd': - hash_traverse (h, destroy); - hash_die (h); - break; - case 'f': - p = hash_find (h, name = what ("symbol")); - printf ("value of \"%s\" is \"%s\"\n", name, p ? p : "NOT-PRESENT"); - break; - case 'h': - printf ("# show old, select new default hash table number\n"); - printf ("? display all hashtable control block addresses\n"); - printf ("a apply a simple display-er to each symbol in table\n"); - printf ("d die: destroy hashtable\n"); - printf ("f find value of nominated symbol\n"); - printf ("h this help\n"); - printf ("i insert value into symbol\n"); - printf ("j jam value into symbol\n"); - printf ("n new hashtable\n"); - printf ("r replace a value with another\n"); - printf ("s say what %% of table is used\n"); - printf ("q exit this program\n"); - printf ("x delete a symbol from table, report its value\n"); - break; - case 'i': - p = hash_insert (h, name = what ("symbol"), value = what ("value")); - if (p) - { - printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value, - p); - } - break; - case 'j': - p = hash_jam (h, name = what ("symbol"), value = what ("value")); - if (p) - { - printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value, p); - } - break; - case 'n': - h = hashtable[number] = (char *) hash_new (); - break; - case 'q': - exit (EXIT_SUCCESS); - case 'r': - p = hash_replace (h, name = what ("symbol"), value = what ("value")); - printf ("old value was \"%s\"\n", p ? p : "{}"); - break; - case 's': - hash_say (h, statbuf, STATBUFSIZE); - for (ip = statbuf; ip < statbuf + STATBUFSIZE; ip++) - { - printf ("%d ", *ip); - } - printf ("\n"); - break; - case 'x': - p = hash_delete (h, name = what ("symbol")); - printf ("old value was \"%s\"\n", p ? p : "{}"); - break; - default: - printf ("I can't understand command \"%c\"\n", command); - break; - } - } -} - -char * -what (description) - char *description; -{ - printf (" %s : ", description); - gets (answer); - return xstrdup (answer); -} - -void -destroy (string, value) - char *string; - char *value; -{ - free (string); - free (value); -} - -void -applicatee (string, value) - char *string; - char *value; -{ - printf ("%.20s-%.20s\n", string, value); -} - -/* Determine number: what hash table to use. - Also determine h: points to hash_control. */ - -void -whattable () -{ - for (;;) - { - printf (" what hash table (%d:%d) ? ", 0, TABLES - 1); - gets (answer); - sscanf (answer, "%d", &number); - if (number >= 0 && number < TABLES) - { - h = hashtable[number]; - if (!h) - { - printf ("warning: current hash-table-#%d. has no hash-control\n", number); - } - return; - } - else - { - printf ("invalid hash table number: %d\n", number); - } - } -} - -#endif /* TEST */ @@ -21,70 +21,6 @@ #ifndef HASH_H #define HASH_H -struct hash_control; - -/* Set the size of the hash table used. */ - -void set_gas_hash_table_size (unsigned long); - -/* Create a hash table. This return a control block. */ - -extern struct hash_control *hash_new (void); -extern struct hash_control *hash_new_sized (unsigned long); - -/* Delete a hash table, freeing all allocated memory. */ - -extern void hash_die (struct hash_control *); - -/* Insert an entry into a hash table. This returns NULL on success. - On error, it returns a printable string indicating the error. It - is considered to be an error if the entry already exists in the - hash table. */ - -extern const char *hash_insert (struct hash_control *, - const char *key, void *value); - -/* Insert or replace an entry in a hash table. This returns NULL on - success. On error, it returns a printable string indicating the - error. If an entry already exists, its value is replaced. */ - -extern const char *hash_jam (struct hash_control *, - const char *key, void *value); - -/* Replace an existing entry in a hash table. This returns the old - value stored for the entry. If the entry is not found in the hash - table, this does nothing and returns NULL. */ - -extern void *hash_replace (struct hash_control *, const char *key, - void *value); - -/* Find an entry in a hash table, returning its value. Returns NULL - if the entry is not found. */ - -extern void *hash_find (struct hash_control *, const char *key); - -/* As hash_find, but KEY is of length LEN and is not guaranteed to be - NUL-terminated. */ - -extern void *hash_find_n (struct hash_control *, const char *key, size_t len); - -/* Delete an entry from a hash table. This returns the value stored - for that entry, or NULL if there is no such entry. */ - -extern void *hash_delete (struct hash_control *, const char *key, int); - -/* Traverse a hash table. Call the function on every entry in the - hash table. */ - -extern void hash_traverse (struct hash_control *, - void (*pfn) (const char *key, void *value)); - -/* Print hash table statistics on the specified file. NAME is the - name of the hash table, used for printing a header. */ - -extern void hash_print_statistics (FILE *, const char *name, - struct hash_control *); - /* Insert ELEMENT into HTAB. If the element exists, it is overwritten. */ extern void htab_insert (htab_t, void *); |