1*1f5207b7SJohn Levon#!/usr/bin/perl
2*1f5207b7SJohn Levon
3*1f5207b7SJohn Levon# This script is supposed to help use the param_mapper output.
4*1f5207b7SJohn Levon# Give it a function and parameter and it lists the functions
5*1f5207b7SJohn Levon# and parameters which are basically equivalent.
6*1f5207b7SJohn Levon
7*1f5207b7SJohn Levonuse strict;
8*1f5207b7SJohn Levon
9*1f5207b7SJohn Levonsub usage()
10*1f5207b7SJohn Levon{
11*1f5207b7SJohn Levon    print("call_tree.pl <smatch output file>\n");
12*1f5207b7SJohn Levon    print("call_tree.pl finds paths between two functions\n");
13*1f5207b7SJohn Levon    exit(1);
14*1f5207b7SJohn Levon}
15*1f5207b7SJohn Levon
16*1f5207b7SJohn Levonmy %param_map;
17*1f5207b7SJohn Levon
18*1f5207b7SJohn Levonmy $UNKNOWN  = 1;
19*1f5207b7SJohn Levonmy $NOTFOUND = 2;
20*1f5207b7SJohn Levonmy $FOUND    = 3;
21*1f5207b7SJohn Levon
22*1f5207b7SJohn Levonmy $path;
23*1f5207b7SJohn Levon
24*1f5207b7SJohn Levonsub print_path()
25*1f5207b7SJohn Levon{
26*1f5207b7SJohn Levon    my $i = 0;
27*1f5207b7SJohn Levon
28*1f5207b7SJohn Levon    foreach my $func (@{$path}) {
29*1f5207b7SJohn Levon	if ($i++) {
30*1f5207b7SJohn Levon	    print(", ");
31*1f5207b7SJohn Levon	}
32*1f5207b7SJohn Levon	print("$func");
33*1f5207b7SJohn Levon    }
34*1f5207b7SJohn Levon    print("\n");
35*1f5207b7SJohn Levon    print("\n");
36*1f5207b7SJohn Levon}
37*1f5207b7SJohn Levon
38*1f5207b7SJohn Levonsub recurse($$)
39*1f5207b7SJohn Levon{
40*1f5207b7SJohn Levon    my $link = shift;
41*1f5207b7SJohn Levon    my $target = shift;
42*1f5207b7SJohn Levon    my $found = 0;
43*1f5207b7SJohn Levon
44*1f5207b7SJohn Levon    if ($link =~ /$target/) {
45*1f5207b7SJohn Levon	print_path();
46*1f5207b7SJohn Levon	return 1;
47*1f5207b7SJohn Levon    }
48*1f5207b7SJohn Levon    if (%{$param_map{$link}}->{found} == $NOTFOUND) {
49*1f5207b7SJohn Levon	return 0;
50*1f5207b7SJohn Levon    }
51*1f5207b7SJohn Levon
52*1f5207b7SJohn Levon    %{$param_map{$link}}->{found} = $NOTFOUND;
53*1f5207b7SJohn Levon
54*1f5207b7SJohn Levon    foreach my $l (@{%{$param_map{$link}}->{links}}){
55*1f5207b7SJohn Levon	push(@{$path}, $l);
56*1f5207b7SJohn Levon	$found = recurse($l, $target);
57*1f5207b7SJohn Levon	if (!$found) {
58*1f5207b7SJohn Levon	    pop(@{$path});
59*1f5207b7SJohn Levon	} else {
60*1f5207b7SJohn Levon	    last;
61*1f5207b7SJohn Levon	}
62*1f5207b7SJohn Levon    }
63*1f5207b7SJohn Levon
64*1f5207b7SJohn Levon    return $found;
65*1f5207b7SJohn Levon}
66*1f5207b7SJohn Levon
67*1f5207b7SJohn Levonsub search($$)
68*1f5207b7SJohn Levon{
69*1f5207b7SJohn Levon    my $start_func = shift;
70*1f5207b7SJohn Levon    my $end_func = shift;
71*1f5207b7SJohn Levon
72*1f5207b7SJohn Levon    foreach my $link (@{%{$param_map{$start_func}}->{links}}){
73*1f5207b7SJohn Levon	%{$param_map{$start_func}}->{found} = $NOTFOUND;
74*1f5207b7SJohn Levon	foreach my $l (@{%{$param_map{$start_func}}->{links}}){
75*1f5207b7SJohn Levon	    %{$param_map{$l}}->{found} = $NOTFOUND;
76*1f5207b7SJohn Levon	}
77*1f5207b7SJohn Levon	$path = [$start_func, $link];
78*1f5207b7SJohn Levon	%{$param_map{$link}}->{found} = $UNKNOWN;
79*1f5207b7SJohn Levon	recurse($link, $end_func);
80*1f5207b7SJohn Levon    }
81*1f5207b7SJohn Levon}
82*1f5207b7SJohn Levon
83*1f5207b7SJohn Levonsub add_link($$)
84*1f5207b7SJohn Levon{
85*1f5207b7SJohn Levon    my $one = shift;
86*1f5207b7SJohn Levon    my $two = shift;
87*1f5207b7SJohn Levon
88*1f5207b7SJohn Levon    if (!defined($param_map{$one})) {
89*1f5207b7SJohn Levon	$param_map{$one} = {found => $UNKNOWN, links => []};
90*1f5207b7SJohn Levon    }
91*1f5207b7SJohn Levon    push @{$param_map{$one}->{links}}, $two;
92*1f5207b7SJohn Levon}
93*1f5207b7SJohn Levon
94*1f5207b7SJohn Levonsub load_all($)
95*1f5207b7SJohn Levon{
96*1f5207b7SJohn Levon    my $file = shift;
97*1f5207b7SJohn Levon
98*1f5207b7SJohn Levon    open(FILE, "<$file");
99*1f5207b7SJohn Levon    while (<FILE>) {
100*1f5207b7SJohn Levon	if (/.*?:\d+ (.*?)\(\) info: func_call (.*)/) {
101*1f5207b7SJohn Levon	    add_link("$1", "$2");
102*1f5207b7SJohn Levon	}
103*1f5207b7SJohn Levon    }
104*1f5207b7SJohn Levon}
105*1f5207b7SJohn Levon
106*1f5207b7SJohn Levonsub set_all_unknown()
107*1f5207b7SJohn Levon{
108*1f5207b7SJohn Levon    my $i = 0;
109*1f5207b7SJohn Levon
110*1f5207b7SJohn Levon    foreach my $func (keys %param_map){
111*1f5207b7SJohn Levon	%{$param_map{$func}}->{found} = $UNKNOWN;
112*1f5207b7SJohn Levon    }
113*1f5207b7SJohn Levon}
114*1f5207b7SJohn Levon
115*1f5207b7SJohn Levonmy $file = shift();
116*1f5207b7SJohn Levonif (!$file) {
117*1f5207b7SJohn Levon    usage();
118*1f5207b7SJohn Levon}
119*1f5207b7SJohn Levon
120*1f5207b7SJohn Levonif (! -e $file) {
121*1f5207b7SJohn Levon    printf("Error:  $file does not exist.\n");
122*1f5207b7SJohn Levon    exit(1);
123*1f5207b7SJohn Levon}
124*1f5207b7SJohn Levon
125*1f5207b7SJohn Levonprint("Loading functions...\n");
126*1f5207b7SJohn Levonload_all($file);
127*1f5207b7SJohn Levon
128*1f5207b7SJohn Levonwhile (1) {
129*1f5207b7SJohn Levon    my $start_func;
130*1f5207b7SJohn Levon    my $end_func;
131*1f5207b7SJohn Levon
132*1f5207b7SJohn Levon    print("Enter the start function:  ");
133*1f5207b7SJohn Levon    $start_func = <STDIN>;
134*1f5207b7SJohn Levon    $start_func =~ s/^\s+|\s+$//g;
135*1f5207b7SJohn Levon    print("Enter the target function:  ");
136*1f5207b7SJohn Levon    $end_func = <STDIN>;
137*1f5207b7SJohn Levon    $end_func =~ s/^\s+|\s+$//g;
138*1f5207b7SJohn Levon
139*1f5207b7SJohn Levon
140*1f5207b7SJohn Levon    print("$start_func to $end_func\n");
141*1f5207b7SJohn Levon    if ($start_func =~ /./ && $end_func =~ /./) {
142*1f5207b7SJohn Levon	search($start_func, $end_func);
143*1f5207b7SJohn Levon    }
144*1f5207b7SJohn Levon
145*1f5207b7SJohn Levon    set_all_unknown();
146*1f5207b7SJohn Levon}
147