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, *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) {
 193                 token = token->next;
 194                 if (token_type(token) != TOKEN_IDENT)
 195                         return NULL;
 196                 ret = deref_expression(ret);
 197                 ret = member_expression(ret, '*', token->ident);
 198                 token = token->next;
 199         }
 200 
 201         if (token_type(token) != TOKEN_STREAMEND)
 202                 return NULL;
 203 
 204         return ret;
 205 }
 206 
 207 void expr_set_parent_expr(struct expression *expr, struct expression *parent)
 208 {
 209         if (!expr)
 210                 return;
 211         if (parent->smatch_flags & Fake)
 212                 return;
 213 
 214         expr->parent = (unsigned long)parent | 0x1UL;
 215 }
 216 
 217 void expr_set_parent_stmt(struct expression *expr, struct statement *parent)
 218 {
 219         if (!expr)
 220                 return;
 221         expr->parent = (unsigned long)parent;
 222 }
 223 
 224 struct expression *expr_get_parent_expr(struct expression *expr)
 225 {
 226         if (!expr)
 227                 return NULL;
 228         if (!(expr->parent & 0x1UL))
 229                 return NULL;
 230         return (struct expression *)(expr->parent & ~0x1UL);
 231 }
 232 
 233 struct statement *expr_get_parent_stmt(struct expression *expr)
 234 {
 235         if (!expr)
 236                 return NULL;
 237         if (expr->parent & 0x1UL)
 238                 return NULL;
 239         return (struct statement *)expr->parent;
 240 }
 241