1*1f5207b7SJohn Levon /* 2*1f5207b7SJohn Levon * Copyright (C) 2006 Dan Carpenter. 3*1f5207b7SJohn Levon * 4*1f5207b7SJohn Levon * This program is free software; you can redistribute it and/or 5*1f5207b7SJohn Levon * modify it under the terms of the GNU General Public License 6*1f5207b7SJohn Levon * as published by the Free Software Foundation; either version 2 7*1f5207b7SJohn Levon * of the License, or (at your option) any later version. 8*1f5207b7SJohn Levon * 9*1f5207b7SJohn Levon * This program is distributed in the hope that it will be useful, 10*1f5207b7SJohn Levon * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*1f5207b7SJohn Levon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*1f5207b7SJohn Levon * GNU General Public License for more details. 13*1f5207b7SJohn Levon * 14*1f5207b7SJohn Levon * You should have received a copy of the GNU General Public License 15*1f5207b7SJohn Levon * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt 16*1f5207b7SJohn Levon */ 17*1f5207b7SJohn Levon 18*1f5207b7SJohn Levon /* 19*1f5207b7SJohn Levon * Miscellaneous helper functions. 20*1f5207b7SJohn Levon */ 21*1f5207b7SJohn Levon 22*1f5207b7SJohn Levon #include <stdlib.h> 23*1f5207b7SJohn Levon #include <stdio.h> 24*1f5207b7SJohn Levon #include "allocate.h" 25*1f5207b7SJohn Levon #include "smatch.h" 26*1f5207b7SJohn Levon #include "smatch_extra.h" 27*1f5207b7SJohn Levon #include "smatch_slist.h" 28*1f5207b7SJohn Levon 29*1f5207b7SJohn Levon #define VAR_LEN 512 30*1f5207b7SJohn Levon 31*1f5207b7SJohn Levon char *alloc_string(const char *str) 32*1f5207b7SJohn Levon { 33*1f5207b7SJohn Levon char *tmp; 34*1f5207b7SJohn Levon 35*1f5207b7SJohn Levon if (!str) 36*1f5207b7SJohn Levon return NULL; 37*1f5207b7SJohn Levon tmp = malloc(strlen(str) + 1); 38*1f5207b7SJohn Levon strcpy(tmp, str); 39*1f5207b7SJohn Levon return tmp; 40*1f5207b7SJohn Levon } 41*1f5207b7SJohn Levon 42*1f5207b7SJohn Levon void free_string(char *str) 43*1f5207b7SJohn Levon { 44*1f5207b7SJohn Levon free(str); 45*1f5207b7SJohn Levon } 46*1f5207b7SJohn Levon 47*1f5207b7SJohn Levon void remove_parens(char *str) 48*1f5207b7SJohn Levon { 49*1f5207b7SJohn Levon char *src, *dst; 50*1f5207b7SJohn Levon 51*1f5207b7SJohn Levon dst = src = str; 52*1f5207b7SJohn Levon while (*src != '\0') { 53*1f5207b7SJohn Levon if (*src == '(' || *src == ')') { 54*1f5207b7SJohn Levon src++; 55*1f5207b7SJohn Levon continue; 56*1f5207b7SJohn Levon } 57*1f5207b7SJohn Levon *dst++ = *src++; 58*1f5207b7SJohn Levon } 59*1f5207b7SJohn Levon *dst = *src; 60*1f5207b7SJohn Levon } 61*1f5207b7SJohn Levon 62*1f5207b7SJohn Levon struct smatch_state *alloc_state_num(int num) 63*1f5207b7SJohn Levon { 64*1f5207b7SJohn Levon struct smatch_state *state; 65*1f5207b7SJohn Levon static char buff[256]; 66*1f5207b7SJohn Levon 67*1f5207b7SJohn Levon state = __alloc_smatch_state(0); 68*1f5207b7SJohn Levon snprintf(buff, 255, "%d", num); 69*1f5207b7SJohn Levon buff[255] = '\0'; 70*1f5207b7SJohn Levon state->name = alloc_string(buff); 71*1f5207b7SJohn Levon state->data = INT_PTR(num); 72*1f5207b7SJohn Levon return state; 73*1f5207b7SJohn Levon } 74*1f5207b7SJohn Levon 75*1f5207b7SJohn Levon struct smatch_state *alloc_state_str(const char *name) 76*1f5207b7SJohn Levon { 77*1f5207b7SJohn Levon struct smatch_state *state; 78*1f5207b7SJohn Levon 79*1f5207b7SJohn Levon state = __alloc_smatch_state(0); 80*1f5207b7SJohn Levon state->name = alloc_string(name); 81*1f5207b7SJohn Levon return state; 82*1f5207b7SJohn Levon } 83*1f5207b7SJohn Levon 84*1f5207b7SJohn Levon struct smatch_state *alloc_state_expr(struct expression *expr) 85*1f5207b7SJohn Levon { 86*1f5207b7SJohn Levon struct smatch_state *state; 87*1f5207b7SJohn Levon char *name; 88*1f5207b7SJohn Levon 89*1f5207b7SJohn Levon state = __alloc_smatch_state(0); 90*1f5207b7SJohn Levon expr = strip_expr(expr); 91*1f5207b7SJohn Levon name = expr_to_str(expr); 92*1f5207b7SJohn Levon state->name = alloc_sname(name); 93*1f5207b7SJohn Levon free_string(name); 94*1f5207b7SJohn Levon state->data = expr; 95*1f5207b7SJohn Levon return state; 96*1f5207b7SJohn Levon } 97*1f5207b7SJohn Levon 98*1f5207b7SJohn Levon void append(char *dest, const char *data, int buff_len) 99*1f5207b7SJohn Levon { 100*1f5207b7SJohn Levon strncat(dest, data, buff_len - strlen(dest) - 1); 101*1f5207b7SJohn Levon } 102*1f5207b7SJohn Levon 103*1f5207b7SJohn Levon /* 104*1f5207b7SJohn Levon * If you have "foo(a, b, 1);" then use 105*1f5207b7SJohn Levon * get_argument_from_call_expr(expr, 0) to return the expression for 106*1f5207b7SJohn Levon * a. Yes, it does start counting from 0. 107*1f5207b7SJohn Levon */ 108*1f5207b7SJohn Levon struct expression *get_argument_from_call_expr(struct expression_list *args, 109*1f5207b7SJohn Levon int num) 110*1f5207b7SJohn Levon { 111*1f5207b7SJohn Levon struct expression *expr; 112*1f5207b7SJohn Levon int i = 0; 113*1f5207b7SJohn Levon 114*1f5207b7SJohn Levon if (!args) 115*1f5207b7SJohn Levon return NULL; 116*1f5207b7SJohn Levon 117*1f5207b7SJohn Levon FOR_EACH_PTR(args, expr) { 118*1f5207b7SJohn Levon if (i == num) 119*1f5207b7SJohn Levon return expr; 120*1f5207b7SJohn Levon i++; 121*1f5207b7SJohn Levon } END_FOR_EACH_PTR(expr); 122*1f5207b7SJohn Levon return NULL; 123*1f5207b7SJohn Levon } 124*1f5207b7SJohn Levon 125*1f5207b7SJohn Levon static struct expression *get_array_expr(struct expression *expr) 126*1f5207b7SJohn Levon { 127*1f5207b7SJohn Levon struct expression *parent; 128*1f5207b7SJohn Levon struct symbol *type; 129*1f5207b7SJohn Levon 130*1f5207b7SJohn Levon if (expr->type != EXPR_BINOP || expr->op != '+') 131*1f5207b7SJohn Levon return NULL; 132*1f5207b7SJohn Levon 133*1f5207b7SJohn Levon type = get_type(expr->left); 134*1f5207b7SJohn Levon if (!type) 135*1f5207b7SJohn Levon return NULL; 136*1f5207b7SJohn Levon if (type->type == SYM_ARRAY) 137*1f5207b7SJohn Levon return expr->left; 138*1f5207b7SJohn Levon if (type->type != SYM_PTR) 139*1f5207b7SJohn Levon return NULL; 140*1f5207b7SJohn Levon 141*1f5207b7SJohn Levon parent = expr_get_parent_expr(expr); 142*1f5207b7SJohn Levon if (!parent) /* Sometimes we haven't set up the ->parent yet. FIXME!! */ 143*1f5207b7SJohn Levon return expr->left; 144*1f5207b7SJohn Levon if (parent->type == EXPR_PREOP && parent->op == '*') 145*1f5207b7SJohn Levon return expr->left; 146*1f5207b7SJohn Levon 147*1f5207b7SJohn Levon return NULL; 148*1f5207b7SJohn Levon } 149*1f5207b7SJohn Levon 150*1f5207b7SJohn Levon static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, 151*1f5207b7SJohn Levon struct expression *expr, int len, 152*1f5207b7SJohn Levon int *complicated, int no_parens) 153*1f5207b7SJohn Levon { 154*1f5207b7SJohn Levon 155*1f5207b7SJohn Levon 156*1f5207b7SJohn Levon if (!expr) { 157*1f5207b7SJohn Levon /* can't happen on valid code */ 158*1f5207b7SJohn Levon *complicated = 1; 159*1f5207b7SJohn Levon return; 160*1f5207b7SJohn Levon } 161*1f5207b7SJohn Levon 162*1f5207b7SJohn Levon switch (expr->type) { 163*1f5207b7SJohn Levon case EXPR_DEREF: { 164*1f5207b7SJohn Levon struct expression *deref; 165*1f5207b7SJohn Levon int op; 166*1f5207b7SJohn Levon 167*1f5207b7SJohn Levon deref = expr->deref; 168*1f5207b7SJohn Levon op = deref->op; 169*1f5207b7SJohn Levon if (op == '*') { 170*1f5207b7SJohn Levon struct expression *unop = strip_expr(deref->unop); 171*1f5207b7SJohn Levon 172*1f5207b7SJohn Levon if (unop->type == EXPR_PREOP && unop->op == '&') { 173*1f5207b7SJohn Levon deref = unop->unop; 174*1f5207b7SJohn Levon op = '.'; 175*1f5207b7SJohn Levon } else { 176*1f5207b7SJohn Levon deref = deref->unop; 177*1f5207b7SJohn Levon if (!is_pointer(deref)) 178*1f5207b7SJohn Levon op = '.'; 179*1f5207b7SJohn Levon } 180*1f5207b7SJohn Levon } 181*1f5207b7SJohn Levon 182*1f5207b7SJohn Levon __get_variable_from_expr(sym_ptr, buf, deref, len, complicated, no_parens); 183*1f5207b7SJohn Levon 184*1f5207b7SJohn Levon if (op == '*') 185*1f5207b7SJohn Levon append(buf, "->", len); 186*1f5207b7SJohn Levon else 187*1f5207b7SJohn Levon append(buf, ".", len); 188*1f5207b7SJohn Levon 189*1f5207b7SJohn Levon if (expr->member) 190*1f5207b7SJohn Levon append(buf, expr->member->name, len); 191*1f5207b7SJohn Levon else 192*1f5207b7SJohn Levon append(buf, "unknown_member", len); 193*1f5207b7SJohn Levon 194*1f5207b7SJohn Levon return; 195*1f5207b7SJohn Levon } 196*1f5207b7SJohn Levon case EXPR_SYMBOL: 197*1f5207b7SJohn Levon if (expr->symbol_name) 198*1f5207b7SJohn Levon append(buf, expr->symbol_name->name, len); 199*1f5207b7SJohn Levon if (sym_ptr) { 200*1f5207b7SJohn Levon if (*sym_ptr) 201*1f5207b7SJohn Levon *complicated = 1; 202*1f5207b7SJohn Levon *sym_ptr = expr->symbol; 203*1f5207b7SJohn Levon } 204*1f5207b7SJohn Levon return; 205*1f5207b7SJohn Levon case EXPR_PREOP: { 206*1f5207b7SJohn Levon const char *tmp; 207*1f5207b7SJohn Levon 208*1f5207b7SJohn Levon if (get_expression_statement(expr)) { 209*1f5207b7SJohn Levon *complicated = 2; 210*1f5207b7SJohn Levon return; 211*1f5207b7SJohn Levon } 212*1f5207b7SJohn Levon 213*1f5207b7SJohn Levon if (expr->op == '(') { 214*1f5207b7SJohn Levon if (!no_parens && expr->unop->type != EXPR_SYMBOL) 215*1f5207b7SJohn Levon append(buf, "(", len); 216*1f5207b7SJohn Levon } else if (expr->op != '*' || !get_array_expr(expr->unop)) { 217*1f5207b7SJohn Levon tmp = show_special(expr->op); 218*1f5207b7SJohn Levon append(buf, tmp, len); 219*1f5207b7SJohn Levon } 220*1f5207b7SJohn Levon __get_variable_from_expr(sym_ptr, buf, expr->unop, 221*1f5207b7SJohn Levon len, complicated, no_parens); 222*1f5207b7SJohn Levon 223*1f5207b7SJohn Levon if (expr->op == '(' && !no_parens && expr->unop->type != EXPR_SYMBOL) 224*1f5207b7SJohn Levon append(buf, ")", len); 225*1f5207b7SJohn Levon 226*1f5207b7SJohn Levon if (expr->op == SPECIAL_DECREMENT || 227*1f5207b7SJohn Levon expr->op == SPECIAL_INCREMENT) 228*1f5207b7SJohn Levon *complicated = 1; 229*1f5207b7SJohn Levon 230*1f5207b7SJohn Levon return; 231*1f5207b7SJohn Levon } 232*1f5207b7SJohn Levon case EXPR_POSTOP: { 233*1f5207b7SJohn Levon const char *tmp; 234*1f5207b7SJohn Levon 235*1f5207b7SJohn Levon __get_variable_from_expr(sym_ptr, buf, expr->unop, 236*1f5207b7SJohn Levon len, complicated, no_parens); 237*1f5207b7SJohn Levon tmp = show_special(expr->op); 238*1f5207b7SJohn Levon append(buf, tmp, len); 239*1f5207b7SJohn Levon 240*1f5207b7SJohn Levon if (expr->op == SPECIAL_DECREMENT || expr->op == SPECIAL_INCREMENT) 241*1f5207b7SJohn Levon *complicated = 1; 242*1f5207b7SJohn Levon return; 243*1f5207b7SJohn Levon } 244*1f5207b7SJohn Levon case EXPR_ASSIGNMENT: 245*1f5207b7SJohn Levon case EXPR_COMPARE: 246*1f5207b7SJohn Levon case EXPR_LOGICAL: 247*1f5207b7SJohn Levon case EXPR_BINOP: { 248*1f5207b7SJohn Levon char tmp[10]; 249*1f5207b7SJohn Levon struct expression *array_expr; 250*1f5207b7SJohn Levon 251*1f5207b7SJohn Levon *complicated = 1; 252*1f5207b7SJohn Levon array_expr = get_array_expr(expr); 253*1f5207b7SJohn Levon if (array_expr) { 254*1f5207b7SJohn Levon __get_variable_from_expr(sym_ptr, buf, array_expr, len, complicated, no_parens); 255*1f5207b7SJohn Levon append(buf, "[", len); 256*1f5207b7SJohn Levon } else { 257*1f5207b7SJohn Levon __get_variable_from_expr(sym_ptr, buf, expr->left, len, complicated, no_parens); 258*1f5207b7SJohn Levon snprintf(tmp, sizeof(tmp), " %s ", show_special(expr->op)); 259*1f5207b7SJohn Levon append(buf, tmp, len); 260*1f5207b7SJohn Levon } 261*1f5207b7SJohn Levon __get_variable_from_expr(NULL, buf, expr->right, len, complicated, no_parens); 262*1f5207b7SJohn Levon if (array_expr) 263*1f5207b7SJohn Levon append(buf, "]", len); 264*1f5207b7SJohn Levon return; 265*1f5207b7SJohn Levon } 266*1f5207b7SJohn Levon case EXPR_VALUE: { 267*1f5207b7SJohn Levon char tmp[25]; 268*1f5207b7SJohn Levon 269*1f5207b7SJohn Levon *complicated = 1; 270*1f5207b7SJohn Levon snprintf(tmp, 25, "%lld", expr->value); 271*1f5207b7SJohn Levon append(buf, tmp, len); 272*1f5207b7SJohn Levon return; 273*1f5207b7SJohn Levon } 274*1f5207b7SJohn Levon case EXPR_STRING: 275*1f5207b7SJohn Levon append(buf, "\"", len); 276*1f5207b7SJohn Levon if (expr->string) 277*1f5207b7SJohn Levon append(buf, expr->string->data, len); 278*1f5207b7SJohn Levon append(buf, "\"", len); 279*1f5207b7SJohn Levon return; 280*1f5207b7SJohn Levon case EXPR_CALL: { 281*1f5207b7SJohn Levon struct expression *tmp; 282*1f5207b7SJohn Levon int i; 283*1f5207b7SJohn Levon 284*1f5207b7SJohn Levon *complicated = 1; 285*1f5207b7SJohn Levon __get_variable_from_expr(NULL, buf, expr->fn, len, complicated, no_parens); 286*1f5207b7SJohn Levon append(buf, "(", len); 287*1f5207b7SJohn Levon i = 0; 288*1f5207b7SJohn Levon FOR_EACH_PTR(expr->args, tmp) { 289*1f5207b7SJohn Levon if (i++) 290*1f5207b7SJohn Levon append(buf, ", ", len); 291*1f5207b7SJohn Levon __get_variable_from_expr(NULL, buf, tmp, len, complicated, no_parens); 292*1f5207b7SJohn Levon } END_FOR_EACH_PTR(tmp); 293*1f5207b7SJohn Levon append(buf, ")", len); 294*1f5207b7SJohn Levon return; 295*1f5207b7SJohn Levon } 296*1f5207b7SJohn Levon case EXPR_CAST: 297*1f5207b7SJohn Levon case EXPR_FORCE_CAST: 298*1f5207b7SJohn Levon __get_variable_from_expr(sym_ptr, buf, 299*1f5207b7SJohn Levon expr->cast_expression, len, 300*1f5207b7SJohn Levon complicated, no_parens); 301*1f5207b7SJohn Levon return; 302*1f5207b7SJohn Levon case EXPR_SIZEOF: { 303*1f5207b7SJohn Levon sval_t sval; 304*1f5207b7SJohn Levon int size; 305*1f5207b7SJohn Levon char tmp[25]; 306*1f5207b7SJohn Levon 307*1f5207b7SJohn Levon if (expr->cast_type && get_base_type(expr->cast_type)) { 308*1f5207b7SJohn Levon size = type_bytes(get_base_type(expr->cast_type)); 309*1f5207b7SJohn Levon snprintf(tmp, 25, "%d", size); 310*1f5207b7SJohn Levon append(buf, tmp, len); 311*1f5207b7SJohn Levon } else if (get_value(expr, &sval)) { 312*1f5207b7SJohn Levon snprintf(tmp, 25, "%s", sval_to_str(sval)); 313*1f5207b7SJohn Levon append(buf, tmp, len); 314*1f5207b7SJohn Levon } 315*1f5207b7SJohn Levon return; 316*1f5207b7SJohn Levon } 317*1f5207b7SJohn Levon case EXPR_IDENTIFIER: 318*1f5207b7SJohn Levon *complicated = 1; 319*1f5207b7SJohn Levon if (expr->expr_ident) 320*1f5207b7SJohn Levon append(buf, expr->expr_ident->name, len); 321*1f5207b7SJohn Levon return; 322*1f5207b7SJohn Levon default: 323*1f5207b7SJohn Levon *complicated = 1; 324*1f5207b7SJohn Levon //printf("unknown type = %d\n", expr->type); 325*1f5207b7SJohn Levon return; 326*1f5207b7SJohn Levon } 327*1f5207b7SJohn Levon } 328*1f5207b7SJohn Levon 329*1f5207b7SJohn Levon struct expr_str_cache_results { 330*1f5207b7SJohn Levon struct expression *expr; 331*1f5207b7SJohn Levon int no_parens; 332*1f5207b7SJohn Levon char str[VAR_LEN]; 333*1f5207b7SJohn Levon struct symbol *sym; 334*1f5207b7SJohn Levon int complicated; 335*1f5207b7SJohn Levon }; 336*1f5207b7SJohn Levon 337*1f5207b7SJohn Levon static void get_variable_from_expr(struct symbol **sym_ptr, char *buf, 338*1f5207b7SJohn Levon struct expression *expr, int len, 339*1f5207b7SJohn Levon int *complicated, int no_parens) 340*1f5207b7SJohn Levon { 341*1f5207b7SJohn Levon static struct expr_str_cache_results cached[8]; 342*1f5207b7SJohn Levon struct symbol *tmp_sym = NULL; 343*1f5207b7SJohn Levon static int idx; 344*1f5207b7SJohn Levon int i; 345*1f5207b7SJohn Levon 346*1f5207b7SJohn Levon for (i = 0; i < ARRAY_SIZE(cached); i++) { 347*1f5207b7SJohn Levon if (expr == cached[i].expr && 348*1f5207b7SJohn Levon no_parens == cached[i].no_parens) { 349*1f5207b7SJohn Levon strncpy(buf, cached[i].str, len); 350*1f5207b7SJohn Levon if (sym_ptr) 351*1f5207b7SJohn Levon *sym_ptr = cached[i].sym; 352*1f5207b7SJohn Levon *complicated = cached[i].complicated; 353*1f5207b7SJohn Levon return; 354*1f5207b7SJohn Levon } 355*1f5207b7SJohn Levon } 356*1f5207b7SJohn Levon 357*1f5207b7SJohn Levon __get_variable_from_expr(&tmp_sym, buf, expr, len, complicated, no_parens); 358*1f5207b7SJohn Levon if (sym_ptr) 359*1f5207b7SJohn Levon *sym_ptr = tmp_sym; 360*1f5207b7SJohn Levon 361*1f5207b7SJohn Levon cached[idx].expr = expr; 362*1f5207b7SJohn Levon cached[idx].no_parens = no_parens; 363*1f5207b7SJohn Levon strncpy(cached[idx].str, buf, VAR_LEN); 364*1f5207b7SJohn Levon cached[idx].sym = tmp_sym; 365*1f5207b7SJohn Levon cached[idx].complicated = *complicated; 366*1f5207b7SJohn Levon 367*1f5207b7SJohn Levon idx = (idx + 1) % ARRAY_SIZE(cached); 368*1f5207b7SJohn Levon } 369*1f5207b7SJohn Levon 370*1f5207b7SJohn Levon /* 371*1f5207b7SJohn Levon * This is returns a stylized "c looking" representation of the 372*1f5207b7SJohn Levon * variable name. 373*1f5207b7SJohn Levon * 374*1f5207b7SJohn Levon * It uses the same buffer every time so you have to save the result 375*1f5207b7SJohn Levon * yourself if you want to keep it. 376*1f5207b7SJohn Levon * 377*1f5207b7SJohn Levon */ 378*1f5207b7SJohn Levon 379*1f5207b7SJohn Levon char *expr_to_str_sym(struct expression *expr, struct symbol **sym_ptr) 380*1f5207b7SJohn Levon { 381*1f5207b7SJohn Levon static char var_name[VAR_LEN]; 382*1f5207b7SJohn Levon int complicated = 0; 383*1f5207b7SJohn Levon 384*1f5207b7SJohn Levon if (sym_ptr) 385*1f5207b7SJohn Levon *sym_ptr = NULL; 386*1f5207b7SJohn Levon var_name[0] = '\0'; 387*1f5207b7SJohn Levon 388*1f5207b7SJohn Levon if (!expr) 389*1f5207b7SJohn Levon return NULL; 390*1f5207b7SJohn Levon get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name), 391*1f5207b7SJohn Levon &complicated, 0); 392*1f5207b7SJohn Levon if (complicated < 2) 393*1f5207b7SJohn Levon return alloc_string(var_name); 394*1f5207b7SJohn Levon else 395*1f5207b7SJohn Levon return NULL; 396*1f5207b7SJohn Levon } 397*1f5207b7SJohn Levon 398*1f5207b7SJohn Levon char *expr_to_str(struct expression *expr) 399*1f5207b7SJohn Levon { 400*1f5207b7SJohn Levon return expr_to_str_sym(expr, NULL); 401*1f5207b7SJohn Levon } 402*1f5207b7SJohn Levon 403*1f5207b7SJohn Levon /* 404*1f5207b7SJohn Levon * get_variable_from_expr_simple() only returns simple variables. 405*1f5207b7SJohn Levon * If it's a complicated variable like a->foo[x] instead of just 'a->foo' 406*1f5207b7SJohn Levon * then it returns NULL. 407*1f5207b7SJohn Levon */ 408*1f5207b7SJohn Levon char *expr_to_var_sym(struct expression *expr, 409*1f5207b7SJohn Levon struct symbol **sym_ptr) 410*1f5207b7SJohn Levon { 411*1f5207b7SJohn Levon static char var_name[VAR_LEN]; 412*1f5207b7SJohn Levon int complicated = 0; 413*1f5207b7SJohn Levon 414*1f5207b7SJohn Levon if (sym_ptr) 415*1f5207b7SJohn Levon *sym_ptr = NULL; 416*1f5207b7SJohn Levon var_name[0] = '\0'; 417*1f5207b7SJohn Levon 418*1f5207b7SJohn Levon if (!expr) 419*1f5207b7SJohn Levon return NULL; 420*1f5207b7SJohn Levon expr = strip_expr(expr); 421*1f5207b7SJohn Levon get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name), 422*1f5207b7SJohn Levon &complicated, 1); 423*1f5207b7SJohn Levon 424*1f5207b7SJohn Levon if (complicated) { 425*1f5207b7SJohn Levon if (sym_ptr) 426*1f5207b7SJohn Levon *sym_ptr = NULL; 427*1f5207b7SJohn Levon return NULL; 428*1f5207b7SJohn Levon } 429*1f5207b7SJohn Levon return alloc_string(var_name); 430*1f5207b7SJohn Levon } 431*1f5207b7SJohn Levon 432*1f5207b7SJohn Levon char *expr_to_var(struct expression *expr) 433*1f5207b7SJohn Levon { 434*1f5207b7SJohn Levon return expr_to_var_sym(expr, NULL); 435*1f5207b7SJohn Levon } 436*1f5207b7SJohn Levon 437*1f5207b7SJohn Levon struct symbol *expr_to_sym(struct expression *expr) 438*1f5207b7SJohn Levon { 439*1f5207b7SJohn Levon struct symbol *sym; 440*1f5207b7SJohn Levon char *name; 441*1f5207b7SJohn Levon 442*1f5207b7SJohn Levon name = expr_to_var_sym(expr, &sym); 443*1f5207b7SJohn Levon free_string(name); 444*1f5207b7SJohn Levon return sym; 445*1f5207b7SJohn Levon } 446*1f5207b7SJohn Levon 447*1f5207b7SJohn Levon int get_complication_score(struct expression *expr) 448*1f5207b7SJohn Levon { 449*1f5207b7SJohn Levon expr = strip_expr(expr); 450*1f5207b7SJohn Levon 451*1f5207b7SJohn Levon /* 452*1f5207b7SJohn Levon * Don't forget to keep get_complication_score() and store_all_links() 453*1f5207b7SJohn Levon * in sync. 454*1f5207b7SJohn Levon * 455*1f5207b7SJohn Levon */ 456*1f5207b7SJohn Levon 457*1f5207b7SJohn Levon if (!expr) 458*1f5207b7SJohn Levon return 990; 459*1f5207b7SJohn Levon 460*1f5207b7SJohn Levon switch (expr->type) { 461*1f5207b7SJohn Levon case EXPR_CALL: 462*1f5207b7SJohn Levon return 991; 463*1f5207b7SJohn Levon case EXPR_COMPARE: 464*1f5207b7SJohn Levon case EXPR_BINOP: 465*1f5207b7SJohn Levon return get_complication_score(expr->left) + 466*1f5207b7SJohn Levon get_complication_score(expr->right); 467*1f5207b7SJohn Levon case EXPR_SYMBOL: 468*1f5207b7SJohn Levon return 1; 469*1f5207b7SJohn Levon case EXPR_PREOP: 470*1f5207b7SJohn Levon if (expr->op == '*' || expr->op == '(') 471*1f5207b7SJohn Levon return get_complication_score(expr->unop); 472*1f5207b7SJohn Levon return 993; 473*1f5207b7SJohn Levon case EXPR_DEREF: 474*1f5207b7SJohn Levon return get_complication_score(expr->deref); 475*1f5207b7SJohn Levon case EXPR_VALUE: 476*1f5207b7SJohn Levon case EXPR_SIZEOF: 477*1f5207b7SJohn Levon return 0; 478*1f5207b7SJohn Levon default: 479*1f5207b7SJohn Levon return 994; 480*1f5207b7SJohn Levon } 481*1f5207b7SJohn Levon } 482*1f5207b7SJohn Levon 483*1f5207b7SJohn Levon struct expression *reorder_expr_alphabetically(struct expression *expr) 484*1f5207b7SJohn Levon { 485*1f5207b7SJohn Levon struct expression *ret; 486*1f5207b7SJohn Levon char *left, *right; 487*1f5207b7SJohn Levon 488*1f5207b7SJohn Levon if (expr->type != EXPR_BINOP) 489*1f5207b7SJohn Levon return expr; 490*1f5207b7SJohn Levon if (expr->op != '+' && expr->op != '*') 491*1f5207b7SJohn Levon return expr; 492*1f5207b7SJohn Levon 493*1f5207b7SJohn Levon left = expr_to_var(expr->left); 494*1f5207b7SJohn Levon right = expr_to_var(expr->right); 495*1f5207b7SJohn Levon ret = expr; 496*1f5207b7SJohn Levon if (!left || !right) 497*1f5207b7SJohn Levon goto free; 498*1f5207b7SJohn Levon if (strcmp(left, right) <= 0) 499*1f5207b7SJohn Levon goto free; 500*1f5207b7SJohn Levon 501*1f5207b7SJohn Levon ret = binop_expression(expr->right, expr->op, expr->left); 502*1f5207b7SJohn Levon free: 503*1f5207b7SJohn Levon free_string(left); 504*1f5207b7SJohn Levon free_string(right); 505*1f5207b7SJohn Levon 506*1f5207b7SJohn Levon return ret; 507*1f5207b7SJohn Levon } 508*1f5207b7SJohn Levon 509*1f5207b7SJohn Levon char *expr_to_chunk_helper(struct expression *expr, struct symbol **sym, struct var_sym_list **vsl) 510*1f5207b7SJohn Levon { 511*1f5207b7SJohn Levon struct var_sym_list *tmp_vsl; 512*1f5207b7SJohn Levon char *name; 513*1f5207b7SJohn Levon struct symbol *tmp; 514*1f5207b7SJohn Levon int score; 515*1f5207b7SJohn Levon 516*1f5207b7SJohn Levon if (vsl) 517*1f5207b7SJohn Levon *vsl = NULL; 518*1f5207b7SJohn Levon if (sym) 519*1f5207b7SJohn Levon *sym = NULL; 520*1f5207b7SJohn Levon 521*1f5207b7SJohn Levon expr = strip_parens(expr); 522*1f5207b7SJohn Levon if (!expr) 523*1f5207b7SJohn Levon return NULL; 524*1f5207b7SJohn Levon 525*1f5207b7SJohn Levon name = expr_to_var_sym(expr, &tmp); 526*1f5207b7SJohn Levon if (name && tmp) { 527*1f5207b7SJohn Levon if (sym) 528*1f5207b7SJohn Levon *sym = tmp; 529*1f5207b7SJohn Levon if (vsl) 530*1f5207b7SJohn Levon *vsl = expr_to_vsl(expr); 531*1f5207b7SJohn Levon return name; 532*1f5207b7SJohn Levon } 533*1f5207b7SJohn Levon free_string(name); 534*1f5207b7SJohn Levon 535*1f5207b7SJohn Levon score = get_complication_score(expr); 536*1f5207b7SJohn Levon if (score <= 0 || score > 2) 537*1f5207b7SJohn Levon return NULL; 538*1f5207b7SJohn Levon 539*1f5207b7SJohn Levon tmp_vsl = expr_to_vsl(expr); 540*1f5207b7SJohn Levon if (vsl) { 541*1f5207b7SJohn Levon *vsl = tmp_vsl; 542*1f5207b7SJohn Levon if (!*vsl) 543*1f5207b7SJohn Levon return NULL; 544*1f5207b7SJohn Levon } 545*1f5207b7SJohn Levon if (sym) { 546*1f5207b7SJohn Levon if (ptr_list_size((struct ptr_list *)tmp_vsl) == 1) { 547*1f5207b7SJohn Levon struct var_sym *vs; 548*1f5207b7SJohn Levon 549*1f5207b7SJohn Levon vs = first_ptr_list((struct ptr_list *)tmp_vsl); 550*1f5207b7SJohn Levon *sym = vs->sym; 551*1f5207b7SJohn Levon } 552*1f5207b7SJohn Levon } 553*1f5207b7SJohn Levon 554*1f5207b7SJohn Levon expr = reorder_expr_alphabetically(expr); 555*1f5207b7SJohn Levon 556*1f5207b7SJohn Levon return expr_to_str(expr); 557*1f5207b7SJohn Levon } 558*1f5207b7SJohn Levon 559*1f5207b7SJohn Levon char *expr_to_known_chunk_sym(struct expression *expr, struct symbol **sym) 560*1f5207b7SJohn Levon { 561*1f5207b7SJohn Levon return expr_to_chunk_helper(expr, sym, NULL); 562*1f5207b7SJohn Levon } 563*1f5207b7SJohn Levon 564*1f5207b7SJohn Levon char *expr_to_chunk_sym_vsl(struct expression *expr, struct symbol **sym, struct var_sym_list **vsl) 565*1f5207b7SJohn Levon { 566*1f5207b7SJohn Levon return expr_to_chunk_helper(expr, sym, vsl); 567*1f5207b7SJohn Levon } 568*1f5207b7SJohn Levon 569*1f5207b7SJohn Levon int sym_name_is(const char *name, struct expression *expr) 570*1f5207b7SJohn Levon { 571*1f5207b7SJohn Levon if (!expr) 572*1f5207b7SJohn Levon return 0; 573*1f5207b7SJohn Levon if (expr->type != EXPR_SYMBOL) 574*1f5207b7SJohn Levon return 0; 575*1f5207b7SJohn Levon if (!strcmp(expr->symbol_name->name, name)) 576*1f5207b7SJohn Levon return 1; 577*1f5207b7SJohn Levon return 0; 578*1f5207b7SJohn Levon } 579*1f5207b7SJohn Levon 580*1f5207b7SJohn Levon int is_zero(struct expression *expr) 581*1f5207b7SJohn Levon { 582*1f5207b7SJohn Levon sval_t sval; 583*1f5207b7SJohn Levon 584*1f5207b7SJohn Levon if (get_value(expr, &sval) && sval.value == 0) 585*1f5207b7SJohn Levon return 1; 586*1f5207b7SJohn Levon return 0; 587*1f5207b7SJohn Levon } 588*1f5207b7SJohn Levon 589*1f5207b7SJohn Levon int is_array(struct expression *expr) 590*1f5207b7SJohn Levon { 591*1f5207b7SJohn Levon struct symbol *type; 592*1f5207b7SJohn Levon 593*1f5207b7SJohn Levon expr = strip_expr(expr); 594*1f5207b7SJohn Levon if (!expr) 595*1f5207b7SJohn Levon return 0; 596*1f5207b7SJohn Levon 597*1f5207b7SJohn Levon if (expr->type == EXPR_PREOP && expr->op == '*') { 598*1f5207b7SJohn Levon expr = strip_expr(expr->unop); 599*1f5207b7SJohn Levon if (!expr) 600*1f5207b7SJohn Levon return 0; 601*1f5207b7SJohn Levon if (expr->type == EXPR_BINOP && expr->op == '+') 602*1f5207b7SJohn Levon return 1; 603*1f5207b7SJohn Levon } 604*1f5207b7SJohn Levon 605*1f5207b7SJohn Levon if (expr->type != EXPR_BINOP || expr->op != '+') 606*1f5207b7SJohn Levon return 0; 607*1f5207b7SJohn Levon 608*1f5207b7SJohn Levon type = get_type(expr->left); 609*1f5207b7SJohn Levon if (!type || type->type != SYM_ARRAY) 610*1f5207b7SJohn Levon return 0; 611*1f5207b7SJohn Levon 612*1f5207b7SJohn Levon return 1; 613*1f5207b7SJohn Levon } 614*1f5207b7SJohn Levon 615*1f5207b7SJohn Levon struct expression *get_array_base(struct expression *expr) 616*1f5207b7SJohn Levon { 617*1f5207b7SJohn Levon if (!is_array(expr)) 618*1f5207b7SJohn Levon return NULL; 619*1f5207b7SJohn Levon expr = strip_expr(expr); 620*1f5207b7SJohn Levon if (expr->type == EXPR_PREOP && expr->op == '*') 621*1f5207b7SJohn Levon expr = strip_expr(expr->unop); 622*1f5207b7SJohn Levon if (expr->type != EXPR_BINOP || expr->op != '+') 623*1f5207b7SJohn Levon return NULL; 624*1f5207b7SJohn Levon return strip_parens(expr->left); 625*1f5207b7SJohn Levon } 626*1f5207b7SJohn Levon 627*1f5207b7SJohn Levon struct expression *get_array_offset(struct expression *expr) 628*1f5207b7SJohn Levon { 629*1f5207b7SJohn Levon if (!is_array(expr)) 630*1f5207b7SJohn Levon return NULL; 631*1f5207b7SJohn Levon expr = strip_expr(expr); 632*1f5207b7SJohn Levon if (expr->type == EXPR_PREOP && expr->op == '*') 633*1f5207b7SJohn Levon expr = strip_expr(expr->unop); 634*1f5207b7SJohn Levon if (expr->type != EXPR_BINOP || expr->op != '+') 635*1f5207b7SJohn Levon return NULL; 636*1f5207b7SJohn Levon return strip_parens(expr->right); 637*1f5207b7SJohn Levon } 638*1f5207b7SJohn Levon 639*1f5207b7SJohn Levon const char *show_state(struct smatch_state *state) 640*1f5207b7SJohn Levon { 641*1f5207b7SJohn Levon if (!state) 642*1f5207b7SJohn Levon return NULL; 643*1f5207b7SJohn Levon return state->name; 644*1f5207b7SJohn Levon } 645*1f5207b7SJohn Levon 646*1f5207b7SJohn Levon struct statement *get_expression_statement(struct expression *expr) 647*1f5207b7SJohn Levon { 648*1f5207b7SJohn Levon /* What are those things called? if (({....; ret;})) { ...*/ 649*1f5207b7SJohn Levon 650*1f5207b7SJohn Levon if (expr->type != EXPR_PREOP) 651*1f5207b7SJohn Levon return NULL; 652*1f5207b7SJohn Levon if (expr->op != '(') 653*1f5207b7SJohn Levon return NULL; 654*1f5207b7SJohn Levon if (!expr->unop) 655*1f5207b7SJohn Levon return NULL; 656*1f5207b7SJohn Levon if (expr->unop->type != EXPR_STATEMENT) 657*1f5207b7SJohn Levon return NULL; 658*1f5207b7SJohn Levon if (expr->unop->statement->type != STMT_COMPOUND) 659*1f5207b7SJohn Levon return NULL; 660*1f5207b7SJohn Levon return expr->unop->statement; 661*1f5207b7SJohn Levon } 662*1f5207b7SJohn Levon 663*1f5207b7SJohn Levon struct expression *strip_parens(struct expression *expr) 664*1f5207b7SJohn Levon { 665*1f5207b7SJohn Levon if (!expr) 666*1f5207b7SJohn Levon return NULL; 667*1f5207b7SJohn Levon 668*1f5207b7SJohn Levon if (expr->type == EXPR_PREOP) { 669*1f5207b7SJohn Levon if (!expr->unop) 670*1f5207b7SJohn Levon return expr; /* parsing invalid code */ 671*1f5207b7SJohn Levon 672*1f5207b7SJohn Levon if (expr->op == '(' && expr->unop->type == EXPR_STATEMENT && 673*1f5207b7SJohn Levon expr->unop->statement->type == STMT_COMPOUND) 674*1f5207b7SJohn Levon return expr; 675*1f5207b7SJohn Levon if (expr->op == '(') 676*1f5207b7SJohn Levon return strip_parens(expr->unop); 677*1f5207b7SJohn Levon } 678*1f5207b7SJohn Levon return expr; 679*1f5207b7SJohn Levon } 680*1f5207b7SJohn Levon 681*1f5207b7SJohn Levon static struct expression *strip_expr_helper(struct expression *expr, bool set_parent) 682*1f5207b7SJohn Levon { 683*1f5207b7SJohn Levon if (!expr) 684*1f5207b7SJohn Levon return NULL; 685*1f5207b7SJohn Levon 686*1f5207b7SJohn Levon switch (expr->type) { 687*1f5207b7SJohn Levon case EXPR_FORCE_CAST: 688*1f5207b7SJohn Levon case EXPR_CAST: 689*1f5207b7SJohn Levon if (set_parent) 690*1f5207b7SJohn Levon expr_set_parent_expr(expr->cast_expression, expr); 691*1f5207b7SJohn Levon 692*1f5207b7SJohn Levon if (!expr->cast_expression) 693*1f5207b7SJohn Levon return expr; 694*1f5207b7SJohn Levon return strip_expr_helper(expr->cast_expression, set_parent); 695*1f5207b7SJohn Levon case EXPR_PREOP: { 696*1f5207b7SJohn Levon struct expression *unop; 697*1f5207b7SJohn Levon 698*1f5207b7SJohn Levon if (!expr->unop) /* parsing invalid code */ 699*1f5207b7SJohn Levon return expr; 700*1f5207b7SJohn Levon if (set_parent) 701*1f5207b7SJohn Levon expr_set_parent_expr(expr->unop, expr); 702*1f5207b7SJohn Levon 703*1f5207b7SJohn Levon 704*1f5207b7SJohn Levon if (expr->op == '(' && expr->unop->type == EXPR_STATEMENT && 705*1f5207b7SJohn Levon expr->unop->statement->type == STMT_COMPOUND) 706*1f5207b7SJohn Levon return expr; 707*1f5207b7SJohn Levon 708*1f5207b7SJohn Levon unop = strip_expr_helper(expr->unop, set_parent); 709*1f5207b7SJohn Levon 710*1f5207b7SJohn Levon if (expr->op == '*' && unop && 711*1f5207b7SJohn Levon unop->type == EXPR_PREOP && unop->op == '&') { 712*1f5207b7SJohn Levon struct symbol *type = get_type(unop->unop); 713*1f5207b7SJohn Levon 714*1f5207b7SJohn Levon if (type && type->type == SYM_ARRAY) 715*1f5207b7SJohn Levon return expr; 716*1f5207b7SJohn Levon return strip_expr_helper(unop->unop, set_parent); 717*1f5207b7SJohn Levon } 718*1f5207b7SJohn Levon 719*1f5207b7SJohn Levon if (expr->op == '(') 720*1f5207b7SJohn Levon return unop; 721*1f5207b7SJohn Levon 722*1f5207b7SJohn Levon return expr; 723*1f5207b7SJohn Levon } 724*1f5207b7SJohn Levon case EXPR_CONDITIONAL: 725*1f5207b7SJohn Levon if (known_condition_true(expr->conditional)) { 726*1f5207b7SJohn Levon if (expr->cond_true) { 727*1f5207b7SJohn Levon if (set_parent) 728*1f5207b7SJohn Levon expr_set_parent_expr(expr->cond_true, expr); 729*1f5207b7SJohn Levon return strip_expr_helper(expr->cond_true, set_parent); 730*1f5207b7SJohn Levon } 731*1f5207b7SJohn Levon if (set_parent) 732*1f5207b7SJohn Levon expr_set_parent_expr(expr->conditional, expr); 733*1f5207b7SJohn Levon return strip_expr_helper(expr->conditional, set_parent); 734*1f5207b7SJohn Levon } 735*1f5207b7SJohn Levon if (known_condition_false(expr->conditional)) { 736*1f5207b7SJohn Levon if (set_parent) 737*1f5207b7SJohn Levon expr_set_parent_expr(expr->cond_false, expr); 738*1f5207b7SJohn Levon return strip_expr_helper(expr->cond_false, set_parent); 739*1f5207b7SJohn Levon } 740*1f5207b7SJohn Levon return expr; 741*1f5207b7SJohn Levon case EXPR_CALL: 742*1f5207b7SJohn Levon if (sym_name_is("__builtin_expect", expr->fn) || 743*1f5207b7SJohn Levon sym_name_is("__builtin_bswap16", expr->fn) || 744*1f5207b7SJohn Levon sym_name_is("__builtin_bswap32", expr->fn) || 745*1f5207b7SJohn Levon sym_name_is("__builtin_bswap64", expr->fn)) { 746*1f5207b7SJohn Levon expr = get_argument_from_call_expr(expr->args, 0); 747*1f5207b7SJohn Levon return strip_expr_helper(expr, set_parent); 748*1f5207b7SJohn Levon } 749*1f5207b7SJohn Levon return expr; 750*1f5207b7SJohn Levon } 751*1f5207b7SJohn Levon return expr; 752*1f5207b7SJohn Levon } 753*1f5207b7SJohn Levon 754*1f5207b7SJohn Levon struct expression *strip_expr(struct expression *expr) 755*1f5207b7SJohn Levon { 756*1f5207b7SJohn Levon return strip_expr_helper(expr, false); 757*1f5207b7SJohn Levon } 758*1f5207b7SJohn Levon 759*1f5207b7SJohn Levon struct expression *strip_expr_set_parent(struct expression *expr) 760*1f5207b7SJohn Levon { 761*1f5207b7SJohn Levon return strip_expr_helper(expr, true); 762*1f5207b7SJohn Levon } 763*1f5207b7SJohn Levon 764*1f5207b7SJohn Levon static void delete_state_tracker(struct tracker *t) 765*1f5207b7SJohn Levon { 766*1f5207b7SJohn Levon delete_state(t->owner, t->name, t->sym); 767*1f5207b7SJohn Levon __free_tracker(t); 768*1f5207b7SJohn Levon } 769*1f5207b7SJohn Levon 770*1f5207b7SJohn Levon void scoped_state(int my_id, const char *name, struct symbol *sym) 771*1f5207b7SJohn Levon { 772*1f5207b7SJohn Levon struct tracker *t; 773*1f5207b7SJohn Levon 774*1f5207b7SJohn Levon t = alloc_tracker(my_id, name, sym); 775*1f5207b7SJohn Levon add_scope_hook((scope_hook *)&delete_state_tracker, t); 776*1f5207b7SJohn Levon } 777*1f5207b7SJohn Levon 778*1f5207b7SJohn Levon int is_error_return(struct expression *expr) 779*1f5207b7SJohn Levon { 780*1f5207b7SJohn Levon struct symbol *cur_func = cur_func_sym; 781*1f5207b7SJohn Levon struct range_list *rl; 782*1f5207b7SJohn Levon sval_t sval; 783*1f5207b7SJohn Levon 784*1f5207b7SJohn Levon if (!expr) 785*1f5207b7SJohn Levon return 0; 786*1f5207b7SJohn Levon if (cur_func->type != SYM_NODE) 787*1f5207b7SJohn Levon return 0; 788*1f5207b7SJohn Levon cur_func = get_base_type(cur_func); 789*1f5207b7SJohn Levon if (cur_func->type != SYM_FN) 790*1f5207b7SJohn Levon return 0; 791*1f5207b7SJohn Levon cur_func = get_base_type(cur_func); 792*1f5207b7SJohn Levon if (cur_func == &void_ctype) 793*1f5207b7SJohn Levon return 0; 794*1f5207b7SJohn Levon if (option_project == PROJ_KERNEL && 795*1f5207b7SJohn Levon get_implied_rl(expr, &rl) && 796*1f5207b7SJohn Levon rl_type(rl) == &int_ctype && 797*1f5207b7SJohn Levon sval_is_negative(rl_min(rl)) && 798*1f5207b7SJohn Levon rl_max(rl).value == -1) 799*1f5207b7SJohn Levon return 1; 800*1f5207b7SJohn Levon if (!get_implied_value(expr, &sval)) 801*1f5207b7SJohn Levon return 0; 802*1f5207b7SJohn Levon if (sval.value < 0) 803*1f5207b7SJohn Levon return 1; 804*1f5207b7SJohn Levon if (cur_func->type == SYM_PTR && sval.value == 0) 805*1f5207b7SJohn Levon return 1; 806*1f5207b7SJohn Levon return 0; 807*1f5207b7SJohn Levon } 808*1f5207b7SJohn Levon 809*1f5207b7SJohn Levon int getting_address(void) 810*1f5207b7SJohn Levon { 811*1f5207b7SJohn Levon struct expression *tmp; 812*1f5207b7SJohn Levon int i = 0; 813*1f5207b7SJohn Levon int dot_ops = 0; 814*1f5207b7SJohn Levon 815*1f5207b7SJohn Levon FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) { 816*1f5207b7SJohn Levon if (!i++) 817*1f5207b7SJohn Levon continue; 818*1f5207b7SJohn Levon if (tmp->type == EXPR_PREOP && tmp->op == '(') 819*1f5207b7SJohn Levon continue; 820*1f5207b7SJohn Levon if (tmp->op == '.' && !dot_ops++) 821*1f5207b7SJohn Levon continue; 822*1f5207b7SJohn Levon if (tmp->op == '&') 823*1f5207b7SJohn Levon return 1; 824*1f5207b7SJohn Levon return 0; 825*1f5207b7SJohn Levon } END_FOR_EACH_PTR_REVERSE(tmp); 826*1f5207b7SJohn Levon return 0; 827*1f5207b7SJohn Levon } 828*1f5207b7SJohn Levon 829*1f5207b7SJohn Levon int get_struct_and_member(struct expression *expr, const char **type, const char **member) 830*1f5207b7SJohn Levon { 831*1f5207b7SJohn Levon struct symbol *sym; 832*1f5207b7SJohn Levon 833*1f5207b7SJohn Levon expr = strip_expr(expr); 834*1f5207b7SJohn Levon if (expr->type != EXPR_DEREF) 835*1f5207b7SJohn Levon return 0; 836*1f5207b7SJohn Levon if (!expr->member) 837*1f5207b7SJohn Levon return 0; 838*1f5207b7SJohn Levon 839*1f5207b7SJohn Levon sym = get_type(expr->deref); 840*1f5207b7SJohn Levon if (!sym) 841*1f5207b7SJohn Levon return 0; 842*1f5207b7SJohn Levon if (sym->type == SYM_UNION) 843*1f5207b7SJohn Levon return 0; 844*1f5207b7SJohn Levon if (!sym->ident) 845*1f5207b7SJohn Levon return 0; 846*1f5207b7SJohn Levon 847*1f5207b7SJohn Levon *type = sym->ident->name; 848*1f5207b7SJohn Levon *member = expr->member->name; 849*1f5207b7SJohn Levon return 1; 850*1f5207b7SJohn Levon } 851*1f5207b7SJohn Levon 852*1f5207b7SJohn Levon char *get_member_name(struct expression *expr) 853*1f5207b7SJohn Levon { 854*1f5207b7SJohn Levon char buf[256]; 855*1f5207b7SJohn Levon struct symbol *sym; 856*1f5207b7SJohn Levon 857*1f5207b7SJohn Levon expr = strip_expr(expr); 858*1f5207b7SJohn Levon if (!expr || expr->type != EXPR_DEREF) 859*1f5207b7SJohn Levon return NULL; 860*1f5207b7SJohn Levon if (!expr->member) 861*1f5207b7SJohn Levon return NULL; 862*1f5207b7SJohn Levon 863*1f5207b7SJohn Levon sym = get_type(expr->deref); 864*1f5207b7SJohn Levon if (!sym) 865*1f5207b7SJohn Levon return NULL; 866*1f5207b7SJohn Levon if (sym->type == SYM_UNION) { 867*1f5207b7SJohn Levon snprintf(buf, sizeof(buf), "(union %s)->%s", 868*1f5207b7SJohn Levon sym->ident ? sym->ident->name : "anonymous", 869*1f5207b7SJohn Levon expr->member->name); 870*1f5207b7SJohn Levon return alloc_string(buf); 871*1f5207b7SJohn Levon } 872*1f5207b7SJohn Levon if (!sym->ident) 873*1f5207b7SJohn Levon return NULL; 874*1f5207b7SJohn Levon snprintf(buf, sizeof(buf), "(struct %s)->%s", sym->ident->name, expr->member->name); 875*1f5207b7SJohn Levon return alloc_string(buf); 876*1f5207b7SJohn Levon } 877*1f5207b7SJohn Levon 878*1f5207b7SJohn Levon int cmp_pos(struct position pos1, struct position pos2) 879*1f5207b7SJohn Levon { 880*1f5207b7SJohn Levon /* the stream position is ... */ 881*1f5207b7SJohn Levon if (pos1.stream > pos2.stream) 882*1f5207b7SJohn Levon return -1; 883*1f5207b7SJohn Levon if (pos1.stream < pos2.stream) 884*1f5207b7SJohn Levon return 1; 885*1f5207b7SJohn Levon 886*1f5207b7SJohn Levon if (pos1.line < pos2.line) 887*1f5207b7SJohn Levon return -1; 888*1f5207b7SJohn Levon if (pos1.line > pos2.line) 889*1f5207b7SJohn Levon return 1; 890*1f5207b7SJohn Levon 891*1f5207b7SJohn Levon if (pos1.pos < pos2.pos) 892*1f5207b7SJohn Levon return -1; 893*1f5207b7SJohn Levon if (pos1.pos > pos2.pos) 894*1f5207b7SJohn Levon return 1; 895*1f5207b7SJohn Levon 896*1f5207b7SJohn Levon return 0; 897*1f5207b7SJohn Levon } 898*1f5207b7SJohn Levon 899*1f5207b7SJohn Levon int positions_eq(struct position pos1, struct position pos2) 900*1f5207b7SJohn Levon { 901*1f5207b7SJohn Levon if (pos1.line != pos2.line) 902*1f5207b7SJohn Levon return 0; 903*1f5207b7SJohn Levon if (pos1.pos != pos2.pos) 904*1f5207b7SJohn Levon return 0; 905*1f5207b7SJohn Levon if (pos1.stream != pos2.stream) 906*1f5207b7SJohn Levon return 0; 907*1f5207b7SJohn Levon return 1; 908*1f5207b7SJohn Levon } 909*1f5207b7SJohn Levon 910*1f5207b7SJohn Levon struct statement *get_current_statement(void) 911*1f5207b7SJohn Levon { 912*1f5207b7SJohn Levon struct statement *prev, *tmp; 913*1f5207b7SJohn Levon 914*1f5207b7SJohn Levon prev = last_ptr_list((struct ptr_list *)big_statement_stack); 915*1f5207b7SJohn Levon 916*1f5207b7SJohn Levon if (!prev || !get_macro_name(prev->pos)) 917*1f5207b7SJohn Levon return prev; 918*1f5207b7SJohn Levon 919*1f5207b7SJohn Levon FOR_EACH_PTR_REVERSE(big_statement_stack, tmp) { 920*1f5207b7SJohn Levon if (positions_eq(tmp->pos, prev->pos)) 921*1f5207b7SJohn Levon continue; 922*1f5207b7SJohn Levon if (prev->pos.line > tmp->pos.line) 923*1f5207b7SJohn Levon return prev; 924*1f5207b7SJohn Levon return tmp; 925*1f5207b7SJohn Levon } END_FOR_EACH_PTR_REVERSE(tmp); 926*1f5207b7SJohn Levon return prev; 927*1f5207b7SJohn Levon } 928*1f5207b7SJohn Levon 929*1f5207b7SJohn Levon struct statement *get_prev_statement(void) 930*1f5207b7SJohn Levon { 931*1f5207b7SJohn Levon struct statement *tmp; 932*1f5207b7SJohn Levon int i; 933*1f5207b7SJohn Levon 934*1f5207b7SJohn Levon i = 0; 935*1f5207b7SJohn Levon FOR_EACH_PTR_REVERSE(big_statement_stack, tmp) { 936*1f5207b7SJohn Levon if (i++ == 1) 937*1f5207b7SJohn Levon return tmp; 938*1f5207b7SJohn Levon } END_FOR_EACH_PTR_REVERSE(tmp); 939*1f5207b7SJohn Levon return NULL; 940*1f5207b7SJohn Levon } 941*1f5207b7SJohn Levon 942*1f5207b7SJohn Levon struct expression *get_last_expr_from_expression_stmt(struct expression *expr) 943*1f5207b7SJohn Levon { 944*1f5207b7SJohn Levon struct statement *stmt; 945*1f5207b7SJohn Levon struct statement *last_stmt; 946*1f5207b7SJohn Levon 947*1f5207b7SJohn Levon while (expr->type == EXPR_PREOP && expr->op == '(') 948*1f5207b7SJohn Levon expr = expr->unop; 949*1f5207b7SJohn Levon if (expr->type != EXPR_STATEMENT) 950*1f5207b7SJohn Levon return NULL; 951*1f5207b7SJohn Levon stmt = expr->statement; 952*1f5207b7SJohn Levon if (!stmt) 953*1f5207b7SJohn Levon return NULL; 954*1f5207b7SJohn Levon if (stmt->type == STMT_COMPOUND) { 955*1f5207b7SJohn Levon last_stmt = last_ptr_list((struct ptr_list *)stmt->stmts); 956*1f5207b7SJohn Levon if (!last_stmt) 957*1f5207b7SJohn Levon return NULL; 958*1f5207b7SJohn Levon if (last_stmt->type == STMT_LABEL) 959*1f5207b7SJohn Levon last_stmt = last_stmt->label_statement; 960*1f5207b7SJohn Levon if (last_stmt->type != STMT_EXPRESSION) 961*1f5207b7SJohn Levon return NULL; 962*1f5207b7SJohn Levon return last_stmt->expression; 963*1f5207b7SJohn Levon } 964*1f5207b7SJohn Levon if (stmt->type == STMT_EXPRESSION) 965*1f5207b7SJohn Levon return stmt->expression; 966*1f5207b7SJohn Levon return NULL; 967*1f5207b7SJohn Levon } 968*1f5207b7SJohn Levon 969*1f5207b7SJohn Levon int get_param_num_from_sym(struct symbol *sym) 970*1f5207b7SJohn Levon { 971*1f5207b7SJohn Levon struct symbol *tmp; 972*1f5207b7SJohn Levon int i; 973*1f5207b7SJohn Levon 974*1f5207b7SJohn Levon if (!cur_func_sym) 975*1f5207b7SJohn Levon return -1; 976*1f5207b7SJohn Levon 977*1f5207b7SJohn Levon i = 0; 978*1f5207b7SJohn Levon FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, tmp) { 979*1f5207b7SJohn Levon if (tmp == sym) 980*1f5207b7SJohn Levon return i; 981*1f5207b7SJohn Levon i++; 982*1f5207b7SJohn Levon } END_FOR_EACH_PTR(tmp); 983*1f5207b7SJohn Levon return -1; 984*1f5207b7SJohn Levon } 985*1f5207b7SJohn Levon 986*1f5207b7SJohn Levon int get_param_num(struct expression *expr) 987*1f5207b7SJohn Levon { 988*1f5207b7SJohn Levon struct symbol *sym; 989*1f5207b7SJohn Levon char *name; 990*1f5207b7SJohn Levon 991*1f5207b7SJohn Levon if (!cur_func_sym) 992*1f5207b7SJohn Levon return -1; 993*1f5207b7SJohn Levon name = expr_to_var_sym(expr, &sym); 994*1f5207b7SJohn Levon free_string(name); 995*1f5207b7SJohn Levon if (!sym) 996*1f5207b7SJohn Levon return -1; 997*1f5207b7SJohn Levon return get_param_num_from_sym(sym); 998*1f5207b7SJohn Levon } 999*1f5207b7SJohn Levon 1000*1f5207b7SJohn Levon int ms_since(struct timeval *start) 1001*1f5207b7SJohn Levon { 1002*1f5207b7SJohn Levon struct timeval end; 1003*1f5207b7SJohn Levon double diff; 1004*1f5207b7SJohn Levon 1005*1f5207b7SJohn Levon gettimeofday(&end, NULL); 1006*1f5207b7SJohn Levon diff = (end.tv_sec - start->tv_sec) * 1000.0; 1007*1f5207b7SJohn Levon diff += (end.tv_usec - start->tv_usec) / 1000.0; 1008*1f5207b7SJohn Levon return (int)diff; 1009*1f5207b7SJohn Levon } 1010*1f5207b7SJohn Levon 1011*1f5207b7SJohn Levon int parent_is_gone_var_sym(const char *name, struct symbol *sym) 1012*1f5207b7SJohn Levon { 1013*1f5207b7SJohn Levon if (!name || !sym) 1014*1f5207b7SJohn Levon return 0; 1015*1f5207b7SJohn Levon 1016*1f5207b7SJohn Levon if (parent_is_null_var_sym(name, sym) || 1017*1f5207b7SJohn Levon parent_is_free_var_sym(name, sym)) 1018*1f5207b7SJohn Levon return 1; 1019*1f5207b7SJohn Levon return 0; 1020*1f5207b7SJohn Levon } 1021*1f5207b7SJohn Levon 1022*1f5207b7SJohn Levon int parent_is_gone(struct expression *expr) 1023*1f5207b7SJohn Levon { 1024*1f5207b7SJohn Levon struct symbol *sym; 1025*1f5207b7SJohn Levon char *var; 1026*1f5207b7SJohn Levon int ret = 0; 1027*1f5207b7SJohn Levon 1028*1f5207b7SJohn Levon expr = strip_expr(expr); 1029*1f5207b7SJohn Levon var = expr_to_var_sym(expr, &sym); 1030*1f5207b7SJohn Levon if (!var || !sym) 1031*1f5207b7SJohn Levon goto free; 1032*1f5207b7SJohn Levon ret = parent_is_gone_var_sym(var, sym); 1033*1f5207b7SJohn Levon free: 1034*1f5207b7SJohn Levon free_string(var); 1035*1f5207b7SJohn Levon return ret; 1036*1f5207b7SJohn Levon } 1037*1f5207b7SJohn Levon 1038*1f5207b7SJohn Levon int invert_op(int op) 1039*1f5207b7SJohn Levon { 1040*1f5207b7SJohn Levon switch (op) { 1041*1f5207b7SJohn Levon case '*': 1042*1f5207b7SJohn Levon return '/'; 1043*1f5207b7SJohn Levon case '/': 1044*1f5207b7SJohn Levon return '*'; 1045*1f5207b7SJohn Levon case '+': 1046*1f5207b7SJohn Levon return '-'; 1047*1f5207b7SJohn Levon case '-': 1048*1f5207b7SJohn Levon return '+'; 1049*1f5207b7SJohn Levon case SPECIAL_LEFTSHIFT: 1050*1f5207b7SJohn Levon return SPECIAL_RIGHTSHIFT; 1051*1f5207b7SJohn Levon case SPECIAL_RIGHTSHIFT: 1052*1f5207b7SJohn Levon return SPECIAL_LEFTSHIFT; 1053*1f5207b7SJohn Levon } 1054*1f5207b7SJohn Levon return 0; 1055*1f5207b7SJohn Levon } 1056*1f5207b7SJohn Levon 1057*1f5207b7SJohn Levon int expr_equiv(struct expression *one, struct expression *two) 1058*1f5207b7SJohn Levon { 1059*1f5207b7SJohn Levon struct symbol *one_sym = NULL; 1060*1f5207b7SJohn Levon struct symbol *two_sym = NULL; 1061*1f5207b7SJohn Levon char *one_name = NULL; 1062*1f5207b7SJohn Levon char *two_name = NULL; 1063*1f5207b7SJohn Levon int ret = 0; 1064*1f5207b7SJohn Levon 1065*1f5207b7SJohn Levon if (!one || !two) 1066*1f5207b7SJohn Levon return 0; 1067*1f5207b7SJohn Levon if (one->type != two->type) 1068*1f5207b7SJohn Levon return 0; 1069*1f5207b7SJohn Levon if (is_fake_call(one) || is_fake_call(two)) 1070*1f5207b7SJohn Levon return 0; 1071*1f5207b7SJohn Levon 1072*1f5207b7SJohn Levon one_name = expr_to_str_sym(one, &one_sym); 1073*1f5207b7SJohn Levon if (!one_name) 1074*1f5207b7SJohn Levon goto free; 1075*1f5207b7SJohn Levon two_name = expr_to_str_sym(two, &two_sym); 1076*1f5207b7SJohn Levon if (!two_name) 1077*1f5207b7SJohn Levon goto free; 1078*1f5207b7SJohn Levon if (one_sym != two_sym) 1079*1f5207b7SJohn Levon goto free; 1080*1f5207b7SJohn Levon /* 1081*1f5207b7SJohn Levon * This is a terrible hack because expr_to_str() sometimes gives up in 1082*1f5207b7SJohn Levon * the middle and just returns what it has. If you see a () you know 1083*1f5207b7SJohn Levon * the string is bogus. 1084*1f5207b7SJohn Levon */ 1085*1f5207b7SJohn Levon if (strstr(one_name, "()")) 1086*1f5207b7SJohn Levon goto free; 1087*1f5207b7SJohn Levon if (strcmp(one_name, two_name) == 0) 1088*1f5207b7SJohn Levon ret = 1; 1089*1f5207b7SJohn Levon free: 1090*1f5207b7SJohn Levon free_string(one_name); 1091*1f5207b7SJohn Levon free_string(two_name); 1092*1f5207b7SJohn Levon return ret; 1093*1f5207b7SJohn Levon } 1094*1f5207b7SJohn Levon 1095*1f5207b7SJohn Levon void push_int(struct int_stack **stack, int num) 1096*1f5207b7SJohn Levon { 1097*1f5207b7SJohn Levon int *munged; 1098*1f5207b7SJohn Levon 1099*1f5207b7SJohn Levon /* 1100*1f5207b7SJohn Levon * Just put the int on directly instead of a pointer to the int. 1101*1f5207b7SJohn Levon * Shift it to the left because Sparse uses the last two bits. 1102*1f5207b7SJohn Levon * This is sort of a dirty hack, yes. 1103*1f5207b7SJohn Levon */ 1104*1f5207b7SJohn Levon 1105*1f5207b7SJohn Levon munged = INT_PTR(num << 2); 1106*1f5207b7SJohn Levon 1107*1f5207b7SJohn Levon add_ptr_list(stack, munged); 1108*1f5207b7SJohn Levon } 1109*1f5207b7SJohn Levon 1110*1f5207b7SJohn Levon int pop_int(struct int_stack **stack) 1111*1f5207b7SJohn Levon { 1112*1f5207b7SJohn Levon int *num; 1113*1f5207b7SJohn Levon 1114*1f5207b7SJohn Levon num = last_ptr_list((struct ptr_list *)*stack); 1115*1f5207b7SJohn Levon delete_ptr_list_last((struct ptr_list **)stack); 1116*1f5207b7SJohn Levon 1117*1f5207b7SJohn Levon return PTR_INT(num) >> 2; 1118*1f5207b7SJohn Levon } 1119