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
;
42 FOR_EACH_PTR(list
, tmp
) {
44 strncat(full
, ",", 254);
45 if (tmp
->min
== tmp
->max
) {
46 strncat(full
, show_num(tmp
->min
), 254);
49 strncat(full
, show_num(tmp
->min
), 254);
50 strncat(full
, "-", 254);
51 strncat(full
, show_num(tmp
->max
), 254);
52 } END_FOR_EACH_PTR(tmp
);
54 return alloc_sname(full
);
57 struct data_range
*alloc_range(long long min
, long long max
)
59 struct data_range
*ret
;
62 printf("Error invalid range %lld to %lld\n", min
, max
);
65 ret
= __alloc_data_range(0);
71 struct data_info
*alloc_dinfo_range(long long min
, long long max
)
73 struct data_info
*ret
;
75 ret
= __alloc_data_info(0);
76 ret
->type
= DATA_RANGE
;
78 ret
->value_ranges
= NULL
;
79 add_range(&ret
->value_ranges
, min
, max
);
83 void add_range(struct range_list
**list
, long long min
, long long max
)
85 struct data_range
*tmp
= NULL
;
86 struct data_range
*new;
88 FOR_EACH_PTR(*list
, tmp
) {
94 if (tmp
->max
>= min
) {
95 new = alloc_range(tmp
->min
, max
);
96 REPLACE_CURRENT_PTR(tmp
, new);
99 new = alloc_range(min
, max
);
100 INSERT_CURRENT(new, tmp
);
103 } END_FOR_EACH_PTR(tmp
);
104 new = alloc_range(min
, max
);
105 add_ptr_list(list
, new);
108 struct range_list
*clone_range_list(struct range_list
*list
)
110 struct data_range
*tmp
;
111 struct range_list
*ret
= NULL
;
113 FOR_EACH_PTR(list
, tmp
) {
114 add_ptr_list(&ret
, tmp
);
115 } END_FOR_EACH_PTR(tmp
);
119 struct range_list
*range_list_union(struct range_list
*one
, struct range_list
*two
)
121 struct data_range
*tmp
;
122 struct range_list
*ret
= NULL
;
124 if (!one
|| !two
) /*having nothing in a list means everything is in */
127 FOR_EACH_PTR(one
, tmp
) {
128 add_range(&ret
, tmp
->min
, tmp
->max
);
129 } END_FOR_EACH_PTR(tmp
);
130 FOR_EACH_PTR(two
, tmp
) {
131 add_range(&ret
, tmp
->min
, tmp
->max
);
132 } END_FOR_EACH_PTR(tmp
);
136 struct range_list
*remove_range(struct range_list
*list
, long long min
, long long max
)
138 struct data_range
*tmp
;
139 struct range_list
*ret
= NULL
;
141 FOR_EACH_PTR(list
, tmp
) {
142 if (tmp
->max
< min
) {
143 add_range(&ret
, tmp
->min
, tmp
->max
);
146 if (tmp
->min
> max
) {
147 add_range(&ret
, tmp
->min
, tmp
->max
);
150 if (tmp
->min
>= min
&& tmp
->max
<= max
)
152 if (tmp
->min
>= min
) {
153 add_range(&ret
, max
+ 1, tmp
->max
);
154 } else if (tmp
->max
<= max
) {
155 add_range(&ret
, tmp
->min
, min
- 1);
157 add_range(&ret
, tmp
->min
, min
- 1);
158 add_range(&ret
, max
+ 1, tmp
->max
);
160 } END_FOR_EACH_PTR(tmp
);
165 * if it can be only one value return that, else return UNDEFINED
167 long long get_single_value_from_range(struct data_info
*dinfo
)
169 struct data_range
*tmp
;
171 long long ret
= UNDEFINED
;
173 if (dinfo
->type
!= DATA_RANGE
)
176 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
178 if (tmp
->min
!= tmp
->max
)
184 } END_FOR_EACH_PTR(tmp
);
188 int possibly_true(int comparison
, struct data_info
*dinfo
, int num
, int left
)
190 struct data_range
*tmp
;
192 struct data_range drange
;
197 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
199 ret
= true_comparison_range(tmp
, comparison
, &drange
);
201 ret
= true_comparison_range(&drange
, comparison
, tmp
);
204 } END_FOR_EACH_PTR(tmp
);
208 int possibly_false(int comparison
, struct data_info
*dinfo
, int num
, int left
)
210 struct data_range
*tmp
;
212 struct data_range drange
;
217 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
219 ret
= false_comparison_range(tmp
, comparison
, &drange
);
221 ret
= false_comparison_range(&drange
, comparison
, tmp
);
224 } END_FOR_EACH_PTR(tmp
);
228 static void free_single_dinfo(struct data_info
*dinfo
)
230 if (dinfo
->type
== DATA_RANGE
)
231 __free_ptr_list((struct ptr_list
**)&dinfo
->value_ranges
);
234 static void free_dinfos(struct allocation_blob
*blob
)
236 unsigned int size
= sizeof(struct data_info
);
237 unsigned int offset
= 0;
239 while (offset
< blob
->offset
) {
240 free_single_dinfo((struct data_info
*)(blob
->data
+ offset
));
245 void free_data_info_allocs(void)
247 struct allocator_struct
*desc
= &data_info_allocator
;
248 struct allocation_blob
*blob
= desc
->blobs
;
251 desc
->allocations
= 0;
252 desc
->total_bytes
= 0;
253 desc
->useful_bytes
= 0;
254 desc
->freelist
= NULL
;
256 struct allocation_blob
*next
= blob
->next
;
258 blob_free(blob
, desc
->chunking
);
261 clear_data_range_alloc();