summaryrefslogtreecommitdiff
path: root/tools/camldep
diff options
context:
space:
mode:
Diffstat (limited to 'tools/camldep')
-rwxr-xr-xtools/camldep91
1 files changed, 91 insertions, 0 deletions
diff --git a/tools/camldep b/tools/camldep
new file mode 100755
index 0000000000..8f53257970
--- /dev/null
+++ b/tools/camldep
@@ -0,0 +1,91 @@
+#!/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] <file> ...
+
+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|\.z[io]$||;
+ undef(%imports);
+ open(SRC, $source_name) || return;
+ while(<SRC>) {
+ 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);
+ if ($target_name =~ m/(.*)\.cmo$/ && -r ($source_name . "i")) {
+ push(@deps, "$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$/.cmi/;
+ push(@deps, $dep);
+ }
+ elsif ($dep = do find_path ("$modl.ml")) {
+ $dep =~ s/\.ml$/.cmo/;
+ push(@deps, $dep);
+ }
+ }
+ if ($#deps >= 0) {
+ print "$target_name: ";
+ $col = length($target_name) + 2;
+ foreach $dep (@deps) {
+ 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;
+}