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 int get_local_rl(struct expression
*expr
, struct range_list
**rl
)
45 struct range_list
*tmp
;
49 name
= expr_to_var(expr
);
55 "select value from local_values where file = '%s' and variable = '%s';",
56 get_filename(), name
);
60 str_to_rl(&llong_ctype
, db_vals
, &tmp
);
61 *rl
= cast_rl(get_type(expr
), tmp
);
67 int get_local_max_helper(struct expression
*expr
, sval_t
*sval
)
69 struct range_list
*rl
;
71 if (!get_local_rl(expr
, &rl
))
77 int get_local_min_helper(struct expression
*expr
, sval_t
*sval
)
79 struct range_list
*rl
;
81 if (!get_local_rl(expr
, &rl
))
87 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
89 return alloc_estate_empty();
92 static void extra_mod_hook(const char *name
, struct symbol
*sym
, struct smatch_state
*state
)
94 struct smatch_state
*old
;
95 struct smatch_state
*new;
97 if (!sym
|| !(sym
->ctype
.modifiers
& MOD_STATIC
))
99 old
= get_state(my_id
, name
, sym
);
101 new = merge_estates(old
, state
);
104 set_state(my_id
, name
, sym
, new);
107 static void process_states(struct AVL
*stree
)
110 struct smatch_state
*extra
;
111 struct range_list
*rl
;
113 FOR_EACH_SM(stree
, sm
) {
114 if (sm
->owner
!= my_id
)
116 extra
= get_state_stree(stree
, SMATCH_EXTRA
, sm
->name
, sm
->sym
);
117 if (extra
&& estate_rl(extra
))
118 rl
= rl_intersection(estate_rl(sm
->state
), estate_rl(extra
));
120 rl
= estate_rl(sm
->state
);
121 rl
= cast_rl(&llong_ctype
, rl
);
123 "insert into local_values values ('%s', '%s', '%s', %lu);",
124 get_filename(), sm
->name
, show_rl(rl
),
125 (unsigned long)sm
->sym
);
126 } END_FOR_EACH_SM(sm
);
129 static int get_initial_value_sym(struct symbol
*sym
, char *name
, sval_t
*sval
)
131 struct expression
*expr_symbol
, *deref
, *tmp
;
137 if (!sym
->initializer
) {
138 *sval
= sval_type_val(&llong_ctype
, 0);
141 if (sym
->initializer
->type
!= EXPR_INITIALIZER
)
142 return get_value(sym
->initializer
, sval
);
144 expr_symbol
= symbol_expression(sym
);
145 FOR_EACH_PTR(sym
->initializer
->expr_list
, tmp
) {
146 if (tmp
->type
!= EXPR_IDENTIFIER
) /* how to handle arrays?? */
148 deref
= member_expression(expr_symbol
, '.', tmp
->expr_ident
);
149 member_name
= expr_to_var(deref
);
152 if (strcmp(name
, member_name
) == 0) {
153 free_string(member_name
);
154 return get_value(tmp
->ident_expression
, sval
);
156 free_string(member_name
);
157 } END_FOR_EACH_PTR(tmp
);
162 static char *cur_name
;
163 static struct symbol
*cur_symbol
;
164 static struct range_list
*cur_rl
;
165 static void add_current_local(void)
169 if (!get_initial_value_sym(cur_symbol
, cur_name
, &initial
)) {
170 free_string(cur_name
);
175 add_range(&cur_rl
, initial
, initial
);
176 if (!is_whole_rl(cur_rl
))
177 sql_insert_local_values(cur_name
, show_rl(cur_rl
));
178 free_string(cur_name
);
183 static int save_final_values(void *unused
, int argc
, char **argv
, char **azColName
)
185 char *name
= argv
[0];
186 char *sym_str
= argv
[1];
187 char *value
= argv
[2];
188 struct range_list
*rl
;
191 cur_name
= alloc_string(name
);
192 cur_symbol
= (struct symbol
*)strtoul(sym_str
, NULL
, 10);
193 } else if (strcmp(cur_name
, name
) != 0) {
195 cur_name
= alloc_string(name
);
196 cur_symbol
= (struct symbol
*)strtoul(sym_str
, NULL
, 10);
200 str_to_rl(&llong_ctype
, value
, &rl
);
201 cur_rl
= rl_union(cur_rl
, rl
);
206 static void match_end_file(struct symbol_list
*sym_list
)
208 mem_sql(save_final_values
,
209 "select distinct variable, symbol, value from local_values order by variable;");
214 void register_local_values(int id
)
221 add_extra_mod_hook(&extra_mod_hook
);
222 add_unmatched_state_hook(my_id
, &unmatched_state
);
223 add_merge_hook(my_id
, &merge_estates
);
224 all_return_states_hook(&process_states
);
225 add_hook(match_end_file
, END_FILE_HOOK
);
226 mem_sql(NULL
, "alter table local_values add column symbol integer;");