function_grep.pl 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #! /usr/bin/perl -w
  2. #
  3. # Copyright 2000 Patrik Stridvall
  4. #
  5. # This library is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Lesser General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 2.1 of the License, or (at your option) any later version.
  9. #
  10. # This library is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. # Lesser General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Lesser General Public
  16. # License along with this library; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  18. #
  19. use strict;
  20. my $name0=$0;
  21. $name0 =~ s%^.*/%%;
  22. my $invert = 0;
  23. my $pattern;
  24. my @files = ();
  25. my $usage;
  26. while(defined($_ = shift)) {
  27. if (/^-v$/) {
  28. $invert = 1;
  29. } elsif (/^--?(\?|h|help)$/) {
  30. $usage=0;
  31. } elsif (/^-/) {
  32. print STDERR "$name0:error: unknown option '$_'\n";
  33. $usage=2;
  34. last;
  35. } elsif(!defined($pattern)) {
  36. $pattern = $_;
  37. } else {
  38. push @files, $_;
  39. }
  40. }
  41. if (defined $usage)
  42. {
  43. print "Usage: $name0 [--help] [-v] pattern files...\n";
  44. print "where:\n";
  45. print "--help Prints this help message\n";
  46. print "-v Return functions that do not match pattern\n";
  47. print "pattern A regular expression for the function name\n";
  48. print "files... A list of files to search the function in\n";
  49. exit $usage;
  50. }
  51. foreach my $file (@files) {
  52. open(IN, "< $file") || die "Error: Can't open $file: $!\n";
  53. my $level = 0;
  54. my $extern_c = 0;
  55. my $again = 0;
  56. my $lookahead = 0;
  57. while($again || defined(my $line = <IN>)) {
  58. if(!$again) {
  59. chomp $line;
  60. if($lookahead) {
  61. $lookahead = 0;
  62. $_ .= "\n" . $line;
  63. } else {
  64. $_ = $line;
  65. }
  66. } else {
  67. $again = 0;
  68. }
  69. # remove C comments
  70. if(s/^(|.*?[^\/])(\/\*.*?\*\/)(.*)$/$1 $3/s) {
  71. $again = 1;
  72. next;
  73. } elsif(/^(.*?)\/\*/s) {
  74. $lookahead = 1;
  75. next;
  76. }
  77. # remove C++ comments
  78. while(s/^(.*?)\/\/.*?$/$1\n/s) { $again = 1; }
  79. if($again) { next; }
  80. # remove empty rows
  81. if(/^\s*$/) { next; }
  82. # remove preprocessor directives
  83. if(s/^\s*\#/\#/m) {
  84. if(/^\#[.\n\r]*?\\$/m) {
  85. $lookahead = 1;
  86. next;
  87. } elsif(s/^\#\s*(.*?)(\s+(.*?))?\s*$//m) {
  88. next;
  89. }
  90. }
  91. # Remove extern "C"
  92. if(s/^\s*extern[\s\n]+"C"[\s\n]+\{//m) {
  93. $extern_c = 1;
  94. $again = 1;
  95. next;
  96. } elsif(m/^\s*extern[\s\n]+"C"/m) {
  97. $lookahead = 1;
  98. next;
  99. }
  100. if($level > 0)
  101. {
  102. my $line = "";
  103. while(/^[^\{\}]/) {
  104. s/^([^\{\}\'\"]*)//s;
  105. $line .= $1;
  106. if(s/^\'//) {
  107. $line .= "\'";
  108. while(/^./ && !s/^\'//) {
  109. s/^([^\'\\]*)//s;
  110. $line .= $1;
  111. if(s/^\\//) {
  112. $line .= "\\";
  113. if(s/^(.)//s) {
  114. $line .= $1;
  115. if($1 eq "0") {
  116. s/^(\d{0,3})//s;
  117. $line .= $1;
  118. }
  119. }
  120. }
  121. }
  122. $line .= "\'";
  123. } elsif(s/^\"//) {
  124. $line .= "\"";
  125. while(/^./ && !s/^\"//) {
  126. s/^([^\"\\]*)//s;
  127. $line .= $1;
  128. if(s/^\\//) {
  129. $line .= "\\";
  130. if(s/^(.)//s) {
  131. $line .= $1;
  132. if($1 eq "0") {
  133. s/^(\d{0,3})//s;
  134. $line .= $1;
  135. }
  136. }
  137. }
  138. }
  139. $line .= "\"";
  140. }
  141. }
  142. if(s/^\{//) {
  143. $_ = $'; $again = 1;
  144. $line .= "{";
  145. $level++;
  146. } elsif(s/^\}//) {
  147. $_ = $'; $again = 1;
  148. $line .= "}" if $level > 1;
  149. $level--;
  150. if($level == -1 && $extern_c) {
  151. $extern_c = 0;
  152. $level = 0;
  153. }
  154. }
  155. next;
  156. } elsif(/^class[^\}]*{/) {
  157. $_ = $'; $again = 1;
  158. $level++;
  159. next;
  160. } elsif(/^class[^\}]*$/) {
  161. $lookahead = 1;
  162. next;
  163. } elsif(/^typedef[^\}]*;/) {
  164. next;
  165. } elsif(/(extern\s+|static\s+)?
  166. (?:__inline__\s+|__inline\s+|inline\s+)?
  167. ((struct\s+|union\s+|enum\s+)?(?:\w+(?:\:\:(?:\s*operator\s*[^\)\s]+)?)?)+((\s*(?:\*|\&))+\s*|\s+))
  168. ((__cdecl|__stdcall|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK)\s+)?
  169. ((?:\w+(?:\:\:)?)+(\(\w+\))?)\s*\(([^\)]*)\)\s*
  170. (?:\w+(?:\s*\([^\)]*\))?\s*)*\s*
  171. (\{|\;)/sx)
  172. {
  173. $_ = $'; $again = 1;
  174. if($11 eq "{") {
  175. $level++;
  176. }
  177. my $linkage = $1;
  178. my $return_type = $2;
  179. my $calling_convention = $7;
  180. my $name = $8;
  181. my $arguments = $10;
  182. if(!defined($linkage)) {
  183. $linkage = "";
  184. }
  185. if(!defined($calling_convention)) {
  186. $calling_convention = "";
  187. }
  188. $linkage =~ s/\s*$//;
  189. $return_type =~ s/\s*$//;
  190. $return_type =~ s/\s*\*\s*/*/g;
  191. $return_type =~ s/(\*+)/ $1/g;
  192. $arguments =~ y/\t\n/ /;
  193. $arguments =~ s/^\s*(.*?)\s*$/$1/;
  194. if($arguments eq "") { $arguments = "void" }
  195. my @argument_types;
  196. my @argument_names;
  197. my @arguments = split(/,/, $arguments);
  198. foreach my $n (0..$#arguments) {
  199. my $argument_type = "";
  200. my $argument_name = "";
  201. my $argument = $arguments[$n];
  202. $argument =~ s/^\s*(.*?)\s*$/$1/;
  203. # print " " . ($n + 1) . ": '$argument'\n";
  204. $argument =~ s/^(IN OUT(?=\s)|IN(?=\s)|OUT(?=\s)|\s*)\s*//;
  205. $argument =~ s/^(const(?=\s)|CONST(?=\s)|__const(?=\s)|__restrict(?=\s)|\s*)\s*//;
  206. if($argument =~ /^\.\.\.$/) {
  207. $argument_type = "...";
  208. $argument_name = "...";
  209. } elsif($argument =~ /^
  210. ((?:struct\s+|union\s+|enum\s+|(?:signed\s+|unsigned\s+)
  211. (?:short\s+(?=int)|long\s+(?=int))?)?(?:\w+(?:\:\:)?)+)\s*
  212. ((?:const(?=\s)|CONST(?=\s)|__const(?=\s)|__restrict(?=\s))?\s*(?:\*\s*?)*)\s*
  213. (?:const(?=\s)|CONST(?=\s)|__const(?=\s)|__restrict(?=\s))?\s*
  214. (\w*)\s*
  215. (?:\[\]|\s+OPTIONAL)?/x)
  216. {
  217. $argument_type = "$1";
  218. if($2 ne "") {
  219. $argument_type .= " $2";
  220. }
  221. $argument_name = $3;
  222. $argument_type =~ s/\s*const\s*/ /;
  223. $argument_type =~ s/^\s*(.*?)\s*$/$1/;
  224. $argument_name =~ s/^\s*(.*?)\s*$/$1/;
  225. } else {
  226. die "$file: $.: syntax error: '$argument'\n";
  227. }
  228. $argument_types[$n] = $argument_type;
  229. $argument_names[$n] = $argument_name;
  230. # print " " . ($n + 1) . ": '$argument_type': '$argument_name'\n";
  231. }
  232. if($#argument_types == 0 && $argument_types[0] =~ /^void$/i) {
  233. $#argument_types = -1;
  234. $#argument_names = -1;
  235. }
  236. @arguments = ();
  237. foreach my $n (0..$#argument_types) {
  238. if($argument_names[$n] && $argument_names[$n] ne "...") {
  239. if($argument_types[$n] !~ /\*$/) {
  240. $arguments[$n] = $argument_types[$n] . " " . $argument_names[$n];
  241. } else {
  242. $arguments[$n] = $argument_types[$n] . $argument_names[$n];
  243. }
  244. } else {
  245. $arguments[$n] = $argument_types[$n];
  246. }
  247. }
  248. $arguments = join(", ", @arguments);
  249. if(!$arguments) { $arguments = "void"; }
  250. if((!$invert && $name =~ /$pattern/) || ($invert && $name !~ /$pattern/)) {
  251. if($calling_convention) {
  252. print "$return_type $calling_convention $name($arguments)\n";
  253. } else {
  254. if($return_type =~ /\*$/) {
  255. print "$return_type$name($arguments)\n";
  256. } else {
  257. print "$return_type $name($arguments)\n";
  258. }
  259. }
  260. }
  261. } elsif(/\'(?:[^\\\']*|\\.)*\'/s) {
  262. $_ = $'; $again = 1;
  263. } elsif(/\"(?:[^\\\"]*|\\.)*\"/s) {
  264. $_ = $'; $again = 1;
  265. } elsif(/;/s) {
  266. $_ = $'; $again = 1;
  267. } elsif(/extern\s+"C"\s+{/s) {
  268. $_ = $'; $again = 1;
  269. } elsif(/\{/s) {
  270. $_ = $'; $again = 1;
  271. $level++;
  272. } else {
  273. $lookahead = 1;
  274. }
  275. }
  276. close(IN);
  277. }