+/* Calculate a hash code for the given partial symbol. The hash is
+ calculated using the symbol's value, language, domain, class
+ and name. These are the values which are set by
+ add_psymbol_to_bcache. */
+
+static unsigned long
+psymbol_hash (const void *addr, int length)
+{
+ unsigned long h = 0;
+ struct partial_symbol *psymbol = (struct partial_symbol *) addr;
+ unsigned int lang = psymbol->ginfo.language;
+ unsigned int domain = PSYMBOL_DOMAIN (psymbol);
+ unsigned int class = PSYMBOL_CLASS (psymbol);
+
+ h = hash_continue (&psymbol->ginfo.value, sizeof (psymbol->ginfo.value), h);
+ h = hash_continue (&lang, sizeof (unsigned int), h);
+ h = hash_continue (&domain, sizeof (unsigned int), h);
+ h = hash_continue (&class, sizeof (unsigned int), h);
+ h = hash_continue (psymbol->ginfo.name, strlen (psymbol->ginfo.name), h);
+
+ return h;
+}
+
+/* Returns true if the symbol at addr1 equals the symbol at addr2.
+ For the comparison this function uses a symbols value,
+ language, domain, class and name. */
+
+static int
+psymbol_compare (const void *addr1, const void *addr2, int length)
+{
+ struct partial_symbol *sym1 = (struct partial_symbol *) addr1;
+ struct partial_symbol *sym2 = (struct partial_symbol *) addr2;
+
+ return (memcmp (&sym1->ginfo.value, &sym1->ginfo.value,
+ sizeof (sym1->ginfo.value)) == 0
+ && sym1->ginfo.language == sym2->ginfo.language
+ && PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)
+ && PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2)
+ && sym1->ginfo.name == sym2->ginfo.name);
+}
+
+/* Initialize a partial symbol bcache. */
+
+struct psymbol_bcache *
+psymbol_bcache_init (void)
+{
+ struct psymbol_bcache *bcache = XCNEW (struct psymbol_bcache);
+ bcache->bcache = bcache_xmalloc (psymbol_hash, psymbol_compare);
+ return bcache;
+}
+
+/* Free a partial symbol bcache. */
+void
+psymbol_bcache_free (struct psymbol_bcache *bcache)
+{
+ if (bcache == NULL)
+ return;
+
+ bcache_xfree (bcache->bcache);
+ xfree (bcache);
+}
+
+/* Return the internal bcache of the psymbol_bcache BCACHE. */
+
+struct bcache *
+psymbol_bcache_get_bcache (struct psymbol_bcache *bcache)
+{
+ return bcache->bcache;
+}
+
+/* Find a copy of the SYM in BCACHE. If BCACHE has never seen this
+ symbol before, add a copy to BCACHE. In either case, return a pointer
+ to BCACHE's copy of the symbol. If optional ADDED is not NULL, return
+ 1 in case of new entry or 0 if returning an old entry. */
+
+static const struct partial_symbol *
+psymbol_bcache_full (struct partial_symbol *sym,
+ struct psymbol_bcache *bcache,
+ int *added)
+{
+ return bcache_full (sym,
+ sizeof (struct partial_symbol),
+ bcache->bcache,
+ added);
+}
+