12166 resync smatch to 0.6.1-rc1-il-3
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 if (expr->type == EXPR_BINOP) 89 expr = preop_expression(expr, '('); 90 return preop_expression(expr, '*'); 91 } 92 93 struct expression *assign_expression(struct expression *left, int op, struct expression *right) 94 { 95 struct expression *expr; 96 97 if (!right) 98 return NULL; 99 100 /* FIXME: make this a tmp expression. */ 101 expr = alloc_expression(right->pos, EXPR_ASSIGNMENT); 102 expr->op = op; 103 expr->left = left; 104 expr->right = right; 105 return expr; 106 } 107 108 struct expression *binop_expression(struct expression *left, int op, struct expression *right) 109 { 110 struct expression *expr; 111 112 expr = alloc_tmp_expression(right->pos, EXPR_BINOP); 113 expr->op = op; 114 expr->left = left; 115 expr->right = right; 116 return expr; 117 } 118 119 struct expression *array_element_expression(struct expression *array, struct expression *offset) 120 { 121 struct expression *expr; 122 123 expr = binop_expression(array, '+', offset); 124 return deref_expression(expr); 125 } 126 127 struct expression *symbol_expression(struct symbol *sym) 128 { 129 struct expression *expr; 130 131 expr = alloc_tmp_expression(sym->pos, EXPR_SYMBOL); 132 expr->symbol = sym; 133 expr->symbol_name = sym->ident; 134 return expr; 135 } 136 137 struct expression *compare_expression(struct expression *left, int op, struct expression *right) 138 { 139 struct expression *expr; 140 141 expr = alloc_tmp_expression(get_cur_pos(), EXPR_COMPARE); 142 expr->op = op; 143 expr->left = left; 144 expr->right = right; 145 return expr; 146 } 147 148 struct expression *string_expression(char *str) 149 { 150 struct expression *ret; 151 struct string *string; 152 int len; 153 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); 159 160 ret = alloc_tmp_expression(get_cur_pos(), EXPR_STRING); 161 ret->wide = 0; 162 ret->string = string; 163 164 return ret; 165 } 166 167 struct expression *call_expression(struct expression *fn, struct expression_list *args) 168 { 169 struct expression *expr; 170 171 expr = alloc_tmp_expression(fn->pos, EXPR_CALL); 172 expr->fn = fn; 173 expr->args = args; 174 175 return expr; 176 } 177 178 static struct expression *get_expression_from_base_and_str(struct expression *base, const char *addition) 179 { 180 struct expression *ret = NULL; 181 struct token *token, *prev, *end; 182 char *alloc; 183 184 if (addition[0] == '\0') 185 return base; 186 187 alloc = alloc_string_newline(addition); 188 189 token = tokenize_buffer(alloc, strlen(alloc), &end); 190 if (!token) 191 goto free; 192 if (token_type(token) != TOKEN_STREAMBEGIN) 193 goto free; 194 token = token->next; 195 196 ret = base; 197 while (token_type(token) == TOKEN_SPECIAL && 198 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) { 199 prev = token; 200 token = token->next; 201 if (token_type(token) != TOKEN_IDENT) 202 goto free; 203 switch (prev->special) { 204 case SPECIAL_DEREFERENCE: 205 ret = deref_expression(ret); 206 ret = member_expression(ret, '*', token->ident); 207 break; 208 case '.': 209 ret = member_expression(ret, '.', token->ident); 210 break; 211 default: 212 goto free; 213 } 214 token = token->next; 215 } 216 217 if (token_type(token) != TOKEN_STREAMEND) 218 goto free; 219 220 free: 221 free_string(alloc); 222 223 return ret; 224 } 225 226 struct expression *gen_expression_from_name_sym(const char *name, struct symbol *sym) 227 { 228 struct expression *base; 229 int skip = 0; 230 struct expression *ret; 231 232 if (!name || !sym) 233 return NULL; 234 235 base = symbol_expression(sym); 236 while (name[skip] != '\0' && name[skip] != '.' && name[skip] != '-') 237 skip++; 238 239 ret = get_expression_from_base_and_str(base, name + skip); 240 if (ret) { 241 char *new = expr_to_str(ret); 242 243 /* 244 * FIXME: this sometimes changes "foo->bar.a.b->c" into 245 * "foo->bar.a.b.c". I don't know why... :( 246 * 247 */ 248 if (!new || strcmp(name, new) != 0) 249 return NULL; 250 } 251 return ret; 252 } 253 254 struct expression *gen_expression_from_key(struct expression *arg, const char *key) 255 { 256 struct expression *ret; 257 struct token *token, *prev, *end; 258 const char *p = key; 259 char buf[4095]; 260 char *alloc; 261 size_t len; 262 263 /* The idea is that we can parse either $0->foo or $->foo */ 264 if (key[0] != '$') 265 return NULL; 266 p++; 267 while (*p >= '0' && *p <= '9') 268 p++; 269 len = snprintf(buf, sizeof(buf), "%s\n", p); 270 alloc = alloc_string(buf); 271 272 token = tokenize_buffer(alloc, len, &end); 273 if (!token) 274 return NULL; 275 if (token_type(token) != TOKEN_STREAMBEGIN) 276 return NULL; 277 token = token->next; 278 279 ret = arg; 280 while (token_type(token) == TOKEN_SPECIAL && 281 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) { 282 prev = token; 283 token = token->next; 284 if (token_type(token) != TOKEN_IDENT) 285 return NULL; 286 ret = deref_expression(ret); 287 ret = member_expression(ret, 288 (prev->special == SPECIAL_DEREFERENCE) ? '*' : '.', 289 token->ident); 290 token = token->next; 291 } 292 293 if (token_type(token) != TOKEN_STREAMEND) 294 return NULL; 295 296 return ret; 297 } 298 299 void expr_set_parent_expr(struct expression *expr, struct expression *parent) 300 { 301 if (!expr) 302 return; 303 if (parent->smatch_flags & Fake) 304 return; 305 306 expr->parent = (unsigned long)parent | 0x1UL; 307 } 308 309 void expr_set_parent_stmt(struct expression *expr, struct statement *parent) 310 { 311 if (!expr) 312 return; 313 expr->parent = (unsigned long)parent; 314 } 315 316 struct expression *expr_get_parent_expr(struct expression *expr) 317 { 318 if (!expr) 319 return NULL; 320 if (!(expr->parent & 0x1UL)) 321 return NULL; 322 return (struct expression *)(expr->parent & ~0x1UL); 323 } 324 325 struct statement *expr_get_parent_stmt(struct expression *expr) 326 { 327 if (!expr) 328 return NULL; 329 if (expr->parent & 0x1UL) 330 return NULL; 331 return (struct statement *)expr->parent; 332 } 333 --- EOF ---