db: split caller_info and sql into separate output file
[smatch.git] / smatch_var_sym.c
blob140e1e6a0bca0ee4b383a4a41c686a0eff44f2d4
1 /*
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
18 #include "smatch.h"
20 ALLOCATOR(var_sym, "var_sym structs");
22 struct var_sym *alloc_var_sym(const char *var, struct symbol *sym)
24 struct var_sym *tmp;
26 tmp = __alloc_var_sym(0);
27 tmp->var = alloc_string(var);
28 tmp->sym = sym;
29 return tmp;
32 struct var_sym_list *expr_to_vsl(struct expression *expr)
34 struct expression *unop;
35 struct var_sym_list *ret = NULL;
36 char *var;
37 struct symbol *sym;
39 expr = strip_expr(expr);
40 if (!expr)
41 return NULL;
43 if ((expr->type == EXPR_PREOP && expr->op == '*') ||
44 expr->type == EXPR_DEREF) {
45 unop = strip_expr(expr->unop);
47 if (unop->type == EXPR_SYMBOL)
48 goto one_var;
49 ret = expr_to_vsl(unop);
50 if (ptr_list_size((struct ptr_list *)ret) == 1) {
51 ret = NULL;
52 goto one_var;
54 return ret;
57 if (expr->type == EXPR_BINOP ||
58 expr->type == EXPR_LOGICAL ||
59 expr->type == EXPR_COMPARE) {
60 struct var_sym_list *left, *right;
62 left = expr_to_vsl(expr->left);
63 right = expr_to_vsl(expr->right);
64 ret = combine_var_sym_lists(left, right);
65 free_var_syms_and_list(&left);
66 free_var_syms_and_list(&right);
67 return ret;
70 one_var:
71 var = expr_to_var_sym(expr, &sym);
72 if (!var || !sym) {
73 free_string(var);
74 return NULL;
76 add_var_sym(&ret, var, sym);
77 return ret;
80 int cmp_var_sym(const struct var_sym *a, const struct var_sym *b)
82 int ret;
84 if (a == b)
85 return 0;
86 if (!b)
87 return -1;
88 if (!a)
89 return 1;
91 ret = strcmp(a->var, b->var);
92 if (ret < 0)
93 return -1;
94 if (ret > 0)
95 return 1;
97 if (!b->sym && a->sym)
98 return -1;
99 if (!a->sym && b->sym)
100 return 1;
101 if (a->sym < b->sym)
102 return -1;
103 if (a->sym > b->sym)
104 return 1;
106 return 0;
109 void add_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym)
111 struct var_sym *tmp, *new;
113 if (in_var_sym_list(*list, var, sym))
114 return;
115 new = alloc_var_sym(var, sym);
117 FOR_EACH_PTR(*list, tmp) {
118 if (cmp_var_sym(tmp, new) < 0)
119 continue;
120 else if (cmp_var_sym(tmp, new) == 0) {
121 return;
122 } else {
123 INSERT_CURRENT(new, tmp);
124 return;
126 } END_FOR_EACH_PTR(tmp);
127 add_ptr_list(list, new);
130 void add_var_sym_expr(struct var_sym_list **list, struct expression *expr)
132 char *var;
133 struct symbol *sym;
135 var = expr_to_var_sym(expr, &sym);
136 if (!var || !sym)
137 goto free;
138 add_var_sym(list, var, sym);
139 free:
140 free_string(var);
143 static void free_var_sym(struct var_sym *vs)
145 free_string(vs->var);
146 __free_var_sym(vs);
149 void del_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym)
151 struct var_sym *tmp;
153 FOR_EACH_PTR(*list, tmp) {
154 if (tmp->sym == sym && strcmp(tmp->var, var) == 0) {
155 DELETE_CURRENT_PTR(tmp);
156 free_var_sym(tmp);
157 return;
159 } END_FOR_EACH_PTR(tmp);
162 int in_var_sym_list(struct var_sym_list *list, const char *var, struct symbol *sym)
164 struct var_sym *tmp;
166 FOR_EACH_PTR(list, tmp) {
167 if (tmp->sym == sym && strcmp(tmp->var, var) == 0)
168 return 1;
169 } END_FOR_EACH_PTR(tmp);
170 return 0;
173 struct var_sym_list *clone_var_sym_list(struct var_sym_list *from_vsl)
175 struct var_sym *tmp, *clone_vs;
176 struct var_sym_list *to_vsl = NULL;
178 FOR_EACH_PTR(from_vsl, tmp) {
179 clone_vs = alloc_var_sym(tmp->var, tmp->sym);
180 add_ptr_list(&to_vsl, clone_vs);
181 } END_FOR_EACH_PTR(tmp);
182 return to_vsl;
185 void merge_var_sym_list(struct var_sym_list **dest, struct var_sym_list *src)
187 struct var_sym *tmp;
189 FOR_EACH_PTR(src, tmp) {
190 add_var_sym(dest, tmp->var, tmp->sym);
191 } END_FOR_EACH_PTR(tmp);
194 struct var_sym_list *combine_var_sym_lists(struct var_sym_list *one, struct var_sym_list *two)
196 struct var_sym_list *to_vsl;
198 to_vsl = clone_var_sym_list(one);
199 merge_var_sym_list(&to_vsl, two);
200 return to_vsl;
203 int var_sym_lists_equiv(struct var_sym_list *one, struct var_sym_list *two)
205 struct var_sym *one_tmp, *two_tmp;
207 if (one == two)
208 return 1;
210 if (ptr_list_size((struct ptr_list *)one) != ptr_list_size((struct ptr_list *)two))
211 return 0;
213 PREPARE_PTR_LIST(one, one_tmp);
214 PREPARE_PTR_LIST(two, two_tmp);
215 for (;;) {
216 if (!one_tmp && !two_tmp)
217 return 1;
218 if (one_tmp->sym != two_tmp->sym)
219 return 0;
220 if (strcmp(one_tmp->var, two_tmp->var) != 0)
221 return 0;
222 NEXT_PTR_LIST(one_tmp);
223 NEXT_PTR_LIST(two_tmp);
225 FINISH_PTR_LIST(two_tmp);
226 FINISH_PTR_LIST(one_tmp);
228 return 1;
231 void free_var_sym_list(struct var_sym_list **list)
233 __free_ptr_list((struct ptr_list **)list);
236 void free_var_syms_and_list(struct var_sym_list **list)
238 struct var_sym *tmp;
240 FOR_EACH_PTR(*list, tmp) {
241 free_var_sym(tmp);
242 } END_FOR_EACH_PTR(tmp);
243 free_var_sym_list(list);