1 /*
   2  * Copyright (C) 2013 Oracle.
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public License
   6  * as published by the Free Software Foundation; either version 2
   7  * of the License, or (at your option) any later version.
   8  *
   9  * This program is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  * GNU General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU General Public License
  15  * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
  16  */
  17 
  18 #include "smatch.h"
  19 #include "smatch_slist.h"
  20 #include "smatch_extra.h"
  21 
  22 static int my_id;
  23 
  24 static char *get_source_parameter(struct expression *expr)
  25 {
  26         struct expression *tmp;
  27         const char *param_name;
  28         struct symbol *sym;
  29         char *name;
  30         int param;
  31         char *ret = NULL;
  32         char buf[32];
  33         int cnt = 0;
  34         bool modified = false;
  35 
  36         tmp = expr;
  37         while ((tmp = get_assigned_expr(tmp))) {
  38                 expr = tmp;
  39                 if (cnt++ > 3)
  40                         break;
  41         }
  42 
  43         expr = strip_expr(expr);
  44         if (expr->type != EXPR_SYMBOL)
  45                 return NULL;
  46 
  47         name = expr_to_var_sym(expr, &sym);
  48         if (!name || !sym)
  49                 goto free;
  50         param = get_param_num_from_sym(sym);
  51         if (param < 0)
  52                 goto free;
  53         param_name = get_param_name_var_sym(name, sym);
  54         if (!param_name)
  55                 goto free;
  56         if (param_was_set_var_sym(name, sym))
  57                 modified = true;
  58 
  59         snprintf(buf, sizeof(buf), "$%d%s%s", param, param_name + 1,
  60                  modified ? " [m]" : "");
  61         ret = alloc_string(buf);
  62 
  63 free:
  64         free_string(name);
  65         return ret;
  66 }
  67 
  68 static char *get_source_assignment(struct expression *expr)
  69 {
  70         struct expression *right;
  71         char *name;
  72         char buf[64];
  73         char *ret;
  74 
  75         right = get_assigned_expr(expr);
  76         right = strip_expr(right);
  77         if (!right)
  78                 return NULL;
  79         if (right->type != EXPR_CALL || right->fn->type != EXPR_SYMBOL)
  80                 return NULL;
  81         if (is_fake_call(right))
  82                 return NULL;
  83         name = expr_to_str(right->fn);
  84         if (!name)
  85                 return NULL;
  86         snprintf(buf, sizeof(buf), "r %s", name);
  87         ret = alloc_string(buf);
  88         free_string(name);
  89         return ret;
  90 }
  91 
  92 static char *get_source_str(struct expression *arg)
  93 {
  94         char *source;
  95 
  96         source = get_source_parameter(arg);
  97         if (source)
  98                 return source;
  99         return get_source_assignment(arg);
 100 }
 101 
 102 static void match_caller_info(struct expression *expr)
 103 {
 104         struct expression *arg;
 105         char *source;
 106         int i;
 107 
 108         i = -1;
 109         FOR_EACH_PTR(expr->args, arg) {
 110                 i++;
 111                 source = get_source_str(arg);
 112                 if (!source)
 113                         continue;
 114                 sql_insert_caller_info(expr, DATA_SOURCE, i, "$", source);
 115                 free_string(source);
 116         } END_FOR_EACH_PTR(arg);
 117 }
 118 
 119 void register_data_source(int id)
 120 {
 121 //      if (!option_info)
 122 //              return;
 123         my_id = id;
 124         add_hook(&match_caller_info, FUNCTION_CALL_HOOK);
 125 }