1#!/usr/bin/perl
2
3use strict;
4
5sub usage()
6{
7    print "$0 <smatch output file> <function> <parameter>\n";
8    print "Give this program a function and parameter and it follows to find\n";
9    print "how the parameter gets passed down to lower levels.\n'";
10    exit(1);
11}
12
13my %param_map;
14
15my $UNUSED   = 0;
16my $USED     = 1;
17
18sub print_link($)
19{
20    my $link = shift;
21
22    $link =~ s/%/ /;
23    print "$link\n";
24}
25
26sub recurse($)
27{
28    my $link = shift;
29
30    if ($param_map{$link}{used} == $USED) {
31	return;
32    }
33    ${param_map}{$link}->{used} = $USED;
34
35    print_link($link);
36
37    foreach my $l (@{$param_map{$link}{links}}){
38	recurse($l);
39    }
40
41}
42
43sub follow($$)
44{
45    my $f = shift;
46    my $p = shift;
47
48    recurse("$f%$p");
49}
50
51sub add_link($$)
52{
53    my $one = shift;
54    my $two = shift;
55
56    if (!defined($param_map{$one})) {
57	$param_map{$one} = {used => $UNUSED, links => []};
58    }
59    push @{$param_map{$one}{links}}, $two;
60}
61
62sub load_all($)
63{
64    my $file = shift;
65
66    open(FILE, "<$file");
67    while (<FILE>) {
68	if (/.*?:\d+ (.*?)\(\) info: param_mapper (\d+) => (.*?) (\d+)/) {
69	    add_link("$1%$2", "$3%$4");
70	}
71    }
72}
73
74sub set_all_unused()
75{
76    foreach my $func (keys %param_map){
77	($param_map{$func}{used} = $UNUSED);
78    }
79
80}
81
82my $file = shift();
83my $func = shift();
84my $param = shift();
85
86if (!defined($file) or !defined($func) or !defined($param)) {
87    usage();
88}
89
90if (! -e $file) {
91    printf("Error:  $file does not exist.\n");
92    exit(1);
93}
94
95load_all($file);
96
97while (1) {
98    follow($func, $param);
99
100    $func = shift();
101    $param = shift();
102    if (!defined($func) || !defined($param)) {
103	last;
104    }
105    set_all_unused();
106}
107