williamr/find_public_apis.pl
changeset 4 60053dab7e2a
parent 3 8b87ea768cb8
child 8 b40f95834f85
equal deleted inserted replaced
3:8b87ea768cb8 4:60053dab7e2a
    19 
    19 
    20 use strict;
    20 use strict;
    21 my $debug = 0;
    21 my $debug = 0;
    22 
    22 
    23 my @public_included = ();
    23 my @public_included = ();
    24 my $reason;
       
    25 
    24 
    26 sub is_public_api($$)
    25 sub analyse_api($$$)
    27   {
    26   {
    28   my ($file,$name) = @_;
    27   my ($file,$name,$includelistref) = @_;
    29   
    28   
    30   if ($name =~ /^epoc32\/include\/platform\//)
    29   if ($name =~ /^epoc32\/include\/platform\//)
    31     {
    30     {
    32     # /epoc32/include/platform files are "Platform by export"
    31     # /epoc32/include/platform files are "Platform by export"
    33     $reason = "Platform by export";
    32     return "Platform by export";
    34     return 0; # Not public
       
    35     }
    33     }
    36   
    34   
    37   if ($name =~ /\./ && $name !~ /\.(h|rh|hrh|inl|c|hpp)$/i)
    35   if ($name =~ /\./ && $name !~ /\.(h|rh|hrh|inl|c|hpp)$/i)
    38     {
    36     {
    39     # Not a file which contains APIs anyway
    37     # Not a file which contains APIs anyway
    40     $reason = "Wrong extension";
    38     return "Non-API extension";
    41     return 0; # not public
       
    42     }
    39     }
    43 
    40 
    44   open FILE, "<$file" or print "ERROR: Cannot open $file: $!\n" and return 1; # assume Public
    41   open FILE, "<$file" or print "ERROR: Cannot open $file: $!\n" and return "Cannot open";
    45   my @lines = <FILE>; # they are all of a modest size
    42   my @lines = <FILE>; # they are all of a modest size
    46   close FILE;
    43   close FILE;
    47   
    44   
    48   my @includelines = grep /^\s*#include\s+/, @lines;
    45   my @includelines = grep /^\s*#include\s+/, @lines;
    49   my @includefiles = ();
    46   my @includefiles = ();
    53       {
    50       {
    54       my $filename = $1;
    51       my $filename = $1;
    55       my $extension = $2;
    52       my $extension = $2;
    56       
    53       
    57       # print "++ $filename ($extension)\n";
    54       # print "++ $filename ($extension)\n";
    58       if ($extension =~ /mbg|rsg|rls|ra/i)
    55       if ($extension =~ /mbg|rsg/i)
    59         {
    56         {
    60         # generated file referenced by #include
    57         # generated file referenced by #include
    61         push @includefiles, $filename; 
    58         push @{$includelistref}, $filename; 
    62         print STDERR "** $file - $includeline";
    59         print STDERR "** $file - $includeline";
    63         }
    60         }
    64       }
    61       }
    65     }
    62     }
    66   
    63   
    67   my @apitaglines = grep /\@published|\@internal/, @lines;
    64   my @apitaglines = grep /\@published|\@internal/, @lines;
    68   if (scalar @apitaglines == 0)
    65   if (scalar @apitaglines == 0)
    69     {
    66     {
    70     # no API classification tags - must be "Public by export" 
    67     # no API classification tags - must be "Public by export" 
    71     $reason = "Public by export";
    68     return "Public by export";
    72     }
    69     }
    73   else
    70   else
    74     {
    71     {
    75     if ($debug)
    72     if ($debug)
    76       {
    73       {
    78       }
    75       }
    79     my @publishedAll = grep /\@publishedAll/, @apitaglines;
    76     my @publishedAll = grep /\@publishedAll/, @apitaglines;
    80     if (scalar @publishedAll == 0)
    77     if (scalar @publishedAll == 0)
    81       {
    78       {
    82       # the API classification tags are all @publishedPartner or @internal
    79       # the API classification tags are all @publishedPartner or @internal
    83       $reason = "Platform by tag";
    80       return "Platform by tag";
    84       return 0; # not public
       
    85       }
    81       }
    86     # contains at least one @publishedAll element - must be "Public by tag"
    82     # contains at least one @publishedAll element - must be "Public by tag"
    87     $reason = "Public by tag";
    83     return "Public by tag";
    88     }
    84     }
    89   push @public_included, @includefiles;   # #included files are therefore also public
       
    90   return 1; # Public API
       
    91   }
    85   }
    92 
    86 
    93 my %classification;
    87 my %location_by_filename;
       
    88 my %precedent;
       
    89 
       
    90 # Read list of Symbian^1 files
       
    91 my $line;
       
    92 while ($line = <>)
       
    93   {
       
    94   chomp $line;
       
    95   $line =~ s/\\/\//g; # Unix separators please
       
    96   if ($line =~ /(epoc32\/include\/(.*\/)?([^\/]+))\s*$/)
       
    97     {
       
    98     my $fullname = $1;
       
    99     my $filename = $3;
       
   100 
       
   101     $precedent{lc $fullname} = $fullname;
       
   102     }
       
   103   }
       
   104 
       
   105 # Process epoc32\include tree
       
   106 
       
   107 my %rationale;
    94 my %origin;
   108 my %origin;
    95 my %ignoring_case;
   109 my %ignoring_case;
    96 
   110 
    97 sub scan_directory($$)
   111 sub scan_directory($$)
    98   {
   112   {
   111       {
   125       {
   112       scan_directory($newpath, $newname);
   126       scan_directory($newpath, $newname);
   113       next;
   127       next;
   114       }
   128       }
   115     
   129     
   116     if (is_public_api($newpath,$newname))
       
   117       {
       
   118       # print "PUBLIC\t$newname\t$reason\n";
       
   119       }
       
   120     else
       
   121       {
       
   122       # print "PARTNER\t$newname\t$reason\n";
       
   123       }
       
   124     $classification{$newname} = $reason;
       
   125     $origin{$newname} = "Symbian^2";
   130     $origin{$newname} = "Symbian^2";
   126     $ignoring_case{lc $newname} = $newname;
   131     $ignoring_case{lc $newname} = $newname;
       
   132     
       
   133     my @includefiles = ();
       
   134     my $reason = analyse_api($newpath,$newname, \@includefiles);
       
   135 
       
   136     if (defined $precedent{lc $newname})
       
   137       {
       
   138       $origin{$newname} = "Symbian^1";  # present in Symbian^1 list of Public apis
       
   139       if ($reason !~ /Public/)
       
   140         {
       
   141         $reason = "Public by precedent";    # was made public in Symbian^1
       
   142         }
       
   143       }
       
   144     $rationale{$newname} = $reason;
       
   145  
       
   146     if ($reason =~ /Public/)
       
   147       {
       
   148       push @public_included, @includefiles;   # #included files are therefore also public
       
   149       }
   127     }
   150     }
   128   }
   151   }
   129 
   152 
   130 scan_directory("/epoc32/include", "epoc32/include");
   153 scan_directory("/epoc32/include", "epoc32/include");
       
   154 
       
   155 # Add the generated files which are included in public API files
   131 
   156 
   132 foreach my $file (@public_included)
   157 foreach my $file (@public_included)
   133   {
   158   {
   134   # print "PUBLIC\tepoc32/include/$file\tIncluded\n";
   159   # print "PUBLIC\tepoc32/include/$file\tIncluded\n";
   135   my $newname = "epoc32/include/$file";
   160   my $newname = "epoc32/include/$file";
   136   $newname = $ignoring_case{lc $newname};
   161   $newname = $ignoring_case{lc $newname};
   137   $classification{$newname} = "Public by Inclusion";
   162   $rationale{$newname} = "Public by Inclusion";
   138   }
   163   }
   139 
   164 
   140 # Read list of Symbian^1 files
   165 # Look for Symbian^1 files which have moved or simply been deleted
   141 my $line;
   166 
   142 while ($line = <>)
   167 foreach my $file (values %precedent)
   143   {
   168   {
   144   chomp $line;
   169   if (!defined $origin{$file})
   145   $line =~ s/\\/\//g; # Unix separators please
       
   146   if ($line =~ /(epoc32\/include\/.*)\s*$/)
       
   147     {
   170     {
   148     my $name = $1;
   171     $rationale{$file} = "Deleted";
   149     $origin{$name} = "Symbian^1";
   172     $origin{$file} = "Symbian^1";
   150     if (!defined $ignoring_case{lc $name})
       
   151       {
       
   152       $classification{$name} = "Deleted";
       
   153       }
       
   154     }
   173     }
   155   }
   174   }
   156 
   175 
   157 print "Filename\tClassification\tReason\tOrigin\n";
   176 print "Filename\tClassification\tReason\tOrigin\n";
   158 foreach my $file (sort keys %classification)
   177 foreach my $file (sort keys %rationale)
   159   {
   178   {
   160   my $reason = $classification{$file};
   179   my $reason = $rationale{$file};
   161   my $type = "Platform";
   180   my $classification = "Platform";
   162   $type = "Public" if ($reason =~ /Public/);
   181   $classification = "Public" if ($reason =~ /Public/);
   163   print "$file\t$type\t$reason\t$origin{$file}\n";
   182   print "$file\t$classification\t$reason\t$origin{$file}\n";
   164   }
   183   }