Start caring about the types a little.
[smatch.git] / smatch_modification_hooks.c
blob3781cfef91aa31f3f6820bce9abaaa749a5836dc
1 /*
2 * sparse/smatch_modification_hooks.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #define _GNU_SOURCE
11 #include <search.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include "smatch.h"
16 struct mcall_back {
17 modification_hook *call_back;
18 void *info;
21 ALLOCATOR(mcall_back, "modification call backs");
22 DECLARE_PTR_LIST(mod_cb_list, struct mcall_back);
24 static struct hsearch_data var_hash;
26 static struct mcall_back *alloc_mcall_back(modification_hook *call_back,
27 void *info)
29 struct mcall_back *cb;
31 cb = __alloc_mcall_back(0);
32 cb->call_back = call_back;
33 cb->info = info;
34 return cb;
37 static struct mod_cb_list *get_mcall_backs(const char *look_for)
39 ENTRY e, *ep;
41 e.key = (char *)look_for;
42 hsearch_r(e, FIND, &ep, &var_hash);
43 if (!ep)
44 return NULL;
45 return (struct mod_cb_list *)ep->data;
48 static void add_mcall_back(const char *look_for, struct mcall_back *cb)
50 ENTRY e, *ep;
51 char *old_key = NULL;
53 e.key = alloc_string(look_for);
54 hsearch_r(e, FIND, &ep, &var_hash);
55 if (!ep) {
56 struct mod_cb_list *list = NULL;
58 add_ptr_list(&list, cb);
59 e.data = list;
60 } else {
61 old_key = e.key;
62 e.key = ep->key;
63 add_ptr_list((struct mod_cb_list **)&ep->data, cb);
64 e.data = ep->data;
66 if (!hsearch_r(e, ENTER, &ep, &var_hash)) {
67 printf("Error hash table too small in smatch_modification_hooks.c\n");
68 exit(1);
70 free_string(old_key);
73 void add_modification_hook(const char *variable, modification_hook *call_back, void *info)
75 struct mcall_back *cb;
77 cb = alloc_mcall_back(call_back, info);
78 add_mcall_back(variable, cb);
81 static void call_call_backs(struct mod_cb_list *list,
82 const char *variable,
83 struct symbol *sym,
84 struct expression *expr)
86 struct mcall_back *tmp;
88 FOR_EACH_PTR(list, tmp) {
89 (tmp->call_back)(variable, sym, expr, tmp->info);
90 } END_FOR_EACH_PTR(tmp);
94 static void match_assign(struct expression *expr)
96 struct mod_cb_list *call_backs;
97 struct expression *left;
98 struct symbol *sym;
99 char *name;
101 left = strip_expr(expr->left);
102 name = get_variable_from_expr(left, &sym);
103 if (!name)
104 return;
105 call_backs = get_mcall_backs(name);
106 if (!call_backs)
107 goto free;
108 call_call_backs(call_backs, name, sym, expr);
109 free:
110 free_string(name);
113 static void match_end_func(struct symbol *sym)
115 hdestroy_r(&var_hash);
116 hcreate_r(1000, &var_hash);
119 void register_modification_hooks(int id)
121 hcreate_r(1000, &var_hash);
122 add_hook(&match_assign, ASSIGNMENT_HOOK);
123 add_hook(&match_end_func, END_FUNC_HOOK);