Completely rewritten
authorshort <>
Tue, 6 Nov 2001 02:48:39 +0000 (02:48 +0000)
committershort <>
Tue, 6 Nov 2001 02:48:39 +0000 (02:48 +0000)
 - now uses Perl instead of bash
   - drastical speed improvement
 - a lot of new diseases is now detected

bin/checkstatic

index e525384..f2d4911 100755 (executable)
-#! /bin/sh
-
-fis="${*:-*.o}"
-
-for i in $fis;do
-       rest="`echo '' $fis ''|sed "s# $i # #"`"
-       trail="()"
-       for t in T BCDRS;do
-               for sym in `nm $i|sed -n 's/^.* ['$t'] \(.*\)$/\1/p'`;do
-                       if nm $rest|grep -q ' U '"$sym"'$';then :;else
-                               echo "$i        $sym$trail"|sed 's/\.o  /.c     /'
-                       fi
-               done
-               trail=""
-       done
-done
-
-echo
-
-function checkextern
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use Cwd;
+use Data::Dumper;
+use Getopt::Long;
+
+
+our(%symtab)=();
+
+our($D);
+die if !GetOptions("d|debug+",\$D);
+
+
+sub defmiss
+{
+my($ref,$missval,$sub)=@_;
+
+       $$ref=$missval if !defined $$ref;
+       &{$sub}($ref);
+}
+
+sub addsymtype
+{
+my($slot,$type,$symref)=@_;
+
+       defmiss(\$slot,{},sub {
+               my($typeref)=@_;
+               push(@{$$$typeref{$type}},$symref);
+               });
+}
+
+sub storesym
 {
-       ctags -f - --c-types=$1 `cvsfiles|grep '\.h$'` | \
-                       if $2;then
-                               grep '  /\^extern '
-                       else
-                               cat
-                       fi \
-                       | while read -r line;do
-               sym="` echo "$line" | awk '{print $1}'`"
-               file="`echo "$line" | awk '{print $2}'`"
-               if nm $fis|grep -q " [$3] ""$sym"'$';then :;else
-                       echo "extern    $file   $sym$4"
-               fi
-       done
+my(%sym)=@_;
+
+       $sym{"fn_c"}=~s#^$ENV{PWD}/#./# if defined $sym{"fn_c"};
+       defmiss(\$symtab{$sym{"name"}},{},sub {
+               my($slotref)=@_;
+               my($type)=$sym{"type"};
+               addsymtype($$slotref,$type,\%sym);
+               addsymtype($$slotref,$type,\%sym)
+                               if ($type!~/nU/ && ($type=~s/(n)[[:upper:]]/$1+/ || $type=~s/(n)[[:lower:]]/$1-/));
+               });
 }
 
-checkextern x true  BCDRS ""
-checkextern p false T     "()"
+open(NM,"-|",'find -name "*.o"|xargs nm -f posix --print-file-name --no-sort --line-numbers')
+               or die "Cannot get nm output: $!";
+while (<NM>) {
+       chomp;
+       die "Line $. of nm output not recognized: $_"
+               #     $1         $2    $3              $4
+               if !/^([^:]*):\s*(\S*) (\w) [^\t]*(?:\t(.*))?$/;
+       storesym(
+               "fn_o"=>$1,
+               "name"=>$2,
+               "type"=>"n$3",
+               "fn_c"=>$4,
+               );
+       }
+close NM;
+
+open(CTAGS,"-|",'find -name "*.h"|xargs ctags -f - --c-types=xp')
+               or die "Cannot get ctags output: $!";
+while (<CTAGS>) {
+       chomp;
+       die "Line $. of ctags output not recognized: $_"
+               #     $1        $2            $3
+               if !/^([^\t]*)\t([^\t]*)\t.*\t(\w)$/;
+       storesym(
+               "name"=>$1,
+               "fn_c"=>$2,
+               "type"=>"c$3",
+               );
+       }
+close CTAGS;
+
+print Data::Dumper->Dump([\%symtab],["%symtab"]) if $D;
+
+sub dumpsyms
+{
+my($error,@arr)=@_;
+
+       print("$error ".$arr[0]{"name"}.($arr[0]{"type"}=~/cp|n[tT]/ ? "()" : "").":\n");
+       my($symref);
+       while ($symref=shift(@arr)) {
+               print("\t");
+               if (defined($$symref{"fn_c"})) {
+                       print($$symref{"fn_c"});
+                       print("\t(".$$symref{"fn_o"}.")") if defined $$symref{"fn_o"};
+                       }
+               else {
+                       my($fn)=$$symref{"fn_o"};
+                       $fn=~s/\.o$/.c/;
+                       print($fn);
+                       }
+               print("\n");
+               }
+}
+
+sub refendef
+{
+my($ref)=@_;
+
+       return [] if !defined($ref);
+       return $ref;
+}
+
+my($symname);
+foreach $symname (sort keys %symtab) {
+       my($typesref)=$symtab{$symname};
+       my($ref,$ref1,$ref2);
+
+# >=2 n[:upper:]\U symbols => global conflict
+       if (@{refendef($ref=$$typesref{"n+"})}>=2) {
+               dumpsyms("global conflict",@{$ref});
+               }
+
+# >=1 n[:upper:]\U symbol && >=1 n[:lower:] symbol => local override
+       if (@{refendef($ref1=$$typesref{"n+"})}>=1 && @{refendef($ref2=$$typesref{"n-"})}>=1) {
+               dumpsyms("local override of global",@{$ref1});
+               dumpsyms(" -- with local",@{$ref2});
+               }
+
+# >=1 n[:upper:]\U symbol && ==0 nU symbol => global singularity
+       if (@{refendef($ref=$$typesref{"n+"})}>=1 && @{refendef($$typesref{"n-"})}==0) {
+               dumpsyms("global singularity",@{$ref});
+               }
+
+# >=1 cx symbol && ==0 n[:upper:]\U symbol => floating extern data
+       if (@{refendef($ref=$$typesref{"cx"})}>=1 && @{refendef($$typesref{"n+"})}==0) {
+               dumpsyms("floating extern data",@{$ref});
+               }
+
+# >=1 cp symbol && ==0 n[:upper:]\U symbol => floating extern func
+       if (@{refendef($ref=$$typesref{"cp"})}>=1 && @{refendef($$typesref{"n+"})}==0) {
+               dumpsyms("floating extern func",@{$ref});
+               }
+       }