2 * smatch/local_values.c
4 * Copyright (C) 2013 Oracle.
6 * Licensed under the Open Software License version 1.1
12 #include "smatch_slist.h"
13 #include "smatch_extra.h"
18 * I'm going to store the states of local data at the end of each function.
19 * Then at the end of the file, I'll combine the possible range lists for
20 * each state and store the value in the on-disk database.
22 * One issue is that when I read the data back from the in-memory database at
23 * the end of the file, then I don't have access to type information. I'll just
24 * cast everything to "long long" for now, I guess. We'll see how that works.
28 static int get_vals(void *unused
, int argc
, char **argv
, char **azColName
)
30 db_vals
= alloc_string(argv
[0]);
34 int get_local_rl(struct expression
*expr
, struct range_list
**rl
)
37 struct range_list
*tmp
;
41 name
= expr_to_var(expr
);
47 "select value from local_values where file = '%s' and variable = '%s'",
48 get_filename(), name
);
52 str_to_rl(&llong_ctype
, db_vals
, &tmp
);
53 *rl
= cast_rl(get_type(expr
), tmp
);
59 int get_local_max_helper(struct expression
*expr
, sval_t
*sval
)
61 struct range_list
*rl
;
63 if (!get_local_rl(expr
, &rl
))
69 int get_local_min_helper(struct expression
*expr
, sval_t
*sval
)
71 struct range_list
*rl
;
73 if (!get_local_rl(expr
, &rl
))
79 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
81 return alloc_estate_empty();
84 static void extra_mod_hook(const char *name
, struct symbol
*sym
, struct smatch_state
*state
)
86 struct smatch_state
*old
;
87 struct smatch_state
*new;
89 if (!(sym
->ctype
.modifiers
& MOD_STATIC
))
91 old
= get_state(my_id
, name
, sym
);
93 new = merge_estates(old
, state
);
96 set_state(my_id
, name
, sym
, new);
99 static void process_states(struct state_list
*slist
)
102 struct smatch_state
*extra
;
103 struct range_list
*rl
;
105 FOR_EACH_PTR(slist
, sm
) {
106 if (sm
->owner
!= my_id
)
108 extra
= get_state_slist(slist
, SMATCH_EXTRA
, sm
->name
, sm
->sym
);
109 if (extra
&& estate_rl(extra
))
110 rl
= rl_intersection(estate_rl(sm
->state
), estate_rl(extra
));
112 rl
= estate_rl(sm
->state
);
113 rl
= cast_rl(&llong_ctype
, rl
);
115 "insert into local_values values ('%s', '%s', '%s', %lu);",
116 get_filename(), sm
->name
, show_rl(rl
),
117 (unsigned long)sm
->sym
);
118 } END_FOR_EACH_PTR(sm
);
121 static int get_initial_value_sym(struct symbol
*sym
, char *name
, sval_t
*sval
)
123 struct expression
*expr_symbol
, *deref
, *tmp
;
129 if (!sym
->initializer
) {
130 *sval
= sval_type_val(&llong_ctype
, 0);
133 if (sym
->initializer
->type
!= EXPR_INITIALIZER
)
134 return get_value(sym
->initializer
, sval
);
136 expr_symbol
= symbol_expression(sym
);
137 FOR_EACH_PTR(sym
->initializer
->expr_list
, tmp
) {
138 if (tmp
->type
!= EXPR_IDENTIFIER
) /* how to handle arrays?? */
140 deref
= member_expression(expr_symbol
, '.', tmp
->expr_ident
);
141 member_name
= expr_to_var(deref
);
144 if (strcmp(name
, member_name
) == 0) {
145 free_string(member_name
);
146 return get_value(tmp
->ident_expression
, sval
);
148 free_string(member_name
);
149 } END_FOR_EACH_PTR(tmp
);
154 static char *cur_name
;
155 static struct symbol
*cur_symbol
;
156 static struct range_list
*cur_rl
;
157 static void add_current_local(void)
161 if (!get_initial_value_sym(cur_symbol
, cur_name
, &initial
)) {
162 free_string(cur_name
);
167 add_range(&cur_rl
, initial
, initial
);
168 if (!is_whole_rl(cur_rl
))
169 sql_insert_local_values(cur_name
, show_rl(cur_rl
));
170 free_string(cur_name
);
175 static int save_final_values(void *unused
, int argc
, char **argv
, char **azColName
)
177 char *name
= argv
[0];
178 char *sym_str
= argv
[1];
179 char *value
= argv
[2];
180 struct range_list
*rl
;
183 cur_name
= alloc_string(name
);
184 cur_symbol
= (struct symbol
*)strtoul(sym_str
, NULL
, 10);
185 } else if (strcmp(cur_name
, name
) != 0) {
187 cur_name
= alloc_string(name
);
188 cur_symbol
= (struct symbol
*)strtoul(sym_str
, NULL
, 10);
192 str_to_rl(&llong_ctype
, value
, &rl
);
193 cur_rl
= rl_union(cur_rl
, rl
);
198 static void match_end_file(struct symbol_list
*sym_list
)
200 mem_sql(save_final_values
,
201 "select distinct variable, symbol, value from local_values order by variable;");
206 void register_local_values(int id
)
211 add_extra_mod_hook(&extra_mod_hook
);
212 add_unmatched_state_hook(my_id
, &unmatched_state
);
213 add_merge_hook(my_id
, &merge_estates
);
214 all_return_states_hook(&process_states
);
215 add_hook(match_end_file
, END_FILE_HOOK
);
216 mem_sql(NULL
, "alter table local_values add column symbol integer;");