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.
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)
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.
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
24 # Written by David MacKenzie <djm@gnu.ai.mit.edu>.
26 eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
31 my $datadir = $ENV{'autom4te_perllibdir'} || '@datadir@';
32 unshift @INC, $datadir;
34 # Override SHELL. On DJGPP SHELL may not be set to a shell
35 # that can handle redirection and quote arguments correctly,
36 # e.g.: COMMAND.COM. For DJGPP always use the shell that configure
38 $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');
41 use Autom4te::ChannelDefs;
42 use Autom4te::Configure_ac;
43 use Autom4te::General;
44 use Autom4te::FileUtils;
50 use vars qw(@cfiles @makefiles @shfiles @subdirs %printed);
52 # The kind of the words we are looking for.
53 my @kinds = qw (function header identifier program
56 # For each kind, the default macro.
59 'function' => 'AC_CHECK_FUNCS',
60 'header' => 'AC_CHECK_HEADERS',
61 'identifier' => 'AC_CHECK_TYPES',
62 'program' => 'AC_CHECK_PROGS',
63 'library' => 'AC_CHECK_LIB'
68 'function' => 'Checks for library functions.',
69 'header' => 'Checks for header files.',
70 'identifier' => 'Checks for typedefs, structures, and compiler characteristics.',
71 'program' => 'Checks for programs.',
74 # $USED{KIND}{ITEM} is the list of locations where the ITEM (of KIND) was used
75 # in the user package.
76 # For instance $USED{function}{alloca} is the list of `file:line' where
77 # `alloca (...)' appears.
80 # $MACRO{KIND}{ITEM} is the list of macros to use to test ITEM.
81 # Initialized from lib/autoscan/*. E.g., $MACRO{function}{alloca} contains
82 # the singleton AC_FUNC_ALLOCA. Some require several checks.
85 # $NEEDED_MACROS{MACRO} is an array of locations requiring MACRO.
86 # E.g., $NEEDED_MACROS{AC_FUNC_ALLOC} the list of `file:line' containing
93 my $configure_scan = 'configure.scan';
96 # Autoconf and lib files.
97 my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
98 my $autoconf = "$autom4te --language=autoconf";
100 my @include = ('@datadir@');
104 $help = "Usage: $0 [OPTION] ... [SRCDIR]
106 Examine source files in the directory tree rooted at SRCDIR, or the
107 current directory if none is given. Search the source files for
108 common portability problems, check for incompleteness of
109 `configure.ac', and create a file `$configure_scan' which is a
110 preliminary `configure.ac' for that package.
112 -h, --help print this help, then exit
113 -V, --version print version number, then exit
114 -v, --verbose verbosely report processing
115 -d, --debug don't remove temporary files
118 -B, --prepend-include=DIR prepend directory DIR to search path
119 -I, --include=DIR append directory DIR to search path
121 Report bugs to <bug-autoconf\@gnu.org>.\n";
125 $version = "autoscan (@PACKAGE_NAME@) @VERSION@
126 Written by David J. MacKenzie and Akim Demaille.
128 Copyright (C) 2006 Free Software Foundation, Inc.
129 This is free software; see the source for copying conditions. There is NO
130 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
135 ## ------------------------ ##
136 ## Command line interface. ##
137 ## ------------------------ ##
141 # Process any command line arguments.
144 getopt ('I|include=s' => \@include,
145 'B|prepend-include=s' => \@prepend_include);
147 die "$me: too many arguments
148 Try `$me --help' for more information.\n"
151 my $srcdir = $ARGV[0] || ".";
153 verb "srcdir = $srcdir";
154 chdir $srcdir || error "cannot cd to $srcdir: $!";
160 # Put values in the tables of what to do with each token.
163 # The data file format supports only one line of macros per function.
164 # If more than that is required for a common portability problem,
165 # a new Autoconf macro should probably be written for that case,
166 # instead of duplicating the code in lots of configure.ac files.
167 my $file = find_file ("autoscan/autoscan.list",
168 reverse (@prepend_include), @include);
169 my $table = new Autom4te::XFile $file;
170 my $tables_are_consistent = 1;
172 while ($_ = $table->getline)
174 # Ignore blank lines and comments.
176 if /^\s*$/ || /^\s*\#/;
178 # '<kind>: <word> <macro invocation>' or...
179 # '<kind>: <word> warn: <message>'.
180 if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
182 my ($kind, $word, $macro) = ($1, $2, $3);
183 error "$file:$.: invalid kind: $_"
184 unless grep { $_ eq $kind } @kinds;
185 push @{$macro{$kind}{$word}}, $macro;
189 error "$file:$.: invalid definition: $_";
195 foreach my $kind (@kinds)
197 foreach my $word (sort keys %{$macro{$kind}})
199 print "$kind: $word: @{$macro{$kind}{$word}}\n";
207 # used ($KIND, $WORD, [$WHERE])
208 # -----------------------------
209 # $WORD is used as a $KIND.
212 my ($kind, $word, $where) = @_;
213 $where ||= "$File::Find::name:$.";
215 # Check for all the libraries. But `-links' is certainly a
216 # `find' argument, and `-le', a `test' argument.
217 ($kind eq 'library' && $word !~ /^(e|inks)$/)
218 # Other than libraries are to be checked only if listed in
219 # the Autoscan library files.
220 || defined $macro{$kind}{$word}
223 push (@{$used{$kind}{$word}}, $where);
229 ## ----------------------- ##
230 ## Scanning source files. ##
231 ## ----------------------- ##
234 # scan_c_file ($FILE-NAME)
235 # ------------------------
238 my ($file_name) = @_;
239 push @cfiles, $File::Find::name;
241 # Nonzero if in a multiline comment.
244 my $file = new Autom4te::XFile "<$file_name";
246 while ($_ = $file->getline)
248 # Strip out comments.
249 if ($in_comment && s,^.*?\*/,,)
253 # The whole line is inside a commment.
258 # Starting on this line.
264 # Preprocessor directives.
267 if (/^include\s*<([^>]*)>/)
271 if (s/^(if|ifdef|ifndef|elif)\s+//)
273 foreach my $word (split (/\W+/))
275 used ('identifier', $word)
276 unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
279 # Ignore other preprocessor directives.
283 # Remove string and character constants.
287 # Tokens in the code.
288 # Maybe we should ignore function definitions (in column 0)?
289 while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
291 used ('function', $1);
293 while (s/\b([a-zA-Z_]\w*)\b/ /)
295 used ('identifier', $1);
303 # scan_makefile($MAKEFILE-NAME)
304 # -----------------------------
305 sub scan_makefile ($)
307 my ($file_name) = @_;
308 push @makefiles, $File::Find::name;
310 my $file = new Autom4te::XFile "<$file_name";
312 while ($_ = $file->getline)
314 # Strip out comments.
317 # Variable assignments.
318 while (s/\b([a-zA-Z_]\w*)\s*=/ /)
320 used ('makevar', $1);
322 # Be sure to catch a whole word. For instance `lex$U.$(OBJEXT)'
323 # is a single token. Otherwise we might believe `lex' is needed.
324 foreach my $word (split (/\s+/))
327 if ($word =~ /^-l([a-zA-Z_]\w*)$/)
329 used ('library', $1);
331 # Tokens in the code.
332 # We allow some additional characters, e.g., `+', since
333 # autoscan/programs includes `c++'.
334 if ($word =~ /^[a-zA-Z_][\w+]*$/)
336 used ('program', $word);
345 # scan_sh_file($SHELL-SCRIPT-NAME)
346 # --------------------------------
349 my ($file_name) = @_;
350 push @shfiles, $File::Find::name;
352 my $file = new Autom4te::XFile "<$file_name";
354 while ($_ = $file->getline)
356 # Strip out comments and variable references.
361 # Tokens in the code.
362 while (s/\b([a-zA-Z_]\w*)\b/ /)
364 used ('program', $1);
374 # Called by &find on each file. $_ contains the current file name with
375 # the current directory of the walk through.
378 # Wanted only if there is no corresponding FILE.in.
382 # Save $_ as Find::File requires it to be preserved.
385 # Strip a useless leading `./'.
386 $File::Find::name =~ s,^\./,,;
388 if ($_ ne '.' and -d $_ and
389 -f "$_/configure.in" ||
390 -f "$_/configure.ac" ||
391 -f "$_/configure.gnu" ||
394 $File::Find::prune = 1;
395 push @subdirs, $File::Find::name;
397 if (/\.[chlym](\.in)?$/)
399 used 'program', 'cc', $File::Find::name;
402 elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
404 used 'program', 'c++', $File::Find::name;
407 elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
408 || /^(?:GNUm|M|m)akefile(\.am)?$/)
412 elsif (/\.sh(\.in)?$/)
421 # Read through the files and collect lists of tokens in them
422 # that might create nonportabilities.
425 find (\&scan_file, '.');
429 print "cfiles: @cfiles\n";
430 print "makefiles: @makefiles\n";
431 print "shfiles: @shfiles\n";
433 foreach my $kind (@kinds)
436 foreach my $word (sort keys %{$used{$kind}})
438 print "$word: @{$used{$kind}{$word}}\n";
445 ## ----------------------- ##
446 ## Output configure.scan. ##
447 ## ----------------------- ##
450 # output_kind ($FILE, $KIND)
451 # --------------------------
454 my ($file, $kind) = @_;
455 # Lists of words to be checked with the generic macro.
458 print $file "\n# $kind_comment{$kind}\n"
459 if exists $kind_comment{$kind};
460 foreach my $word (sort keys %{$used{$kind}})
462 # Output the needed macro invocations in $configure_scan if not
463 # already printed, and remember these macros are needed.
464 foreach my $macro (@{$macro{$kind}{$word}})
466 if ($macro =~ /^warn:\s+(.*)/)
469 foreach my $location (@{$used{$kind}{$word}})
471 warn "$location: warning: $message\n";
474 elsif (exists $generic_macro{$kind}
475 && $macro eq $generic_macro{$kind})
478 push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
479 @{$used{$kind}{$word}});
483 if (! $printed{$macro})
485 print $file "$macro\n";
486 $printed{$macro} = 1;
488 push (@{$needed_macros{$macro}},
489 @{$used{$kind}{$word}});
493 print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
498 # output_libraries ($FILE)
499 # ------------------------
500 sub output_libraries ($)
504 print $file "\n# Checks for libraries.\n";
505 foreach my $word (sort keys %{$used{'library'}})
507 print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
508 print $file "AC_CHECK_LIB([$word], [main])\n";
513 # output ($CONFIGURE_SCAN)
514 # ------------------------
515 # Print a proto configure.ac.
518 my $configure_scan = shift;
519 my %unique_makefiles;
521 my $file = new Autom4te::XFile ">$configure_scan";
524 ("# -*- Autoconf -*-\n" .
525 "# Process this file with autoconf to produce a configure script.\n" .
527 "AC_PREREQ(@VERSION@)\n" .
528 "AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)\n");
529 if (defined $cfiles[0])
531 print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
532 print $file "AC_CONFIG_HEADER([config.h])\n";
535 output_kind ($file, 'program');
536 output_kind ($file, 'makevar');
537 output_libraries ($file);
538 output_kind ($file, 'header');
539 output_kind ($file, 'identifier');
540 output_kind ($file, 'function');
545 # Change DIR/Makefile.in to DIR/Makefile.
546 foreach my $m (@makefiles)
548 $m =~ s/\.(?:in|am)$//;
549 $unique_makefiles{$m}++;
551 print $file ("AC_CONFIG_FILES([",
553 sort keys %unique_makefiles), "])\n");
557 print $file ("AC_CONFIG_SUBDIRS([",
559 sort @subdirs), "])\n");
561 print $file "AC_OUTPUT\n";
568 ## --------------------------------------- ##
569 ## Checking the accuracy of configure.ac. ##
570 ## --------------------------------------- ##
573 # &check_configure_ac ($CONFIGURE_AC)
574 # -----------------------------------
575 # Use autoconf to check if all the suggested macros are included
577 sub check_configure_ac ($)
579 my ($configure_ac) = @_;
581 # Find what needed macros are invoked in CONFIGURE_AC.
582 # I'd be very happy if someone could explain to me why sort (uniq ...)
583 # doesn't work properly: I need `uniq (sort ...)'. --akim
585 join (' --trace=', '',
586 uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
588 verb "running: $autoconf $trace_option $configure_ac";
590 new Autom4te::XFile "$autoconf $trace_option $configure_ac|";
592 while ($_ = $traces->getline)
595 my ($file, $line, $macro, @args) = split (/:/, $_);
596 if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
598 # To be rigorous, we should distinguish between space and comma
599 # separated macros. But there is no point.
600 foreach my $word (split (/\s|,/, $args[0]))
602 # AC_CHECK_MEMBERS wants `struct' or `union'.
603 if ($macro eq "AC_CHECK_MEMBERS"
604 && $word =~ /^stat.st_/)
606 $word = "struct " . $word;
608 delete $needed_macros{"$macro([$word])"};
613 delete $needed_macros{$macro};
619 # Report the missing macros.
620 foreach my $macro (sort keys %needed_macros)
622 warn ("$configure_ac: warning: missing $macro wanted by: "
623 . (${$needed_macros{$macro}}[0])
625 print $log "$me: warning: missing $macro wanted by: \n";
626 foreach my $need (@{$needed_macros{$macro}})
628 print $log "\t$need\n";
639 $log = new Autom4te::XFile ">$me.log";
641 $autoconf .= " --debug" if $debug;
642 $autoconf .= " --verbose" if $verbose;
643 $autoconf .= join (' --include=', '', @include);
644 $autoconf .= join (' --prepend-include=', '', @prepend_include);
646 my $configure_ac = find_configure_ac;
649 output ('configure.scan');
650 if (-f $configure_ac)
652 check_configure_ac ($configure_ac);
654 # This close is really needed. For some reason, probably best named
655 # a bug, it seems that the dtor of $LOG is not called automatically
656 # at END. It results in a truncated file.
660 ### Setup "GNU" style for perl-mode and cperl-mode.
662 ## perl-indent-level: 2
663 ## perl-continued-statement-offset: 2
664 ## perl-continued-brace-offset: 0
665 ## perl-brace-offset: 0
666 ## perl-brace-imaginary-offset: 0
667 ## perl-label-offset: -2
668 ## cperl-indent-level: 2
669 ## cperl-brace-offset: 0
670 ## cperl-continued-brace-offset: 0
671 ## cperl-label-offset: -2
672 ## cperl-extra-newline-before-brace: t
673 ## cperl-merge-trailing-else: nil
674 ## cperl-continued-statement-offset: 2