2 #include "smatch_extra.h"
4 DECLARE_ALLOCATOR(sname
);
5 __ALLOCATOR(struct expression
, "temporary expr", tmp_expression
);
7 static struct position
get_cur_pos(void)
9 static struct position pos
;
10 static struct position none
;
11 struct expression
*expr
;
12 struct statement
*stmt
;
14 expr
= last_ptr_list((struct ptr_list
*)big_expression_stack
);
15 stmt
= last_ptr_list((struct ptr_list
*)big_statement_stack
);
25 struct expression
*alloc_tmp_expression(struct position pos
, int type
)
27 struct expression
*expr
;
29 expr
= __alloc_tmp_expression(0);
30 expr
->smatch_flags
|= Tmp
;
36 void free_tmp_expressions(void)
38 clear_tmp_expression_alloc();
41 struct expression
*zero_expr(void)
43 struct expression
*zero
;
45 zero
= alloc_tmp_expression(get_cur_pos(), EXPR_VALUE
);
47 zero
->ctype
= &int_ctype
;
51 struct expression
*value_expr(long long val
)
53 struct expression
*expr
;
58 expr
= alloc_tmp_expression(get_cur_pos(), EXPR_VALUE
);
60 expr
->ctype
= &llong_ctype
;
64 struct expression
*member_expression(struct expression
*deref
, int op
, struct ident
*member
)
66 struct expression
*expr
;
68 expr
= alloc_tmp_expression(deref
->pos
, EXPR_DEREF
);
71 expr
->member
= member
;
72 expr
->member_offset
= -1;
76 struct expression
*preop_expression(struct expression
*expr
, int op
)
78 struct expression
*preop
;
80 preop
= alloc_tmp_expression(expr
->pos
, EXPR_PREOP
);
86 struct expression
*deref_expression(struct expression
*expr
)
88 if (expr
->type
== EXPR_BINOP
)
89 expr
= preop_expression(expr
, '(');
90 return preop_expression(expr
, '*');
93 struct expression
*assign_expression(struct expression
*left
, int op
, struct expression
*right
)
95 struct expression
*expr
;
100 /* FIXME: make this a tmp expression. */
101 expr
= alloc_expression(right
->pos
, EXPR_ASSIGNMENT
);
108 struct expression
*binop_expression(struct expression
*left
, int op
, struct expression
*right
)
110 struct expression
*expr
;
112 expr
= alloc_tmp_expression(right
->pos
, EXPR_BINOP
);
119 struct expression
*array_element_expression(struct expression
*array
, struct expression
*offset
)
121 struct expression
*expr
;
123 expr
= binop_expression(array
, '+', offset
);
124 return deref_expression(expr
);
127 struct expression
*symbol_expression(struct symbol
*sym
)
129 struct expression
*expr
;
131 expr
= alloc_tmp_expression(sym
->pos
, EXPR_SYMBOL
);
133 expr
->symbol_name
= sym
->ident
;
137 struct expression
*compare_expression(struct expression
*left
, int op
, struct expression
*right
)
139 struct expression
*expr
;
141 expr
= alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE
);
148 struct expression
*gen_string_expression(char *str
)
150 struct expression
*ret
;
151 struct string
*string
;
154 len
= strlen(str
) + 1;
155 string
= (void *)__alloc_sname(4 + len
);
156 string
->length
= len
;
157 string
->immutable
= 0;
158 memcpy(string
->data
, str
, len
);
160 ret
= alloc_tmp_expression(get_cur_pos(), EXPR_STRING
);
162 ret
->string
= string
;
167 struct expression
*call_expression(struct expression
*fn
, struct expression_list
*args
)
169 struct expression
*expr
;
171 expr
= alloc_tmp_expression(fn
->pos
, EXPR_CALL
);
178 static struct expression
*get_expression_from_base_and_str(struct expression
*base
, const char *addition
)
180 struct expression
*ret
= NULL
;
181 struct token
*token
, *prev
, *end
;
184 if (addition
[0] == '\0')
187 alloc
= alloc_string_newline(addition
);
189 token
= tokenize_buffer(alloc
, strlen(alloc
), &end
);
192 if (token_type(token
) != TOKEN_STREAMBEGIN
)
197 while (token_type(token
) == TOKEN_SPECIAL
&&
198 (token
->special
== SPECIAL_DEREFERENCE
|| token
->special
== '.')) {
201 if (token_type(token
) != TOKEN_IDENT
)
203 switch (prev
->special
) {
204 case SPECIAL_DEREFERENCE
:
205 ret
= deref_expression(ret
);
206 ret
= member_expression(ret
, '*', token
->ident
);
209 ret
= member_expression(ret
, '.', token
->ident
);
217 if (token_type(token
) != TOKEN_STREAMEND
)
226 struct expression
*gen_expression_from_name_sym(const char *name
, struct symbol
*sym
)
228 struct expression
*base
;
230 struct expression
*ret
;
235 base
= symbol_expression(sym
);
236 while (name
[skip
] != '\0' && name
[skip
] != '.' && name
[skip
] != '-')
239 ret
= get_expression_from_base_and_str(base
, name
+ skip
);
241 char *new = expr_to_str(ret
);
244 * FIXME: this sometimes changes "foo->bar.a.b->c" into
245 * "foo->bar.a.b.c". I don't know why... :(
248 if (!new || strcmp(name
, new) != 0)
254 struct expression
*gen_expression_from_key(struct expression
*arg
, const char *key
)
256 struct expression
*ret
;
257 struct token
*token
, *prev
, *end
;
263 /* The idea is that we can parse either $0->foo or $->foo */
267 while (*p
>= '0' && *p
<= '9')
269 len
= snprintf(buf
, sizeof(buf
), "%s\n", p
);
270 alloc
= alloc_string(buf
);
272 token
= tokenize_buffer(alloc
, len
, &end
);
275 if (token_type(token
) != TOKEN_STREAMBEGIN
)
280 while (token_type(token
) == TOKEN_SPECIAL
&&
281 (token
->special
== SPECIAL_DEREFERENCE
|| token
->special
== '.')) {
284 if (token_type(token
) != TOKEN_IDENT
)
286 ret
= deref_expression(ret
);
287 ret
= member_expression(ret
,
288 (prev
->special
== SPECIAL_DEREFERENCE
) ? '*' : '.',
293 if (token_type(token
) != TOKEN_STREAMEND
)
299 struct expression
*fake_variable(struct symbol
*type
, const char *name
)
301 struct symbol
*sym
, *node
;
302 struct expression
*ret
;
308 ident
= alloc_ident(name
, strlen(name
));
310 sym
= alloc_symbol(get_cur_pos(), type
->type
);
312 sym
->ctype
.base_type
= type
;
313 sym
->ctype
.modifiers
|= MOD_AUTO
;
315 node
= alloc_symbol(get_cur_pos(), SYM_NODE
);
317 node
->ctype
.base_type
= type
;
318 node
->ctype
.modifiers
|= MOD_AUTO
;
320 ret
= symbol_expression(node
);
321 ret
->smatch_flags
|= Fake
;
326 void expr_set_parent_expr(struct expression
*expr
, struct expression
*parent
)
330 if (parent
&& parent
->smatch_flags
& Tmp
)
333 expr
->parent
= (unsigned long)parent
| 0x1UL
;
336 void expr_set_parent_stmt(struct expression
*expr
, struct statement
*parent
)
340 expr
->parent
= (unsigned long)parent
;
343 struct expression
*expr_get_parent_expr(struct expression
*expr
)
345 struct expression
*parent
;
349 if (!(expr
->parent
& 0x1UL
))
352 parent
= (struct expression
*)(expr
->parent
& ~0x1UL
);
353 if (parent
&& (parent
->smatch_flags
& Fake
))
354 return expr_get_parent_expr(parent
);
358 struct expression
*expr_get_fake_parent_expr(struct expression
*expr
)
360 struct expression
*parent
;
364 if (!(expr
->parent
& 0x1UL
))
367 parent
= (struct expression
*)(expr
->parent
& ~0x1UL
);
368 if (parent
&& (parent
->smatch_flags
& Fake
))
373 struct statement
*expr_get_parent_stmt(struct expression
*expr
)
377 if (expr
->parent
& 0x1UL
)
379 return (struct statement
*)expr
->parent
;