Don't free bin_dir.
[smatch.git] / smatch_helper.c
blobac13baa6112adaf29619f35b8de0a964a1ddfdf7
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 struct symbol *get_ptr_type_ptr(struct symbol *sym)
268 if (!sym) {
269 return NULL;
272 if (sym->type != SYM_NODE)
273 return NULL;
274 sym = get_base_type(sym);
275 if (sym->type != SYM_PTR)
276 return NULL;
277 sym = get_base_type(sym);
278 return sym;
281 static struct symbol *get_struct_sym(struct expression *expr)
283 struct symbol *base_type;
284 struct symbol *parent_struct;
285 struct symbol *tmp;
287 if (expr->type != EXPR_PREOP)
288 return NULL;
290 expr = expr->unop;
291 if (expr->type == EXPR_DEREF) {
292 parent_struct = get_struct_sym(expr->deref);
293 if (!parent_struct)
294 return NULL;
295 tmp = NULL;
296 FOR_EACH_PTR(parent_struct->symbol_list, tmp) {
297 if (tmp->ident == expr->member)
298 break;
299 } END_FOR_EACH_PTR(tmp);
300 if (!tmp || tmp->ident != expr->member)
301 return NULL;
302 base_type = get_base_type(tmp);
303 } else if (expr->type == EXPR_SYMBOL) {
304 base_type = get_base_type(expr->symbol);
305 } else {
306 return NULL;
308 if (base_type->type != SYM_PTR)
309 return NULL;
310 base_type = get_base_type(base_type);
311 if (base_type->type != SYM_STRUCT && base_type->type != SYM_UNION)
312 return NULL;
313 return base_type;
316 struct symbol *get_deref_type(struct expression *expr)
318 struct ident *member = expr->member;
319 struct symbol *struct_sym;
320 struct symbol *tmp;
322 struct_sym = get_struct_sym(expr->deref);
323 if (!struct_sym || (struct_sym->type != SYM_STRUCT
324 && struct_sym->type != SYM_UNION))
325 return NULL;
326 FOR_EACH_PTR(struct_sym->symbol_list, tmp) {
327 if (tmp->ident == member)
328 return get_ptr_type_ptr(tmp);
329 } END_FOR_EACH_PTR(tmp);
330 return NULL;
333 struct symbol *get_ptr_type(struct expression *expr)
335 struct symbol *ptr_type = NULL;
337 if (!expr)
338 return NULL;
339 if (expr->type == EXPR_DEREF)
340 ptr_type = get_deref_type(expr);
341 if (expr->type == EXPR_SYMBOL)
342 ptr_type = get_ptr_type_ptr(expr->symbol);
343 return ptr_type;
346 int sym_name_is(const char *name, struct expression *expr)
348 if (!expr)
349 return 0;
350 if (expr->type != EXPR_SYMBOL)
351 return 0;
352 if (!strcmp(expr->symbol_name->name, name))
353 return 1;
354 return 0;
357 static int _get_value(struct expression *expr, int *discard)
359 int dis = 0;
360 int ret = UNDEFINED;
362 if (!expr)
363 return UNDEFINED;
364 if (!discard)
365 discard = &dis;
366 if (*discard)
367 return UNDEFINED;
369 expr = strip_expr(expr);
371 switch (expr->type){
372 case EXPR_VALUE:
373 ret = expr->value;
374 break;
375 case EXPR_PREOP:
376 if (!strcmp("-", show_special(expr->op)))
377 ret = - _get_value(expr->unop, discard);
378 else
379 *discard = 1;
380 break;
381 case EXPR_BINOP: {
382 int left, right;
384 if (!show_special(expr->op)) {
385 *discard = 1;
386 break;
388 left = _get_value(expr->left, discard);
389 right = _get_value(expr->right, discard);
390 if (!strcmp("*", show_special(expr->op))) {
391 ret = left * right;
392 } else if (!strcmp("/", show_special(expr->op))) {
393 ret = left / right;
394 } else if (!strcmp("+", show_special(expr->op))) {
395 ret = left + right;
396 } else if (!strcmp("-", show_special(expr->op))) {
397 ret = left - right;
398 } else if (!strcmp("|", show_special(expr->op))) {
399 ret = left | right;
400 } else {
401 *discard = 1;
403 break;
405 case EXPR_SIZEOF:
406 if (expr->cast_type && get_base_type(expr->cast_type))
407 ret = (get_base_type(expr->cast_type))->bit_size / 8;
408 else
409 *discard = 1;
410 break;
411 default:
412 //printf("ouchies-->%d\n", expr->type);
413 *discard = 1;
415 if (*discard)
416 return UNDEFINED;
417 return ret;
420 /* returns UNDEFINED on error */
421 int get_value(struct expression *expr)
423 return _get_value(expr, NULL);
426 int is_zero(struct expression *expr)
428 if (get_value(expr) == 0)
429 return 1;
430 return 0;
433 const char *show_state(struct smatch_state *state)
435 if (!state)
436 return NULL;
437 return state->name;
440 struct statement *get_block_thing(struct expression *expr)
442 /* What are those things called? if (({....; ret;})) { ...*/
444 if (expr->type != EXPR_PREOP)
445 return NULL;
446 if (expr->op != '(')
447 return NULL;
448 if (expr->unop->type != EXPR_STATEMENT)
449 return NULL;
450 if (expr->unop->statement->type != STMT_COMPOUND)
451 return NULL;
452 return expr->unop->statement;
455 struct expression *strip_expr(struct expression *expr)
457 if (!expr)
458 return NULL;
460 switch(expr->type) {
461 case EXPR_CAST:
462 return strip_expr(expr->cast_expression);
463 case EXPR_PREOP:
464 if (expr->op == '(' && expr->unop->type == EXPR_STATEMENT &&
465 expr->unop->statement->type == STMT_COMPOUND)
466 return expr;
467 if (expr->op == '(')
468 return strip_expr(expr->unop);
470 return expr;