From 0d2391442e620fa206058ade558ad0b244dcf209 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 12 Jun 2013 10:27:59 +0300 Subject: [PATCH] db, comparison, ranges: improve how comparisons will be stored in the db I started to add this but didn't get it finished. It's the code to get relationship information from the database. The code to store it in the database has not been added yet. The new format for storing relationships is something like: [==p0] This means that the return value is equal to parameter zero. For example ERR_PTR() just casts parameter zero and returns it. But a more interesting case might look like: 0-[<=p1] This means that the return value is range 0 up to parameter one. Signed-off-by: Dan Carpenter --- smatch_comparison.c | 19 ++----------- smatch_extra.h | 1 + smatch_ranges.c | 79 ++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 70 insertions(+), 29 deletions(-) diff --git a/smatch_comparison.c b/smatch_comparison.c index f62843d5..ffda7e50 100644 --- a/smatch_comparison.c +++ b/smatch_comparison.c @@ -466,23 +466,10 @@ free: void __add_comparison_info(struct expression *expr, struct expression *call, const char *range) { struct expression *arg; - int param; - const char *p = range; - - if (*p == '<') - return; - while (1) { - if (*p == '\0') - return; - if (*p == '<') - break; - p++; - } - p++; + int comparison; + const char *c = range; - param = strtoll(p, NULL, 10); - arg = get_argument_from_call_expr(call->args, param); - if (!arg) + if (!str_to_comparison_arg(c, call, &comparison, &arg, NULL)) return; add_comparison(expr, SPECIAL_LTE, arg); } diff --git a/smatch_extra.h b/smatch_extra.h index 387ec606..7d8eeec7 100644 --- a/smatch_extra.h +++ b/smatch_extra.h @@ -28,6 +28,7 @@ extern struct string_list *__ignored_macros; /* these are implemented in smatch_ranges.c */ char *show_rl(struct range_list *list); +int str_to_comparison_arg(const char *c, struct expression *call, int *comparison, struct expression **arg, char **endp); void str_to_rl(struct symbol *type, char *value, struct range_list **rl); void call_results_to_rl(struct expression *call, struct symbol *type, char *value, struct range_list **rl); diff --git a/smatch_ranges.c b/smatch_ranges.c index ba6a9078..6e80b2d8 100644 --- a/smatch_ranges.c +++ b/smatch_ranges.c @@ -39,10 +39,61 @@ char *show_rl(struct range_list *list) return alloc_sname(full); } +int str_to_comparison_arg(const char *str, struct expression *call, int *comparison, struct expression **arg, char **endp) +{ + int param; + char *c = (char *)str; + + if (*c != '[') + return 0; + c++; + + if (*c == '<') { + c++; + if (*c == '=') { + *comparison = SPECIAL_LTE; + c++; + } else { + *comparison = '<'; + } + } else if (*c == '=') { + c++; + c++; + *comparison = SPECIAL_EQUAL; + } else if (*c == '>') { + c++; + if (*c == '=') { + *comparison = SPECIAL_GTE; + c++; + } else { + *comparison = '>'; + } + } else { + return 0; + } + + if (*c != 'p') + return 0; + c++; + + param = strtoll(c, &c, 10); + c++; /* skip the ']' character */ + if (endp) + *endp = (char *)c; + + if (!call) + return 0; + *arg = get_argument_from_call_expr(call->args, param); + if (!*arg) + return 0; + return 1; +} + + static sval_t get_val_from_key(int use_max, struct symbol *type, char *c, struct expression *call, char **endp) { struct expression *arg; - int param; + int comparison; sval_t ret, tmp; if (use_max) @@ -50,21 +101,23 @@ static sval_t get_val_from_key(int use_max, struct symbol *type, char *c, struct else ret = sval_type_min(type); - c++; /* skip the '<' character */ - param = strtoll(c, &c, 10); - c++; /* skip the '>' character */ - *endp = c; - - if (!call) - return ret; - arg = get_argument_from_call_expr(call->args, param); - if (!arg) + if (!str_to_comparison_arg(c, call, &comparison, &arg, endp)) return ret; - if (use_max && get_implied_max(arg, &tmp)) + if (use_max && get_implied_max(arg, &tmp)) { ret = tmp; - if (!use_max && get_implied_min(arg, &tmp)) + if (comparison == '<') { + tmp.value = 1; + ret = sval_binop(ret, '-', tmp); + } + } + if (!use_max && get_implied_min(arg, &tmp)) { ret = tmp; + if (comparison == '>') { + tmp.value = 1; + ret = sval_binop(ret, '+', tmp); + } + } return ret; } @@ -107,7 +160,7 @@ static sval_t parse_val(int use_max, struct expression *call, struct symbol *typ } else if (!strncmp(start, "s16min", 6)) { ret = sval_type_val(type, SHRT_MIN); c += 6; - } else if (start[0] == '<') { + } else if (start[0] == '[') { ret = get_val_from_key(1, type, start, call, &c); } else { ret = sval_type_val(type, strtoll(start, &c, 10)); -- 2.11.4.GIT