Identify for(;;) type loops as forever loops. This nullifies the path if
[smatch.git] / smatch_helper.c
blobb6e2331b0aa313ab6815628a76eec710f08cf650
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(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)++;
93 *sym_ptr = expr->symbol;
95 return;
96 case EXPR_PREOP: {
97 const char *tmp;
99 if (expr->op == '*')
100 star_count++;
102 __get_variable_from_expr(sym_ptr, buf, expr->unop,
103 len, complicated);
104 tmp = show_special(expr->op);
105 if (tmp[0] == '*') {
106 if (star_count-- >= 0) {
107 prepend(buf, tmp, len);
109 } else {
110 prepend(buf, tmp, len);
113 if (tmp[0] == '(') {
114 strncat(buf, ")", len);
115 buf[len - 1] = '\0';
118 if ((!strcmp(tmp, "--")) || (!strcmp(tmp, "++")))
119 (*complicated)++;
121 return;
123 case EXPR_POSTOP: {
124 const char *tmp;
126 tmp = show_special(expr->op);
127 prepend(buf, tmp, len);
128 __get_variable_from_expr(sym_ptr, buf, expr->unop,
129 len, complicated);
131 if ((!strcmp(tmp, "--")) || (!strcmp(tmp, "++")))
132 (*complicated)++;
134 return;
136 case EXPR_BINOP: {
137 const char *tmp;
139 prepend(buf, ")", len);
140 __get_variable_from_expr(NULL, buf, expr->right, len,
141 complicated);
142 tmp = show_special(expr->op);
143 prepend(buf, tmp, len);
144 __get_variable_from_expr(sym_ptr, buf, expr->left,
145 len, complicated);
146 prepend(buf, "(", len);
147 return;
149 case EXPR_VALUE: {
150 char tmp[25];
152 snprintf(tmp, 25, "%lld", expr->value);
153 prepend(buf, tmp, len);
154 return;
156 case EXPR_STRING:
157 prepend(buf, expr->string->data, len);
158 return;
159 case EXPR_CALL: {
160 struct expression *tmp;
161 int i = 0;
163 (*complicated)++;
164 prepend(buf, ")", len);
165 FOR_EACH_PTR_REVERSE(expr->args, tmp) {
166 if (i++)
167 prepend(buf, ", ", len);
168 __get_variable_from_expr(NULL, buf, tmp, len,
169 complicated);
170 } END_FOR_EACH_PTR_REVERSE(tmp);
171 prepend(buf, "(", len);
172 __get_variable_from_expr(NULL, buf, expr->fn, len,
173 complicated);
174 return;
176 case EXPR_CAST:
177 __get_variable_from_expr(sym_ptr, buf,
178 expr->cast_expression, len,
179 complicated);
180 return;
181 case EXPR_SIZEOF: {
182 int size;
183 char tmp[25];
185 if (expr->cast_type && get_base_type(expr->cast_type)) {
186 size = (get_base_type(expr->cast_type))->bit_size;
187 snprintf(tmp, 25, "%d", size);
188 prepend(buf, tmp, len);
190 return;
192 default:
193 (*complicated)++;
194 //printf("unknown type = %d\n", expr->type);
195 return;
201 * This is returns a stylized "c looking" representation of the
202 * variable name.
204 * It uses the same buffer every time so you have to save the result
205 * yourself if you want to keep it.
209 char *get_variable_from_expr(struct expression *expr, struct symbol **sym_ptr)
211 static char var_name[VAR_LEN];
212 int junk;
214 if (sym_ptr)
215 *sym_ptr = NULL;
216 star_count = 0;
217 var_name[0] = '\0';
219 if (!expr)
220 return NULL;
221 __get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name),
222 &junk);
224 return var_name;
228 * get_variable_from_expr_simple() only returns simple variables.
229 * If it's a complicated variable like a->foo instead of just 'a'
230 * then it returns NULL.
233 char *get_variable_from_expr_simple(struct expression *expr,
234 struct symbol **sym_ptr)
236 static char var_name[VAR_LEN];
237 int complicated = 0;
239 if (sym_ptr)
240 *sym_ptr = NULL;
241 star_count = 0;
242 var_name[0] = '\0';
244 if (!expr)
245 return NULL;
246 __get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name),
247 &complicated);
249 if (complicated) {
250 if (sym_ptr)
251 *sym_ptr = NULL;
252 return NULL;
254 return var_name;