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
;
57 sm
= get_sm_state(my_id
, name
, NULL
);
59 add_tracker(&starts_right
, my_id
, name
, NULL
);
60 if (sm
&& slist_has_state(sm
->possible
, &left
))
61 sm_msg("warn: double '%s'", fn
);
62 set_state(my_id
, (char *)data
, NULL
, &left
);
65 static void match_right(const char *fn
, struct expression
*expr
, void *data
)
68 char *name
= (char *)data
;
73 sm
= get_sm_state(my_id
, name
, NULL
);
75 add_tracker(&starts_left
, my_id
, name
, NULL
);
76 if (sm
&& slist_has_state(sm
->possible
, &right
))
77 sm_msg("warn: double '%s'", fn
);
78 set_state(my_id
, (char *)data
, NULL
, &right
);
81 static void check_possible(struct sm_state
*sm
)
88 FOR_EACH_PTR(sm
->possible
, tmp
) {
89 if (tmp
->state
== &left
)
91 if (tmp
->state
== &right
)
93 if (tmp
->state
== &start_state
) {
94 struct smatch_state
*s
;
96 s
= get_start_state(tmp
);
104 if (tmp
->state
== &undefined
)
105 undef
= 1; // i don't think this is possible any more.
106 } END_FOR_EACH_PTR(tmp
);
107 if ((is_left
&& is_right
) || undef
)
108 sm_msg("warn: returning with unbalanced %s", sm
->name
);
111 static void match_return(struct expression
*expr
)
113 struct state_list
*slist
;
114 struct sm_state
*tmp
;
119 slist
= get_all_states(my_id
);
120 FOR_EACH_PTR(slist
, tmp
) {
121 if (tmp
->state
== &merged
)
123 } END_FOR_EACH_PTR(tmp
);
127 static void clear_lists(void)
129 free_trackers_and_list(&starts_left
);
130 free_trackers_and_list(&starts_right
);
133 static void match_func_end(struct symbol
*sym
)
142 static void get_left_funcs(const char *name
, struct token
**token
)
146 while (token_type(*token
) == TOKEN_IDENT
) {
147 func
= show_ident((*token
)->ident
);
148 add_function_hook(func
, &match_left
, (char *)name
);
149 *token
= (*token
)->next
;
151 if (token_type(*token
) == TOKEN_SPECIAL
)
152 *token
= (*token
)->next
;
155 static void get_right_funcs(const char *name
, struct token
**token
)
159 while (token_type(*token
) == TOKEN_IDENT
) {
160 func
= show_ident((*token
)->ident
);
161 add_function_hook(func
, &match_right
, (char *)name
);
162 *token
= (*token
)->next
;
164 if (token_type(*token
) == TOKEN_SPECIAL
)
165 *token
= (*token
)->next
;
168 static void register_funcs_from_file(void)
173 token
= get_tokens_file("kernel.balanced_funcs");
176 if (token_type(token
) != TOKEN_STREAMBEGIN
)
179 while (token_type(token
) != TOKEN_STREAMEND
) {
180 if (token_type(token
) != TOKEN_IDENT
)
182 name
= alloc_string(show_ident(token
->ident
));
184 get_left_funcs(name
, &token
);
185 get_right_funcs(name
, &token
);
190 void check_balanced(int id
)
193 add_unmatched_state_hook(my_id
, &unmatched_state
);
194 add_hook(&match_return
, RETURN_HOOK
);
195 add_hook(&match_func_end
, END_FUNC_HOOK
);
196 register_funcs_from_file();