+/* Produce an unsigned hash value from STRING0 that is consistent
+ with strcmp_iw, strcmp, and, at least on Ada symbols, wild_match.
+ That is, two identifiers equivalent according to any of those three
+ comparison operators hash to the same value. */
+
+static unsigned int
+dict_hash (const char *string0)
+{
+ /* The Ada-encoded version of a name P1.P2...Pn has either the form
+ P1__P2__...Pn<suffix> or _ada_P1__P2__...Pn<suffix> (where the Pi
+ are lower-cased identifiers). The <suffix> (which can be empty)
+ encodes additional information about the denoted entity. This
+ routine hashes such names to msymbol_hash_iw(Pn). It actually
+ does this for a superset of both valid Pi and of <suffix>, but
+ in other cases it simply returns msymbol_hash_iw(STRING0). */
+
+ const char *string;
+ unsigned int hash;
+
+ string = string0;
+ if (*string == '_')
+ {
+ if (strncmp (string, "_ada_", 5) == 0)
+ string += 5;
+ else
+ return msymbol_hash_iw (string0);
+ }
+
+ hash = 0;
+ while (*string)
+ {
+ /* Ignore "TKB" suffixes.
+
+ These are used by Ada for subprograms implementing a task body.
+ For instance for a task T inside package Pck, the name of the
+ subprogram implementing T's body is `pck__tTKB'. We need to
+ ignore the "TKB" suffix because searches for this task body
+ subprogram are going to be performed using `pck__t' (the encoded
+ version of the natural name `pck.t'). */
+ if (strcmp (string, "TKB") == 0)
+ return hash;
+
+ switch (*string)
+ {
+ case '$':
+ case '.':
+ case 'X':
+ if (string0 == string)
+ return msymbol_hash_iw (string0);
+ else
+ return hash;
+ case ' ':
+ case '(':
+ return msymbol_hash_iw (string0);
+ case '_':
+ if (string[1] == '_' && string != string0)
+ {
+ int c = string[2];
+
+ if ((c < 'a' || c > 'z') && c != 'O')
+ return hash;
+ hash = 0;
+ string += 2;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ hash = SYMBOL_HASH_NEXT (hash, *string);
+ string += 1;
+ break;
+ }
+ }
+ return hash;
+}
+