+\f
+/* Version handling. This is only useful for ELF. */
+
+/* This global variable holds the version tree that we build. */
+
+struct bfd_elf_version_tree *lang_elf_version_info;
+
+/* This is called for each variable name or match expression. */
+
+struct bfd_elf_version_expr *
+lang_new_vers_regex (orig, new)
+ struct bfd_elf_version_expr *orig;
+ const char *new;
+{
+ struct bfd_elf_version_expr *ret;
+
+ ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
+ ret->next = orig;
+ ret->match = new;
+ return ret;
+}
+
+/* This is called for each set of variable names and match
+ expressions. */
+
+struct bfd_elf_version_tree *
+lang_new_vers_node (globals, locals)
+ struct bfd_elf_version_expr *globals;
+ struct bfd_elf_version_expr *locals;
+{
+ struct bfd_elf_version_tree *ret;
+
+ ret = (struct bfd_elf_version_tree *) xmalloc (sizeof *ret);
+ ret->next = NULL;
+ ret->name = NULL;
+ ret->vernum = 0;
+ ret->globals = globals;
+ ret->locals = locals;
+ ret->deps = NULL;
+ ret->name_indx = (unsigned int) -1;
+ ret->used = 0;
+ return ret;
+}
+
+/* This static variable keeps track of version indices. */
+
+static int version_index;
+
+/* This is called when we know the name and dependencies of the
+ version. */
+
+void
+lang_register_vers_node (name, version, deps)
+ const char *name;
+ struct bfd_elf_version_tree *version;
+ struct bfd_elf_version_deps *deps;
+{
+ struct bfd_elf_version_tree *t, **pp;
+ struct bfd_elf_version_expr *e1;
+
+ /* Make sure this node has a unique name. */
+ for (t = lang_elf_version_info; t != NULL; t = t->next)
+ if (strcmp (t->name, name) == 0)
+ einfo ("%X%P: duplicate version tag `%s'\n", name);
+
+ /* Check the global and local match names, and make sure there
+ aren't any duplicates. */
+
+ for (e1 = version->globals; e1 != NULL; e1 = e1->next)
+ {
+ for (t = lang_elf_version_info; t != NULL; t = t->next)
+ {
+ struct bfd_elf_version_expr *e2;
+
+ for (e2 = t->globals; e2 != NULL; e2 = e2->next)
+ if (strcmp (e1->match, e2->match) == 0)
+ einfo ("%X%P: duplicate expression `%s' in version information\n",
+ e1->match);
+
+ for (e2 = t->locals; e2 != NULL; e2 = e2->next)
+ if (strcmp (e1->match, e2->match) == 0)
+ einfo ("%X%P: duplicate expression `%s' in version information\n",
+ e1->match);
+ }
+ }
+
+ for (e1 = version->locals; e1 != NULL; e1 = e1->next)
+ {
+ for (t = lang_elf_version_info; t != NULL; t = t->next)
+ {
+ struct bfd_elf_version_expr *e2;
+
+ for (e2 = t->globals; e2 != NULL; e2 = e2->next)
+ if (strcmp (e1->match, e2->match) == 0)
+ einfo ("%X%P: duplicate expression `%s' in version information\n",
+ e1->match);
+
+ for (e2 = t->locals; e2 != NULL; e2 = e2->next)
+ if (strcmp (e1->match, e2->match) == 0)
+ einfo ("%X%P: duplicate expression `%s' in version information\n",
+ e1->match);
+ }
+ }
+
+ version->deps = deps;
+ version->name = name;
+ ++version_index;
+ version->vernum = version_index;
+
+ for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next)
+ ;
+ *pp = version;
+}
+
+/* This is called when we see a version dependency. */
+
+struct bfd_elf_version_deps *
+lang_add_vers_depend (list, name)
+ struct bfd_elf_version_deps *list;
+ const char *name;
+{
+ struct bfd_elf_version_deps *ret;
+ struct bfd_elf_version_tree *t;
+
+ ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
+ ret->next = list;
+
+ for (t = lang_elf_version_info; t != NULL; t = t->next)
+ {
+ if (strcmp (t->name, name) == 0)
+ {
+ ret->version_needed = t;
+ return ret;
+ }
+ }
+
+ einfo ("%X%P: unable to find version dependency `%s'\n", name);
+
+ return ret;
+}