/ [gnulib] / gnulib / check-module
To checkout: cvs -d:pserver:anonymous@cvs.gnu.org.ua:/cvsmirror/gnulib co gnulib/check-module
Puszcza

Contents of /gnulib/check-module

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations)
Fri Jul 20 13:17:47 2007 UTC (14 years, 6 months ago) by meyering
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +5 -2 lines
* check-module: Diagnose a self-dependency.

1 #!/usr/bin/perl -w
2 # Check a gnulib module.
3
4 # Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
5
6 # This file is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 # Read a module description file and derive the set of files
23 # included directly by any .c or .h file listed in the `Files:' section.
24 # Take the union of all such sets for any dependent modules.
25 # Then, compare that set with the set derived from the names
26 # listed in the various Files: sections.
27
28 # This script makes no attempt to diagnose invalid or empty
29 # module-description files.
30
31 # Written by Jim Meyering
32
33 # FIXME:
34 # for each .m4 file listed in the Files: section(s)
35 # parse it for AC_LIBSOURCES directives, and accumulate the set
36 # of files `required' via all AC_LIBSOURCES.
37 # If this set is not empty, ensure that it contains
38 # the same (.c and .h only?) files as are listed in the Files: sections.
39
40 use strict;
41 use Getopt::Long;
42 #use Coda;
43
44 my $COPYRIGHT_NOTICE = "Copyright (C) 2006 Free Software Foundation, Inc.\n".
45 "This is free software. You may redistribute copies of it under the terms of\n".
46 "the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n".
47 "There is NO WARRANTY, to the extent permitted by law.\n";
48
49 (my $VERSION = '$Revision: 1.7 $ ') =~ tr/[0-9].//cd;
50 (my $ME = $0) =~ s|.*/||;
51
52 use constant ST_INIT => 1;
53 use constant ST_FILES => 2;
54 use constant ST_DEPENDENTS => 3;
55
56 # Parse a module file (returning list of Files: names and
57 # list of dependent-modules.
58 # my ($file, $dep) = parse_module_file $module_file;
59 sub parse_module_file ($)
60 {
61 my ($module_file) = @_;
62
63 open FH, '<', $module_file
64 or die "$ME: can't open `$module_file' for reading: $!\n";
65
66 my %file_set;
67 my %dep_set;
68
69 my $state = ST_INIT;
70 while (defined (my $line = <FH>))
71 {
72 if ($state eq ST_INIT)
73 {
74 if ($line =~ /^Files:$/)
75 {
76 $state = ST_FILES;
77 }
78 elsif ($line =~ /^Depends-on:$/)
79 {
80 $state = ST_DEPENDENTS;
81 }
82 }
83 else
84 {
85 chomp $line;
86 $line =~ s/^\s+//;
87 $line =~ s/\s+$//;
88 if ( ! $line)
89 {
90 $state = ST_INIT;
91 next;
92 }
93
94 if ($state eq ST_FILES)
95 {
96 $file_set{$line} = 1;
97 }
98 elsif ($state eq ST_DEPENDENTS)
99 {
100 $dep_set{$line} = 1;
101 (my $base = $module_file) =~ s,.*/,,;
102 $line eq $base
103 and die "$ME: module $module_file depends on itself\n";
104 }
105 }
106 }
107 close FH;
108
109 # my @t = sort keys %file_set;
110 # print "files: @t\n";
111 # my @u = sort keys %dep_set;
112 # print "dependents: @u\n";
113
114 return (\%file_set, \%dep_set);
115 }
116
117 # Extract the set of files required for this module, including
118 # those required via dependent modules.
119
120 # Files:
121 # lib/stat.c
122 # m4/stat.m4
123 # lib/foo.h
124 #
125 # Depends-on:
126 # some-other-module
127
128 sub usage ($)
129 {
130 my ($exit_code) = @_;
131 my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
132 if ($exit_code != 0)
133 {
134 print $STREAM "Try `$ME --help' for more information.\n";
135 }
136 else
137 {
138 print $STREAM <<EOF;
139 Usage: $ME [OPTIONS] FILE...
140
141 Read a module description file and derive the set of files
142 included directly by any .c or .h file listed in the `Files:' section.
143 Take the union of all such sets for any dependent modules.
144 Then, compare that set with the set derived from the names
145 listed in the various Files: sections.
146
147 OPTIONS:
148
149 --help display this help and exit
150 --version output version information and exit
151
152 EOF
153 }
154 exit $exit_code;
155 }
156
157 sub find_included_lib_files ($)
158 {
159 my ($file) = @_;
160
161 # Special cases...
162 my %special_non_dup = ( 'fnmatch_loop.c' => 1,
163 'regex.c' => 1, 'at-func.c' => 1 );
164
165 my %inc;
166 open FH, '<', $file
167 or die "$ME: can't open `$file' for reading: $!\n";
168
169 while (defined (my $line = <FH>))
170 {
171 # Ignore test-driver code at end of file.
172 $line =~ m!^\#if(def)? TEST_!
173 and last;
174
175 $line =~ m!^\s*\#\s*include\s+"!
176 or next;
177 $line =~ s///;
178 chomp $line;
179 $line =~ s/".*//;
180 exists $inc{$line} && ! exists $special_non_dup{$line}
181 and warn "$ME: $file: duplicate inclusion of $line\n";
182
183 $inc{$line} = 1;
184 }
185 close FH;
186
187 return \%inc;
188 }
189
190 my %exempt_header =
191 (
192 # Exempt headers like unlocked-io.h that are `#include'd
193 # but not necessarily used.
194 'unlocked-io.h' => 1,
195
196 # Give gettext.h a free pass only when included from lib/error.c,
197 # since we've made that exception solely to make the error
198 # module easier to use -- at RMS's request.
199 'lib/error.c:gettext.h' => 1,
200
201 # The full-read module shares code with the full-write module.
202 'lib/full-write.c:full-read.h' => 1,
203
204 # The safe-write module shares code with the safe-read module.
205 'lib/safe-read.c:safe-write.h' => 1,
206
207 # The use of obstack.h in the hash module is conditional, off by default.
208 'lib/hash.c:obstack.h' => 1,
209
210 # C files in the gc module have conditional includes.
211 'lib/gc-gnulib.c:des.h' => 1,
212 'lib/gc-gnulib.c:arcfour.h' => 1,
213 'lib/gc-gnulib.c:arctwo.h' => 1,
214 'lib/gc-gnulib.c:md2.h' => 1,
215 'lib/gc-gnulib.c:md4.h' => 1,
216 'lib/gc-gnulib.c:md5.h' => 1,
217 'lib/gc-gnulib.c:rijndael.h' => 1,
218 'lib/gc-gnulib.c:sha1.h' => 1,
219 'lib/gc-gnulib.c:rijndael-api-fst.h' => 1,
220 'lib/gc-gnulib.c:hmac.h' => 1,
221 'lib/gc-libgcrypt.c:md2.h' => 1,
222
223 # The fts-lgpl module doesn't actually use fts-cycle.c and unistd-safer.h.
224 'lib/fts.c:fts-cycle.c' => 1,
225 'lib/fts.c:unistd-safer.h' => 1,
226 );
227
228 sub check_module ($)
229 {
230 my @m = @_;
231
232 my %file;
233 my %module_all_files;
234 my %dep;
235 my %seen_module;
236
237 while (@m)
238 {
239 my $m = pop @m;
240 # warn "M: $m\n";
241 exists $seen_module{$m}
242 and next;
243 $seen_module{$m} = 1;
244 my ($file, $dep) = parse_module_file $m;
245 push @m, keys %$dep;
246 foreach my $f (keys %$file)
247 {
248 $module_all_files{$f} = 1;
249 }
250 }
251
252 my @t = sort keys %module_all_files;
253 # warn "ALL files: @t\n";
254
255 # Derive from %module_all_files (by parsing the .c and .h files therein),
256 # the list of all #include'd files that reside in lib/.
257 foreach my $f (keys %module_all_files)
258 {
259 $f =~ /\.[ch]$/
260 or next;
261 # FIXME: this is too naive
262 my $inc = find_included_lib_files "../$f";
263 foreach my $i (sort keys %$inc)
264 {
265 my $lib_file = "lib/$i";
266 exists $exempt_header{"$f:$i"}
267 || exists $exempt_header{$i}
268 and next;
269 !exists $module_all_files{$lib_file} && -f "../lib/$i"
270 and warn "$f: $i is `#include'd, but not "
271 . "listed in module's Files: section\n";
272 }
273 #my @t = sort keys %$inc;
274 #print "** $f: @t\n";
275 }
276 }
277
278 {
279 GetOptions
280 (
281 help => sub { usage 0 },
282 version => sub { print "$ME version $VERSION\n$COPYRIGHT_NOTICE"; exit },
283 ) or usage 1;
284
285 @ARGV < 1
286 and (warn "$ME: missing FILE argument\n"), usage 1;
287
288 foreach my $module (@ARGV)
289 {
290 check_module $module;
291 }
292
293 exit 0;
294 }

Send suggestions and bug reports to Sergey Poznyakoff
ViewVC Help
Powered by ViewVC 1.1.20