estate, ranges: move whole_range from estate to ranges
[smatch.git] / smatch_ranges.c
blobaa8f4cc70467f50c7cabfc011c019d0da93dd6f2
1 /*
2 * sparse/smatch_ranges.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "parse.h"
11 #include "smatch.h"
12 #include "smatch_extra.h"
13 #include "smatch_slist.h"
15 ALLOCATOR(data_info, "smatch extra data");
16 ALLOCATOR(data_range, "data range");
17 __DO_ALLOCATOR(struct data_range, sizeof(struct data_range), __alignof__(struct data_range),
18 "permanent ranges", perm_data_range);
20 struct data_range whole_range = {
21 .min = LLONG_MIN,
22 .max = LLONG_MAX,
25 static char *show_num(long long num)
27 static char buff[256];
29 if (num == whole_range.min)
30 snprintf(buff, 255, "min");
31 else if (num == whole_range.max)
32 snprintf(buff, 255, "max");
33 else if (num < 0)
34 snprintf(buff, 255, "(%lld)", num);
35 else
36 snprintf(buff, 255, "%lld", num);
38 buff[255] = '\0';
39 return buff;
42 char *show_ranges(struct range_list *list)
44 struct data_range *tmp;
45 char full[256];
46 int i = 0;
48 full[0] = '\0';
49 full[255] = '\0';
50 FOR_EACH_PTR(list, tmp) {
51 if (i++)
52 strncat(full, ",", 254 - strlen(full));
53 if (tmp->min == tmp->max) {
54 strncat(full, show_num(tmp->min), 254 - strlen(full));
55 continue;
57 strncat(full, show_num(tmp->min), 254 - strlen(full));
58 strncat(full, "-", 254 - strlen(full));
59 strncat(full, show_num(tmp->max), 254 - strlen(full));
60 } END_FOR_EACH_PTR(tmp);
61 return alloc_sname(full);
64 void get_value_ranges(char *value, struct range_list **rl)
66 long long val1, val2;
67 char *start;
68 char *c;
70 c = value;
71 while (*c) {
72 if (*c == '(')
73 c++;
74 start = c;
75 if (!strncmp(start, "min", 3)) {
76 val1 = LLONG_MIN;
77 c += 3;
78 } else {
79 while (*c && *c != ',' && *c != '-')
80 c++;
81 val1 = strtoll(start, &c, 10);
83 if (*c == ')')
84 c++;
85 if (!*c) {
86 add_range(rl, val1, val1);
87 break;
89 if (*c == ',') {
90 add_range(rl, val1, val1);
91 c++;
92 start = c;
93 continue;
95 c++; /* skip the dash in eg. 4-5 */
96 if (*c == '(')
97 c++;
98 start = c;
99 if (!strncmp(start, "max", 3)) {
100 val2 = LLONG_MAX;
101 c += 3;
102 } else {
104 while (*c && *c != ',' && *c != '-')
105 c++;
106 val2 = strtoll(start, &c, 10);
108 add_range(rl, val1, val2);
109 if (!*c)
110 break;
111 if (*c == ')')
112 c++;
113 c++; /* skip the comma in eg: 4-5,7 */
118 static struct data_range range_zero = {
119 .min = 0,
120 .max = 0,
123 static struct data_range range_one = {
124 .min = 1,
125 .max = 1,
128 int is_whole_range_rl(struct range_list *rl)
130 struct data_range *drange;
132 if (ptr_list_empty(rl))
133 return 1;
134 drange = first_ptr_list((struct ptr_list *)rl);
135 if (drange->min == whole_range.min && drange->max == whole_range.max)
136 return 1;
137 return 0;
140 long long rl_min(struct range_list *rl)
142 struct data_range *drange;
144 if (ptr_list_empty(rl))
145 return whole_range.min;
146 drange = first_ptr_list((struct ptr_list *)rl);
147 return drange->min;
150 long long rl_max(struct range_list *rl)
152 struct data_range *drange;
154 if (ptr_list_empty(rl))
155 return whole_range.max;
156 drange = last_ptr_list((struct ptr_list *)rl);
157 return drange->max;
160 static struct data_range *alloc_range_helper(long long min, long long max, int perm)
162 struct data_range *ret;
164 if (min > max) {
165 sm_msg("Error invalid range %lld to %lld", min, max);
166 min = whole_range.min;
167 max = whole_range.max;
169 if (min == whole_range.min && max == whole_range.max)
170 return &whole_range;
171 if (min == 0 && max == 0)
172 return &range_zero;
173 if (min == 1 && max == 1)
174 return &range_one;
176 if (perm)
177 ret = __alloc_perm_data_range(0);
178 else
179 ret = __alloc_data_range(0);
180 ret->min = min;
181 ret->max = max;
182 return ret;
185 struct data_range *alloc_range(long long min, long long max)
187 return alloc_range_helper(min, max, 0);
190 struct data_range *alloc_range_perm(long long min, long long max)
192 return alloc_range_helper(min, max, 1);
195 struct range_list *alloc_range_list(long long min, long long max)
197 struct range_list *rl = NULL;
199 add_range(&rl, min, max);
200 return rl;
203 void add_range(struct range_list **list, long long min, long long max)
205 struct data_range *tmp = NULL;
206 struct data_range *new = NULL;
207 int check_next = 0;
210 * FIXME: This has a problem merging a range_list like: min-0,3-max
211 * with a range like 1-2. You end up with min-2,3-max instead of
212 * just min-max.
214 FOR_EACH_PTR(*list, tmp) {
215 if (check_next) {
216 /* Sometimes we overlap with more than one range
217 so we have to delete or modify the next range. */
218 if (max + 1 == tmp->min) {
219 /* join 2 ranges here */
220 new->max = tmp->max;
221 DELETE_CURRENT_PTR(tmp);
222 return;
225 /* Doesn't overlap with the next one. */
226 if (max < tmp->min)
227 return;
228 /* Partially overlaps with the next one. */
229 if (max < tmp->max) {
230 tmp->min = max + 1;
231 return;
233 /* Completely overlaps with the next one. */
234 if (max >= tmp->max) {
235 DELETE_CURRENT_PTR(tmp);
236 /* there could be more ranges to delete */
237 continue;
240 if (max != whole_range.max && max + 1 == tmp->min) {
241 /* join 2 ranges into a big range */
242 new = alloc_range(min, tmp->max);
243 REPLACE_CURRENT_PTR(tmp, new);
244 return;
246 if (max < tmp->min) { /* new range entirely below */
247 new = alloc_range(min, max);
248 INSERT_CURRENT(new, tmp);
249 return;
251 if (min < tmp->min) { /* new range partially below */
252 if (max < tmp->max)
253 max = tmp->max;
254 else
255 check_next = 1;
256 new = alloc_range(min, max);
257 REPLACE_CURRENT_PTR(tmp, new);
258 if (!check_next)
259 return;
260 continue;
262 if (max <= tmp->max) /* new range already included */
263 return;
264 if (min <= tmp->max) { /* new range partially above */
265 min = tmp->min;
266 new = alloc_range(min, max);
267 REPLACE_CURRENT_PTR(tmp, new);
268 check_next = 1;
269 continue;
271 if (min != whole_range.min && min - 1 == tmp->max) {
272 /* join 2 ranges into a big range */
273 new = alloc_range(tmp->min, max);
274 REPLACE_CURRENT_PTR(tmp, new);
275 check_next = 1;
276 continue;
278 /* the new range is entirely above the existing ranges */
279 } END_FOR_EACH_PTR(tmp);
280 if (check_next)
281 return;
282 new = alloc_range(min, max);
283 add_ptr_list(list, new);
286 struct range_list *clone_range_list(struct range_list *list)
288 struct data_range *tmp;
289 struct range_list *ret = NULL;
291 FOR_EACH_PTR(list, tmp) {
292 add_ptr_list(&ret, tmp);
293 } END_FOR_EACH_PTR(tmp);
294 return ret;
297 struct range_list *range_list_union(struct range_list *one, struct range_list *two)
299 struct data_range *tmp;
300 struct range_list *ret = NULL;
302 FOR_EACH_PTR(one, tmp) {
303 add_range(&ret, tmp->min, tmp->max);
304 } END_FOR_EACH_PTR(tmp);
305 FOR_EACH_PTR(two, tmp) {
306 add_range(&ret, tmp->min, tmp->max);
307 } END_FOR_EACH_PTR(tmp);
308 return ret;
311 struct range_list *remove_range(struct range_list *list, long long min, long long max)
313 struct data_range *tmp;
314 struct range_list *ret = NULL;
316 FOR_EACH_PTR(list, tmp) {
317 if (tmp->max < min) {
318 add_range(&ret, tmp->min, tmp->max);
319 continue;
321 if (tmp->min > max) {
322 add_range(&ret, tmp->min, tmp->max);
323 continue;
325 if (tmp->min >= min && tmp->max <= max)
326 continue;
327 if (tmp->min >= min) {
328 add_range(&ret, max + 1, tmp->max);
329 } else if (tmp->max <= max) {
330 add_range(&ret, tmp->min, min - 1);
331 } else {
332 add_range(&ret, tmp->min, min - 1);
333 add_range(&ret, max + 1, tmp->max);
335 } END_FOR_EACH_PTR(tmp);
336 return ret;
340 * if it can be only one and only value return 1, else return 0
342 int estate_get_single_value(struct smatch_state *state, long long *val)
344 struct data_info *dinfo;
345 struct data_range *tmp;
346 int count = 0;
348 dinfo = get_dinfo(state);
349 if (!dinfo || dinfo->type != DATA_RANGE)
350 return 0;
352 FOR_EACH_PTR(dinfo->value_ranges, tmp) {
353 if (!count++) {
354 if (tmp->min != tmp->max)
355 return 0;
356 *val = tmp->min;
357 } else {
358 return 0;
360 } END_FOR_EACH_PTR(tmp);
361 return count;
364 int true_comparison_range(struct data_range *left, int comparison, struct data_range *right)
366 switch (comparison) {
367 case '<':
368 case SPECIAL_UNSIGNED_LT:
369 if (left->min < right->max)
370 return 1;
371 return 0;
372 case SPECIAL_UNSIGNED_LTE:
373 case SPECIAL_LTE:
374 if (left->min <= right->max)
375 return 1;
376 return 0;
377 case SPECIAL_EQUAL:
378 if (left->max < right->min)
379 return 0;
380 if (left->min > right->max)
381 return 0;
382 return 1;
383 case SPECIAL_UNSIGNED_GTE:
384 case SPECIAL_GTE:
385 if (left->max >= right->min)
386 return 1;
387 return 0;
388 case '>':
389 case SPECIAL_UNSIGNED_GT:
390 if (left->max > right->min)
391 return 1;
392 return 0;
393 case SPECIAL_NOTEQUAL:
394 if (left->min != left->max)
395 return 1;
396 if (right->min != right->max)
397 return 1;
398 if (left->min != right->min)
399 return 1;
400 return 0;
401 default:
402 sm_msg("unhandled comparison %d\n", comparison);
403 return 0;
405 return 0;
408 int true_comparison_range_lr(int comparison, struct data_range *var, struct data_range *val, int left)
410 if (left)
411 return true_comparison_range(var, comparison, val);
412 else
413 return true_comparison_range(val, comparison, var);
416 static int false_comparison_range(struct data_range *left, int comparison, struct data_range *right)
418 switch (comparison) {
419 case '<':
420 case SPECIAL_UNSIGNED_LT:
421 if (left->max >= right->min)
422 return 1;
423 return 0;
424 case SPECIAL_UNSIGNED_LTE:
425 case SPECIAL_LTE:
426 if (left->max > right->min)
427 return 1;
428 return 0;
429 case SPECIAL_EQUAL:
430 if (left->min != left->max)
431 return 1;
432 if (right->min != right->max)
433 return 1;
434 if (left->min != right->min)
435 return 1;
436 return 0;
437 case SPECIAL_UNSIGNED_GTE:
438 case SPECIAL_GTE:
439 if (left->min < right->max)
440 return 1;
441 return 0;
442 case '>':
443 case SPECIAL_UNSIGNED_GT:
444 if (left->min <= right->max)
445 return 1;
446 return 0;
447 case SPECIAL_NOTEQUAL:
448 if (left->max < right->min)
449 return 0;
450 if (left->min > right->max)
451 return 0;
452 return 1;
453 default:
454 sm_msg("unhandled comparison %d\n", comparison);
455 return 0;
457 return 0;
460 int false_comparison_range_lr(int comparison, struct data_range *var, struct data_range *val, int left)
462 if (left)
463 return false_comparison_range(var, comparison, val);
464 else
465 return false_comparison_range(val, comparison, var);
468 int possibly_true(int comparison, struct expression *expr, long long num, int left)
470 struct data_range *tmp;
471 struct data_range drange;
472 struct range_list *rl;
474 if (!get_implied_range_list(expr, &rl))
475 return 1;
477 drange.min = num;
478 drange.max = num;
480 FOR_EACH_PTR(rl, tmp) {
481 if (true_comparison_range_lr(comparison, tmp, &drange, left))
482 return 1;
483 } END_FOR_EACH_PTR(tmp);
484 return 0;
487 int possibly_false(int comparison, struct expression *expr, long long num, int left)
489 struct data_range *tmp;
490 struct data_range drange;
491 struct range_list *rl;
493 if (!get_implied_range_list(expr, &rl))
494 return 1;
496 drange.min = num;
497 drange.max = num;
499 FOR_EACH_PTR(rl, tmp) {
500 if (false_comparison_range_lr(comparison, tmp, &drange, left))
501 return 1;
502 } END_FOR_EACH_PTR(tmp);
503 return 0;
506 int possibly_true_range_lists(struct range_list *left_ranges, int comparison, struct range_list *right_ranges)
508 struct data_range *left_tmp, *right_tmp;
510 if (!left_ranges || !right_ranges)
511 return 1;
513 FOR_EACH_PTR(left_ranges, left_tmp) {
514 FOR_EACH_PTR(right_ranges, right_tmp) {
515 if (true_comparison_range(left_tmp, comparison, right_tmp))
516 return 1;
517 } END_FOR_EACH_PTR(right_tmp);
518 } END_FOR_EACH_PTR(left_tmp);
519 return 0;
522 int possibly_true_range_list_lr(int comparison, struct smatch_state *state, struct range_list *values, int left)
524 struct data_range *tmp, *tmp2;
526 FOR_EACH_PTR(estate_ranges(state), tmp) {
527 FOR_EACH_PTR(values, tmp2) {
528 if (true_comparison_range_lr(comparison, tmp, tmp2, left))
529 return 1;
530 } END_FOR_EACH_PTR(tmp2);
531 } END_FOR_EACH_PTR(tmp);
532 return 0;
535 int possibly_false_range_lists(struct range_list *left_ranges, int comparison, struct range_list *right_ranges)
537 struct data_range *left_tmp, *right_tmp;
539 if (!left_ranges || !right_ranges)
540 return 1;
542 FOR_EACH_PTR(left_ranges, left_tmp) {
543 FOR_EACH_PTR(right_ranges, right_tmp) {
544 if (false_comparison_range(left_tmp, comparison, right_tmp))
545 return 1;
546 } END_FOR_EACH_PTR(right_tmp);
547 } END_FOR_EACH_PTR(left_tmp);
548 return 0;
551 int possibly_false_range_list_lr(int comparison, struct smatch_state *state, struct range_list *values, int left)
553 struct data_range *tmp, *tmp2;
555 FOR_EACH_PTR(estate_ranges(state), tmp) {
556 FOR_EACH_PTR(values, tmp2) {
557 if (false_comparison_range_lr(comparison, tmp, tmp2, left))
558 return 1;
559 } END_FOR_EACH_PTR(tmp2);
560 } END_FOR_EACH_PTR(tmp);
561 return 0;
564 void tack_on(struct range_list **list, struct data_range *drange)
566 add_ptr_list(list, drange);
569 int in_list_exact(struct range_list *list, struct data_range *drange)
571 struct data_range *tmp;
573 FOR_EACH_PTR(list, tmp) {
574 if (tmp->min == drange->min && tmp->max == drange->max)
575 return 1;
576 } END_FOR_EACH_PTR(tmp);
577 return 0;
581 void push_range_list(struct range_list_stack **rl_stack, struct range_list *rl)
583 add_ptr_list(rl_stack, rl);
586 struct range_list *pop_range_list(struct range_list_stack **rl_stack)
588 struct range_list *rl;
590 rl = last_ptr_list((struct ptr_list *)*rl_stack);
591 delete_ptr_list_last((struct ptr_list **)rl_stack);
592 return rl;
595 struct range_list *top_range_list(struct range_list_stack *rl_stack)
597 struct range_list *rl;
599 rl = last_ptr_list((struct ptr_list *)rl_stack);
600 return rl;
603 void filter_top_range_list(struct range_list_stack **rl_stack, long long num)
605 struct range_list *rl;
607 rl = pop_range_list(rl_stack);
608 rl = remove_range(rl, num, num);
609 push_range_list(rl_stack, rl);
612 void free_range_list(struct range_list **rlist)
614 __free_ptr_list((struct ptr_list **)rlist);
617 static void free_single_dinfo(struct data_info *dinfo)
619 if (dinfo->type == DATA_RANGE)
620 free_range_list(&dinfo->value_ranges);
623 static void free_dinfos(struct allocation_blob *blob)
625 unsigned int size = sizeof(struct data_info);
626 unsigned int offset = 0;
628 while (offset < blob->offset) {
629 free_single_dinfo((struct data_info *)(blob->data + offset));
630 offset += size;
634 void free_data_info_allocs(void)
636 struct allocator_struct *desc = &data_info_allocator;
637 struct allocation_blob *blob = desc->blobs;
639 desc->blobs = NULL;
640 desc->allocations = 0;
641 desc->total_bytes = 0;
642 desc->useful_bytes = 0;
643 desc->freelist = NULL;
644 while (blob) {
645 struct allocation_blob *next = blob->next;
646 free_dinfos(blob);
647 blob_free(blob, desc->chunking);
648 blob = next;
650 clear_data_range_alloc();