math: cleanup create separate handle_binop() function
[smatch.git] / smatch_math.c
blob9416776f96704a8a8ab729e9baa3fc5ffa13d115
1 /*
2 * sparse/smatch_helper.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
11 #include "smatch_extra.h"
13 static long long _get_value(struct expression *expr, int *discard, int *undefined, int implied);
15 #define BOGUS 12345
17 #define NOTIMPLIED 0
18 #define IMPLIED 1
19 #define FUZZYMAX 2
20 #define FUZZYMIN 3
22 static long long cast_to_type(struct expression *expr, long long val)
24 struct symbol *type = get_type(expr);
26 if (!type)
27 return val;
29 switch (type->bit_size) {
30 case 8:
31 if (type->ctype.modifiers & MOD_UNSIGNED)
32 val = (long long)(unsigned char) val;
33 else
34 val = (long long)(char) val;
35 break;
36 case 16:
37 if (type->ctype.modifiers & MOD_UNSIGNED)
38 val = (long long)(unsigned short) val;
39 else
40 val = (long long)(short) val;
41 break;
42 case 32:
43 if (type->ctype.modifiers & MOD_UNSIGNED)
44 val = (long long)(unsigned int) val;
45 else
46 val = (long long)(int) val;
47 break;
49 return val;
52 static long long handle_preop(struct expression *expr, int *discard, int *undefined, int implied)
54 long long ret = BOGUS;
56 switch(expr->op) {
57 case '~':
58 ret = ~ _get_value(expr->unop, discard, undefined, implied);
59 ret = cast_to_type(expr->unop, ret);
60 break;
61 case '-':
62 ret = - _get_value(expr->unop, discard, undefined, implied);
63 break;
64 default:
65 *undefined = 1;
66 *discard = 1;
68 return ret;
71 static long long handle_binop(struct expression *expr, int *discard, int *undefined, int implied)
73 long long left;
74 long long right;
75 long long ret = BOGUS;
77 if (expr->type != EXPR_BINOP) {
78 *undefined = 1;
79 *discard = 1;
80 return ret;
83 left = _get_value(expr->left, discard, undefined, implied);
84 right = _get_value(expr->right, discard, undefined, implied);
85 if (expr->op == '*') {
86 ret = left * right;
87 } else if (expr->op == '/') {
88 ret = left / right;
89 } else if (expr->op == '+') {
90 ret = left + right;
91 } else if (expr->op == '-') {
92 ret = left - right;
93 } else if (expr->op == '|') {
94 ret = left | right;
95 } else if (expr->op == '&') {
96 ret = left & right;
97 } else if (expr->op == SPECIAL_RIGHTSHIFT) {
98 ret = left >> right;
99 } else if (expr->op == SPECIAL_LEFTSHIFT) {
100 ret = left << right;
101 } else if (expr->op == '^') {
102 ret = left ^ right;
103 } else {
104 *undefined = 1;
105 *discard = 1;
107 return ret;
110 static long long _get_value(struct expression *expr, int *discard, int *undefined, int implied)
112 int dis = 0;
113 long long ret = BOGUS;
115 if (!expr) {
116 *undefined = 1;
117 return BOGUS;
119 if (!discard)
120 discard = &dis;
121 if (*discard) {
122 *undefined = 1;
123 return BOGUS;
126 expr = strip_parens(expr);
128 switch (expr->type){
129 case EXPR_VALUE:
130 ret = expr->value;
131 ret = cast_to_type(expr, ret);
132 break;
133 case EXPR_PREOP:
134 ret = handle_preop(expr, discard, undefined, implied);
135 break;
136 case EXPR_CAST:
137 case EXPR_FORCE_CAST:
138 case EXPR_IMPLIED_CAST:
139 ret = _get_value(expr->cast_expression, discard, undefined, implied);
140 return cast_to_type(expr, ret);
141 case EXPR_BINOP:
142 ret = handle_binop(expr, discard, undefined, implied);
143 break;
144 case EXPR_PTRSIZEOF:
145 case EXPR_SIZEOF:
146 ret = get_expression_value(expr);
147 break;
148 default:
149 switch (implied) {
150 case IMPLIED:
151 if (!get_implied_single_val(expr, &ret)) {
152 *undefined = 1;
153 *discard = 1;
155 break;
156 case FUZZYMAX:
157 if (!get_implied_single_fuzzy_max(expr, &ret)) {
158 *undefined = 1;
159 *discard = 1;
161 break;
162 case FUZZYMIN:
163 if (!get_implied_single_fuzzy_min(expr, &ret)) {
164 *undefined = 1;
165 *discard = 1;
167 break;
168 default:
169 *undefined = 1;
170 *discard = 1;
173 if (*discard) {
174 *undefined = 1;
175 return BOGUS;
177 return ret;
180 /* returns 1 if it can get a value literal or else returns 0 */
181 int get_value(struct expression *expr, long long *val)
183 int undefined = 0;
185 *val = _get_value(expr, NULL, &undefined, NOTIMPLIED);
186 if (undefined)
187 return 0;
188 return 1;
191 int get_implied_value(struct expression *expr, long long *val)
193 int undefined = 0;
195 *val = _get_value(expr, NULL, &undefined, IMPLIED);
196 return !undefined;
199 int get_fuzzy_max(struct expression *expr, long long *val)
201 int undefined = 0;
203 *val = _get_value(expr, NULL, &undefined, FUZZYMAX);
204 return !undefined;
207 int get_fuzzy_min(struct expression *expr, long long *val)
209 int undefined = 0;
211 *val = _get_value(expr, NULL, &undefined, FUZZYMIN);
212 return !undefined;