+struct library_exported_names_each_context
+{
+ enum callback_status (*inner_cb)(const char *, void *);
+ void *data;
+ bool failure : 1;
+};
+static enum callback_status
+library_exported_names_each_cb(const char **key, uint64_t *value, void *data)
+{
+ struct library_exported_names_each_context *context =
+ (struct library_exported_names_each_context*)data;
+ enum callback_status status = context->inner_cb(*key, context->data);
+ if(status == CBS_FAIL)
+ context->failure = true;
+ return status;
+}
+bool library_exported_names_each(const struct library_exported_names *names,
+ enum callback_status (*cb)(const char *,
+ void *),
+ void *data)
+{
+ struct library_exported_names_each_context context =
+ {.inner_cb = cb,
+ .data = data,
+ .failure = false};
+ DICT_EACH(&names->names,
+ const char*, uint64_t,
+ NULL, library_exported_names_each_cb, &context);
+ return !context.failure;
+}
+
+struct library_exported_names_each_alias_context
+{
+ enum callback_status (*inner_cb)(const char *, void *);
+ const char *origname;
+ void *data;
+ bool failure : 1;
+};
+static enum callback_status
+library_exported_names_each_alias_cb(const char **name, void *data)
+{
+ struct library_exported_names_each_alias_context *context =
+ (struct library_exported_names_each_alias_context*)data;
+
+ // I do not report the original name we were asked about. Otherwise, any
+ // time the caller asks for aliases of symbol "sym", I'll always report
+ // "sym" along with any actual aliases
+ if(strcmp(*name, context->origname) == 0)
+ return CBS_CONT;
+
+ enum callback_status status = context->inner_cb(*name, context->data);
+ if(status == CBS_FAIL)
+ context->failure = true;
+ return status;
+}
+
+bool library_exported_names_each_alias(
+ const struct library_exported_names *names,
+ const char *aliasname,
+ enum callback_status (*cb)(const char *,
+ void *),
+ void *data)
+{
+ // I have a symbol name. I look up its address, then get the list of
+ // aliased names
+ uint64_t *addr = DICT_FIND_REF(&names->names,
+ &aliasname, uint64_t);
+ if(addr == NULL)
+ return false;
+
+ // OK. I have an address. Get the list of symbols at this address
+ struct vect **aliases = DICT_FIND_REF(&names->addrs,
+ addr, struct vect*);
+ if(aliases == NULL)
+ return false;
+
+ struct library_exported_names_each_alias_context context =
+ {.inner_cb = cb,
+ .origname = aliasname,
+ .data = data,
+ .failure = false};
+ VECT_EACH(*aliases, const char*, NULL,
+ library_exported_names_each_alias_cb, &context);
+}
+
+
+
+