implied: use a time based timeout instead of counting ->nr_children
[smatch.git] / smatch_expressions.c
blob05c8564c1eebd4c0d43bca2b03ab3076e48bdd19
1 #include "smatch.h"
3 static struct position get_cur_pos(void)
5 static struct position pos;
6 static struct position none;
7 struct expression *expr;
8 struct statement *stmt;
10 expr = last_ptr_list((struct ptr_list *)big_expression_stack);
11 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
12 if (expr)
13 pos = expr->pos;
14 else if (stmt)
15 pos = stmt->pos;
16 else
17 pos = none;
18 return pos;
21 struct expression *zero_expr(void)
23 static struct expression *zero;
25 if (zero)
26 return zero;
28 zero = alloc_expression(get_cur_pos(), EXPR_VALUE);
29 zero->value = 0;
30 zero->ctype = &char_ctype;
31 return zero;
34 struct expression *value_expr(long long val)
36 struct expression *expr;
38 if (!val)
39 return zero_expr();
41 expr = alloc_expression(get_cur_pos(), EXPR_VALUE);
42 expr->value = val;
43 expr->ctype = &llong_ctype;
44 return expr;
47 struct expression *member_expression(struct expression *deref, int op, struct ident *member)
49 struct expression *expr;
51 expr = alloc_expression(deref->pos, EXPR_DEREF);
52 expr->op = op;
53 expr->deref = deref;
54 expr->member = member;
55 expr->member_offset = -1;
56 return expr;
59 struct expression *deref_expression(struct expression *expr)
61 struct expression *preop;
63 preop = alloc_expression(expr->pos, EXPR_PREOP);
64 preop->unop = expr;
65 preop->op = '*';
66 return preop;
69 struct expression *assign_expression(struct expression *left, struct expression *right)
71 struct expression *expr;
73 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT);
74 expr->op = '=';
75 expr->left = left;
76 expr->right = right;
77 return expr;
80 struct expression *binop_expression(struct expression *left, int op, struct expression *right)
82 struct expression *expr;
84 expr = alloc_expression(right->pos, EXPR_BINOP);
85 expr->op = op;
86 expr->left = left;
87 expr->right = right;
88 return expr;
91 struct expression *array_element_expression(struct expression *array, struct expression *offset)
93 struct expression *expr;
95 expr = binop_expression(array, '+', offset);
96 return deref_expression(expr);
99 struct expression *symbol_expression(struct symbol *sym)
101 struct expression *expr;
103 expr = alloc_expression(sym->pos, EXPR_SYMBOL);
104 expr->symbol = sym;
105 expr->symbol_name = sym->ident;
106 return expr;
109 struct expression *compare_expression(struct expression *left, int op, struct expression *right)
111 struct expression *expr;
113 expr = alloc_expression(get_cur_pos(), EXPR_COMPARE);
114 expr->op = op;
115 expr->left = left;
116 expr->right = right;
117 return expr;
120 struct expression *gen_expression_from_key(struct expression *arg, const char *key)
122 struct expression *ret = NULL;
123 struct token *token, *end;
124 const char *p = key;
125 char buf[4095];
126 char *alloc;
127 size_t len;
129 /* The idea is that we can parse either $0->foo or $->foo */
130 if (key[0] != '$')
131 goto free;
132 p++;
133 while (*p >= '0' && *p <= '9')
134 p++;
135 len = snprintf(buf, sizeof(buf), "%s\n", p);
136 alloc = alloc_string(buf);
138 token = tokenize_buffer(alloc, len, &end);
139 if (!token)
140 goto free;
141 if (token_type(token) != TOKEN_STREAMBEGIN)
142 goto free;
143 token = token->next;
145 ret = arg;
146 while (token_type(token) == TOKEN_SPECIAL &&
147 token->special == SPECIAL_DEREFERENCE) {
148 token = token->next;
149 if (token_type(token) != TOKEN_IDENT) {
150 ret = NULL;
151 goto free;
153 ret = deref_expression(ret);
154 ret = member_expression(ret, '*', token->ident);
155 token = token->next;
158 if (token_type(token) != TOKEN_STREAMEND)
159 ret = NULL;
161 free:
162 return ret;