6 #include "smatch_slist.h"
7 #include "smatch_extra.h"
9 ALLOCATOR(fcall_back
, "call backs");
11 static struct hsearch_data func_hash
;
13 static struct state_list
*cond_true
= NULL
;
14 static struct state_list
*cond_false
= NULL
;
15 static int in_hook
= 0;
16 #define REGULAR_CALL 0
17 #define CONDITIONAL_CALL 1
20 static struct fcall_back
*alloc_fcall_back(int type
, func_hook
*call_back
,
23 struct fcall_back
*cb
;
25 cb
= __alloc_fcall_back(0);
27 cb
->call_back
= call_back
;
32 static struct call_back_list
*get_call_backs(const char *look_for
)
36 e
.key
= (char *)look_for
;
37 hsearch_r(e
, FIND
, &ep
, &func_hash
);
40 return (struct call_back_list
*)ep
->data
;
43 static void add_cb_hook(const char *look_for
, struct fcall_back
*cb
)
48 e
.key
= alloc_string(look_for
);
49 hsearch_r(e
, FIND
, &ep
, &func_hash
);
51 struct call_back_list
*list
= NULL
;
53 add_ptr_list(&list
, cb
);
58 add_ptr_list((struct call_back_list
**)&ep
->data
, cb
);
61 if (!hsearch_r(e
, ENTER
, &ep
, &func_hash
)) {
62 printf("Error hash table too small in smatch_function_hooks.c\n");
68 void add_function_hook(const char *look_for
, func_hook
*call_back
, void *info
)
70 struct fcall_back
*cb
;
72 cb
= alloc_fcall_back(REGULAR_CALL
, call_back
, info
);
73 add_cb_hook(look_for
, cb
);
76 void add_conditional_hook(const char *look_for
, func_hook
*call_back
,
79 struct fcall_back
*cb
;
81 cb
= alloc_fcall_back(CONDITIONAL_CALL
, call_back
, info
);
82 add_cb_hook(look_for
, cb
);
85 void add_function_assign_hook(const char *look_for
, func_hook
*call_back
,
88 struct fcall_back
*cb
;
90 cb
= alloc_fcall_back(ASSIGN_CALL
, call_back
, info
);
91 add_cb_hook(look_for
, cb
);
94 static void call_call_backs(struct call_back_list
*list
, int type
,
95 const char *fn
, struct expression
*expr
)
97 struct fcall_back
*tmp
;
99 FOR_EACH_PTR(list
, tmp
) {
100 if (tmp
->type
== type
)
101 (tmp
->call_back
)(fn
, expr
, tmp
->info
);
102 } END_FOR_EACH_PTR(tmp
);
105 static void match_function_call(struct expression
*expr
)
107 struct call_back_list
*call_backs
;
109 if (expr
->fn
->type
!= EXPR_SYMBOL
|| !expr
->fn
->symbol
)
111 call_backs
= get_call_backs(expr
->fn
->symbol
->ident
->name
);
114 call_call_backs(call_backs
, REGULAR_CALL
, expr
->fn
->symbol
->ident
->name
,
118 static void assign_condition_funcs(const char *fn
, struct expression
*expr
,
119 struct call_back_list
*call_backs
)
121 struct fcall_back
*tmp
;
126 struct smatch_state
*zero_state
, *non_zero_state
;
128 var_name
= get_variable_from_expr(expr
->left
, &sym
);
129 if (!var_name
|| !sym
)
133 FOR_EACH_PTR(call_backs
, tmp
) {
134 if (tmp
->type
!= CONDITIONAL_CALL
)
138 (tmp
->call_back
)(fn
, expr
->right
, tmp
->info
);
139 } END_FOR_EACH_PTR(tmp
);
141 zero_state
= alloc_extra_state(0);
142 non_zero_state
= add_filter(extra_undefined(), 0);
143 set_cond_states(var_name
, SMATCH_EXTRA
, sym
, non_zero_state
, zero_state
);
150 merge_slist(&cond_true
, cond_false
);
152 FOR_EACH_PTR(cond_true
, sm
) {
154 } END_FOR_EACH_PTR(sm
);
155 free_slist(&cond_true
);
156 free_slist(&cond_false
);
158 free_string(var_name
);
162 void __match_initializer_call(struct symbol
*sym
)
164 struct call_back_list
*call_backs
;
165 struct expression
*initializer
= sym
->initializer
;
166 struct expression
*e_assign
, *e_symbol
;
169 if (initializer
->fn
->type
!= EXPR_SYMBOL
170 || !initializer
->fn
->symbol
)
172 fn
= initializer
->fn
->symbol
->ident
->name
;
173 call_backs
= get_call_backs(fn
);
177 e_assign
= alloc_expression(initializer
->pos
, EXPR_ASSIGNMENT
);
178 e_symbol
= alloc_expression(initializer
->pos
, EXPR_SYMBOL
);
179 e_symbol
->symbol
= sym
;
180 e_symbol
->symbol_name
= sym
->ident
;
181 e_assign
->left
= e_symbol
;
182 e_assign
->right
= initializer
;
183 call_call_backs(call_backs
, ASSIGN_CALL
, fn
, e_assign
);
184 assign_condition_funcs(fn
, e_assign
, call_backs
);
187 static void match_assign_call(struct expression
*expr
)
189 struct call_back_list
*call_backs
;
192 if (expr
->right
->fn
->type
!= EXPR_SYMBOL
|| !expr
->right
->fn
->symbol
)
194 fn
= expr
->right
->fn
->symbol
->ident
->name
;
195 call_backs
= get_call_backs(fn
);
198 call_call_backs(call_backs
, ASSIGN_CALL
, fn
, expr
);
199 assign_condition_funcs(fn
, expr
, call_backs
);
202 static void match_conditional_call(struct expression
*expr
)
204 struct call_back_list
*call_backs
;
205 struct fcall_back
*tmp
;
209 if (expr
->type
!= EXPR_CALL
)
212 if (expr
->fn
->type
!= EXPR_SYMBOL
|| !expr
->fn
->symbol
)
215 fn
= expr
->fn
->symbol
->ident
->name
;
216 call_backs
= get_call_backs(fn
);
220 FOR_EACH_PTR(call_backs
, tmp
) {
221 if (tmp
->type
!= CONDITIONAL_CALL
)
224 (tmp
->call_back
)(fn
, expr
, tmp
->info
);
226 FOR_EACH_PTR(cond_true
, sm
) {
227 __set_true_false_sm(sm
, NULL
);
228 } END_FOR_EACH_PTR(sm
);
229 free_slist(&cond_true
);
231 FOR_EACH_PTR(cond_false
, sm
) {
232 __set_true_false_sm(NULL
, sm
);
233 } END_FOR_EACH_PTR(sm
);
234 free_slist(&cond_false
);
236 } END_FOR_EACH_PTR(tmp
);
240 void set_cond_states(const char *name
, int owner
, struct symbol
*sym
,
241 struct smatch_state
*true_state
,
242 struct smatch_state
*false_state
)
245 printf("Error: call set_true_false_states() not"
246 "set_cond_states()\n");
251 struct smatch_state
*tmp
;
253 tmp
= get_state(name
, owner
, sym
);
254 SM_DEBUG("%d set_true_false '%s'. Was %s. Now T:%s F:%s\n",
255 get_lineno(), name
, show_state(tmp
),
256 show_state(true_state
), show_state(false_state
));
260 set_state_slist(&cond_true
, name
, owner
, sym
, true_state
);
263 set_state_slist(&cond_false
, name
, owner
, sym
, false_state
);
266 void create_function_hash(void)
268 hcreate_r(10000, &func_hash
); // Apparently 1000 is too few...
271 void register_function_hooks(int id
)
273 add_hook(&match_function_call
, FUNCTION_CALL_HOOK
);
274 add_hook(&match_assign_call
, CALL_ASSIGNMENT_HOOK
);
275 add_hook(&match_conditional_call
, CONDITION_HOOK
);