#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "dis_target.h"
#include "dis_list.h"
#include "dis_util.h"
typedef struct unresolved_name {
const char *un_name;
int un_value;
int un_mark;
uu_list_node_t un_node;
} unresolved_name_t;
typedef struct resolved_name {
void *rn_data;
int rn_value;
uu_list_node_t rn_node;
} resolved_name_t;
static uu_list_pool_t *unresolved_pool;
static uu_list_pool_t *resolved_pool;
static int current_mark = 0;
static void
initialize_pools(void)
{
unresolved_pool = uu_list_pool_create(
"unresolved_pool", sizeof (unresolved_name_t),
offsetof(unresolved_name_t, un_node), NULL, 0);
resolved_pool = uu_list_pool_create(
"resolved_pool", sizeof (resolved_name_t),
offsetof(resolved_name_t, rn_node), NULL, 0);
if (unresolved_pool == NULL ||
resolved_pool == NULL)
die("out of memory");
}
dis_namelist_t *
dis_namelist_create(void)
{
uu_list_t *listp;
if (unresolved_pool == NULL)
initialize_pools();
if ((listp = uu_list_create(unresolved_pool, NULL, 0)) == NULL)
die("out of memory");
return (listp);
}
void
dis_namelist_add(dis_namelist_t *list, const char *name, int value)
{
unresolved_name_t *node;
node = safe_malloc(sizeof (unresolved_name_t));
node->un_name = name;
node->un_value = value;
node->un_mark = 0;
(void) uu_list_insert_before(list, NULL, node);
}
typedef struct cb_data {
int cb_mark;
uu_list_t *cb_source;
uu_list_t *cb_resolved;
} cb_data_t;
static void
walk_sections(dis_tgt_t *tgt, dis_scn_t *scn, void *data)
{
cb_data_t *cb = data;
unresolved_name_t *unp;
uu_list_walk_t *walk;
if ((walk = uu_list_walk_start(cb->cb_source, UU_DEFAULT)) == NULL)
die("out of memory");
while ((unp = uu_list_walk_next(walk)) != NULL) {
if (strcmp(unp->un_name, dis_section_name(scn)) == 0) {
resolved_name_t *resolved;
unp->un_mark = cb->cb_mark;
resolved = safe_malloc(sizeof (resolved_name_t));
resolved->rn_data = dis_section_copy(scn);
resolved->rn_value = unp->un_value;
(void) uu_list_insert_before(cb->cb_resolved, NULL,
resolved);
}
}
uu_list_walk_end(walk);
}
dis_scnlist_t *
dis_namelist_resolve_sections(dis_namelist_t *namelist, dis_tgt_t *tgt)
{
uu_list_t *listp;
cb_data_t cb;
unresolved_name_t *unp;
uu_list_walk_t *walk;
if ((listp = uu_list_create(resolved_pool, NULL, UU_DEFAULT)) == NULL)
die("out of memory");
cb.cb_mark = ++current_mark;
cb.cb_source = namelist;
cb.cb_resolved = listp;
dis_tgt_section_iter(tgt, walk_sections, &cb);
if ((walk = uu_list_walk_start(namelist, UU_DEFAULT)) == NULL)
die("out of memory");
while ((unp = uu_list_walk_next(walk)) != NULL) {
if (unp->un_mark != current_mark)
warn("failed to find section '%s' in '%s'",
unp->un_name, dis_tgt_name(tgt));
}
uu_list_walk_end(walk);
return (listp);
}
static void
walk_functions(dis_tgt_t *tgt, dis_func_t *func, void *data)
{
cb_data_t *cb = data;
unresolved_name_t *unp;
uu_list_walk_t *walk;
if ((walk = uu_list_walk_start(cb->cb_source, UU_DEFAULT)) == NULL)
die("out of memory");
while ((unp = uu_list_walk_next(walk)) != NULL) {
if (strcmp(unp->un_name, dis_function_name(func)) == 0) {
resolved_name_t *resolved;
unp->un_mark = cb->cb_mark;
resolved = safe_malloc(sizeof (resolved_name_t));
resolved->rn_data = dis_function_copy(func);
resolved->rn_value = unp->un_value;
(void) uu_list_insert_before(cb->cb_resolved, NULL,
resolved);
}
}
uu_list_walk_end(walk);
}
dis_funclist_t *
dis_namelist_resolve_functions(dis_namelist_t *namelist, dis_tgt_t *tgt)
{
uu_list_t *listp;
uu_list_walk_t *walk;
unresolved_name_t *unp;
cb_data_t cb;
if ((listp = uu_list_create(resolved_pool, NULL, UU_DEFAULT)) == NULL)
die("out of memory");
cb.cb_mark = ++current_mark;
cb.cb_source = namelist;
cb.cb_resolved = listp;
dis_tgt_function_iter(tgt, walk_functions, &cb);
if ((walk = uu_list_walk_start(namelist, UU_DEFAULT)) == NULL)
die("out of memory");
while ((unp = uu_list_walk_next(walk)) != NULL) {
if (unp->un_mark != current_mark)
warn("failed to find function '%s' in '%s'",
unp->un_name, dis_tgt_name(tgt));
}
uu_list_walk_end(walk);
return (listp);
}
int
dis_namelist_empty(dis_namelist_t *list)
{
return (uu_list_numnodes(list) == 0);
}
static void
free_list(uu_list_t *list)
{
uu_list_walk_t *walk;
void *data;
if ((walk = uu_list_walk_start(list, UU_WALK_ROBUST)) == NULL)
die("out of memory");
while ((data = uu_list_walk_next(walk)) != NULL) {
uu_list_remove(list, data);
free(data);
}
uu_list_walk_end(walk);
uu_list_destroy(list);
}
void
dis_scnlist_destroy(dis_scnlist_t *list)
{
uu_list_walk_t *walk;
resolved_name_t *data;
if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
die("out of memory");
while ((data = uu_list_walk_next(walk)) != NULL)
dis_section_free(data->rn_data);
uu_list_walk_end(walk);
free_list(list);
}
void
dis_funclist_destroy(dis_funclist_t *list)
{
uu_list_walk_t *walk;
resolved_name_t *data;
if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
die("out of memory");
while ((data = uu_list_walk_next(walk)) != NULL)
dis_function_free(data->rn_data);
uu_list_walk_end(walk);
free_list(list);
}
void
dis_namelist_destroy(dis_namelist_t *list)
{
free_list(list);
}
void
dis_scnlist_iter(uu_list_t *list, void (*func)(dis_scn_t *, int, void *),
void *arg)
{
uu_list_walk_t *walk;
resolved_name_t *data;
if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
die("out of memory");
while ((data = uu_list_walk_next(walk)) != NULL)
func(data->rn_data, data->rn_value, arg);
uu_list_walk_end(walk);
}
void
dis_funclist_iter(uu_list_t *list, void (*func)(dis_func_t *, int, void *),
void *arg)
{
uu_list_walk_t *walk;
resolved_name_t *data;
if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL)
die("out of memory");
while ((data = uu_list_walk_next(walk)) != NULL)
func(data->rn_data, data->rn_value, arg);
uu_list_walk_end(walk);
}