orig rh72
[nethome.git] / bin / checkstatic
1 #! /usr/bin/perl
2
3 use strict;
4 use warnings;
5 use Cwd;
6 use Data::Dumper;
7 use Getopt::Long;
8
9
10 my(%symtab)=();
11
12 my($D);
13 die if !GetOptions("d|debug+",\$D);
14
15
16 sub defmiss
17 {
18 my($ref,$missval,$sub)=@_;
19
20         $$ref=$missval if !defined $$ref;
21         &{$sub}($ref);
22 }
23
24 sub addsymtype
25 {
26 my($slot,$type,$symref)=@_;
27
28         defmiss(\$slot,{},sub {
29                 my($typeref)=@_;
30                 push(@{$$$typeref{$type}},$symref);
31                 });
32 }
33
34 sub storesym
35 {
36 my(%sym)=@_;
37
38         $sym{"fn_c"}=~s#^$ENV{PWD}/#./# if defined $sym{"fn_c"};
39         defmiss(\$symtab{$sym{"name"}},{},sub {
40                 my($slotref)=@_;
41                 my($type)=$sym{"type"};
42                 addsymtype($$slotref,$type,\%sym);
43                 addsymtype($$slotref,$type,\%sym)
44                                 if ($type!~/nU/ && ($type=~s/(n)[[:upper:]]/$1+/ || $type=~s/(n)[[:lower:]]/$1-/));
45                 });
46 }
47
48 open(NM,"-|",'find -name "*.o"|xargs nm -f posix --print-file-name --no-sort --line-numbers')
49                 or die "Cannot get nm output: $!";
50 while (<NM>) {
51         chomp;
52         die "Line $. of nm output not recognized: $_"
53                 #     $1         $2    $3              $4
54                 if !/^([^:]*):\s*(\S*) (\w) [^\t]*(?:\t(.*))?$/;
55         storesym(
56                 "fn_o"=>$1,
57                 "name"=>$2,
58                 "type"=>"n$3",
59                 "fn_c"=>$4,
60                 );
61         }
62 close NM;
63
64 open(CTAGS,"-|",'find -name "*.h"|xargs ctags -f - --c-types=xp')
65                 or die "Cannot get ctags output: $!";
66 while (<CTAGS>) {
67         chomp;
68         die "Line $. of ctags output not recognized: $_"
69                 #     $1        $2            $3
70                 if !/^([^\t]*)\t([^\t]*)\t.*\t(\w)$/;
71         storesym(
72                 "name"=>$1,
73                 "fn_c"=>$2,
74                 "type"=>"c$3",
75                 );
76         }
77 close CTAGS;
78
79 print Data::Dumper->Dump([\%symtab],["%symtab"]) if $D;
80
81 sub dumpsyms
82 {
83 my($error,@arr)=@_;
84
85         print("$error ".$arr[0]{"name"}.($arr[0]{"type"}=~/cp|n[tT]/ ? "()" : "").":\n");
86         my($symref);
87         while ($symref=shift(@arr)) {
88                 print("\t");
89                 if (defined($$symref{"fn_c"})) {
90                         print($$symref{"fn_c"});
91                         print("\t(".$$symref{"fn_o"}.")") if defined $$symref{"fn_o"};
92                         }
93                 else {
94                         my($fn)=$$symref{"fn_o"};
95                         $fn=~s/\.o$/.c/;
96                         print($fn);
97                         }
98                 print("\n");
99                 }
100 }
101
102 sub refendef
103 {
104 my($ref)=@_;
105
106         return [] if !defined($ref);
107         return $ref;
108 }
109
110 my($symname);
111 foreach $symname (sort keys %symtab) {
112         my($typesref)=$symtab{$symname};
113         my($ref,$ref1,$ref2);
114
115 # >=2 n[:upper:]\U symbols => global conflict
116         if (@{refendef($ref=$$typesref{"n+"})}>=2) {
117                 dumpsyms("global conflict",@{$ref});
118                 }
119
120 # >=1 n[:upper:]\U symbol && >=1 n[:lower:] symbol => local override
121         if (@{refendef($ref1=$$typesref{"n+"})}>=1 && @{refendef($ref2=$$typesref{"n-"})}>=1) {
122                 dumpsyms("local override of global",@{$ref1});
123                 dumpsyms(" -- with local",@{$ref2});
124                 }
125
126 # >=1 n[:upper:]\U symbol && ==0 nU symbol => global singularity
127         if (@{refendef($ref=$$typesref{"n+"})}>=1 && @{refendef($$typesref{"n-"})}==0) {
128                 dumpsyms("global singularity",@{$ref});
129                 }
130
131 # >=1 cx symbol && ==0 n[:upper:]\U symbol => floating extern data
132         if (@{refendef($ref=$$typesref{"cx"})}>=1 && @{refendef($$typesref{"n+"})}==0) {
133                 dumpsyms("floating extern data",@{$ref});
134                 }
135
136 # >=1 cp symbol && ==0 n[:upper:]\U symbol => floating extern func
137         if (@{refendef($ref=$$typesref{"cp"})}>=1 && @{refendef($$typesref{"n+"})}==0) {
138                 dumpsyms("floating extern func",@{$ref});
139                 }
140         }