Clean ups and add some __unnullify_path stuff. Hopefully this is a way
[smatch.git] / smatch_slist.c
blob29548bd3589ec04505269b7e35302114652d8660
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 FOR_EACH_PTR(slist, state) {
229 merge_state_slist(&cur_slist, state->name, state->owner,
230 state->sym, state->state);
231 } END_FOR_EACH_PTR(state);
235 * and_slist_stack() ands an slist with the top slist in an slist stack.
238 void and_slist_stack(struct state_list_stack **slist_stack,
239 struct state_list *tmp_slist)
241 struct smatch_state *tmp;
242 int tmp_state;
244 FOR_EACH_PTR(tmp_slist, tmp) {
245 if (!tmp)
246 continue;
247 tmp_state = get_state_stack(*slist_stack, tmp->name,
248 tmp->owner, tmp->sym);
249 if (tmp_state >= 0 && tmp_state != tmp->state) {
250 smatch_msg("wierdness merging 'and' conditions states '%s': %d & %d.\n",
251 tmp->name, tmp_state, tmp->state);
252 tmp->state = merge_states(tmp->name, tmp->owner,
253 tmp->sym, tmp->state,
254 tmp_state);
257 set_state_stack(slist_stack, tmp->name, tmp->owner, tmp->sym,
258 tmp->state);
260 } END_FOR_EACH_PTR(tmp);
261 // del_slist(&tmp_slist);
264 void or_slist_stack(struct state_list_stack **slist_stack)
266 struct state_list *one;
267 struct state_list *two;
268 struct state_list *res = NULL;
270 struct smatch_state *tmp;
272 one = pop_slist(slist_stack);
273 two = pop_slist(slist_stack);
275 FOR_EACH_PTR(one, tmp) {
276 if (tmp &&
277 get_state_slist(two, tmp->name, tmp->owner, tmp->sym)) {
278 set_state_slist(&res, tmp->name, tmp->owner, tmp->sym,
279 tmp->state);
281 } END_FOR_EACH_PTR(tmp);
283 push_slist(slist_stack, res);
285 // del_slist(&one);
286 // del_slist(&two);
289 struct state_list *get_slist_from_slist_stack(struct slist_stack *stack,
290 const char *name)
292 struct named_slist *tmp;
294 FOR_EACH_PTR(stack, tmp) {
295 if (!strcmp(tmp->name, name))
296 return tmp->slist;
297 } END_FOR_EACH_PTR(tmp);
298 return NULL;
301 void overwrite_slist(struct state_list *from, struct state_list **to)
303 struct smatch_state *tmp;
305 FOR_EACH_PTR(from, tmp) {
306 set_state_slist(to, tmp->name, tmp->owner, tmp->sym, tmp->state);
307 } END_FOR_EACH_PTR(tmp);