If the pointer is initialized to non-null then set the state appropriately.
[smatch.git] / smatch_slist.c
blob6d4287e66163c836680a66eef31846f0ac5afee9
1 /*
2 * sparse/smatch_slist.c
4 * Copyright (C) 2008 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 ALLOCATOR(smatch_state, "smatch state");
16 ALLOCATOR(named_slist, "named slist");
18 void add_history(struct smatch_state *state)
20 struct state_history *tmp;
22 if (!state)
23 return;
24 tmp = malloc(sizeof(*tmp));
25 tmp->loc = get_lineno();
26 add_ptr_list(&state->line_history, tmp);
29 struct smatch_state *alloc_state(const char *name, int owner,
30 struct symbol *sym, int state)
32 struct smatch_state *sm_state = __alloc_smatch_state(0);
34 sm_state->name = (char *)name;
35 sm_state->owner = owner;
36 sm_state->sym = sym;
37 sm_state->state = state;
38 sm_state->line_history = NULL;
39 sm_state->path_history = NULL;
40 add_history(sm_state);
41 return sm_state;
44 struct smatch_state *clone_state(struct smatch_state *s)
46 return alloc_state(s->name, s->owner, s->sym, s->state);
49 struct state_list *clone_slist(struct state_list *from_slist)
51 struct smatch_state *state;
52 struct smatch_state *tmp;
53 struct state_list *to_slist = NULL;
55 FOR_EACH_PTR(from_slist, state) {
56 tmp = clone_state(state);
57 add_ptr_list(&to_slist, tmp);
58 } END_FOR_EACH_PTR(state);
59 return to_slist;
62 int merge_states(const char *name, int owner, struct symbol *sym,
63 int state1, int state2)
65 int ret;
67 if (state1 == state2)
68 ret = state1;
69 else if (__has_merge_function(owner))
70 ret = __client_merge_function(owner, name, sym,
71 (state1 < state2?state1:state2),
72 (state1 > state2?state1:state2));
73 else
74 ret = UNDEFINED;
76 SM_DEBUG("%d merge name='%s' owner=%d: %d + %d => %d\n",
77 get_lineno(), name, owner, state1, state2, ret);
79 return ret;
82 void merge_state_slist(struct state_list **slist, const char *name, int owner,
83 struct symbol *sym, int state)
85 struct smatch_state *tmp;
86 int s;
88 FOR_EACH_PTR(*slist, tmp) {
89 if (tmp->owner == owner && tmp->sym == sym
90 && !strcmp(tmp->name, name)){
91 s = merge_states(name, owner, sym, tmp->state, state);
92 if (tmp->state != s) {
93 add_history(tmp);
95 tmp->state = s;
96 return;
98 } END_FOR_EACH_PTR(tmp);
99 tmp = alloc_state(name, owner, sym, state);
100 add_state_slist(slist, tmp);
103 int get_state_slist(struct state_list *slist, const char *name, int owner,
104 struct symbol *sym)
106 struct smatch_state *state;
108 if (!name)
109 return NOTFOUND;
111 FOR_EACH_PTR(slist, state) {
112 if (state->owner == owner && state->sym == sym
113 && !strcmp(state->name, name))
114 return state->state;
115 } END_FOR_EACH_PTR(state);
116 return NOTFOUND;
119 void add_state_slist(struct state_list **slist, struct smatch_state *state)
121 add_ptr_list(slist, state);
124 void set_state_slist(struct state_list **slist, const char *name, int owner,
125 struct symbol *sym, int state)
127 struct smatch_state *tmp;
129 FOR_EACH_PTR(*slist, tmp) {
130 if (tmp->owner == owner && tmp->sym == sym
131 && !strcmp(tmp->name, name)){
132 tmp->state = state;
133 return;
135 } END_FOR_EACH_PTR(tmp);
136 tmp = alloc_state(name, owner, sym, state);
137 add_state_slist(slist, tmp);
140 void delete_state_slist(struct state_list **slist, const char *name, int owner,
141 struct symbol *sym)
143 struct smatch_state *state;
145 FOR_EACH_PTR(*slist, state) {
146 if (state->owner == owner && state->sym == sym
147 && !strcmp(state->name, name)){
148 delete_ptr_list_entry((struct ptr_list **)slist,
149 state, 1);
150 __free_smatch_state(state);
151 return;
153 } END_FOR_EACH_PTR(state);
157 void push_slist(struct state_list_stack **list_stack, struct state_list *slist)
159 add_ptr_list(list_stack, slist);
162 struct state_list *pop_slist(struct state_list_stack **list_stack)
164 struct state_list *slist;
166 slist = last_ptr_list((struct ptr_list *)*list_stack);
167 delete_ptr_list_entry((struct ptr_list **)list_stack, slist, 1);
168 return slist;
171 void del_slist(struct state_list **slist)
173 __free_ptr_list((struct ptr_list **)slist);
176 void del_slist_stack(struct state_list_stack **slist_stack)
178 struct state_list *slist;
180 FOR_EACH_PTR(*slist_stack, slist) {
181 __free_ptr_list((struct ptr_list **)&slist);
182 } END_FOR_EACH_PTR(slist);
183 __free_ptr_list((struct ptr_list **)slist_stack);
187 * set_state_stack() sets the state for the top slist on the stack.
189 void set_state_stack(struct state_list_stack **stack, const char *name,
190 int owner, struct symbol *sym, int state)
192 struct state_list *slist;
194 slist = pop_slist(stack);
195 set_state_slist(&slist, name, owner, sym, state);
196 push_slist(stack, slist);
200 * get_state_stack() gets the state for the top slist on the stack.
202 int get_state_stack(struct state_list_stack *stack, const char *name,
203 int owner, struct symbol *sym)
205 struct state_list *slist;
206 int ret;
208 slist = pop_slist(&stack);
209 ret = get_state_slist(slist, name, owner, sym);
210 push_slist(&stack, slist);
211 return ret;
214 void merge_state_stack(struct state_list_stack **stack, const char *name,
215 int owner, struct symbol *sym, int state)
217 struct state_list *slist;
219 slist = pop_slist(stack);
220 merge_state_slist(&slist, name, owner, sym, state);
221 push_slist(stack, slist);
224 void merge_slist(struct state_list *slist)
226 struct smatch_state *state;
228 if (get_state_slist(slist, "null_path", 0, NULL) == 1) {
229 SM_DEBUG("%d ignoring merge of null path\n", get_lineno());
230 return;
233 FOR_EACH_PTR(slist, state) {
234 merge_state_slist(&cur_slist, state->name, state->owner,
235 state->sym, state->state);
236 } END_FOR_EACH_PTR(state);
238 FOR_EACH_PTR(cur_slist, state) {
239 if (get_state_slist(slist, state->name, state->owner,
240 state->sym) == NOTFOUND) {
241 merge_state_slist(&cur_slist, state->name, state->owner,
242 state->sym, NOTFOUND);
244 } END_FOR_EACH_PTR(state);
248 * and_slist_stack() ands an slist with the top slist in an slist stack.
251 void and_slist_stack(struct state_list_stack **slist_stack,
252 struct state_list *tmp_slist)
254 struct smatch_state *tmp;
255 int tmp_state;
257 FOR_EACH_PTR(tmp_slist, tmp) {
258 tmp_state = get_state_stack(*slist_stack, tmp->name,
259 tmp->owner, tmp->sym);
260 if (tmp_state >= 0 && tmp_state != tmp->state) {
261 smatch_msg("wierdness merging 'and' conditions states '%s': %d & %d.\n",
262 tmp->name, tmp_state, tmp->state);
263 tmp->state = merge_states(tmp->name, tmp->owner,
264 tmp->sym, tmp->state,
265 tmp_state);
268 set_state_stack(slist_stack, tmp->name, tmp->owner, tmp->sym,
269 tmp->state);
271 } END_FOR_EACH_PTR(tmp);
272 // del_slist(&tmp_slist);
275 void or_slist_stack(struct state_list_stack **slist_stack)
277 struct state_list *one;
278 struct state_list *two;
279 struct state_list *res = NULL;
280 struct smatch_state *tmp;
281 int s;
283 one = pop_slist(slist_stack);
284 two = pop_slist(slist_stack);
286 FOR_EACH_PTR(one, tmp) {
287 s = get_state_slist(two, tmp->name, tmp->owner, tmp->sym);
288 s = merge_states(tmp->name, tmp->owner, tmp->sym,
289 tmp->state, s);
290 set_state_slist(&res, tmp->name, tmp->owner, tmp->sym, s);
291 } END_FOR_EACH_PTR(tmp);
293 push_slist(slist_stack, res);
295 del_slist(&one);
296 del_slist(&two);
299 struct state_list *get_slist_from_slist_stack(struct slist_stack *stack,
300 const char *name)
302 struct named_slist *tmp;
304 FOR_EACH_PTR(stack, tmp) {
305 if (!strcmp(tmp->name, name))
306 return tmp->slist;
307 } END_FOR_EACH_PTR(tmp);
308 return NULL;
311 void overwrite_slist(struct state_list *from, struct state_list **to)
313 struct smatch_state *tmp;
315 FOR_EACH_PTR(from, tmp) {
316 set_state_slist(to, tmp->name, tmp->owner, tmp->sym, tmp->state);
317 } END_FOR_EACH_PTR(tmp);