#!/usr/local/bin/perl -w # # Copyright 2000 by Ken Coar. # Redistribution permitted in original or modified form provided # the copyright holder is attributed. # # This script uses the API dictionary module and the list of files # on the command line to update the dictionary from the current # sources. # # Use: # # find ~/apache-1.3 -type f -name \*.h |xargs ./findapi # # It's currently pretty inefficient and very poorly documented, but # it was a rush job. # # History: # # 2000-09-15 Ken Coar # Original version. # use APIdict; $dict = new APIdict; $dict->readfile("api.list"); $collecting = 0; $last_file = ""; while (<>) { if ($ARGV ne $last_file) { $last_file = $ARGV; } chomp; if (! $collecting) { if ($_ =~ m:^\s*(extern)?\s*API_[A-Z]+\s*(\([^)]*\)\s*)?:) { $collecting++; $file = $ARGV; $call = $_; $lineno = $.; } } else { s:^\s+::; $call .= " $_"; } if ($_ =~ m:;:) { $collecting = 0; } if ((! $collecting) && $call) { while ($call =~ m:"[^"]*[^\\]" ":) { $call =~ s:("[^"]*[^\\])"\s+":$1:g; } $call =~ s:<:\<:g; $call =~ s:>:\>:g; analyse($call, $file, $lineno); $call = ""; } } $dict->checkpoint(); sub analyse { my($call, $file, $lineno) = @_; $_ = $call; # # Throw away any leading or trailing whitespace, comments, et cetera. # s/^\s*([^;]+;).*/$1/; s:/\*.*?\*/::g; s:([^(]+)\s+\(:$1\(:g; # # Do some cleanup, such as removing extraneous whitespace and adding # it where it's missing. # s/\s{2,}/ /g; s/,(\S)/, $1/g; s/\)\s+;/\);/; # # Remove the export prefix and any 'extern' keyword for variable # declarations. # s/^extern\s+//; s/^API[_A-Z0-9]+\s*\(([^)]+\*)\)\s*/$1/; s/^API[_A-Z0-9]+\s*\(([^)]+)\)/$1/; s/^API[_A-Z0-9]+\s*//; s/^extern\s+//; # # Join up any pointer marks with the pointer identifier. We need to # do this now rather than earlier because of the removal of the # API prefix, which may have introduced the space. # s/ \* / \*/g; $definition = $_; # # Okey, we've obtained the definition. Now we need to take it to the # next level and figure out the name and type of the thing being # defined. # if (m:\);:) { # Trailing routine closure? $itype = 'R'; } else { $itype = 'D'; } # # Extract just the routine name from definitions. # s/[^(]*\s+\**([a-zA-Z][a-zA-Z0-9_]+)\(.*/$1/; s/\([^)]+\)\s*;/;/; /\**(\S+);/; $_ = $1; s/\[.+?\]//g; $item = $_; if ($_ && (! $dict->defined($item))) { print "Adding " . (($itype eq 'R') ? "routine" : "cell") . " $_\n"; if ($itype eq 'R') { $dict->define_routine($item, $definition, "", "", ""); } else { $dict->define_cell($item, $definition, "", "", ""); } } }