1#!/usr/bin/perl
2# -*- perl -*-
3
4#   Copyright (C) 2001
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., 59 Temple Place - Suite 330,
21# Boston, MA 02111-1307, 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
32if ($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
41exit 0;
42
43format STDOUT =
44^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~
45$out
46        ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
47$out
48.
49
50######################################################################
51
52sub 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
88sub 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	next if $filename =~ /mpw\.c/;
149
150	s/ VPARAMS//;
151	s/ *\177.*//;
152	s/,$//;
153	s/DEFUN\(//;
154	s/\(//;
155
156	next if /^static /;
157	next if /\s/;
158	next if /^_/;
159	next if $documented{$_};
160	next if /_H_?$/;
161
162	if ($seen_in{$_} ne $filename) {
163	    $saw{$_} ++;
164	}
165	$seen_in{$_} = $filename;
166    }
167
168    for $k (keys %saw) {
169	delete $saw{$k} if $saw{$k} > 1;
170    }
171
172    for $k (sort keys %saw) {
173	$fromfile{$seen_in{$k}} .= " " if $fromfile{$seen_in{$k}};
174	$fromfile{$seen_in{$k}} .= $k;
175    }
176
177    for $f (sort keys %fromfile) {
178	$out = "$f: $fromfile{$f}";
179	write;
180    }
181}
182
183######################################################################
184
185sub deps_for {
186    my($f) = @_;
187    my(%d);
188    open(F, $f);
189    %d = ();
190    while (<F>) {
191	if (/^#\s*include\s+["<](.*)[">]/) {
192	    $d{$1} = 1;
193	}
194    }
195    close(F);
196    return keys %d;
197}
198
199sub canonicalize {
200    my ($p) = @_;
201    0 while $p =~ s@/\./@/@g;
202    0 while $p =~ s@^\./@@g;
203    0 while $p =~ s@/[^/]+/\.\./@/@g;
204    return $p;
205}
206
207sub locals_first {
208    my ($a,$b) = @_;
209    return -1 if $a eq "config.h";
210    return  1 if $b eq "config.h";
211    return $a cmp $b;
212}
213
214sub deps {
215
216    $crule  = "\tif [ x\"\$(PICFLAG)\" != x ]; then \\\n";
217    $crule .= "\t  \$(COMPILE.c) \$(PICFLAG) \$< -o pic/\$@; \\\n";
218    $crule .= "\telse true; fi\n";
219    $crule .= "\t\$(COMPILE.c) \$< \$(OUTPUT_OPTION)\n";
220    $crule .= "\n";
221
222    $incdir = shift @ARGV;
223
224    opendir(INC, $incdir);
225    while ($f = readdir INC) {
226	next unless $f =~ /\.h$/;
227	$mine{$f} = "\$(INCDIR)/$f";
228	$deps{$f} = join(' ', &deps_for("$incdir/$f"));
229    }
230    $mine{'config.h'} = "config.h";
231
232    opendir(INC, $srcdir);
233    while ($f = readdir INC) {
234	next unless $f =~ /\.h$/;
235	$mine{$f} = "\$(srcdir)/$f";
236	$deps{$f} = join(' ', &deps_for("$srcdir/$f"));
237    }
238    $mine{'config.h'} = "config.h";
239
240    open(IN, "$srcdir/Makefile.in");
241    open(OUT, ">$srcdir/Makefile.tmp");
242    while (<IN>) {
243	last if /remainder of this file/;
244	print OUT;
245    }
246    print OUT "# The dependencies in the remainder of this file are automatically\n";
247    print OUT "# generated by \"make maint-deps\".  Manual edits will be lost.\n\n";
248
249    opendir(S, $srcdir);
250    for $f (sort readdir S) {
251	if ($f =~ /\.c$/) {
252
253	    %scanned = ();
254	    @pending = &deps_for("$srcdir/$f");
255	    while (@pending) {
256		@tmp = @pending;
257		@pending = ();
258		for $p (@tmp) {
259		    next unless $mine{$p};
260		    if (!$scanned{$p}) {
261			push(@pending, split(' ', $deps{$p}));
262			$scanned{$p} = 1;
263		    }
264		}
265	    }
266	    @deps = sort { &locals_first($a,$b) } keys %scanned;
267	    $obj = $f;
268	    $obj =~ s/\.c$/.o/;
269	    $obj = "./$obj:";
270	    if ($#deps >= 0) {
271		print OUT "$obj \$(srcdir)/$f";
272		$len = length("$obj $f");
273		for $dt (@deps) {
274		    $d = $mine{$dt};
275		    if ($len + length($d) > 70) {
276			printf OUT " \\\n\t$d";
277			$len = 8 + length($d);
278		    } else {
279			print OUT " $d";
280			$len += length($d) + 1;
281		    }
282		}
283		print OUT "\n";
284	    } else {
285		print OUT "$obj \$(srcdir)/$f\n";
286	    }
287	    $c = $crule;
288	    $c =~ s@\$\<@\$\(srcdir\)\/$f@g;
289	    print OUT $c;
290	}
291    }
292    closedir(S);
293    close(IN);
294    close(OUT);
295
296    rename("$srcdir/Makefile.tmp", "$srcdir/Makefile.in");
297}
298