123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- #! /usr/bin/perl -w
- #
- # Copyright 2000 Patrik Stridvall
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
- # License as published by the Free Software Foundation; either
- # version 2.1 of the License, or (at your option) any later version.
- #
- # This library is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # Lesser General Public License for more details.
- #
- # You should have received a copy of the GNU Lesser General Public
- # License along with this library; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- #
- use strict;
- my $name0=$0;
- $name0 =~ s%^.*/%%;
- my $invert = 0;
- my $pattern;
- my @files = ();
- my $usage;
- while(defined($_ = shift)) {
- if (/^-v$/) {
- $invert = 1;
- } elsif (/^--?(\?|h|help)$/) {
- $usage=0;
- } elsif (/^-/) {
- print STDERR "$name0:error: unknown option '$_'\n";
- $usage=2;
- last;
- } elsif(!defined($pattern)) {
- $pattern = $_;
- } else {
- push @files, $_;
- }
- }
- if (defined $usage)
- {
- print "Usage: $name0 [--help] [-v] pattern files...\n";
- print "where:\n";
- print "--help Prints this help message\n";
- print "-v Return functions that do not match pattern\n";
- print "pattern A regular expression for the function name\n";
- print "files... A list of files to search the function in\n";
- exit $usage;
- }
- foreach my $file (@files) {
- open(IN, "< $file") || die "Error: Can't open $file: $!\n";
- my $level = 0;
- my $extern_c = 0;
- my $again = 0;
- my $lookahead = 0;
- while($again || defined(my $line = <IN>)) {
- if(!$again) {
- chomp $line;
- if($lookahead) {
- $lookahead = 0;
- $_ .= "\n" . $line;
- } else {
- $_ = $line;
- }
- } else {
- $again = 0;
- }
- # remove C comments
- if(s/^(|.*?[^\/])(\/\*.*?\*\/)(.*)$/$1 $3/s) {
- $again = 1;
- next;
- } elsif(/^(.*?)\/\*/s) {
- $lookahead = 1;
- next;
- }
- # remove C++ comments
- while(s/^(.*?)\/\/.*?$/$1\n/s) { $again = 1; }
- if($again) { next; }
- # remove empty rows
- if(/^\s*$/) { next; }
- # remove preprocessor directives
- if(s/^\s*\#/\#/m) {
- if(/^\#[.\n\r]*?\\$/m) {
- $lookahead = 1;
- next;
- } elsif(s/^\#\s*(.*?)(\s+(.*?))?\s*$//m) {
- next;
- }
- }
- # Remove extern "C"
- if(s/^\s*extern[\s\n]+"C"[\s\n]+\{//m) {
- $extern_c = 1;
- $again = 1;
- next;
- } elsif(m/^\s*extern[\s\n]+"C"/m) {
- $lookahead = 1;
- next;
- }
- if($level > 0)
- {
- my $line = "";
- while(/^[^\{\}]/) {
- s/^([^\{\}\'\"]*)//s;
- $line .= $1;
- if(s/^\'//) {
- $line .= "\'";
- while(/^./ && !s/^\'//) {
- s/^([^\'\\]*)//s;
- $line .= $1;
- if(s/^\\//) {
- $line .= "\\";
- if(s/^(.)//s) {
- $line .= $1;
- if($1 eq "0") {
- s/^(\d{0,3})//s;
- $line .= $1;
- }
- }
- }
- }
- $line .= "\'";
- } elsif(s/^\"//) {
- $line .= "\"";
- while(/^./ && !s/^\"//) {
- s/^([^\"\\]*)//s;
- $line .= $1;
- if(s/^\\//) {
- $line .= "\\";
- if(s/^(.)//s) {
- $line .= $1;
- if($1 eq "0") {
- s/^(\d{0,3})//s;
- $line .= $1;
- }
- }
- }
- }
- $line .= "\"";
- }
- }
- if(s/^\{//) {
- $_ = $'; $again = 1;
- $line .= "{";
- $level++;
- } elsif(s/^\}//) {
- $_ = $'; $again = 1;
- $line .= "}" if $level > 1;
- $level--;
- if($level == -1 && $extern_c) {
- $extern_c = 0;
- $level = 0;
- }
- }
- next;
- } elsif(/^class[^\}]*{/) {
- $_ = $'; $again = 1;
- $level++;
- next;
- } elsif(/^class[^\}]*$/) {
- $lookahead = 1;
- next;
- } elsif(/^typedef[^\}]*;/) {
- next;
- } elsif(/(extern\s+|static\s+)?
- (?:__inline__\s+|__inline\s+|inline\s+)?
- ((struct\s+|union\s+|enum\s+)?(?:\w+(?:\:\:(?:\s*operator\s*[^\)\s]+)?)?)+((\s*(?:\*|\&))+\s*|\s+))
- ((__cdecl|__stdcall|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK)\s+)?
- ((?:\w+(?:\:\:)?)+(\(\w+\))?)\s*\(([^\)]*)\)\s*
- (?:\w+(?:\s*\([^\)]*\))?\s*)*\s*
- (\{|\;)/sx)
- {
- $_ = $'; $again = 1;
- if($11 eq "{") {
- $level++;
- }
- my $linkage = $1;
- my $return_type = $2;
- my $calling_convention = $7;
- my $name = $8;
- my $arguments = $10;
- if(!defined($linkage)) {
- $linkage = "";
- }
- if(!defined($calling_convention)) {
- $calling_convention = "";
- }
- $linkage =~ s/\s*$//;
- $return_type =~ s/\s*$//;
- $return_type =~ s/\s*\*\s*/*/g;
- $return_type =~ s/(\*+)/ $1/g;
- $arguments =~ y/\t\n/ /;
- $arguments =~ s/^\s*(.*?)\s*$/$1/;
- if($arguments eq "") { $arguments = "void" }
- my @argument_types;
- my @argument_names;
- my @arguments = split(/,/, $arguments);
- foreach my $n (0..$#arguments) {
- my $argument_type = "";
- my $argument_name = "";
- my $argument = $arguments[$n];
- $argument =~ s/^\s*(.*?)\s*$/$1/;
- # print " " . ($n + 1) . ": '$argument'\n";
- $argument =~ s/^(IN OUT(?=\s)|IN(?=\s)|OUT(?=\s)|\s*)\s*//;
- $argument =~ s/^(const(?=\s)|CONST(?=\s)|__const(?=\s)|__restrict(?=\s)|\s*)\s*//;
- if($argument =~ /^\.\.\.$/) {
- $argument_type = "...";
- $argument_name = "...";
- } elsif($argument =~ /^
- ((?:struct\s+|union\s+|enum\s+|(?:signed\s+|unsigned\s+)
- (?:short\s+(?=int)|long\s+(?=int))?)?(?:\w+(?:\:\:)?)+)\s*
- ((?:const(?=\s)|CONST(?=\s)|__const(?=\s)|__restrict(?=\s))?\s*(?:\*\s*?)*)\s*
- (?:const(?=\s)|CONST(?=\s)|__const(?=\s)|__restrict(?=\s))?\s*
- (\w*)\s*
- (?:\[\]|\s+OPTIONAL)?/x)
- {
- $argument_type = "$1";
- if($2 ne "") {
- $argument_type .= " $2";
- }
- $argument_name = $3;
- $argument_type =~ s/\s*const\s*/ /;
- $argument_type =~ s/^\s*(.*?)\s*$/$1/;
- $argument_name =~ s/^\s*(.*?)\s*$/$1/;
- } else {
- die "$file: $.: syntax error: '$argument'\n";
- }
- $argument_types[$n] = $argument_type;
- $argument_names[$n] = $argument_name;
- # print " " . ($n + 1) . ": '$argument_type': '$argument_name'\n";
- }
- if($#argument_types == 0 && $argument_types[0] =~ /^void$/i) {
- $#argument_types = -1;
- $#argument_names = -1;
- }
- @arguments = ();
- foreach my $n (0..$#argument_types) {
- if($argument_names[$n] && $argument_names[$n] ne "...") {
- if($argument_types[$n] !~ /\*$/) {
- $arguments[$n] = $argument_types[$n] . " " . $argument_names[$n];
- } else {
- $arguments[$n] = $argument_types[$n] . $argument_names[$n];
- }
- } else {
- $arguments[$n] = $argument_types[$n];
- }
- }
- $arguments = join(", ", @arguments);
- if(!$arguments) { $arguments = "void"; }
- if((!$invert && $name =~ /$pattern/) || ($invert && $name !~ /$pattern/)) {
- if($calling_convention) {
- print "$return_type $calling_convention $name($arguments)\n";
- } else {
- if($return_type =~ /\*$/) {
- print "$return_type$name($arguments)\n";
- } else {
- print "$return_type $name($arguments)\n";
- }
- }
- }
- } elsif(/\'(?:[^\\\']*|\\.)*\'/s) {
- $_ = $'; $again = 1;
- } elsif(/\"(?:[^\\\"]*|\\.)*\"/s) {
- $_ = $'; $again = 1;
- } elsif(/;/s) {
- $_ = $'; $again = 1;
- } elsif(/extern\s+"C"\s+{/s) {
- $_ = $'; $again = 1;
- } elsif(/\{/s) {
- $_ = $'; $again = 1;
- $level++;
- } else {
- $lookahead = 1;
- }
- }
- close(IN);
- }
|