extra: parse asm and unops after everyone else is finished with them
[smatch.git] / smatch_modification_hooks.c
blob491d53e485df61dca00c771b40e206e24999411c
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_slist.h"
15 enum {
16 match_none = 0,
17 match_exact,
18 match_indirect
21 static modification_hook **hooks;
22 static modification_hook **indirect_hooks; /* parent struct modified etc */
24 void add_modification_hook(int owner, modification_hook *call_back)
26 hooks[owner] = call_back;
29 void add_indirect_modification_hook(int owner, modification_hook *call_back)
31 indirect_hooks[owner] = call_back;
34 static int matches(char *name, struct symbol *sym, struct sm_state *sm)
36 int len;
38 if (sym != sm->sym)
39 return match_none;
41 len = strlen(name);
42 if (strncmp(sm->name, name, len) == 0) {
43 if (sm->name[len] == '\0')
44 return match_exact;
45 if (sm->name[len] == '-' || sm->name[len] == '.')
46 return match_indirect;
48 if (sm->name[0] != '*')
49 return match_none;
50 if (strncmp(sm->name + 1, name, len) == 0) {
51 if (sm->name[len + 1] == '\0')
52 return match_indirect;
53 if (sm->name[len + 1] == '-' || sm->name[len + 1] == '.')
54 return match_indirect;
56 return match_none;
59 static void call_modification_hooks(struct expression *expr)
61 char *name;
62 struct symbol *sym;
63 struct state_list *slist;
64 struct sm_state *sm;
65 int match;
67 name = get_variable_from_expr(expr, &sym);
68 if (!name || !sym)
69 goto free;
70 slist = __get_cur_slist();
72 FOR_EACH_PTR(slist, sm) {
73 if (sm->owner > num_checks)
74 continue;
75 match = matches(name, sym, sm);
77 if (match && hooks[sm->owner])
78 (hooks[sm->owner])(sm);
80 if (match == match_indirect && indirect_hooks[sm->owner])
81 (indirect_hooks[sm->owner])(sm);
82 } END_FOR_EACH_PTR(sm);
83 free:
84 free_string(name);
87 static void match_assign(struct expression *expr)
89 call_modification_hooks(expr->left);
92 static void unop_expr(struct expression *expr)
94 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
95 return;
97 expr = strip_expr(expr->unop);
98 call_modification_hooks(expr);
101 static void match_call(struct expression *expr)
103 struct expression *arg, *tmp;
105 FOR_EACH_PTR(expr->args, arg) {
106 tmp = strip_expr(arg);
107 if (tmp->type != EXPR_PREOP || tmp->op != '&')
108 continue;
109 tmp = strip_expr(tmp->unop);
110 call_modification_hooks(tmp);
111 } END_FOR_EACH_PTR(arg);
114 static void asm_expr(struct statement *stmt)
117 struct expression *expr;
118 int state = 0;
120 FOR_EACH_PTR(stmt->asm_outputs, expr) {
121 switch (state) {
122 case 0: /* identifier */
123 case 1: /* constraint */
124 state++;
125 continue;
126 case 2: /* expression */
127 state = 0;
128 call_modification_hooks(expr);
129 continue;
131 } END_FOR_EACH_PTR(expr);
134 void register_modification_hooks(int id)
136 hooks = malloc((num_checks + 1) * sizeof(*hooks));
137 memset(hooks, 0, (num_checks + 1) * sizeof(*hooks));
138 indirect_hooks = malloc((num_checks + 1) * sizeof(*hooks));
139 memset(indirect_hooks, 0, (num_checks + 1) * sizeof(*hooks));
141 add_hook(&match_assign, ASSIGNMENT_HOOK);
142 add_hook(&unop_expr, OP_HOOK);
143 add_hook(&asm_expr, ASM_HOOK);
146 void register_modification_hooks_late(int id)
148 add_hook(&match_call, FUNCTION_CALL_HOOK);