2 * sparse/smatch_states.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
14 ALLOCATOR(smatch_state
, "smatch state");
15 DECLARE_PTR_LIST(state_list
, struct smatch_state
);
16 DECLARE_PTR_LIST(state_list_stack
, struct state_list
);
18 static struct state_list
*cur_slist
;
19 static struct state_list_stack
*false_stack
;
20 static struct state_list_stack
*true_stack
;
21 static struct state_list_stack
*break_stack
;
22 static struct state_list_stack
*switch_stack
;
23 static struct state_list_stack
*default_stack
;
24 static struct state_list_stack
*continue_stack
;
25 static struct state_list_stack
*mini_false_stack
;
26 static struct state_list
*and_clumps
[2];
30 struct state_list
*slist
;
32 ALLOCATOR(slist_head
, "goto stack");
33 DECLARE_PTR_LIST(slist_stack
, struct slist_head
);
34 static struct slist_stack
*goto_stack
;
38 void __print_cur_slist()
40 struct smatch_state
*state
;
42 printf("dumping slist at %d\n", get_lineno());
43 FOR_EACH_PTR(cur_slist
, state
) {
44 printf("%s=%d\n", state
->name
, state
->state
);
45 } END_FOR_EACH_PTR(state
);
49 static void add_history(struct smatch_state
*state
)
51 struct state_history
*tmp
;
55 tmp
= malloc(sizeof(*tmp
));
56 tmp
->loc
= get_lineno();
57 add_ptr_list(&state
->line_history
, tmp
);
58 tmp
= malloc(sizeof(*tmp
));
59 tmp
->loc
= get_path_id();
60 add_ptr_list(&state
->line_history
, tmp
);
63 struct smatch_state
*alloc_state(const char *name
, int owner
,
64 struct symbol
*sym
, int state
)
66 struct smatch_state
*sm_state
= __alloc_smatch_state(0);
68 sm_state
->name
= (char *)name
;
69 sm_state
->owner
= owner
;
71 sm_state
->state
= state
;
72 sm_state
->line_history
= NULL
;
73 sm_state
->path_history
= NULL
;
74 add_history(sm_state
);
78 static struct smatch_state
*clone_state(struct smatch_state
*s
)
80 return alloc_state(s
->name
, s
->owner
, s
->sym
, s
->state
);
83 static void push_slist(struct state_list_stack
**list_stack
,
84 struct state_list
*slist
)
86 add_ptr_list(list_stack
, slist
);
89 static struct state_list
*pop_slist(struct state_list_stack
**list_stack
)
91 struct state_list
*slist
;
93 slist
= last_ptr_list((struct ptr_list
*)*list_stack
);
94 delete_ptr_list_entry((struct ptr_list
**)list_stack
, slist
, 1);
98 static struct state_list
*clone_slist(struct state_list
*from_slist
)
100 struct smatch_state
*state
;
101 struct smatch_state
*tmp
;
102 struct state_list
*to_slist
= NULL
;
104 FOR_EACH_PTR(from_slist
, state
) {
105 tmp
= clone_state(state
);
106 add_ptr_list(&to_slist
, tmp
);
107 } END_FOR_EACH_PTR(state
);
111 static void del_slist(struct state_list
**slist
)
113 __free_ptr_list((struct ptr_list
**)slist
);
116 static void del_slist_stack(struct state_list_stack
**slist_stack
)
118 struct state_list
*slist
;
120 FOR_EACH_PTR(*slist_stack
, slist
) {
121 __free_ptr_list((struct ptr_list
**)&slist
);
122 } END_FOR_EACH_PTR(slist
);
123 __free_ptr_list((struct ptr_list
**)slist_stack
);
126 static void add_state_slist(struct state_list
**slist
,
127 struct smatch_state
*state
)
129 add_ptr_list(slist
, state
);
132 static void set_state_slist(struct state_list
**slist
, const char *name
,
133 int owner
, struct symbol
*sym
, int state
)
135 struct smatch_state
*tmp
;
137 FOR_EACH_PTR(*slist
, tmp
) {
138 if (tmp
->owner
== owner
&& tmp
->sym
== sym
139 && !strcmp(tmp
->name
, name
)){
143 } END_FOR_EACH_PTR(tmp
);
144 tmp
= alloc_state(name
, owner
, sym
, state
);
145 add_state_slist(slist
, tmp
);
148 static inline void set_state_stack(struct state_list_stack
**stack
,
149 const char *name
, int owner
,
150 struct symbol
*sym
, int state
)
152 struct state_list
*slist
;
154 slist
= pop_slist(stack
);
155 set_state_slist(&slist
, name
, owner
, sym
, state
);
156 push_slist(stack
, slist
);
159 static int merge_states(const char *name
, int owner
, struct symbol
*sym
,
160 int state1
, int state2
)
162 if (state1
== state2
)
164 if (__has_merge_function(owner
))
165 return __client_merge_function(owner
, name
, sym
, (state1
< state2
?state1
:state2
), (state1
> state2
?state1
:state2
));
169 static void merge_state_slist(struct state_list
**slist
, const char *name
,
170 int owner
, struct symbol
*sym
, int state
)
172 struct smatch_state
*tmp
;
175 FOR_EACH_PTR(*slist
, tmp
) {
176 if (tmp
->owner
== owner
&& tmp
->sym
== sym
177 && !strcmp(tmp
->name
, name
)){
178 s
= merge_states(name
, owner
, sym
, tmp
->state
, state
);
179 if (tmp
->state
!= s
) {
181 SM_DEBUG("%d merge name='%s' owner=%d: %d + %d => %d\n",
182 get_lineno(), name
, owner
, tmp
->state
, state
, s
);
187 } END_FOR_EACH_PTR(tmp
);
188 tmp
= alloc_state(name
, owner
, sym
, state
);
189 add_state_slist(slist
, tmp
);
192 static void merge_state_stack(struct state_list_stack
** stack
,
193 const char *name
, int owner
, struct symbol
*sym
,
196 struct state_list
*slist
;
198 slist
= pop_slist(stack
);
199 merge_state_slist(&slist
, name
, owner
, sym
, state
);
200 push_slist(stack
, slist
);
203 static void delete_state_slist(struct state_list
**slist
, const char *name
,
204 int owner
, struct symbol
*sym
)
206 struct smatch_state
*state
;
208 FOR_EACH_PTR(*slist
, state
) {
209 if (state
->owner
== owner
&& state
->sym
== sym
210 && !strcmp(state
->name
, name
)){
211 delete_ptr_list_entry((struct ptr_list
**)slist
,
213 __free_smatch_state(state
);
216 } END_FOR_EACH_PTR(state
);
219 static void merge_slist(struct state_list
*slist
)
221 struct smatch_state
*state
;
222 FOR_EACH_PTR(slist
, state
) {
223 merge_state_slist(&cur_slist
, state
->name
, state
->owner
,
224 state
->sym
, state
->state
);
225 } END_FOR_EACH_PTR(state
);
228 void set_state(const char *name
, int owner
, struct symbol
*sym
, int state
)
230 struct smatch_state
*tmp
;
235 FOR_EACH_PTR(cur_slist
, tmp
) {
236 if (tmp
->owner
== owner
&& tmp
->sym
== sym
237 && !strcmp(tmp
->name
, name
)){
238 SM_DEBUG("%d state change name='%s' owner=%d: %d => %d\n"
239 , get_lineno(), name
, owner
, tmp
->state
, state
);
244 } END_FOR_EACH_PTR(tmp
);
245 SM_DEBUG("%d new state. name='%s' owner=%d: %d\n", get_lineno(), name
,
247 tmp
= alloc_state(name
, owner
, sym
, state
);
248 add_state_slist(&cur_slist
, tmp
);
252 static int get_state_slist(struct state_list
*slist
, const char *name
,
253 int owner
, struct symbol
*sym
)
255 struct smatch_state
*state
;
260 FOR_EACH_PTR(cur_slist
, state
) {
261 if (state
->owner
== owner
&& state
->sym
== sym
262 && !strcmp(state
->name
, name
))
264 } END_FOR_EACH_PTR(state
);
268 int get_state(const char *name
, int owner
, struct symbol
*sym
)
270 return get_state_slist(cur_slist
, name
, owner
, sym
);
273 struct state_list
*get_current_states(int owner
)
275 struct state_list
*slist
;
276 struct smatch_state
*tmp
;
278 FOR_EACH_PTR(cur_slist
, tmp
) {
279 if (tmp
->owner
== owner
) {
280 add_ptr_list(&slist
, tmp
);
282 } END_FOR_EACH_PTR(tmp
);
287 void set_true_false_states(const char *name
, int owner
, struct symbol
*sym
,
288 int true_state
, int false_state
)
290 int merged
= merge_states(name
, owner
, sym
, true_state
, false_state
);
292 /* fixme. history plus don't call get_state() when not needed*/
293 //SM_DEBUG("%d set_true_false %s. Was %d. Now T:%d F:%d\n",
294 // get_lineno(), name, get_state(name, owner, sym), true_state,
297 if (!false_stack
|| !true_stack
|| !mini_false_stack
) {
298 printf("Error: missing true/false stacks\n");
302 int tmp
= true_state
;
304 true_state
= false_state
;
307 set_state(name
, owner
, sym
, true_state
);
308 set_state_stack(&mini_false_stack
, name
, owner
, sym
, false_state
);
309 set_state_slist(&and_clumps
[1], name
, owner
, sym
, true_state
);
310 set_state_stack(&true_stack
, name
, owner
, sym
,
311 (__ors
?merged
:true_state
));
312 set_state_stack(&false_stack
, name
, owner
, sym
,
313 (__ands
?merged
:false_state
));
316 void delete_state(const char *name
, int owner
, struct symbol
*sym
)
318 delete_state_slist(&cur_slist
, name
, owner
, sym
);
323 del_slist(&cur_slist
);
326 void clear_all_states()
328 struct slist_head
*slist_head
;
331 del_slist_stack(&false_stack
);
332 del_slist_stack(&true_stack
);
333 del_slist_stack(&break_stack
);
334 del_slist_stack(&switch_stack
);
335 del_slist_stack(&continue_stack
);
336 del_slist_stack(&mini_false_stack
);
337 del_slist(&and_clumps
[0]);
338 del_slist(&and_clumps
[1]);
340 FOR_EACH_PTR(goto_stack
, slist_head
) {
341 del_slist(&slist_head
->slist
);
342 } END_FOR_EACH_PTR(slist_head
);
343 __free_ptr_list((struct ptr_list
**)&goto_stack
);
346 void __first_and_clump()
348 and_clumps
[0] = and_clumps
[1];
349 and_clumps
[1] = NULL
;
352 void __merge_and_clump()
354 struct smatch_state
*tmp
;
356 FOR_EACH_PTR(and_clumps
[0], tmp
) {
357 if (tmp
->state
!= get_state_slist(and_clumps
[1], tmp
->name
,
358 tmp
->owner
, tmp
->sym
))
359 DELETE_CURRENT_PTR(tmp
);
360 } END_FOR_EACH_PTR(tmp
);
361 del_slist(&and_clumps
[1]);
364 void __use_and_clumps()
366 struct smatch_state
*tmp
;
369 FOR_EACH_PTR(and_clumps
[0], tmp
) {
371 set_state_stack(&true_stack
, tmp
->name
, tmp
->owner
,
372 tmp
->sym
, tmp
->state
);
373 } END_FOR_EACH_PTR(tmp
);
374 del_slist(&and_clumps
[0]);
377 void __split_false_states_mini()
379 push_slist(&mini_false_stack
, clone_slist(cur_slist
));
382 void __use_false_states_mini()
384 struct state_list
*slist
;
387 slist
= pop_slist(&mini_false_stack
);
392 void __pop_false_states_mini()
394 struct state_list
*slist
;
396 slist
= pop_slist(&mini_false_stack
);
400 void __split_true_false_paths()
402 push_slist(&false_stack
, clone_slist(cur_slist
));
403 push_slist(&true_stack
, clone_slist(cur_slist
));
404 __split_false_states_mini();
407 void __use_true_states()
409 struct state_list
*slist
;
411 __pop_false_states_mini();
413 slist
= pop_slist(&true_stack
);
418 void __use_false_states()
420 struct state_list
*slist
;
422 push_slist(&true_stack
, clone_slist(cur_slist
));
424 slist
= pop_slist(&false_stack
);
429 void __pop_false_states()
431 struct state_list
*slist
;
433 slist
= pop_slist(&false_stack
);
437 void __merge_false_states()
439 struct state_list
*slist
;
441 slist
= pop_slist(&false_stack
);
446 void __merge_true_states()
448 struct state_list
*slist
;
450 slist
= pop_slist(&true_stack
);
455 void __pop_true_states()
457 struct state_list
*slist
;
459 slist
= pop_slist(&true_stack
);
463 void __push_continues()
465 push_slist(&continue_stack
, NULL
);
468 void __pop_continues()
470 struct state_list
*slist
;
472 slist
= pop_slist(&continue_stack
);
476 void __process_continues()
478 struct smatch_state
*state
;
480 FOR_EACH_PTR(cur_slist
, state
) {
481 merge_state_stack(&continue_stack
, state
->name
, state
->owner
,
482 state
->sym
, state
->state
);
483 } END_FOR_EACH_PTR(state
);
486 void __merge_continues()
488 struct state_list
*slist
;
490 slist
= pop_slist(&continue_stack
);
497 push_slist(&break_stack
, NULL
);
500 void __process_breaks()
502 struct smatch_state
*state
;
504 FOR_EACH_PTR(cur_slist
, state
) {
505 merge_state_stack(&break_stack
, state
->name
, state
->owner
,
506 state
->sym
, state
->state
);
507 } END_FOR_EACH_PTR(state
);
510 void __merge_breaks()
512 struct state_list
*slist
;
514 slist
= pop_slist(&break_stack
);
521 struct state_list
*slist
;
523 slist
= pop_slist(&break_stack
);
527 void __save_switch_states()
529 push_slist(&switch_stack
, clone_slist(cur_slist
));
532 void __merge_switches()
534 struct state_list
*slist
;
536 slist
= pop_slist(&switch_stack
);
538 push_slist(&switch_stack
, slist
);
541 void __pop_switches()
543 struct state_list
*slist
;
545 slist
= pop_slist(&switch_stack
);
549 void __push_default()
551 push_slist(&default_stack
, NULL
);
552 set_state_stack(&default_stack
, "has_default", 0, NULL
, 0);
557 set_state_stack(&default_stack
, "has_default", 0, NULL
, 1);
562 struct state_list
*slist
;
563 struct smatch_state
*state
;
566 slist
= pop_slist(&default_stack
);
567 FOR_EACH_PTR(slist
, state
) {
568 if (!strcmp(state
->name
, "has_default"))
570 } END_FOR_EACH_PTR(state
);
575 static struct slist_head
*alloc_slist_head(const char *name
,
576 struct state_list
*slist
)
578 struct slist_head
*slist_head
= __alloc_slist_head(0);
580 slist_head
->name
= (char *)name
;
581 slist_head
->slist
= slist
;
585 static struct state_list
*get_slist_from_slist_stack(const char *name
)
587 struct slist_head
*tmp
;
589 FOR_EACH_PTR(goto_stack
, tmp
) {
590 if (!strcmp(tmp
->name
, name
))
592 } END_FOR_EACH_PTR(tmp
);
596 void __save_gotos(const char *name
)
598 struct state_list
*slist
;
600 slist
= get_slist_from_slist_stack(name
);
602 struct smatch_state
*state
;
603 FOR_EACH_PTR(cur_slist
, state
) {
604 merge_state_slist(&slist
, state
->name
, state
->owner
,
605 state
->sym
, state
->state
);
606 } END_FOR_EACH_PTR(state
);
609 struct state_list
*slist
;
610 struct slist_head
*slist_head
;
611 slist
= clone_slist(cur_slist
);
612 slist_head
= alloc_slist_head(name
, slist
);
613 add_ptr_list(&goto_stack
, slist_head
);
617 void __merge_gotos(const char *name
)
619 struct state_list
*slist
;
621 slist
= get_slist_from_slist_stack(name
);