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 ALLOCATOR(var_sym
, "var_sym structs");
22 struct smatch_state
*alloc_var_sym_state(const char *var
, struct symbol
*sym
)
24 struct smatch_state
*state
;
26 state
= __alloc_smatch_state(0);
27 state
->name
= alloc_string(var
);
28 state
->data
= alloc_var_sym(var
, sym
);
32 struct var_sym
*alloc_var_sym(const char *var
, struct symbol
*sym
)
36 tmp
= __alloc_var_sym(0);
37 tmp
->var
= alloc_string(var
);
42 struct var_sym_list
*expr_to_vsl(struct expression
*expr
)
44 struct expression
*unop
;
45 struct var_sym_list
*ret
= NULL
;
49 expr
= strip_expr(expr
);
53 if (expr_to_sym(expr
))
56 if (expr
->type
== EXPR_BINOP
||
57 expr
->type
== EXPR_LOGICAL
||
58 expr
->type
== EXPR_COMPARE
) {
59 struct var_sym_list
*left
, *right
;
61 left
= expr_to_vsl(expr
->left
);
62 right
= expr_to_vsl(expr
->right
);
63 ret
= combine_var_sym_lists(left
, right
);
64 free_var_syms_and_list(&left
);
65 free_var_syms_and_list(&right
);
69 // handle "*(foo[bar])" I guess */
70 if ((expr
->type
== EXPR_PREOP
&& expr
->op
== '*')) {
71 unop
= strip_expr(expr
->unop
);
73 if (unop
->type
== EXPR_SYMBOL
)
75 return expr_to_vsl(unop
);
78 if (expr
->type
== EXPR_DEREF
)
79 return expr_to_vsl(expr
->deref
);
82 var
= expr_to_var_sym(expr
, &sym
);
87 add_var_sym(&ret
, var
, sym
);
91 int cmp_var_sym(const struct var_sym
*a
, const struct var_sym
*b
)
102 ret
= strcmp(a
->var
, b
->var
);
108 if (!b
->sym
&& a
->sym
)
110 if (!a
->sym
&& b
->sym
)
120 void add_var_sym(struct var_sym_list
**list
, const char *var
, struct symbol
*sym
)
122 struct var_sym
*tmp
, *new;
124 if (in_var_sym_list(*list
, var
, sym
))
126 new = alloc_var_sym(var
, sym
);
128 FOR_EACH_PTR(*list
, tmp
) {
129 if (cmp_var_sym(tmp
, new) < 0)
131 else if (cmp_var_sym(tmp
, new) == 0) {
134 INSERT_CURRENT(new, tmp
);
137 } END_FOR_EACH_PTR(tmp
);
138 add_ptr_list(list
, new);
141 void add_var_sym_expr(struct var_sym_list
**list
, struct expression
*expr
)
146 var
= expr_to_var_sym(expr
, &sym
);
149 add_var_sym(list
, var
, sym
);
154 static void free_var_sym(struct var_sym
*vs
)
156 free_string(vs
->var
);
160 void del_var_sym(struct var_sym_list
**list
, const char *var
, struct symbol
*sym
)
164 FOR_EACH_PTR(*list
, tmp
) {
165 if (tmp
->sym
== sym
&& strcmp(tmp
->var
, var
) == 0) {
166 DELETE_CURRENT_PTR(tmp
);
170 } END_FOR_EACH_PTR(tmp
);
173 int in_var_sym_list(struct var_sym_list
*list
, const char *var
, struct symbol
*sym
)
177 FOR_EACH_PTR(list
, tmp
) {
178 if (tmp
->sym
== sym
&& strcmp(tmp
->var
, var
) == 0)
180 } END_FOR_EACH_PTR(tmp
);
184 struct var_sym_list
*clone_var_sym_list(struct var_sym_list
*from_vsl
)
186 struct var_sym
*tmp
, *clone_vs
;
187 struct var_sym_list
*to_vsl
= NULL
;
189 FOR_EACH_PTR(from_vsl
, tmp
) {
190 clone_vs
= alloc_var_sym(tmp
->var
, tmp
->sym
);
191 add_ptr_list(&to_vsl
, clone_vs
);
192 } END_FOR_EACH_PTR(tmp
);
196 void merge_var_sym_list(struct var_sym_list
**dest
, struct var_sym_list
*src
)
200 FOR_EACH_PTR(src
, tmp
) {
201 add_var_sym(dest
, tmp
->var
, tmp
->sym
);
202 } END_FOR_EACH_PTR(tmp
);
205 struct var_sym_list
*combine_var_sym_lists(struct var_sym_list
*one
, struct var_sym_list
*two
)
207 struct var_sym_list
*to_vsl
;
209 to_vsl
= clone_var_sym_list(one
);
210 merge_var_sym_list(&to_vsl
, two
);
214 int var_sym_lists_equiv(struct var_sym_list
*one
, struct var_sym_list
*two
)
216 struct var_sym
*one_tmp
, *two_tmp
;
221 if (ptr_list_size((struct ptr_list
*)one
) != ptr_list_size((struct ptr_list
*)two
))
224 PREPARE_PTR_LIST(one
, one_tmp
);
225 PREPARE_PTR_LIST(two
, two_tmp
);
227 if (!one_tmp
&& !two_tmp
)
229 if (one_tmp
->sym
!= two_tmp
->sym
)
231 if (strcmp(one_tmp
->var
, two_tmp
->var
) != 0)
233 NEXT_PTR_LIST(one_tmp
);
234 NEXT_PTR_LIST(two_tmp
);
236 FINISH_PTR_LIST(two_tmp
);
237 FINISH_PTR_LIST(one_tmp
);
242 void free_var_sym_list(struct var_sym_list
**list
)
244 __free_ptr_list((struct ptr_list
**)list
);
247 void free_var_syms_and_list(struct var_sym_list
**list
)
251 FOR_EACH_PTR(*list
, tmp
) {
253 } END_FOR_EACH_PTR(tmp
);
254 free_var_sym_list(list
);