merge from gcc
[external/binutils.git] / libiberty / maint-tool
1 #!/usr/bin/perl
2 # -*- perl -*-
3
4 #   Copyright (C) 2001, 2007, 2010
5 #   Free Software Foundation
6 #
7 # This file is part of the libiberty library.
8 # Libiberty is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Library General Public
10 # License as published by the Free Software Foundation; either
11 # version 2 of the License, or (at your option) any later version.
12 #
13 # Libiberty is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Library General Public License for more details.
17 #
18 # You should have received a copy of the GNU Library General Public
19 # License along with libiberty; see the file COPYING.LIB.  If not,
20 # write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
21 # Boston, MA 02110-1301, USA.
22 #
23 # Originally written by DJ Delorie <dj@redhat.com>
24
25
26 # This is a trivial script which checks the lists of C and O files in
27 # the Makefile for consistency.
28
29 $mode = shift;
30 $srcdir = ".";
31
32 if ($mode eq "-s") {
33     $srcdir = shift;
34     $mode = shift;
35 }
36
37 &missing() if $mode eq "missing";
38 &undoc() if $mode eq "undoc";
39 &deps() if $mode eq "deps";
40
41 exit 0;
42
43 format STDOUT =
44 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~
45 $out
46         ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
47 $out
48 .
49
50 ######################################################################
51
52 sub missing {
53
54     opendir(S, $srcdir);
55     while ($f = readdir S) {
56         $have{$f} = 1;
57     }
58     closedir(S);
59     opendir(S, ".");
60     while ($f = readdir S) {
61         $have{$f} = 1;
62     }
63     closedir(S);
64
65     for $a (@ARGV) {
66         $listed{$a} = 1;
67         $have{$a} = 0;
68     }
69
70     for $f (sort keys %have) {
71         next unless $have{$f};
72         if ($f =~ /\.c$/) {
73             print "S $f\n";
74         }
75     }
76     for $f (sort keys %listed) {
77         if ($f =~ /(.*)\.c$/) {
78             $base = $1;
79             if (! $listed{"./$base.o"}) {
80                 print "O $f\n";
81             }
82         }
83     }
84 }
85
86 ######################################################################
87
88 sub undoc {
89
90     opendir(S, $srcdir);
91     while ($file = readdir S) {
92         if ($file =~ /\.texi$/) {
93             open(T, "$srcdir/$file");
94             while (<T>) {
95                 if (/^\@deftype[^\(]* ([^\s\(]+) *\(/) {
96                     $documented{$1} = 1;
97                 }
98             }
99             close(T);
100         }
101         if ($file =~ /\.c$/) {
102             open(C, "$srcdir/$file");
103             while (<C>) {
104                 if (/\@undocumented (\S+)/) {
105                     $documented{$1} = 1;
106                 }
107                 if (/^static /) {
108                     if (! /[\(;]/) {
109                         s/[\r\n]+$/ /;
110                         $_ .= <C>;
111                     }
112                     while ($_ =~ /\([^\)]*$/) {
113                         s/[\r\n]+$/ /;
114                         $_ .= <C>;
115                     }
116                 }
117                 s/ VPARAMS([ \(])/$1/;
118                 s/PREFIX\(([^\)]*)\)/byte_$1/;
119                 if (/^static [^\(]* ([^\s\(]+) *\(.*\)$/) {
120                     $documented{$1} = 1;
121                 }
122             }
123         }
124     }
125     closedir(D);
126
127     # $out = join(' ', sort keys %documented);
128     # write;
129     # print "\n";
130
131     system "etags $srcdir/*.c $srcdir/../include/*.h";
132     open(TAGS, "TAGS");
133     while (<TAGS>) {
134         s/[\r\n]+$//;
135         if (/^\014$/) {
136             $filename = <TAGS>;
137             $filename =~ s/[\r\n]+$//;
138             $filename =~ s/,\d+$//;
139             $filename =~ s@.*[/\\]@@;
140             next;
141         }
142         if ($filename =~ /\.c$/ ) {
143             next unless /^[_a-zA-Z]/;
144         } else {
145             next unless /^\# *define/;
146             s/\# *define *//;
147         }
148
149         s/ VPARAMS//;
150         s/ *\177.*//;
151         s/,$//;
152         s/DEFUN\(//;
153         s/\(//;
154
155         next if /^static /;
156         next if /\s/;
157         next if /^_/;
158         next if $documented{$_};
159         next if /_H_?$/;
160
161         if ($seen_in{$_} ne $filename) {
162             $saw{$_} ++;
163         }
164         $seen_in{$_} = $filename;
165     }
166
167     for $k (keys %saw) {
168         delete $saw{$k} if $saw{$k} > 1;
169     }
170
171     for $k (sort keys %saw) {
172         $fromfile{$seen_in{$k}} .= " " if $fromfile{$seen_in{$k}};
173         $fromfile{$seen_in{$k}} .= $k;
174     }
175
176     for $f (sort keys %fromfile) {
177         $out = "$f: $fromfile{$f}";
178         write;
179     }
180 }
181
182 ######################################################################
183
184 sub deps_for {
185     my($f) = @_;
186     my(%d);
187     open(F, $f);
188     %d = ();
189     while (<F>) {
190         if (/^#\s*include\s+["<](.*)[">]/) {
191             $d{$1} = 1;
192         }
193     }
194     close(F);
195     return keys %d;
196 }
197
198 sub canonicalize {
199     my ($p) = @_;
200     0 while $p =~ s@/\./@/@g;
201     0 while $p =~ s@^\./@@g;
202     0 while $p =~ s@/[^/]+/\.\./@/@g;
203     return $p;
204 }
205
206 sub locals_first {
207     my ($a,$b) = @_;
208     return -1 if $a eq "config.h";
209     return  1 if $b eq "config.h";
210     return $a cmp $b;
211 }
212
213 sub deps {
214
215     $crule  = "\tif [ x\"\$(PICFLAG)\" != x ]; then \\\n";
216     $crule .= "\t  \$(COMPILE.c) \$(PICFLAG) \$< -o pic/\$@; \\\n";
217     $crule .= "\telse true; fi\n";
218     $crule .= "\t\$(COMPILE.c) \$< \$(OUTPUT_OPTION)\n";
219     $crule .= "\n";
220
221     $incdir = shift @ARGV;
222
223     opendir(INC, $incdir);
224     while ($f = readdir INC) {
225         next unless $f =~ /\.h$/;
226         $mine{$f} = "\$(INCDIR)/$f";
227         $deps{$f} = join(' ', &deps_for("$incdir/$f"));
228     }
229     $mine{'config.h'} = "config.h";
230
231     opendir(INC, $srcdir);
232     while ($f = readdir INC) {
233         next unless $f =~ /\.h$/;
234         $mine{$f} = "\$(srcdir)/$f";
235         $deps{$f} = join(' ', &deps_for("$srcdir/$f"));
236     }
237     $mine{'config.h'} = "config.h";
238
239     open(IN, "$srcdir/Makefile.in");
240     open(OUT, ">$srcdir/Makefile.tmp");
241     while (<IN>) {
242         last if /remainder of this file/;
243         print OUT;
244     }
245     print OUT "# The dependencies in the remainder of this file are automatically\n";
246     print OUT "# generated by \"make maint-deps\".  Manual edits will be lost.\n\n";
247
248     opendir(S, $srcdir);
249     for $f (sort readdir S) {
250         if ($f =~ /\.c$/) {
251
252             %scanned = ();
253             @pending = &deps_for("$srcdir/$f");
254             while (@pending) {
255                 @tmp = @pending;
256                 @pending = ();
257                 for $p (@tmp) {
258                     next unless $mine{$p};
259                     if (!$scanned{$p}) {
260                         push(@pending, split(' ', $deps{$p}));
261                         $scanned{$p} = 1;
262                     }
263                 }
264             }
265             @deps = sort { &locals_first($a,$b) } keys %scanned;
266             $obj = $f;
267             $obj =~ s/\.c$/.\$(objext)/;
268             $obj = "./$obj:";
269             if ($#deps >= 0) {
270                 print OUT "$obj \$(srcdir)/$f";
271                 $len = length("$obj $f");
272                 for $dt (@deps) {
273                     $d = $mine{$dt};
274                     if ($len + length($d) > 70) {
275                         printf OUT " \\\n\t$d";
276                         $len = 8 + length($d);
277                     } else {
278                         print OUT " $d";
279                         $len += length($d) + 1;
280                     }
281                 }
282                 print OUT "\n";
283             } else {
284                 print OUT "$obj \$(srcdir)/$f\n";
285             }
286             $c = $crule;
287             $c =~ s@\$\<@\$\(srcdir\)\/$f@g;
288             print OUT $c;
289         }
290     }
291     closedir(S);
292     close(IN);
293     close(OUT);
294
295     rename("$srcdir/Makefile.tmp", "$srcdir/Makefile.in");
296 }