source: trunk/essentials/sys-devel/autoconf/bin/autoscan.in

Last change on this file was 3095, checked in by bird, 18 years ago

unixroot changes.

File size: 16.7 KB
Line 
1#! @PERL@ -w
2# -*- perl -*-
3# @configure_input@
4
5# autoscan - Create configure.scan (a preliminary configure.ac) for a package.
6# Copyright (C) 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
7# Free Software Foundation, Inc.
8
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2, or (at your option)
12# any later version.
13
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22# 02110-1301, USA.
23
24# Written by David MacKenzie <djm@gnu.ai.mit.edu>.
25
26eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
27 if 0;
28
29BEGIN
30{
31 my $datadir = $ENV{'autom4te_perllibdir'} || '@datadir@';
32 $datadir =~ s/\/\@unixroot/$ENV{'UNIXROOT'}/; # The EMX built perl doesn't know @unixroot.
33 unshift @INC, $datadir;
34
35 # Override SHELL. On DJGPP SHELL may not be set to a shell
36 # that can handle redirection and quote arguments correctly,
37 # e.g.: COMMAND.COM. For DJGPP always use the shell that configure
38 # has detected.
39 $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');
40}
41
42use Autom4te::ChannelDefs;
43use Autom4te::Configure_ac;
44use Autom4te::General;
45use Autom4te::FileUtils;
46use Autom4te::XFile;
47use File::Basename;
48use File::Find;
49use strict;
50
51use vars qw(@cfiles @makefiles @shfiles @subdirs %printed);
52
53# The kind of the words we are looking for.
54my @kinds = qw (function header identifier program
55 makevar librarie);
56
57# For each kind, the default macro.
58my %generic_macro =
59 (
60 'function' => 'AC_CHECK_FUNCS',
61 'header' => 'AC_CHECK_HEADERS',
62 'identifier' => 'AC_CHECK_TYPES',
63 'program' => 'AC_CHECK_PROGS',
64 'library' => 'AC_CHECK_LIB'
65 );
66
67my %kind_comment =
68 (
69 'function' => 'Checks for library functions.',
70 'header' => 'Checks for header files.',
71 'identifier' => 'Checks for typedefs, structures, and compiler characteristics.',
72 'program' => 'Checks for programs.',
73 );
74
75# $USED{KIND}{ITEM} is the list of locations where the ITEM (of KIND) was used
76# in the user package.
77# For instance $USED{function}{alloca} is the list of `file:line' where
78# `alloca (...)' appears.
79my %used = ();
80
81# $MACRO{KIND}{ITEM} is the list of macros to use to test ITEM.
82# Initialized from lib/autoscan/*. E.g., $MACRO{function}{alloca} contains
83# the singleton AC_FUNC_ALLOCA. Some require several checks.
84my %macro = ();
85
86# $NEEDED_MACROS{MACRO} is an array of locations requiring MACRO.
87# E.g., $NEEDED_MACROS{AC_FUNC_ALLOC} the list of `file:line' containing
88# `alloca (...)'.
89my %needed_macros =
90 (
91 'AC_PREREQ' => [$me],
92 );
93
94my $configure_scan = 'configure.scan';
95my $log;
96
97# Autoconf and lib files.
98my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
99$autom4te =~ s/\/\@unixroot/$ENV{'UNIXROOT'}/; # The EMX built perl doesn't know @unixroot.
100my $autoconf = "$autom4te --language=autoconf";
101my @prepend_include;
102my $first_include = '@datadir@';
103$first_include =~ s/\/\@unixroot/$ENV{'UNIXROOT'}/; # The EMX built perl doesn't know @unixroot.
104my @include = ("$first_include");
105
106# $help
107# -----
108$help = "Usage: $0 [OPTION] ... [SRCDIR]
109
110Examine source files in the directory tree rooted at SRCDIR, or the
111current directory if none is given. Search the source files for
112common portability problems, check for incompleteness of
113`configure.ac', and create a file `$configure_scan' which is a
114preliminary `configure.ac' for that package.
115
116 -h, --help print this help, then exit
117 -V, --version print version number, then exit
118 -v, --verbose verbosely report processing
119 -d, --debug don't remove temporary files
120
121Library directories:
122 -B, --prepend-include=DIR prepend directory DIR to search path
123 -I, --include=DIR append directory DIR to search path
124
125Report bugs to <bug-autoconf\@gnu.org>.\n";
126
127# $version
128# --------
129$version = "autoscan (@PACKAGE_NAME@) @VERSION@
130Copyright (C) 2006 Free Software Foundation, Inc.
131This is free software. You may redistribute copies of it under the terms of
132the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
133There is NO WARRANTY, to the extent permitted by law.
134
135Written by David J. MacKenzie and Akim Demaille.
136";
137
138
139
140
141## ------------------------ ##
142## Command line interface. ##
143## ------------------------ ##
144
145# parse_args ()
146# -------------
147# Process any command line arguments.
148sub parse_args ()
149{
150 getopt ('I|include=s' => \@include,
151 'B|prepend-include=s' => \@prepend_include);
152
153 die "$me: too many arguments
154Try `$me --help' for more information.\n"
155 if @ARGV > 1;
156
157 my $srcdir = $ARGV[0] || ".";
158
159 verb "srcdir = $srcdir";
160 chdir $srcdir || error "cannot cd to $srcdir: $!";
161}
162
163
164# init_tables ()
165# --------------
166# Put values in the tables of what to do with each token.
167sub init_tables ()
168{
169 # The data file format supports only one line of macros per function.
170 # If more than that is required for a common portability problem,
171 # a new Autoconf macro should probably be written for that case,
172 # instead of duplicating the code in lots of configure.ac files.
173 my $file = find_file ("autoscan/autoscan.list",
174 reverse (@prepend_include), @include);
175 my $table = new Autom4te::XFile $file;
176 my $tables_are_consistent = 1;
177
178 while ($_ = $table->getline)
179 {
180 # Ignore blank lines and comments.
181 next
182 if /^\s*$/ || /^\s*\#/;
183
184 # '<kind>: <word> <macro invocation>' or...
185 # '<kind>: <word> warn: <message>'.
186 if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
187 {
188 my ($kind, $word, $macro) = ($1, $2, $3);
189 error "$file:$.: invalid kind: $_"
190 unless grep { $_ eq $kind } @kinds;
191 push @{$macro{$kind}{$word}}, $macro;
192 }
193 else
194 {
195 error "$file:$.: invalid definition: $_";
196 }
197 }
198
199 if ($debug)
200 {
201 foreach my $kind (@kinds)
202 {
203 foreach my $word (sort keys %{$macro{$kind}})
204 {
205 print "$kind: $word: @{$macro{$kind}{$word}}\n";
206 }
207 }
208
209 }
210}
211
212
213# used ($KIND, $WORD, [$WHERE])
214# -----------------------------
215# $WORD is used as a $KIND.
216sub used ($$;$)
217{
218 my ($kind, $word, $where) = @_;
219 $where ||= "$File::Find::name:$.";
220 if (
221 # Check for all the libraries. But `-links' is certainly a
222 # `find' argument, and `-le', a `test' argument.
223 ($kind eq 'library' && $word !~ /^(e|inks)$/)
224 # Other than libraries are to be checked only if listed in
225 # the Autoscan library files.
226 || defined $macro{$kind}{$word}
227 )
228 {
229 push (@{$used{$kind}{$word}}, $where);
230 }
231}
232
233
234
235## ----------------------- ##
236## Scanning source files. ##
237## ----------------------- ##
238
239
240# scan_c_file ($FILE-NAME)
241# ------------------------
242sub scan_c_file ($)
243{
244 my ($file_name) = @_;
245 push @cfiles, $File::Find::name;
246
247 # Nonzero if in a multiline comment.
248 my $in_comment = 0;
249
250 my $file = new Autom4te::XFile "<$file_name";
251
252 while ($_ = $file->getline)
253 {
254 # Strip out comments.
255 if ($in_comment && s,^.*?\*/,,)
256 {
257 $in_comment = 0;
258 }
259 # The whole line is inside a commment.
260 next if $in_comment;
261 # All on one line.
262 s,/\*.*?\*/,,g;
263
264 # Starting on this line.
265 if (s,/\*.*$,,)
266 {
267 $in_comment = 1;
268 }
269
270 # Preprocessor directives.
271 if (s/^\s*\#\s*//)
272 {
273 if (/^include\s*<([^>]*)>/)
274 {
275 used ('header', $1);
276 }
277 if (s/^(if|ifdef|ifndef|elif)\s+//)
278 {
279 foreach my $word (split (/\W+/))
280 {
281 used ('identifier', $word)
282 unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
283 }
284 }
285 # Ignore other preprocessor directives.
286 next;
287 }
288
289 # Remove string and character constants.
290 s,\"[^\"]*\",,g;
291 s,\'[^\']*\',,g;
292
293 # Tokens in the code.
294 # Maybe we should ignore function definitions (in column 0)?
295 while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
296 {
297 used ('function', $1);
298 }
299 while (s/\b([a-zA-Z_]\w*)\b/ /)
300 {
301 used ('identifier', $1);
302 }
303 }
304
305 $file->close;
306}
307
308
309# scan_makefile($MAKEFILE-NAME)
310# -----------------------------
311sub scan_makefile ($)
312{
313 my ($file_name) = @_;
314 push @makefiles, $File::Find::name;
315
316 my $file = new Autom4te::XFile "<$file_name";
317
318 while ($_ = $file->getline)
319 {
320 # Strip out comments.
321 s/#.*//;
322
323 # Variable assignments.
324 while (s/\b([a-zA-Z_]\w*)\s*=/ /)
325 {
326 used ('makevar', $1);
327 }
328 # Be sure to catch a whole word. For instance `lex$U.$(OBJEXT)'
329 # is a single token. Otherwise we might believe `lex' is needed.
330 foreach my $word (split (/\s+/))
331 {
332 # Libraries.
333 if ($word =~ /^-l([a-zA-Z_]\w*)$/)
334 {
335 used ('library', $1);
336 }
337 # Tokens in the code.
338 # We allow some additional characters, e.g., `+', since
339 # autoscan/programs includes `c++'.
340 if ($word =~ /^[a-zA-Z_][\w+]*$/)
341 {
342 used ('program', $word);
343 }
344 }
345 }
346
347 $file->close;
348}
349
350
351# scan_sh_file($SHELL-SCRIPT-NAME)
352# --------------------------------
353sub scan_sh_file ($)
354{
355 my ($file_name) = @_;
356 push @shfiles, $File::Find::name;
357
358 my $file = new Autom4te::XFile "<$file_name";
359
360 while ($_ = $file->getline)
361 {
362 # Strip out comments and variable references.
363 s/#.*//;
364 s/\${[^\}]*}//g;
365 s/@[^@]*@//g;
366
367 # Tokens in the code.
368 while (s/\b([a-zA-Z_]\w*)\b/ /)
369 {
370 used ('program', $1);
371 }
372 }
373
374 $file->close;
375}
376
377
378# scan_file ()
379# ------------
380# Called by &find on each file. $_ contains the current file name with
381# the current directory of the walk through.
382sub scan_file ()
383{
384 # Wanted only if there is no corresponding FILE.in.
385 return
386 if -f "$_.in";
387
388 # Save $_ as Find::File requires it to be preserved.
389 local $_ = $_;
390
391 # Strip a useless leading `./'.
392 $File::Find::name =~ s,^\./,,;
393
394 if ($_ ne '.' and -d $_ and
395 -f "$_/configure.in" ||
396 -f "$_/configure.ac" ||
397 -f "$_/configure.gnu" ||
398 -f "$_/configure")
399 {
400 $File::Find::prune = 1;
401 push @subdirs, $File::Find::name;
402 }
403 if (/\.[chlym](\.in)?$/)
404 {
405 used 'program', 'cc', $File::Find::name;
406 scan_c_file ($_);
407 }
408 elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
409 {
410 used 'program', 'c++', $File::Find::name;
411 scan_c_file ($_);
412 }
413 elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
414 || /^(?:GNUm|M|m)akefile(\.am)?$/)
415 {
416 scan_makefile ($_);
417 }
418 elsif (/\.sh(\.in)?$/)
419 {
420 scan_sh_file ($_);
421 }
422}
423
424
425# scan_files ()
426# -------------
427# Read through the files and collect lists of tokens in them
428# that might create nonportabilities.
429sub scan_files ()
430{
431 find (\&scan_file, '.');
432
433 if ($verbose)
434 {
435 print "cfiles: @cfiles\n";
436 print "makefiles: @makefiles\n";
437 print "shfiles: @shfiles\n";
438
439 foreach my $kind (@kinds)
440 {
441 print "\n$kind:\n";
442 foreach my $word (sort keys %{$used{$kind}})
443 {
444 print "$word: @{$used{$kind}{$word}}\n";
445 }
446 }
447 }
448}
449
450
451## ----------------------- ##
452## Output configure.scan. ##
453## ----------------------- ##
454
455
456# output_kind ($FILE, $KIND)
457# --------------------------
458sub output_kind ($$)
459{
460 my ($file, $kind) = @_;
461 # Lists of words to be checked with the generic macro.
462 my @have;
463
464 print $file "\n# $kind_comment{$kind}\n"
465 if exists $kind_comment{$kind};
466 foreach my $word (sort keys %{$used{$kind}})
467 {
468 # Output the needed macro invocations in $configure_scan if not
469 # already printed, and remember these macros are needed.
470 foreach my $macro (@{$macro{$kind}{$word}})
471 {
472 if ($macro =~ /^warn:\s+(.*)/)
473 {
474 my $message = $1;
475 foreach my $location (@{$used{$kind}{$word}})
476 {
477 warn "$location: warning: $message\n";
478 }
479 }
480 elsif (exists $generic_macro{$kind}
481 && $macro eq $generic_macro{$kind})
482 {
483 push (@have, $word);
484 push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
485 @{$used{$kind}{$word}});
486 }
487 else
488 {
489 if (! $printed{$macro})
490 {
491 print $file "$macro\n";
492 $printed{$macro} = 1;
493 }
494 push (@{$needed_macros{$macro}},
495 @{$used{$kind}{$word}});
496 }
497 }
498 }
499 print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
500 if @have;
501}
502
503
504# output_libraries ($FILE)
505# ------------------------
506sub output_libraries ($)
507{
508 my ($file) = @_;
509
510 print $file "\n# Checks for libraries.\n";
511 foreach my $word (sort keys %{$used{'library'}})
512 {
513 print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
514 print $file "AC_CHECK_LIB([$word], [main])\n";
515 }
516}
517
518
519# output ($CONFIGURE_SCAN)
520# ------------------------
521# Print a proto configure.ac.
522sub output ($)
523{
524 my $configure_scan = shift;
525 my %unique_makefiles;
526
527 my $file = new Autom4te::XFile ">$configure_scan";
528
529 print $file
530 ("# -*- Autoconf -*-\n" .
531 "# Process this file with autoconf to produce a configure script.\n" .
532 "\n" .
533 "AC_PREREQ(@VERSION@)\n" .
534 "AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)\n");
535 if (defined $cfiles[0])
536 {
537 print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
538 print $file "AC_CONFIG_HEADER([config.h])\n";
539 }
540
541 output_kind ($file, 'program');
542 output_kind ($file, 'makevar');
543 output_libraries ($file);
544 output_kind ($file, 'header');
545 output_kind ($file, 'identifier');
546 output_kind ($file, 'function');
547
548 print $file "\n";
549 if (@makefiles)
550 {
551 # Change DIR/Makefile.in to DIR/Makefile.
552 foreach my $m (@makefiles)
553 {
554 $m =~ s/\.(?:in|am)$//;
555 $unique_makefiles{$m}++;
556 }
557 print $file ("AC_CONFIG_FILES([",
558 join ("\n ",
559 sort keys %unique_makefiles), "])\n");
560 }
561 if (@subdirs)
562 {
563 print $file ("AC_CONFIG_SUBDIRS([",
564 join ("\n ",
565 sort @subdirs), "])\n");
566 }
567 print $file "AC_OUTPUT\n";
568
569 $file->close;
570}
571
572
573
574## --------------------------------------- ##
575## Checking the accuracy of configure.ac. ##
576## --------------------------------------- ##
577
578
579# &check_configure_ac ($CONFIGURE_AC)
580# -----------------------------------
581# Use autoconf to check if all the suggested macros are included
582# in CONFIGURE_AC.
583sub check_configure_ac ($)
584{
585 my ($configure_ac) = @_;
586
587 # Find what needed macros are invoked in CONFIGURE_AC.
588 # I'd be very happy if someone could explain to me why sort (uniq ...)
589 # doesn't work properly: I need `uniq (sort ...)'. --akim
590 my $trace_option =
591 join (' --trace=', '',
592 uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
593
594 verb "running: $autoconf $trace_option $configure_ac";
595 my $traces =
596 new Autom4te::XFile "$autoconf $trace_option $configure_ac|";
597
598 while ($_ = $traces->getline)
599 {
600 chomp;
601 my ($file, $line, $macro, @args) = split (/:/, $_);
602 if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
603 {
604 # To be rigorous, we should distinguish between space and comma
605 # separated macros. But there is no point.
606 foreach my $word (split (/\s|,/, $args[0]))
607 {
608 # AC_CHECK_MEMBERS wants `struct' or `union'.
609 if ($macro eq "AC_CHECK_MEMBERS"
610 && $word =~ /^stat.st_/)
611 {
612 $word = "struct " . $word;
613 }
614 delete $needed_macros{"$macro([$word])"};
615 }
616 }
617 else
618 {
619 delete $needed_macros{$macro};
620 }
621 }
622
623 $traces->close;
624
625 # Report the missing macros.
626 foreach my $macro (sort keys %needed_macros)
627 {
628 warn ("$configure_ac: warning: missing $macro wanted by: "
629 . (${$needed_macros{$macro}}[0])
630 . "\n");
631 print $log "$me: warning: missing $macro wanted by: \n";
632 foreach my $need (@{$needed_macros{$macro}})
633 {
634 print $log "\t$need\n";
635 }
636 }
637}
638
639
640## -------------- ##
641## Main program. ##
642## -------------- ##
643
644parse_args;
645$log = new Autom4te::XFile ">$me.log";
646
647$autoconf .= " --debug" if $debug;
648$autoconf .= " --verbose" if $verbose;
649$autoconf .= join (' --include=', '', @include);
650$autoconf .= join (' --prepend-include=', '', @prepend_include);
651
652my $configure_ac = find_configure_ac;
653init_tables;
654scan_files;
655output ('configure.scan');
656if (-f $configure_ac)
657 {
658 check_configure_ac ($configure_ac);
659 }
660# This close is really needed. For some reason, probably best named
661# a bug, it seems that the dtor of $LOG is not called automatically
662# at END. It results in a truncated file.
663$log->close;
664exit 0;
665
666### Setup "GNU" style for perl-mode and cperl-mode.
667## Local Variables:
668## perl-indent-level: 2
669## perl-continued-statement-offset: 2
670## perl-continued-brace-offset: 0
671## perl-brace-offset: 0
672## perl-brace-imaginary-offset: 0
673## perl-label-offset: -2
674## cperl-indent-level: 2
675## cperl-brace-offset: 0
676## cperl-continued-brace-offset: 0
677## cperl-label-offset: -2
678## cperl-extra-newline-before-brace: t
679## cperl-merge-trailing-else: nil
680## cperl-continued-statement-offset: 2
681## End:
Note: See TracBrowser for help on using the repository browser.