smatch.h, db: add numbers to the info_type enum
[smatch.git] / smatch_modification_hooks.c
blob09fe7eceb12411cf06a3bb8a1f0f3e1b63356772
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_extra.h"
14 #include "smatch_slist.h"
16 enum {
17 match_none = 0,
18 match_exact,
19 match_indirect
22 static modification_hook **hooks;
23 static modification_hook **indirect_hooks; /* parent struct modified etc */
25 void add_modification_hook(int owner, modification_hook *call_back)
27 hooks[owner] = call_back;
30 void add_indirect_modification_hook(int owner, modification_hook *call_back)
32 indirect_hooks[owner] = call_back;
35 static int matches(char *name, struct symbol *sym, struct sm_state *sm)
37 int len;
39 if (sym != sm->sym)
40 return match_none;
42 len = strlen(name);
43 if (strncmp(sm->name, name, len) == 0) {
44 if (sm->name[len] == '\0')
45 return match_exact;
46 if (sm->name[len] == '-' || sm->name[len] == '.')
47 return match_indirect;
49 if (sm->name[0] != '*')
50 return match_none;
51 if (strncmp(sm->name + 1, name, len) == 0) {
52 if (sm->name[len + 1] == '\0')
53 return match_indirect;
54 if (sm->name[len + 1] == '-' || sm->name[len + 1] == '.')
55 return match_indirect;
57 return match_none;
60 static void call_modification_hooks(struct expression *expr)
62 char *name;
63 struct symbol *sym;
64 struct state_list *slist;
65 struct sm_state *sm;
66 int match;
68 name = expr_to_var_sym(expr, &sym);
69 if (!name || !sym)
70 goto free;
71 slist = __get_cur_slist();
73 FOR_EACH_PTR(slist, sm) {
74 if (sm->owner > num_checks)
75 continue;
76 match = matches(name, sym, sm);
78 if (match && hooks[sm->owner])
79 (hooks[sm->owner])(sm);
81 if (match == match_indirect && indirect_hooks[sm->owner])
82 (indirect_hooks[sm->owner])(sm);
83 } END_FOR_EACH_PTR(sm);
84 free:
85 free_string(name);
88 static void match_assign(struct expression *expr)
90 call_modification_hooks(expr->left);
93 static void unop_expr(struct expression *expr)
95 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
96 return;
98 expr = strip_expr(expr->unop);
99 call_modification_hooks(expr);
102 static void match_call(struct expression *expr)
104 struct expression *arg, *tmp;
106 FOR_EACH_PTR(expr->args, arg) {
107 tmp = strip_expr(arg);
108 if (tmp->type == EXPR_PREOP && tmp->op == '&') {
109 tmp = strip_expr(tmp->unop);
110 call_modification_hooks(tmp);
111 } else {
112 call_modification_hooks(deref_expression(tmp));
114 } END_FOR_EACH_PTR(arg);
117 static void asm_expr(struct statement *stmt)
120 struct expression *expr;
121 int state = 0;
123 FOR_EACH_PTR(stmt->asm_outputs, expr) {
124 switch (state) {
125 case 0: /* identifier */
126 case 1: /* constraint */
127 state++;
128 continue;
129 case 2: /* expression */
130 state = 0;
131 call_modification_hooks(expr);
132 continue;
134 } END_FOR_EACH_PTR(expr);
137 void register_modification_hooks(int id)
139 hooks = malloc((num_checks + 1) * sizeof(*hooks));
140 memset(hooks, 0, (num_checks + 1) * sizeof(*hooks));
141 indirect_hooks = malloc((num_checks + 1) * sizeof(*hooks));
142 memset(indirect_hooks, 0, (num_checks + 1) * sizeof(*hooks));
144 add_hook(&match_assign, ASSIGNMENT_HOOK);
145 add_hook(&unop_expr, OP_HOOK);
146 add_hook(&asm_expr, ASM_HOOK);
149 void register_modification_hooks_late(int id)
151 add_hook(&match_call, FUNCTION_CALL_HOOK);