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_extra.h"
14 #include "smatch_slist.h"
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
)
43 if (strncmp(sm
->name
, name
, len
) == 0) {
44 if (sm
->name
[len
] == '\0')
46 if (sm
->name
[len
] == '-' || sm
->name
[len
] == '.')
47 return match_indirect
;
49 if (sm
->name
[0] != '*')
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
;
60 static void call_modification_hooks_name_sym(char *name
, struct symbol
*sym
, struct expression
*mod_expr
)
62 struct state_list
*slist
;
66 slist
= __get_cur_slist();
68 FOR_EACH_PTR(slist
, sm
) {
69 if (sm
->owner
> num_checks
)
71 match
= matches(name
, sym
, sm
);
73 if (match
&& hooks
[sm
->owner
])
74 (hooks
[sm
->owner
])(sm
, mod_expr
);
76 if (match
== match_indirect
&& indirect_hooks
[sm
->owner
])
77 (indirect_hooks
[sm
->owner
])(sm
, mod_expr
);
78 } END_FOR_EACH_PTR(sm
);
81 static void call_modification_hooks(struct expression
*expr
, struct expression
*mod_expr
)
86 name
= expr_to_var_sym(expr
, &sym
);
89 call_modification_hooks_name_sym(name
, sym
, mod_expr
);
94 static void db_param_add(struct expression
*expr
, int param
, char *key
, char *value
)
96 struct expression
*arg
;
100 while (expr
->type
== EXPR_ASSIGNMENT
)
101 expr
= strip_expr(expr
->right
);
102 if (expr
->type
!= EXPR_CALL
)
105 arg
= get_argument_from_call_expr(expr
->args
, param
);
109 name
= get_variable_from_key(arg
, key
, &sym
);
113 call_modification_hooks_name_sym(name
, sym
, expr
);
118 static void match_assign(struct expression
*expr
)
120 call_modification_hooks(expr
->left
, expr
);
123 static void unop_expr(struct expression
*expr
)
125 if (expr
->op
!= SPECIAL_DECREMENT
&& expr
->op
!= SPECIAL_INCREMENT
)
128 call_modification_hooks(expr
->unop
, expr
);
131 static void match_call(struct expression
*expr
)
133 struct expression
*arg
, *tmp
;
135 FOR_EACH_PTR(expr
->args
, arg
) {
136 tmp
= strip_expr(arg
);
137 if (tmp
->type
== EXPR_PREOP
&& tmp
->op
== '&')
138 call_modification_hooks(tmp
->unop
, expr
);
140 call_modification_hooks(deref_expression(tmp
), expr
);
141 } END_FOR_EACH_PTR(arg
);
144 static void asm_expr(struct statement
*stmt
)
146 struct expression
*expr
;
149 FOR_EACH_PTR(stmt
->asm_outputs
, expr
) {
151 case 0: /* identifier */
152 case 1: /* constraint */
155 case 2: /* expression */
157 call_modification_hooks(expr
, NULL
);
160 } END_FOR_EACH_PTR(expr
);
163 void register_modification_hooks(int id
)
165 hooks
= malloc((num_checks
+ 1) * sizeof(*hooks
));
166 memset(hooks
, 0, (num_checks
+ 1) * sizeof(*hooks
));
167 indirect_hooks
= malloc((num_checks
+ 1) * sizeof(*hooks
));
168 memset(indirect_hooks
, 0, (num_checks
+ 1) * sizeof(*hooks
));
170 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
171 add_hook(&unop_expr
, OP_HOOK
);
172 add_hook(&asm_expr
, ASM_HOOK
);
175 void register_modification_hooks_late(int id
)
177 add_hook(&match_call
, FUNCTION_CALL_HOOK
);
178 select_return_states_hook(ADDED_VALUE
, &db_param_add
);