1 #include "smatch.h" 2 #include "smatch_extra.h" 3 4 DECLARE_ALLOCATOR(sname); 5 __ALLOCATOR(struct expression, "temporary expr", tmp_expression); 6 7 static struct position get_cur_pos(void) 8 { 9 static struct position pos; 10 static struct position none; 11 struct expression *expr; 12 struct statement *stmt; 13 14 expr = last_ptr_list((struct ptr_list *)big_expression_stack); 15 stmt = last_ptr_list((struct ptr_list *)big_statement_stack); 16 if (expr) 17 pos = expr->pos; 18 else if (stmt) 19 pos = stmt->pos; 20 else 21 pos = none; 22 return pos; 23 } 24 25 struct expression *alloc_tmp_expression(struct position pos, int type) 26 { 27 struct expression *expr; 28 29 expr = __alloc_tmp_expression(0); 30 expr->smatch_flags |= Fake; 31 expr->type = type; 32 expr->pos = pos; 33 return expr; 34 } 35 36 void free_tmp_expressions(void) 37 { 38 clear_tmp_expression_alloc(); 39 } 40 41 struct expression *zero_expr(void) 42 { 43 struct expression *zero; 44 45 zero = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE); 46 zero->value = 0; 47 zero->ctype = &int_ctype; 48 return zero; 49 } 50 51 struct expression *value_expr(long long val) 52 { 53 struct expression *expr; 54 55 if (!val) 56 return zero_expr(); 57 58 expr = alloc_tmp_expression(get_cur_pos(), EXPR_VALUE); 59 expr->value = val; 60 expr->ctype = &llong_ctype; 61 return expr; 62 } 63 64 struct expression *member_expression(struct expression *deref, int op, struct ident *member) 65 { 66 struct expression *expr; 67 68 expr = alloc_tmp_expression(deref->pos, EXPR_DEREF); 69 expr->op = op; 70 expr->deref = deref; 71 expr->member = member; 72 expr->member_offset = -1; 73 return expr; 74 } 75 76 struct expression *preop_expression(struct expression *expr, int op) 77 { 78 struct expression *preop; 79 80 preop = alloc_tmp_expression(expr->pos, EXPR_PREOP); 81 preop->unop = expr; 82 preop->op = op; 83 return preop; 84 } 85 86 struct expression *deref_expression(struct expression *expr) 87 { 88 return preop_expression(expr, '*'); 89 } 90 91 struct expression *assign_expression(struct expression *left, int op, struct expression *right) 92 { 93 struct expression *expr; 94 95 if (!right) 96 return NULL; 97 98 /* FIXME: make this a tmp expression. */ 99 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT); 100 expr->op = op; 101 expr->left = left; 102 expr->right = right; 103 return expr; 104 } 105 106 struct expression *binop_expression(struct expression *left, int op, struct expression *right) 107 { 108 struct expression *expr; 109 110 expr = alloc_tmp_expression(right->pos, EXPR_BINOP); 111 expr->op = op; 112 expr->left = left; 113 expr->right = right; 114 return expr; 115 } 116 117 struct expression *array_element_expression(struct expression *array, struct expression *offset) 118 { 119 struct expression *expr; 120 121 expr = binop_expression(array, '+', offset); 122 return deref_expression(expr); 123 } 124 125 struct expression *symbol_expression(struct symbol *sym) 126 { 127 struct expression *expr; 128 129 expr = alloc_tmp_expression(sym->pos, EXPR_SYMBOL); 130 expr->symbol = sym; 131 expr->symbol_name = sym->ident; 132 return expr; 133 } 134 135 struct expression *compare_expression(struct expression *left, int op, struct expression *right) 136 { 137 struct expression *expr; 138 139 expr = alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE); 140 expr->op = op; 141 expr->left = left; 142 expr->right = right; 143 return expr; 144 } 145 146 struct expression *string_expression(char *str) 147 { 148 struct expression *ret; 149 struct string *string; 150 int len; 151 152 len = strlen(str) + 1; 153 string = (void *)__alloc_sname(4 + len); 154 string->length = len; 155 string->immutable = 0; 156 memcpy(string->data, str, len); 157 158 ret = alloc_tmp_expression(get_cur_pos(), EXPR_STRING); 159 ret->wide = 0; 160 ret->string = string; 161 162 return ret; 163 } 164 165 struct expression *gen_expression_from_key(struct expression *arg, const char *key) 166 { 167 struct expression *ret; 168 struct token *token, *prev, *end; 169 const char *p = key; 170 char buf[4095]; 171 char *alloc; 172 size_t len; 173 174 /* The idea is that we can parse either $0->foo or $->foo */ 175 if (key[0] != '$') 176 return NULL; 177 p++; 178 while (*p >= '0' && *p <= '9') 179 p++; 180 len = snprintf(buf, sizeof(buf), "%s\n", p); 181 alloc = alloc_string(buf); 182 183 token = tokenize_buffer(alloc, len, &end); 184 if (!token) 185 return NULL; 186 if (token_type(token) != TOKEN_STREAMBEGIN) 187 return NULL; 188 token = token->next; 189 190 ret = arg; 191 while (token_type(token) == TOKEN_SPECIAL && 192 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) { 193 prev = token; 194 token = token->next; 195 if (token_type(token) != TOKEN_IDENT) 196 return NULL; 197 ret = deref_expression(ret); 198 ret = member_expression(ret, 199 (prev->special == SPECIAL_DEREFERENCE) ? '*' : '.', 200 token->ident); 201 token = token->next; 202 } 203 204 if (token_type(token) != TOKEN_STREAMEND) 205 return NULL; 206 207 return ret; 208 } 209 210 void expr_set_parent_expr(struct expression *expr, struct expression *parent) 211 { 212 if (!expr) 213 return; 214 if (parent->smatch_flags & Fake) 215 return; 216 217 expr->parent = (unsigned long)parent | 0x1UL; 218 } 219 220 void expr_set_parent_stmt(struct expression *expr, struct statement *parent) 221 { 222 if (!expr) 223 return; 224 expr->parent = (unsigned long)parent; 225 } 226 227 struct expression *expr_get_parent_expr(struct expression *expr) 228 { 229 if (!expr) 230 return NULL; 231 if (!(expr->parent & 0x1UL)) 232 return NULL; 233 return (struct expression *)(expr->parent & ~0x1UL); 234 } 235 236 struct statement *expr_get_parent_stmt(struct expression *expr) 237 { 238 if (!expr) 239 return NULL; 240 if (expr->parent & 0x1UL) 241 return NULL; 242 return (struct statement *)expr->parent; 243 } 244