#!/usr/local/bin/perl # To scan a Caml Light source file, find all references to external modules # (open Foo or Foo.bar), and output the dependencies on standard output. # # Usage: camldep [-I path] ... while ($#ARGV >= 0) { $_ = shift(@ARGV); if (/^-I(.*)$/) { $dir = $1 ? $1 : shift(@ARGV); $dir =~ s|/$||; unshift(@path, $dir); } elsif (/(.*)\.mli$/ || /(.*)\.cmi$/) { do scan_source ($_, "$1.cmi"); } elsif (/(.*)\.ml$/ || /(.*)\.cmo$/) { do scan_source ($_, "$1.cmo"); } else { die "Don't know what to do with $_"; } } sub scan_source { local ($source_name, $target_name) = @_; $modname = $target_name; $modname =~ s|^.*/||; $modname =~ s|\.cm[iox]$||; undef(%imports); open(SRC, $source_name) || return; while() { if (m/\bopen\s*([A-Z][a-zA-Z0-9_]*)\b/) { $imports{$1} = 1; } while(m/\b([A-Z][a-zA-Z0-9_]*)\./) { $imports{$1} = 1; $_ = $'; } } close(SRC); undef(@deps); undef(@optdeps); if ($target_name =~ m/(.*)\.cmo$/ && -r ($source_name . "i")) { push(@deps, "$1.cmi"); push(@optdeps, "$1.cmi"); } foreach $modl (keys(%imports)) { $modl = do lowercase($modl); next if ($modl eq $modname); if ($dep = do find_path ("$modl.mli")) { $dep =~ s/\.mli$//; push(@deps, "$dep.cmi"); if (-f "$dep.ml") { push(@optdeps, "$dep.cmx"); } else { push(@optdeps, "$dep.cmi"); } } elsif ($dep = do find_path ("$modl.ml")) { $dep =~ s/\.ml$//; push(@deps, "$dep.cmo"); push(@optdeps, "$dep.cmx"); } } if ($#deps >= 0) { print "$target_name: "; do print_deps(@deps); } if ($target_name =~ /^(.*)\.cmo$/ && $#optdeps >= 0) { print "$1.cmx: "; do print_deps(@optdeps); } } sub print_deps { $col = length($target_name) + 3; foreach $dep (@_) { next if $dep eq $target_name; $col += length($dep) + 1; if ($col >= 77) { print "\\\n "; $col = length($dep) + 5; } print $dep, " "; } print "\n"; } sub find_path { local ($filename) = @_; return $filename if (-r $filename); foreach $dir (@path) { return "$dir/$filename" if (-r "$dir/$filename"); } return 0; } sub lowercase { local ($_) = @_; m/^(.)(.*)$/; $hd = $1; $tl = $2; $hd =~ tr/A-Z/a-z/; return $hd . $tl; }