2 * sparse/check_prempt.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * This test checks that prempt is enabled at the end of every function.
15 #include "smatch_slist.h"
23 static struct tracker_list
*starts_left
;
24 static struct tracker_list
*starts_right
;
26 static struct smatch_state
*get_start_state(struct sm_state
*sm
)
31 if (in_tracker_list(starts_left
, my_id
, sm
->name
, sm
->sym
))
33 if (in_tracker_list(starts_right
, my_id
, sm
->name
, sm
->sym
))
35 if (is_left
&& is_right
)
44 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
49 static void match_left(const char *fn
, struct expression
*expr
, void *data
)
52 char *name
= (char *)data
;
54 sm
= get_sm_state(my_id
, name
, NULL
);
56 add_tracker(&starts_right
, my_id
, name
, NULL
);
57 if (sm
&& slist_has_state(sm
->possible
, &left
))
58 sm_msg("warn: double '%s'", fn
);
59 set_state(my_id
, (char *)data
, NULL
, &left
);
62 static void match_right(const char *fn
, struct expression
*expr
, void *data
)
65 char *name
= (char *)data
;
67 sm
= get_sm_state(my_id
, name
, NULL
);
69 add_tracker(&starts_left
, my_id
, name
, NULL
);
70 if (sm
&& slist_has_state(sm
->possible
, &right
))
71 sm_msg("warn: double '%s'", fn
);
72 set_state(my_id
, (char *)data
, NULL
, &right
);
75 static void check_possible(struct sm_state
*sm
)
82 FOR_EACH_PTR(sm
->possible
, tmp
) {
83 if (tmp
->state
== &left
)
85 if (tmp
->state
== &right
)
87 if (tmp
->state
== &start_state
) {
88 struct smatch_state
*s
;
90 s
= get_start_state(tmp
);
98 if (tmp
->state
== &undefined
)
99 undef
= 1; // i don't think this is possible any more.
100 } END_FOR_EACH_PTR(tmp
);
101 if ((is_left
&& is_right
) || undef
)
102 sm_msg("warn: returning with unbalanced %s", sm
->name
);
105 static void match_return(struct expression
*expr
)
107 struct state_list
*slist
;
108 struct sm_state
*tmp
;
110 slist
= get_all_states(my_id
);
111 FOR_EACH_PTR(slist
, tmp
) {
112 if (tmp
->state
== &merged
)
114 } END_FOR_EACH_PTR(tmp
);
118 static void clear_lists(void)
120 free_trackers_and_list(&starts_left
);
121 free_trackers_and_list(&starts_right
);
124 static void match_func_end(struct symbol
*sym
)
131 static void get_left_funcs(const char *name
, struct token
**token
)
135 while (token_type(*token
) == TOKEN_IDENT
) {
136 func
= show_ident((*token
)->ident
);
137 add_function_hook(func
, &match_left
, (char *)name
);
138 *token
= (*token
)->next
;
140 if (token_type(*token
) == TOKEN_SPECIAL
)
141 *token
= (*token
)->next
;
144 static void get_right_funcs(const char *name
, struct token
**token
)
148 while (token_type(*token
) == TOKEN_IDENT
) {
149 func
= show_ident((*token
)->ident
);
150 add_function_hook(func
, &match_right
, (char *)name
);
151 *token
= (*token
)->next
;
153 if (token_type(*token
) == TOKEN_SPECIAL
)
154 *token
= (*token
)->next
;
157 static void register_funcs_from_file(void)
162 token
= get_tokens_file("kernel.balanced_funcs");
165 if (token_type(token
) != TOKEN_STREAMBEGIN
)
168 while (token_type(token
) != TOKEN_STREAMEND
) {
169 if (token_type(token
) != TOKEN_IDENT
)
171 name
= alloc_string(show_ident(token
->ident
));
173 get_left_funcs(name
, &token
);
174 get_right_funcs(name
, &token
);
179 void check_balanced(int id
)
182 add_unmatched_state_hook(my_id
, &unmatched_state
);
183 add_hook(&match_return
, RETURN_HOOK
);
184 add_hook(&match_func_end
, END_FUNC_HOOK
);
185 register_funcs_from_file();