summaryrefslogtreecommitdiff
path: root/tools/camldep
blob: 8f53257970a2473336b539f078d20c8ddda27f9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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;
}