blob: c6972be327155eda03a8157e0009891408f0bd57 [file] [log] [blame]
Reid Spencer8dd91272005-05-16 18:30:38 +00001#!/usr/bin/perl -w
2#
3# Program: userloc.pl
4#
5# Synopsis: This program uses "cvs annotate" to get a summary of how many lines
6# of code the various developres are responsible for. It takes one
7# argument, the directory to process. If the argument is not specified
8# then the cwd is used. The directory must be an LLVM tree checked out
9# from cvs.
10#
Reid Spencer8ca43d72006-08-11 23:50:27 +000011# Syntax: userloc.pl [-tag=tag|-html... <directory>...
Reid Spencer8dd91272005-05-16 18:30:38 +000012#
13# Options:
Reid Spencer8dd91272005-05-16 18:30:38 +000014# -tag=tag
15# Use "tag" to select the revision (as per cvs -r option)
Reid Spencer1f0b9a12006-08-11 20:44:17 +000016# -filedetails
17# Report details about lines of code in each file for each user
Reid Spencer8dd91272005-05-16 18:30:38 +000018# -html
19# Generate HTML output instead of text output
Reid Spencer8ca43d72006-08-11 23:50:27 +000020# Directories:
21# The directories passed after the options should be relative paths to
22# directories of interest from the top of the llvm source tree, e.g. "lib"
23# or "include", etc.
Reid Spencer8dd91272005-05-16 18:30:38 +000024
Reid Spencer8ca43d72006-08-11 23:50:27 +000025die "Usage userloc.pl [-tag=tag|-html] <directories>..."
Reid Spencer8dd91272005-05-16 18:30:38 +000026 if ($#ARGV < 0);
27
28my $tag = "";
Reid Spencer8dd91272005-05-16 18:30:38 +000029my $html = 0;
Reid Spencer092ae902006-08-11 18:36:55 +000030my $debug = 0;
Reid Spencer1f0b9a12006-08-11 20:44:17 +000031my $filedetails = "";
Reid Spencer8ca43d72006-08-11 23:50:27 +000032while ( defined($ARGV[0]) && substr($ARGV[0],0,1) eq '-' )
Reid Spencer8dd91272005-05-16 18:30:38 +000033{
Reid Spencer8ca43d72006-08-11 23:50:27 +000034 if ($ARGV[0] =~ /-tag=.*/) {
Reid Spencer8dd91272005-05-16 18:30:38 +000035 $tag = $ARGV[0];
36 $tag =~ s#-tag=(.*)#$1#;
Reid Spencer1f0b9a12006-08-11 20:44:17 +000037 } elsif ($ARGV[0] =~ /-filedetails/) {
38 $filedetails = 1;
Reid Spencer092ae902006-08-11 18:36:55 +000039 } elsif ($ARGV[0] eq "-html") {
Reid Spencer8dd91272005-05-16 18:30:38 +000040 $html = 1;
Reid Spencer092ae902006-08-11 18:36:55 +000041 } elsif ($ARGV[0] eq "-debug") {
42 $debug = 1;
43 } else {
Reid Spencer8dd91272005-05-16 18:30:38 +000044 die "Invalid option: $ARGV[0]";
45 }
46 shift;
47}
48
Reid Spencer8ca43d72006-08-11 23:50:27 +000049chomp(my $srcroot = `llvm-config --src-root`);
50my $llvmdo = "$srcroot/utils/llvmdo";
Reid Spencer8dd91272005-05-16 18:30:38 +000051my %Stats;
Reid Spencer1f0b9a12006-08-11 20:44:17 +000052my %FileStats;
Reid Spencer8dd91272005-05-16 18:30:38 +000053
Reid Spencer8ca43d72006-08-11 23:50:27 +000054my $annotate = "cvs -z6 annotate -lf ";
55if (length($tag) > 0)
Reid Spencer8dd91272005-05-16 18:30:38 +000056{
Reid Spencer8ca43d72006-08-11 23:50:27 +000057 $annotate = $annotate . " -r" . $tag;
Reid Spencer8dd91272005-05-16 18:30:38 +000058}
59
60sub GetCVSFiles
61{
62 my $d = $_[0];
63 my $files ="";
Reid Spencer8ca43d72006-08-11 23:50:27 +000064 open FILELIST,
65 "$llvmdo -dirs \"$d\" echo |" || die "Can't get list of files with llvmdo";
66 while ( defined($line = <FILELIST>) ) {
67 chomp($file = $line);
68 $files = "$files $file";
Reid Spencer8dd91272005-05-16 18:30:38 +000069 }
70 return $files;
71}
72
Reid Spencer092ae902006-08-11 18:36:55 +000073sub ScanDir
Reid Spencer8dd91272005-05-16 18:30:38 +000074{
75 my $Dir = $_[0];
76 my $files = GetCVSFiles($Dir);
77
Reid Spencer1f0b9a12006-08-11 20:44:17 +000078 open (DATA,"$annotate $files 2>&1 |")
Reid Spencer8dd91272005-05-16 18:30:38 +000079 || die "Can't read cvs annotation data";
80
Reid Spencer1f0b9a12006-08-11 20:44:17 +000081 my $curfile = "";
Reid Spencer8dd91272005-05-16 18:30:38 +000082 while ( defined($line = <DATA>) )
83 {
Reid Spencer1f0b9a12006-08-11 20:44:17 +000084 chomp($line);
85 if ($line =~ '^Annotations for.*') {
86 $curfile = $line;
87 $curfile =~ s#^Annotations for ([[:print:]]*)#$1#;
88 } elsif ($line =~ /^[0-9.]*[ \t]*\([^)]*\):/) {
89 $uname = $line;
90 $uname =~ s#^[0-9.]*[ \t]*\(([a-zA-Z0-9_.-]*) [^)]*\):.*#$1#;
91 $Stats{$uname}++;
92 if ($filedetails) {
93 $FileStats{$uname} = {} unless exists $FileStats{$uname};
94 ${$FileStats{$uname}}{$curfile}++;
95 }
Reid Spencer8dd91272005-05-16 18:30:38 +000096 }
97 }
Reid Spencer8dd91272005-05-16 18:30:38 +000098 close DATA;
99}
100
Reid Spencer8dd91272005-05-16 18:30:38 +0000101sub printStats
102{
103 my $dir = $_[0];
104 my $hash = $_[1];
Reid Spencer8ca43d72006-08-11 23:50:27 +0000105 my $user;
Reid Spencer8dd91272005-05-16 18:30:38 +0000106 my $total = 0;
107
Reid Spencer8ca43d72006-08-11 23:50:27 +0000108 foreach $user (keys %Stats) { $total += $Stats{$user}; }
Reid Spencer1f0b9a12006-08-11 20:44:17 +0000109
110 if ($html) {
111 print "<table>";
112 print " <tr><th style=\"text-align:right\">LOC</th>\n";
113 print " <th style=\"text-align:right\">\%LOC</th>\n";
114 print " <th style=\"text-align:left\">User</th>\n";
115 print "</tr>\n";
Reid Spencer8dd91272005-05-16 18:30:38 +0000116 }
117
Reid Spencer8ca43d72006-08-11 23:50:27 +0000118 foreach $user ( sort keys %Stats )
Reid Spencer8dd91272005-05-16 18:30:38 +0000119 {
Reid Spencer8ca43d72006-08-11 23:50:27 +0000120 my $v = $Stats{$user};
Reid Spencer8dd91272005-05-16 18:30:38 +0000121 if (defined($v))
122 {
Reid Spencer1f0b9a12006-08-11 20:44:17 +0000123 if ($html) {
Reid Spencer8ca43d72006-08-11 23:50:27 +0000124 printf "<tr><td style=\"text-align:right\">%d</td><td style=\"text-align:right\">(%4.1f%%)</td><td style=\"text-align:left\">", $v, (100.0/$total)*$v;
125 if ($filedetails) {
126 print "<a href=\"#$user\">$user</a></td></tr>";
127 } else {
128 print $user,"</td></tr>";
129 }
Reid Spencer1f0b9a12006-08-11 20:44:17 +0000130 } else {
Reid Spencer8ca43d72006-08-11 23:50:27 +0000131 printf "%8d (%4.1f%%) %s\n", $v, (100.0/$total)*$v, $user;
Reid Spencer8dd91272005-05-16 18:30:38 +0000132 }
Reid Spencer8dd91272005-05-16 18:30:38 +0000133 }
134 }
Reid Spencer1f0b9a12006-08-11 20:44:17 +0000135 print "</table>\n" if ($html);
136
137 if ($filedetails) {
138 foreach $user (sort keys %FileStats) {
139 my $total = 0;
140 foreach $file (sort keys %{$FileStats{$user}}) {
141 $total += ${$FileStats{$user}}{$file}
142 }
143 if ($html) {
Reid Spencer8ca43d72006-08-11 23:50:27 +0000144 print "<table><tr><th style=\"text-align:left\" colspan=\"3\"><a name=\"$user\">$user</a></th></tr>\n";
Reid Spencer1f0b9a12006-08-11 20:44:17 +0000145 } else {
146 print $user,":\n";
147 }
148 foreach $file (sort keys %{$FileStats{$user}}) {
149 my $v = ${$FileStats{$user}}{$file};
150 if ($html) {
151 printf "<tr><td style=\"text-align:right\">&nbsp;&nbsp;%d</td><td
152 style=\"text-align:right\">&nbsp;%4.1f%%</td><td
153 style=\"text-align:left\">%s</td></tr>",$v, (100.0/$total)*$v,$file;
154 } else {
155 printf "%8d (%4.1f%%) %s\n", $v, (100.0/$total)*$v, $file;
156 }
157 }
158 if ($html) { print "</table>\n"; }
159 }
160 }
Reid Spencer8dd91272005-05-16 18:30:38 +0000161}
162
Reid Spencer8dd91272005-05-16 18:30:38 +0000163
164if ($html)
165{
166print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
167print "<html>\n<head>\n";
168print " <title>LLVM LOC Based On CVS Annotation</title>\n";
169print " <link rel=\"stylesheet\" href=\"llvm.css\" type=\"text/css\"/>\n";
170print "</head>\n";
171print "<body><div class=\"doc_title\">LLVM LOC Based On CVS Annotation</div>\n";
172print "<p>This document shows the total lines of code per user in each\n";
173print "LLVM directory. Lines of code are attributed by the user that last\n";
174print "committed the line. This does not necessarily reflect authorship.</p>\n";
Reid Spencer8dd91272005-05-16 18:30:38 +0000175}
176
Reid Spencer8ca43d72006-08-11 23:50:27 +0000177my @DIRS;
178if ($#ARGV > 0) {
179 @DIRS = @ARGV;
180} else {
181 push @DIRS, 'include';
182 push @DIRS, 'lib';
183 push @DIRS, 'tools';
184 push @DIRS, 'runtime';
185 push @DIRS, 'docs';
186 push @DIRS, 'test';
187 push @DIRS, 'utils';
188 push @DIRS, 'examples';
189 push @DIRS, 'projects/Stacker';
190 push @DIRS, 'projects/sample';
191 push @DIRS, 'autoconf';
192}
193
194for $Index ( 0 .. $#DIRS) {
195 ScanDir($DIRS[$Index]);
Reid Spencer8dd91272005-05-16 18:30:38 +0000196}
197
Reid Spencer1f0b9a12006-08-11 20:44:17 +0000198printStats;
Reid Spencer8dd91272005-05-16 18:30:38 +0000199
Reid Spencer8ca43d72006-08-11 23:50:27 +0000200print "</body></html>\n" if ($html) ;