1#!/usr/bin/perl
2# -*- perl -*-
3
4#   Copyright (C) 2001, 2007, 2010, 2014
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
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
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
184sub 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
198sub 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
206sub 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
213sub 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 .= "\tif [ x\"\$(NOASANFLAG)\" != x ]; then \\\n";
219    $crule .= "\t  \$(COMPILE.c) \$(PICFLAG) \$(NOASANFLAG) \$< -o noasan/\$@; \\\n";
220    $crule .= "\telse true; fi\n";
221    $crule .= "\t\$(COMPILE.c) \$< \$(OUTPUT_OPTION)\n";
222    $crule .= "\n";
223
224    $incdir = shift @ARGV;
225
226    opendir(INC, $incdir);
227    while ($f = readdir INC) {
228	next unless $f =~ /\.h$/ || $f =~ /\.def$/;
229	$mine{$f} = "\$(INCDIR)/$f";
230	$deps{$f} = join(' ', &deps_for("$incdir/$f"));
231    }
232    $mine{'config.h'} = "config.h";
233
234    opendir(INC, $srcdir);
235    while ($f = readdir INC) {
236	next unless $f =~ /\.h$/;
237	$mine{$f} = "\$(srcdir)/$f";
238	$deps{$f} = join(' ', &deps_for("$srcdir/$f"));
239    }
240    $mine{'config.h'} = "config.h";
241
242    open(IN, "$srcdir/Makefile.in");
243    open(OUT, ">$srcdir/Makefile.tmp");
244    while (<IN>) {
245	last if /remainder of this file/;
246	print OUT;
247    }
248    print OUT "# The dependencies in the remainder of this file are automatically\n";
249    print OUT "# generated by \"make maint-deps\".  Manual edits will be lost.\n\n";
250
251    opendir(S, $srcdir);
252    for $f (sort readdir S) {
253	if ($f =~ /\.c$/) {
254
255	    %scanned = ();
256	    @pending = &deps_for("$srcdir/$f");
257	    while (@pending) {
258		@tmp = @pending;
259		@pending = ();
260		for $p (@tmp) {
261		    next unless $mine{$p};
262		    if (!$scanned{$p}) {
263			push(@pending, split(' ', $deps{$p}));
264			$scanned{$p} = 1;
265		    }
266		}
267	    }
268	    @deps = sort { &locals_first($a,$b) } keys %scanned;
269	    $obj = $f;
270	    $obj =~ s/\.c$/.\$(objext)/;
271	    $obj = "./$obj:";
272	    if ($#deps >= 0) {
273		print OUT "$obj \$(srcdir)/$f";
274		$len = length("$obj $f");
275		for $dt (@deps) {
276		    $d = $mine{$dt};
277		    if ($len + length($d) > 70) {
278			printf OUT " \\\n\t$d";
279			$len = 8 + length($d);
280		    } else {
281			print OUT " $d";
282			$len += length($d) + 1;
283		    }
284		}
285		print OUT "\n";
286	    } else {
287		print OUT "$obj \$(srcdir)/$f\n";
288	    }
289	    $c = $crule;
290	    $c =~ s@\$\<@\$\(srcdir\)\/$f@g;
291	    print OUT $c;
292	}
293    }
294    closedir(S);
295    close(IN);
296    close(OUT);
297
298    rename("$srcdir/Makefile.tmp", "$srcdir/Makefile.in");
299}
300