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
= alloc_extra_state(UNDEFINED
);
143 non_zero_state
= add_filter(non_zero_state
, 0);
144 set_cond_states(var_name
, SMATCH_EXTRA
, sym
, non_zero_state
, zero_state
);
151 merge_slist(&cond_true
, cond_false
);
153 FOR_EACH_PTR(cond_true
, sm
) {
155 } END_FOR_EACH_PTR(sm
);
156 free_slist(&cond_true
);
157 free_slist(&cond_false
);
159 free_string(var_name
);
163 void __match_initializer_call(struct symbol
*sym
)
165 struct call_back_list
*call_backs
;
166 struct expression
*initializer
= sym
->initializer
;
167 struct expression
*e_assign
, *e_symbol
;
170 if (initializer
->fn
->type
!= EXPR_SYMBOL
171 || !initializer
->fn
->symbol
)
173 fn
= initializer
->fn
->symbol
->ident
->name
;
174 call_backs
= get_call_backs(fn
);
178 e_assign
= alloc_expression(initializer
->pos
, EXPR_ASSIGNMENT
);
179 e_symbol
= alloc_expression(initializer
->pos
, EXPR_SYMBOL
);
180 e_symbol
->symbol
= sym
;
181 e_symbol
->symbol_name
= sym
->ident
;
182 e_assign
->left
= e_symbol
;
183 e_assign
->right
= initializer
;
184 call_call_backs(call_backs
, ASSIGN_CALL
, fn
, e_assign
);
185 assign_condition_funcs(fn
, e_assign
, call_backs
);
188 static void match_assign_call(struct expression
*expr
)
190 struct call_back_list
*call_backs
;
193 if (expr
->right
->fn
->type
!= EXPR_SYMBOL
|| !expr
->right
->fn
->symbol
)
195 fn
= expr
->right
->fn
->symbol
->ident
->name
;
196 call_backs
= get_call_backs(fn
);
199 call_call_backs(call_backs
, ASSIGN_CALL
, fn
, expr
);
200 assign_condition_funcs(fn
, expr
, call_backs
);
203 static void match_conditional_call(struct expression
*expr
)
205 struct call_back_list
*call_backs
;
206 struct fcall_back
*tmp
;
210 if (expr
->type
!= EXPR_CALL
)
213 if (expr
->fn
->type
!= EXPR_SYMBOL
|| !expr
->fn
->symbol
)
216 fn
= expr
->fn
->symbol
->ident
->name
;
217 call_backs
= get_call_backs(fn
);
221 FOR_EACH_PTR(call_backs
, tmp
) {
222 if (tmp
->type
!= CONDITIONAL_CALL
)
225 (tmp
->call_back
)(fn
, expr
, tmp
->info
);
227 FOR_EACH_PTR(cond_true
, sm
) {
228 __set_true_false_sm(sm
, NULL
);
229 } END_FOR_EACH_PTR(sm
);
230 free_slist(&cond_true
);
232 FOR_EACH_PTR(cond_false
, sm
) {
233 __set_true_false_sm(NULL
, sm
);
234 } END_FOR_EACH_PTR(sm
);
235 free_slist(&cond_false
);
237 } END_FOR_EACH_PTR(tmp
);
241 void set_cond_states(const char *name
, int owner
, struct symbol
*sym
,
242 struct smatch_state
*true_state
,
243 struct smatch_state
*false_state
)
246 printf("Error: call set_true_false_states() not"
247 "set_cond_states()\n");
252 struct smatch_state
*tmp
;
254 tmp
= get_state(name
, owner
, sym
);
255 SM_DEBUG("%d set_true_false '%s'. Was %s. Now T:%s F:%s\n",
256 get_lineno(), name
, show_state(tmp
),
257 show_state(true_state
), show_state(false_state
));
261 set_state_slist(&cond_true
, name
, owner
, sym
, true_state
);
264 set_state_slist(&cond_false
, name
, owner
, sym
, false_state
);
267 void create_function_hash(void)
269 hcreate_r(10000, &func_hash
); // Apparently 1000 is too few...
272 void register_function_hooks(int id
)
274 add_hook(&match_function_call
, FUNCTION_CALL_HOOK
);
275 add_hook(&match_assign_call
, CALL_ASSIGNMENT_HOOK
);
276 add_hook(&match_conditional_call
, CONDITION_HOOK
);