2 * sparse/smatch_extra_helper.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
12 #include "smatch_extra.h"
13 #include "smatch_slist.h"
15 ALLOCATOR(data_info
, "smatch extra data");
16 ALLOCATOR(data_range
, "data range");
18 static char *show_num(long long num
)
20 static char buff
[256];
22 if (num
== whole_range
.min
) {
23 snprintf(buff
, 255, "min");
24 } else if (num
== whole_range
.max
) {
25 snprintf(buff
, 255, "max");
27 snprintf(buff
, 255, "(%lld)", num
);
29 snprintf(buff
, 255, "%lld", num
);
35 char *show_ranges(struct range_list
*list
)
37 struct data_range
*tmp
;
43 FOR_EACH_PTR(list
, tmp
) {
45 strncat(full
, ",", 254 - strlen(full
));
46 if (tmp
->min
== tmp
->max
) {
47 strncat(full
, show_num(tmp
->min
), 254 - strlen(full
));
50 strncat(full
, show_num(tmp
->min
), 254 - strlen(full
));
51 strncat(full
, "-", 254 - strlen(full
));
52 strncat(full
, show_num(tmp
->max
), 254 - strlen(full
));
53 } END_FOR_EACH_PTR(tmp
);
54 return alloc_sname(full
);
57 static struct data_range range_zero
= {
62 static struct data_range range_one
= {
67 struct data_range
*alloc_range(long long min
, long long max
)
69 struct data_range
*ret
;
72 printf("Error invalid range %lld to %lld\n", min
, max
);
74 if (min
== whole_range
.min
&& max
== whole_range
.max
)
76 if (min
== 0 && max
== 0)
78 if (min
== 1 && max
== 1)
80 ret
= __alloc_data_range(0);
86 struct data_info
*alloc_dinfo_range(long long min
, long long max
)
88 struct data_info
*ret
;
90 ret
= __alloc_data_info(0);
91 ret
->type
= DATA_RANGE
;
93 ret
->value_ranges
= NULL
;
94 add_range(&ret
->value_ranges
, min
, max
);
98 void add_range(struct range_list
**list
, long long min
, long long max
)
100 struct data_range
*tmp
= NULL
;
101 struct data_range
*new;
103 FOR_EACH_PTR(*list
, tmp
) {
104 if (max
!= whole_range
.max
&& max
+ 1 == tmp
->min
) {
105 /* join 2 ranges into a big range */
106 new = alloc_range(min
, tmp
->max
);
107 REPLACE_CURRENT_PTR(tmp
, new);
110 if (max
< tmp
->min
) { /* new range entirely below */
111 new = alloc_range(min
, max
);
112 INSERT_CURRENT(new, tmp
);
115 if (min
< tmp
->min
) { /* new range partially below */
118 new = alloc_range(min
, max
);
119 REPLACE_CURRENT_PTR(tmp
, new);
122 if (max
<= tmp
->max
) /* new range already included */
124 if (min
<= tmp
->max
) { /* new range partially above */
126 new = alloc_range(min
, max
);
127 REPLACE_CURRENT_PTR(tmp
, new);
130 if (min
!= whole_range
.min
&& min
- 1 == tmp
->max
) {
131 /* join 2 ranges into a big range */
132 new = alloc_range(tmp
->min
, max
);
133 REPLACE_CURRENT_PTR(tmp
, new);
136 } END_FOR_EACH_PTR(tmp
);
137 new = alloc_range(min
, max
);
138 add_ptr_list(list
, new);
141 struct range_list
*clone_range_list(struct range_list
*list
)
143 struct data_range
*tmp
;
144 struct range_list
*ret
= NULL
;
146 FOR_EACH_PTR(list
, tmp
) {
147 add_ptr_list(&ret
, tmp
);
148 } END_FOR_EACH_PTR(tmp
);
152 struct range_list
*range_list_union(struct range_list
*one
, struct range_list
*two
)
154 struct data_range
*tmp
;
155 struct range_list
*ret
= NULL
;
157 if (!one
|| !two
) /*having nothing in a list means everything is in */
160 FOR_EACH_PTR(one
, tmp
) {
161 add_range(&ret
, tmp
->min
, tmp
->max
);
162 } END_FOR_EACH_PTR(tmp
);
163 FOR_EACH_PTR(two
, tmp
) {
164 add_range(&ret
, tmp
->min
, tmp
->max
);
165 } END_FOR_EACH_PTR(tmp
);
169 struct range_list
*remove_range(struct range_list
*list
, long long min
, long long max
)
171 struct data_range
*tmp
;
172 struct range_list
*ret
= NULL
;
174 FOR_EACH_PTR(list
, tmp
) {
175 if (tmp
->max
< min
) {
176 add_range(&ret
, tmp
->min
, tmp
->max
);
179 if (tmp
->min
> max
) {
180 add_range(&ret
, tmp
->min
, tmp
->max
);
183 if (tmp
->min
>= min
&& tmp
->max
<= max
)
185 if (tmp
->min
>= min
) {
186 add_range(&ret
, max
+ 1, tmp
->max
);
187 } else if (tmp
->max
<= max
) {
188 add_range(&ret
, tmp
->min
, min
- 1);
190 add_range(&ret
, tmp
->min
, min
- 1);
191 add_range(&ret
, max
+ 1, tmp
->max
);
193 } END_FOR_EACH_PTR(tmp
);
197 long long get_dinfo_min(struct data_info
*dinfo
)
199 struct data_range
*drange
;
201 if (!dinfo
|| !dinfo
->value_ranges
)
202 return whole_range
.min
;
203 drange
= first_ptr_list((struct ptr_list
*)dinfo
->value_ranges
);
207 long long get_dinfo_max(struct data_info
*dinfo
)
209 struct data_range
*drange
;
211 if (!dinfo
|| !dinfo
->value_ranges
)
212 return whole_range
.max
;
213 drange
= first_ptr_list((struct ptr_list
*)dinfo
->value_ranges
);
217 int is_whole_range(struct range_list
*ranges
)
219 struct data_range
*drange
;
224 drange
= first_ptr_list((struct ptr_list
*)ranges
);
225 if (drange
->min
== whole_range
.min
&& drange
->max
== whole_range
.max
)
231 * if it can be only one value return that, else return UNDEFINED
233 long long get_single_value_from_range(struct data_info
*dinfo
)
235 struct data_range
*tmp
;
237 long long ret
= UNDEFINED
;
239 if (dinfo
->type
!= DATA_RANGE
)
242 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
244 if (tmp
->min
!= tmp
->max
)
250 } END_FOR_EACH_PTR(tmp
);
254 static int true_comparison_range(struct data_range
*left
, int comparison
, struct data_range
*right
)
258 case SPECIAL_UNSIGNED_LT
:
259 if (left
->min
< right
->max
)
262 case SPECIAL_UNSIGNED_LTE
:
264 if (left
->min
<= right
->max
)
268 if (left
->max
< right
->min
)
270 if (left
->min
> right
->max
)
273 case SPECIAL_UNSIGNED_GTE
:
275 if (left
->max
>= right
->min
)
279 case SPECIAL_UNSIGNED_GT
:
280 if (left
->max
> right
->min
)
283 case SPECIAL_NOTEQUAL
:
284 if (left
->min
!= left
->max
)
286 if (right
->min
!= right
->max
)
288 if (left
->min
!= right
->min
)
292 smatch_msg("unhandled comparison %d\n", comparison
);
298 static int false_comparison_range(struct data_range
*left
, int comparison
, struct data_range
*right
)
302 case SPECIAL_UNSIGNED_LT
:
303 if (left
->max
>= right
->min
)
306 case SPECIAL_UNSIGNED_LTE
:
308 if (left
->max
> right
->min
)
312 if (left
->min
!= left
->max
)
314 if (right
->min
!= right
->max
)
316 if (left
->min
!= right
->min
)
319 case SPECIAL_UNSIGNED_GTE
:
321 if (left
->min
< right
->max
)
325 case SPECIAL_UNSIGNED_GT
:
326 if (left
->min
<= right
->max
)
329 case SPECIAL_NOTEQUAL
:
330 if (left
->max
< right
->min
)
332 if (left
->min
> right
->max
)
336 smatch_msg("unhandled comparison %d\n", comparison
);
342 int possibly_true(int comparison
, struct data_info
*dinfo
, int num
, int left
)
344 struct data_range
*tmp
;
346 struct data_range drange
;
351 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
353 ret
= true_comparison_range(tmp
, comparison
, &drange
);
355 ret
= true_comparison_range(&drange
, comparison
, tmp
);
358 } END_FOR_EACH_PTR(tmp
);
362 int possibly_false(int comparison
, struct data_info
*dinfo
, int num
, int left
)
364 struct data_range
*tmp
;
366 struct data_range drange
;
371 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
373 ret
= false_comparison_range(tmp
, comparison
, &drange
);
375 ret
= false_comparison_range(&drange
, comparison
, tmp
);
378 } END_FOR_EACH_PTR(tmp
);
382 static void free_single_dinfo(struct data_info
*dinfo
)
384 if (dinfo
->type
== DATA_RANGE
)
385 __free_ptr_list((struct ptr_list
**)&dinfo
->value_ranges
);
388 static void free_dinfos(struct allocation_blob
*blob
)
390 unsigned int size
= sizeof(struct data_info
);
391 unsigned int offset
= 0;
393 while (offset
< blob
->offset
) {
394 free_single_dinfo((struct data_info
*)(blob
->data
+ offset
));
399 void free_data_info_allocs(void)
401 struct allocator_struct
*desc
= &data_info_allocator
;
402 struct allocation_blob
*blob
= desc
->blobs
;
405 desc
->allocations
= 0;
406 desc
->total_bytes
= 0;
407 desc
->useful_bytes
= 0;
408 desc
->freelist
= NULL
;
410 struct allocation_blob
*next
= blob
->next
;
412 blob_free(blob
, desc
->chunking
);
415 clear_data_range_alloc();