*new* check_macros: find macro precedence bugs
[smatch.git] / smatch_modification_hooks.c
blobe0fc2b8fafe4a10a6b5b907b9e0f9038fcdb5ec7
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 #include <stdlib.h>
11 #include <stdio.h>
12 #include "smatch.h"
13 #include "smatch_function_hashtable.h"
15 struct mcall_back {
16 int owner;
17 modification_hook *call_back;
18 void *info;
21 static modification_hook **default_hooks;
23 ALLOCATOR(mcall_back, "modification call backs");
24 DECLARE_PTR_LIST(mod_cb_list, struct mcall_back);
26 DEFINE_FUNCTION_HASHTABLE_STATIC(mcall, struct mcall_back, struct mod_cb_list);
27 static struct hashtable *var_hash;
29 static struct mcall_back *alloc_mcall_back(int owner, modification_hook *call_back,
30 void *info)
32 struct mcall_back *cb;
34 cb = __alloc_mcall_back(0);
35 cb->owner = owner;
36 cb->call_back = call_back;
37 cb->info = info;
38 return cb;
41 static int is_duplicate(int owner, const char *variable)
43 struct mod_cb_list *call_backs;
44 struct mcall_back *cb;
46 call_backs = search_mcall(var_hash, (char *)variable);
47 FOR_EACH_PTR(call_backs, cb) {
48 if (cb->owner == owner)
49 return 1;
50 } END_FOR_EACH_PTR(cb);
51 return 0;
54 void add_modification_hook(int owner, const char *variable, modification_hook *call_back, void *info)
56 struct mcall_back *cb;
58 if (is_duplicate(owner, variable))
59 return;
60 cb = alloc_mcall_back(owner, call_back, info);
61 add_mcall(var_hash, variable, cb);
64 void add_modification_hook_expr(int owner, struct expression *expr, modification_hook *call_back, void *info)
66 struct mcall_back *cb;
67 char *name;
69 expr = strip_expr(expr);
70 name = get_variable_from_expr(expr, NULL);
71 if (!name)
72 return;
73 if (is_duplicate(owner, name))
74 return;
75 cb = alloc_mcall_back(owner, call_back, info);
76 add_mcall(var_hash, name, cb);
77 free_string(name);
80 void set_default_modification_hook(int owner, modification_hook *call_back)
82 default_hooks[owner] = call_back;
85 void __use_default_modification_hook(int owner, const char *variable)
87 if (owner < 0 || owner >= num_checks)
88 return;
89 if (!default_hooks[owner])
90 return;
91 add_modification_hook(owner, variable, default_hooks[owner], NULL);
94 static void call_call_backs(struct mod_cb_list *list,
95 const char *variable,
96 struct symbol *sym,
97 struct expression *expr)
99 struct mcall_back *tmp;
101 FOR_EACH_PTR(list, tmp) {
102 (tmp->call_back)(variable, sym, expr, tmp->info);
103 } END_FOR_EACH_PTR(tmp);
107 static void match_assign(struct expression *expr)
109 struct mod_cb_list *call_backs;
110 struct expression *left;
111 struct symbol *sym;
112 char *name;
114 left = strip_expr(expr->left);
115 name = get_variable_from_expr(left, &sym);
116 if (!name)
117 return;
118 call_backs = search_mcall(var_hash, name);
119 if (!call_backs)
120 goto free;
121 call_call_backs(call_backs, name, sym, expr);
122 free:
123 free_string(name);
126 static void unop_expr(struct expression *expr)
128 struct mod_cb_list *call_backs;
129 struct symbol *sym;
130 char *name = NULL;
132 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
133 return;
135 expr = strip_expr(expr->unop);
136 name = get_variable_from_expr(expr, &sym);
137 if (!name)
138 goto free;
139 call_backs = search_mcall(var_hash, name);
140 if (!call_backs)
141 goto free;
142 call_call_backs(call_backs, name, sym, expr);
143 free:
144 free_string(name);
147 static void match_call(struct expression *expr)
149 struct mod_cb_list *call_backs;
150 struct expression *arg;
151 struct symbol *sym;
152 char *name;
154 FOR_EACH_PTR(expr->args, arg) {
155 arg = strip_expr(arg);
156 if (arg->type != EXPR_PREOP || arg->op != '&')
157 continue;
158 arg = strip_expr(arg->unop);
159 name = get_variable_from_expr(arg, &sym);
160 if (!name)
161 continue;
162 call_backs = search_mcall(var_hash, name);
163 if (call_backs)
164 call_call_backs(call_backs, name, sym, expr);
165 free_string(name);
166 } END_FOR_EACH_PTR(arg);
169 static void match_end_func(struct symbol *sym)
171 destroy_function_hashtable(var_hash);
172 var_hash = create_function_hashtable(100);
175 void register_modification_hooks(int id)
177 int i;
179 var_hash = create_function_hashtable(100);
180 default_hooks = malloc(num_checks * sizeof(*default_hooks));
181 for (i = 0; i < num_checks; i++)
182 default_hooks[i] = NULL;
183 add_hook(&match_assign, ASSIGNMENT_HOOK);
184 add_hook(&unop_expr, OP_HOOK);
185 add_hook(&match_call, FUNCTION_CALL_HOOK);
186 add_hook(&match_end_func, END_FUNC_HOOK);