@libraries = (); @includes = (); %defines = (); %read_files = (); $debug = 0; $includes[++$#includes] = "."; $filename = ""; foreach $arg (@ARGV) { if ($arg =~ /^-d$/) { $debug = 1; } elsif ($arg =~ /^-D(.*)$/) { local($def) = $1; local($symbol) = $1; $def =~ s/^.*=//; $symbol =~ s/=.*$//; $defines{$symbol} = $def; } elsif ($arg =~ /^-I(.*)$/) { $includes[++$#includes] = $1; } else { $filename = $arg; } } if ($filename eq "") { print STDERR "listlibs.pl: require a filename\n"; exit 1; } if (-d "$filename") { %current_includes = (); @libraries = (); %known_libs = (); %known_includes = (); &process_directory($filename); } else { &process_file($filename); %current_includes = (); @libraries = (); %known_libs = (); %known_includes = (); &find_libraries($filename); } @libraries = reverse(@libraries); print "got $#libraries of them\n" if ($debug); &substitute_defines(); foreach $i (0..$#libraries) { printf "%s", $libraries[$i]; if ($i < $#libraries) { printf " "; } } printf "\n"; ########################################################################### sub process_file { local($filename) = shift; if ($debug) { printf "process_file: filename: %s\n", $filename; } # find the file local($ifile) = ""; if ($filename =~ /^\//) { $ifile = $filename; } else { foreach $include (@includes) { $ifile = "$include/$filename"; if ($debug) { #printf "process_file: looking for: %s\n", $ifile; } if (-f $ifile) { last; } } } if ($ifile eq "" || ! -f $ifile) { print STDERR "listlibs.pl: couldn't find file $file\n"; exit 1; } # read the file local($filecontents) = ""; open(IFILE,"<$ifile"); while () { if (/^\s*$/) { next; } $filecontents = "$filecontents$_"; } close(IFILE); $read_files{$filename} = $filecontents; # an empty file will look like a new file below so put in a newline if ($read_files{$filename} eq "") { $read_files{$filename} = "\n" } # read in other files referenced by this file foreach $line (&get_lines($filecontents)) { if ($line =~ /^\#\s*include\s*<(.+)>/) { local($newfile) = $1; if ($read_files{$newfile} eq "") { &process_file($newfile); } } } } sub get_lines { local($filecontents) = shift; local(@lines) = (); local($ifdepth) = 0; while ($filecontents ne "") { # get next line $filecontents =~ s/^(.*)\n//; local($line) = $1; # remove comments $line =~ s/\/\/.*$//; # remove leading trailing whitespace $line =~ s/^\s*//; $line =~ s/\s*$//; # this only handles ifdef's that are one level deep if ($line =~ /\#\s*ifdef\s+([a-zA-Z_]\w*)/) { local($symbol) = $1; if (! defined $defines{$symbol}) { while ($filecontents ne "") { $filecontents =~ s/^(.*)\n//; local($tline) = $1; last if ($tline =~ /\#\s*endif/); } } } elsif ($line =~ /\#\s*endif/) { # eat this endif } else { $lines[++$#lines] = $line if ($line ne ""); } } return @lines; } sub find_libraries { local($filename) = shift; if ($current_includes{$filename} == 1) { print STDERR "listlibs.pl: recursive include detected for $filename\n"; exit 1; } $current_includes{$filename} = 1; foreach $line (reverse(&get_lines($read_files{$filename}))) { if ($line =~ /^\#\s*include\s*<(.+)>/) { local($newfile) = $1; if ($known_includes{$newfile} != 1) { $known_includes{$newfile} = 1; &find_libraries($newfile); } } elsif ($known_libs{$line} != 1) { $known_libs{$line} = 1; $libraries[++$#libraries] = $line; } } delete $current_includes{$filename}; } sub substitute_defines { local($i); local($symbol); foreach $i (0..$#libraries) { foreach $symbol (keys(%defines)) { $libraries[$i] =~ s/$symbol/$defines{$symbol}/g; } } } sub process_directory { local ($dir) = shift; opendir(DIR,"$dir"); local (@files) = readdir(DIR); closedir(DIR); local ($i); foreach $i (@files) { if ("$i" eq "." || "$i" eq "..") { # skip } elsif (-d "$dir/$i") { process_directory("$dir/$i"); } elsif ("$i" eq "LIBS.h") { process_file("$dir/$i"); &find_libraries("$dir/$i"); } } }