2 * Copyright (C) 2013 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
20 #include "smatch_slist.h"
21 #include "smatch_extra.h"
26 * I'm going to store the states of local data at the end of each function.
27 * Then at the end of the file, I'll combine the possible range lists for
28 * each state and store the value in the on-disk database.
30 * One issue is that when I read the data back from the in-memory database at
31 * the end of the file, then I don't have access to type information. I'll just
32 * cast everything to "long long" for now, I guess. We'll see how that works.
36 static int get_vals(void *unused
, int argc
, char **argv
, char **azColName
)
38 db_vals
= alloc_string(argv
[0]);
42 static int is_array_symbol(struct expression
*expr
)
46 if (!expr
|| expr
->type
!= EXPR_SYMBOL
)
48 type
= get_type(expr
);
51 if (type
->type
== SYM_ARRAY
)
56 int get_local_rl(struct expression
*expr
, struct range_list
**rl
)
59 struct range_list
*tmp
;
63 if (is_array_symbol(expr
))
65 name
= expr_to_var(expr
);
70 run_sql(get_vals
, NULL
,
71 "select value from local_values where file = '%s' and variable = '%s';",
72 get_filename(), name
);
76 str_to_rl(&llong_ctype
, db_vals
, &tmp
);
77 *rl
= cast_rl(get_type(expr
), tmp
);
83 int get_local_max_helper(struct expression
*expr
, sval_t
*sval
)
85 struct range_list
*rl
;
87 if (!get_local_rl(expr
, &rl
))
93 int get_local_min_helper(struct expression
*expr
, sval_t
*sval
)
95 struct range_list
*rl
;
97 if (!get_local_rl(expr
, &rl
))
103 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
105 return alloc_estate_empty();
108 static void extra_mod_hook(const char *name
, struct symbol
*sym
, struct smatch_state
*state
)
110 struct smatch_state
*old
;
111 struct smatch_state
*new;
113 if (!sym
|| !(sym
->ctype
.modifiers
& MOD_STATIC
))
115 old
= get_state(my_id
, name
, sym
);
117 new = merge_estates(old
, state
);
120 set_state(my_id
, name
, sym
, new);
123 static void process_states(void)
126 struct smatch_state
*extra
;
127 struct range_list
*rl
;
129 FOR_EACH_SM(__get_cur_stree(), sm
) {
130 if (sm
->owner
!= my_id
)
132 extra
= get_state(SMATCH_EXTRA
, sm
->name
, sm
->sym
);
133 if (extra
&& estate_rl(extra
))
134 rl
= rl_intersection(estate_rl(sm
->state
), estate_rl(extra
));
136 rl
= estate_rl(sm
->state
);
137 rl
= cast_rl(&llong_ctype
, rl
);
139 "insert into local_values values ('%s', '%s', '%s', %lu);",
140 get_filename(), sm
->name
, show_rl(rl
),
141 (unsigned long)sm
->sym
);
142 } END_FOR_EACH_SM(sm
);
145 static int get_initial_value_sym(struct symbol
*sym
, char *name
, sval_t
*sval
)
147 struct expression
*expr_symbol
, *deref
, *tmp
;
153 if (!sym
->initializer
) {
154 *sval
= sval_type_val(&llong_ctype
, 0);
157 if (sym
->initializer
->type
!= EXPR_INITIALIZER
)
158 return get_value(sym
->initializer
, sval
);
160 expr_symbol
= symbol_expression(sym
);
161 FOR_EACH_PTR(sym
->initializer
->expr_list
, tmp
) {
162 if (tmp
->type
!= EXPR_IDENTIFIER
) /* how to handle arrays?? */
164 deref
= member_expression(expr_symbol
, '.', tmp
->expr_ident
);
165 member_name
= expr_to_var(deref
);
168 if (strcmp(name
, member_name
) == 0) {
169 free_string(member_name
);
170 return get_value(tmp
->ident_expression
, sval
);
172 free_string(member_name
);
173 } END_FOR_EACH_PTR(tmp
);
178 static char *cur_name
;
179 static struct symbol
*cur_symbol
;
180 static struct range_list
*cur_rl
;
181 static void add_current_local(void)
185 if (!get_initial_value_sym(cur_symbol
, cur_name
, &initial
)) {
186 free_string(cur_name
);
191 add_range(&cur_rl
, initial
, initial
);
192 if (!is_whole_rl(cur_rl
))
193 sql_insert_local_values(cur_name
, show_rl(cur_rl
));
194 free_string(cur_name
);
199 static int save_final_values(void *unused
, int argc
, char **argv
, char **azColName
)
201 char *name
= argv
[0];
202 char *sym_str
= argv
[1];
203 char *value
= argv
[2];
204 struct range_list
*rl
;
207 cur_name
= alloc_string(name
);
208 cur_symbol
= (struct symbol
*)strtoul(sym_str
, NULL
, 10);
209 } else if (strcmp(cur_name
, name
) != 0) {
211 cur_name
= alloc_string(name
);
212 cur_symbol
= (struct symbol
*)strtoul(sym_str
, NULL
, 10);
216 str_to_rl(&llong_ctype
, value
, &rl
);
217 cur_rl
= rl_union(cur_rl
, rl
);
222 static void match_end_file(struct symbol_list
*sym_list
)
224 mem_sql(save_final_values
, NULL
,
225 "select distinct variable, symbol, value from local_values order by variable;");
230 void register_local_values(int id
)
237 add_extra_mod_hook(&extra_mod_hook
);
238 add_unmatched_state_hook(my_id
, &unmatched_state
);
239 add_merge_hook(my_id
, &merge_estates
);
240 all_return_states_hook(&process_states
);
241 add_hook(match_end_file
, END_FILE_HOOK
);
242 mem_sql(NULL
, NULL
, "alter table local_values add column symbol integer;");