Fix OpenBSD compile
[smatch.git] / smatch_modification_hooks.c
blob72dcfc72d2af02fd6fd7ae8e667817d98fb47061
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 modification_hook *call_back;
17 void *info;
20 ALLOCATOR(mcall_back, "modification call backs");
21 DECLARE_PTR_LIST(mod_cb_list, struct mcall_back);
23 DEFINE_FUNCTION_HASHTABLE_STATIC(mcall, struct mcall_back, struct mod_cb_list);
24 static struct hashtable *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 void add_modification_hook(const char *variable, modification_hook *call_back, void *info)
39 struct mcall_back *cb;
41 cb = alloc_mcall_back(call_back, info);
42 add_mcall(var_hash, variable, cb);
45 void add_modification_hook_expr(struct expression *expr, modification_hook *call_back, void *info)
47 struct mcall_back *cb;
48 char *name;
50 expr = strip_expr(expr);
51 name = get_variable_from_expr(expr, NULL);
52 if (!name)
53 return;
54 cb = alloc_mcall_back(call_back, info);
55 add_mcall(var_hash, name, cb);
56 free_string(name);
59 static void call_call_backs(struct mod_cb_list *list,
60 const char *variable,
61 struct symbol *sym,
62 struct expression *expr)
64 struct mcall_back *tmp;
66 FOR_EACH_PTR(list, tmp) {
67 (tmp->call_back)(variable, sym, expr, tmp->info);
68 } END_FOR_EACH_PTR(tmp);
72 static void match_assign(struct expression *expr)
74 struct mod_cb_list *call_backs;
75 struct expression *left;
76 struct symbol *sym;
77 char *name;
79 left = strip_expr(expr->left);
80 name = get_variable_from_expr(left, &sym);
81 if (!name)
82 return;
83 call_backs = search_mcall(var_hash, name);
84 if (!call_backs)
85 goto free;
86 call_call_backs(call_backs, name, sym, expr);
87 free:
88 free_string(name);
91 static void unop_expr(struct expression *expr)
93 struct mod_cb_list *call_backs;
94 struct symbol *sym;
95 char *name = NULL;
97 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
98 return;
100 expr = strip_expr(expr->unop);
101 name = get_variable_from_expr(expr, &sym);
102 if (!name)
103 goto free;
104 call_backs = search_mcall(var_hash, name);
105 if (!call_backs)
106 goto free;
107 call_call_backs(call_backs, name, sym, expr);
108 free:
109 free_string(name);
112 static void match_call(struct expression *expr)
114 struct mod_cb_list *call_backs;
115 struct expression *arg;
116 struct symbol *sym;
117 char *name;
119 FOR_EACH_PTR(expr->args, arg) {
120 arg = strip_expr(arg);
121 if (arg->type != EXPR_PREOP || arg->op != '&')
122 continue;
123 arg = strip_expr(arg->unop);
124 name = get_variable_from_expr(arg, &sym);
125 if (!name)
126 continue;
127 call_backs = search_mcall(var_hash, name);
128 if (call_backs)
129 call_call_backs(call_backs, name, sym, expr);
130 free_string(name);
131 } END_FOR_EACH_PTR(arg);
134 static void match_end_func(struct symbol *sym)
136 destroy_function_hashtable(var_hash);
137 var_hash = create_function_hashtable(100);
140 void register_modification_hooks(int id)
142 var_hash = create_function_hashtable(100);
143 add_hook(&match_assign, ASSIGNMENT_HOOK);
144 add_hook(&unop_expr, OP_HOOK);
145 add_hook(&match_call, FUNCTION_CALL_HOOK);
146 add_hook(&match_end_func, END_FUNC_HOOK);