Save function lists in smatch_data/
[smatch.git] / smatch_helper.c
blobd51c03dfc489b77ecac0fc9d9fdd8a4e7c077bec
1 /*
2 * sparse/smatch_helper.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include "allocate.h"
13 #include "smatch.h"
15 static int star_count;
16 #define VAR_LEN 512
19 char *alloc_string(const char *str)
21 char *tmp;
23 if (!str)
24 return NULL;
25 tmp = malloc(strlen(str) + 1);
26 strcpy(tmp, str);
27 return tmp;
30 void free_string(char *str)
32 free(str);
35 static void prepend(char *dest, const char *data, int buff_len)
37 int space_needed;
38 int i;
40 space_needed = strlen(data);
41 for (i = buff_len - space_needed - 1; i >= 0 ; i--)
42 dest[i + space_needed] = dest[i];
43 for (i = 0; i < space_needed % buff_len ; i++)
44 dest[i] = data[i];
45 dest[buff_len - 1] = '\0';
49 * If you have "foo(a, b, 1);" then use
50 * get_argument_from_call_expr(expr, 0) to return the expression for
51 * a. Yes, it does start counting from 0.
53 struct expression *get_argument_from_call_expr(struct expression_list *args,
54 int num)
56 struct expression *expr;
57 int i = 0;
59 if (!args)
60 return NULL;
62 FOR_EACH_PTR(args, expr) {
63 if (i == num)
64 return expr;
65 i++;
66 } END_FOR_EACH_PTR(expr);
67 return NULL;
70 static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf,
71 struct expression *expr, int len,
72 int *complicated)
74 switch(expr->type) {
75 case EXPR_DEREF:
76 prepend(buf, expr->member->name, len);
77 if (!strcmp(show_special(expr->deref->op), "*"))
78 prepend(buf, "->", len);
79 else
80 prepend(buf, ".", len);
82 //printf("debug: %d\n", expr->deref
84 __get_variable_from_expr(sym_ptr, buf, expr->deref,
85 len, complicated);
86 return;
87 case EXPR_SYMBOL:
88 if (expr->symbol_name)
89 prepend(buf, expr->symbol_name->name, len);
90 if (sym_ptr) {
91 if (*sym_ptr)
92 *complicated = 1;
93 *sym_ptr = expr->symbol;
95 return;
96 case EXPR_PREOP: {
97 const char *tmp;
99 if (get_block_thing(expr)) {
100 *complicated = 2;
101 return;
104 if (expr->op == '*')
105 star_count++;
107 __get_variable_from_expr(sym_ptr, buf, expr->unop,
108 len, complicated);
109 tmp = show_special(expr->op);
110 if (tmp[0] == '*') {
111 if (star_count-- >= 0) {
112 prepend(buf, tmp, len);
114 } else {
115 prepend(buf, tmp, len);
118 if (tmp[0] == '(') {
119 strncat(buf, ")", len);
120 buf[len - 1] = '\0';
123 if ((!strcmp(tmp, "--")) || (!strcmp(tmp, "++")))
124 *complicated = 1;
126 return;
128 case EXPR_POSTOP: {
129 const char *tmp;
131 tmp = show_special(expr->op);
132 prepend(buf, tmp, len);
133 __get_variable_from_expr(sym_ptr, buf, expr->unop,
134 len, complicated);
136 if ((!strcmp(tmp, "--")) || (!strcmp(tmp, "++")))
137 *complicated = 1;
139 return;
141 case EXPR_BINOP: {
142 const char *tmp;
144 *complicated = 1;
145 prepend(buf, ")", len);
146 __get_variable_from_expr(NULL, buf, expr->right, len,
147 complicated);
148 tmp = show_special(expr->op);
149 prepend(buf, tmp, len);
150 __get_variable_from_expr(sym_ptr, buf, expr->left,
151 len, complicated);
152 prepend(buf, "(", len);
153 return;
155 case EXPR_VALUE: {
156 char tmp[25];
158 snprintf(tmp, 25, "%lld", expr->value);
159 prepend(buf, tmp, len);
160 return;
162 case EXPR_STRING:
163 prepend(buf, expr->string->data, len);
164 return;
165 case EXPR_CALL: {
166 struct expression *tmp;
167 int i = 0;
169 *complicated = 1;
170 prepend(buf, ")", len);
171 FOR_EACH_PTR_REVERSE(expr->args, tmp) {
172 if (i++)
173 prepend(buf, ", ", len);
174 __get_variable_from_expr(NULL, buf, tmp, len,
175 complicated);
176 } END_FOR_EACH_PTR_REVERSE(tmp);
177 prepend(buf, "(", len);
178 __get_variable_from_expr(NULL, buf, expr->fn, len,
179 complicated);
180 return;
182 case EXPR_CAST:
183 __get_variable_from_expr(sym_ptr, buf,
184 expr->cast_expression, len,
185 complicated);
186 return;
187 case EXPR_SIZEOF: {
188 int size;
189 char tmp[25];
191 if (expr->cast_type && get_base_type(expr->cast_type)) {
192 size = (get_base_type(expr->cast_type))->bit_size;
193 snprintf(tmp, 25, "%d", size);
194 prepend(buf, tmp, len);
196 return;
198 default:
199 *complicated = 1;
200 //printf("unknown type = %d\n", expr->type);
201 return;
207 * This is returns a stylized "c looking" representation of the
208 * variable name.
210 * It uses the same buffer every time so you have to save the result
211 * yourself if you want to keep it.
215 char *get_variable_from_expr_complex(struct expression *expr, struct symbol **sym_ptr)
217 static char var_name[VAR_LEN];
218 int complicated = 0;
220 if (sym_ptr)
221 *sym_ptr = NULL;
222 star_count = 0;
223 var_name[0] = '\0';
225 if (!expr)
226 return NULL;
227 __get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name),
228 &complicated);
229 if (complicated < 2)
230 return alloc_string(var_name);
231 else
232 return NULL;
236 * get_variable_from_expr_simple() only returns simple variables.
237 * If it's a complicated variable like a->foo instead of just 'a'
238 * then it returns NULL.
241 char *get_variable_from_expr(struct expression *expr,
242 struct symbol **sym_ptr)
244 static char var_name[VAR_LEN];
245 int complicated = 0;
247 if (sym_ptr)
248 *sym_ptr = NULL;
249 star_count = 0;
250 var_name[0] = '\0';
252 if (!expr)
253 return NULL;
254 expr = strip_expr(expr);
255 __get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name),
256 &complicated);
258 if (complicated) {
259 if (sym_ptr)
260 *sym_ptr = NULL;
261 return NULL;
263 return alloc_string(var_name);
266 int sym_name_is(const char *name, struct expression *expr)
268 if (!expr)
269 return 0;
270 if (expr->type != EXPR_SYMBOL)
271 return 0;
272 if (!strcmp(expr->symbol_name->name, name))
273 return 1;
274 return 0;
277 static int _get_value(struct expression *expr, int *discard)
279 int dis = 0;
280 int ret = UNDEFINED;
282 if (!expr)
283 return UNDEFINED;
284 if (!discard)
285 discard = &dis;
286 if (*discard)
287 return UNDEFINED;
289 expr = strip_expr(expr);
291 switch (expr->type){
292 case EXPR_VALUE:
293 ret = expr->value;
294 break;
295 case EXPR_PREOP:
296 if (!strcmp("-", show_special(expr->op)))
297 ret = - _get_value(expr->unop, discard);
298 else
299 *discard = 1;
300 break;
301 case EXPR_BINOP: {
302 int left, right;
304 if (!show_special(expr->op)) {
305 *discard = 1;
306 break;
308 left = _get_value(expr->left, discard);
309 right = _get_value(expr->right, discard);
310 if (!strcmp("*", show_special(expr->op))) {
311 ret = left * right;
312 } else if (!strcmp("/", show_special(expr->op))) {
313 ret = left / right;
314 } else if (!strcmp("+", show_special(expr->op))) {
315 ret = left + right;
316 } else if (!strcmp("-", show_special(expr->op))) {
317 ret = left - right;
318 } else if (!strcmp("|", show_special(expr->op))) {
319 ret = left | right;
320 } else {
321 *discard = 1;
323 break;
325 case EXPR_SIZEOF:
326 if (expr->cast_type && get_base_type(expr->cast_type))
327 ret = (get_base_type(expr->cast_type))->bit_size / 8;
328 else
329 *discard = 1;
330 break;
331 default:
332 //printf("ouchies-->%d\n", expr->type);
333 *discard = 1;
335 if (*discard)
336 return UNDEFINED;
337 return ret;
340 /* returns UNDEFINED on error */
341 int get_value(struct expression *expr)
343 return _get_value(expr, NULL);
346 int is_zero(struct expression *expr)
348 if (get_value(expr) == 0)
349 return 1;
350 return 0;
353 const char *show_state(struct smatch_state *state)
355 if (!state)
356 return NULL;
357 return state->name;
360 struct statement *get_block_thing(struct expression *expr)
362 /* What are those things called? if (({....; ret;})) { ...*/
364 if (expr->type != EXPR_PREOP)
365 return NULL;
366 if (expr->op != '(')
367 return NULL;
368 if (expr->unop->type != EXPR_STATEMENT)
369 return NULL;
370 if (expr->unop->statement->type != STMT_COMPOUND)
371 return NULL;
372 return expr->unop->statement;
375 struct expression *strip_expr(struct expression *expr)
377 if (!expr)
378 return NULL;
380 switch(expr->type) {
381 case EXPR_CAST:
382 return strip_expr(expr->cast_expression);
383 case EXPR_PREOP:
384 if (expr->op == '(' && expr->unop->type == EXPR_STATEMENT &&
385 expr->unop->statement->type == STMT_COMPOUND)
386 return expr;
387 if (expr->op == '(')
388 return strip_expr(expr->unop);
390 return expr;