2 * sparse/smatch_modification_hooks.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
13 #include "smatch_function_hashtable.h"
17 modification_hook
*call_back
;
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
,
32 struct mcall_back
*cb
;
34 cb
= __alloc_mcall_back(0);
36 cb
->call_back
= call_back
;
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
)
50 } END_FOR_EACH_PTR(cb
);
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
))
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
;
69 expr
= strip_expr(expr
);
70 name
= get_variable_from_expr(expr
, NULL
);
73 if (is_duplicate(owner
, name
))
75 cb
= alloc_mcall_back(owner
, call_back
, info
);
76 add_mcall(var_hash
, name
, cb
);
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
)
89 if (!default_hooks
[owner
])
91 add_modification_hook(owner
, variable
, default_hooks
[owner
], NULL
);
94 static void call_call_backs(struct mod_cb_list
*list
,
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
;
114 left
= strip_expr(expr
->left
);
115 name
= get_variable_from_expr(left
, &sym
);
118 call_backs
= search_mcall(var_hash
, name
);
121 call_call_backs(call_backs
, name
, sym
, expr
);
126 static void unop_expr(struct expression
*expr
)
128 struct mod_cb_list
*call_backs
;
132 if (expr
->op
!= SPECIAL_DECREMENT
&& expr
->op
!= SPECIAL_INCREMENT
)
135 expr
= strip_expr(expr
->unop
);
136 name
= get_variable_from_expr(expr
, &sym
);
139 call_backs
= search_mcall(var_hash
, name
);
142 call_call_backs(call_backs
, name
, sym
, expr
);
147 static void match_call(struct expression
*expr
)
149 struct mod_cb_list
*call_backs
;
150 struct expression
*arg
;
154 FOR_EACH_PTR(expr
->args
, arg
) {
155 arg
= strip_expr(arg
);
156 if (arg
->type
!= EXPR_PREOP
|| arg
->op
!= '&')
158 arg
= strip_expr(arg
->unop
);
159 name
= get_variable_from_expr(arg
, &sym
);
162 call_backs
= search_mcall(var_hash
, name
);
164 call_call_backs(call_backs
, name
, sym
, expr
);
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
)
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
);