#include "smatch.h"
#include "smatch_slist.h"
static struct smatch_state *alloc_link(struct var_sym_list *links)
{
struct smatch_state *state;
static char buf[256];
struct var_sym *tmp;
int i;
state = __alloc_smatch_state(0);
i = 0;
FOR_EACH_PTR(links, tmp) {
if (!i++) {
snprintf(buf, sizeof(buf), "%s", tmp->var);
} else {
append(buf, ", ", sizeof(buf));
append(buf, tmp->var, sizeof(buf));
}
} END_FOR_EACH_PTR(tmp);
state->name = alloc_sname(buf);
state->data = links;
return state;
}
struct smatch_state *merge_link_states(struct smatch_state *s1, struct smatch_state *s2)
{
struct var_sym_list *new_links;
if (s1 == &undefined)
return s2;
if (s2 == &undefined)
return s1;
if (var_sym_lists_equiv(s1->data, s2->data))
return s1;
new_links = clone_var_sym_list(s1->data);
merge_var_sym_list(&new_links, s2->data);
return alloc_link(new_links);
}
void store_link(int link_id, const char *var, struct symbol *sym, const char *link_name, struct symbol *link_sym)
{
struct smatch_state *old_state;
struct var_sym_list *links;
if (!cur_func_sym)
return;
old_state = get_state(link_id, var, sym);
if (old_state)
links = clone_var_sym_list(old_state->data);
else
links = NULL;
add_var_sym(&links, link_name, link_sym);
set_state(link_id, var, sym, alloc_link(links));
}
static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
{
struct var_sym_list *links;
struct var_sym *tmp;
links = sm->state->data;
FOR_EACH_PTR(links, tmp) {
set_state(sm->owner - 1, tmp->var, tmp->sym, &undefined);
} END_FOR_EACH_PTR(tmp);
set_state(sm->owner, sm->name, sm->sym, &undefined);
}
void set_up_link_functions(int id, int link_id)
{
if (id + 1 != link_id)
sm_fatal("FATAL ERROR: links need to be registered directly after the check");
set_dynamic_states(link_id);
add_merge_hook(link_id, &merge_link_states);
add_modification_hook(link_id, &match_link_modify);
}