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 # 2007, 2008, 2009, 2010 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 3 of the License, or
12 # (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
22 # Written by David MacKenzie <djm@gnu.ai.mit.edu>.
24 eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
29 my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
30 unshift @INC, $pkgdatadir;
32 # Override SHELL. On DJGPP SHELL may not be set to a shell
33 # that can handle redirection and quote arguments correctly,
34 # e.g.: COMMAND.COM. For DJGPP always use the shell that configure
36 $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');
39 use Autom4te::ChannelDefs;
40 use Autom4te::Configure_ac;
41 use Autom4te::General;
42 use Autom4te::FileUtils;
48 use vars qw(@cfiles @makefiles @shfiles @subdirs %printed);
50 # The kind of the words we are looking for.
51 my @kinds = qw (function header identifier program
54 # For each kind, the default macro.
57 'function' => 'AC_CHECK_FUNCS',
58 'header' => 'AC_CHECK_HEADERS',
59 'identifier' => 'AC_CHECK_TYPES',
60 'program' => 'AC_CHECK_PROGS',
61 'library' => 'AC_CHECK_LIB'
66 'function' => 'Checks for library functions.',
67 'header' => 'Checks for header files.',
68 'identifier' => 'Checks for typedefs, structures, and compiler characteristics.',
69 'program' => 'Checks for programs.',
72 # $USED{KIND}{ITEM} is the list of locations where the ITEM (of KIND) was used
73 # in the user package.
74 # For instance $USED{function}{alloca} is the list of `file:line' where
75 # `alloca (...)' appears.
78 # $MACRO{KIND}{ITEM} is the list of macros to use to test ITEM.
79 # Initialized from lib/autoscan/*. E.g., $MACRO{function}{alloca} contains
80 # the singleton AC_FUNC_ALLOCA. Some require several checks.
83 # $NEEDED_MACROS{MACRO} is an array of locations requiring MACRO.
84 # E.g., $NEEDED_MACROS{AC_FUNC_ALLOC} the list of `file:line' containing
91 my $configure_scan = 'configure.scan';
94 # Autoconf and lib files.
95 my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
96 my $autoconf = "$autom4te --language=autoconf";
98 my @include = ('@pkgdatadir@');
102 $help = "Usage: $0 [OPTION]... [SRCDIR]
104 Examine source files in the directory tree rooted at SRCDIR, or the
105 current directory if none is given. Search the source files for
106 common portability problems, check for incompleteness of
107 `configure.ac', and create a file `$configure_scan' which is a
108 preliminary `configure.ac' for that package.
110 -h, --help print this help, then exit
111 -V, --version print version number, then exit
112 -v, --verbose verbosely report processing
113 -d, --debug don't remove temporary files
116 -B, --prepend-include=DIR prepend directory DIR to search path
117 -I, --include=DIR append directory DIR to search path
119 Report bugs to <bug-autoconf\@gnu.org>.
120 GNU Autoconf home page: <http://www.gnu.org/software/autoconf/>.
121 General help using GNU software: <http://www.gnu.org/gethelp/>.
126 $version = "autoscan (@PACKAGE_NAME@) @VERSION@
127 Copyright (C) @RELEASE_YEAR@ Free Software Foundation, Inc.
128 License GPLv3+/Autoconf: GNU GPL version 3 or later
129 <http://gnu.org/licenses/gpl.html>, <http://gnu.org/licenses/exceptions.html>
130 This is free software: you are free to change and redistribute it.
131 There is NO WARRANTY, to the extent permitted by law.
133 Written by David J. MacKenzie and Akim Demaille.
139 ## ------------------------ ##
140 ## Command line interface. ##
141 ## ------------------------ ##
145 # Process any command line arguments.
148 getopt ('I|include=s' => \@include,
149 'B|prepend-include=s' => \@prepend_include);
151 die "$me: too many arguments
152 Try `$me --help' for more information.\n"
155 my $srcdir = $ARGV[0] || ".";
157 verb "srcdir = $srcdir";
158 chdir $srcdir || error "cannot cd to $srcdir: $!";
164 # Put values in the tables of what to do with each token.
167 # The data file format supports only one line of macros per function.
168 # If more than that is required for a common portability problem,
169 # a new Autoconf macro should probably be written for that case,
170 # instead of duplicating the code in lots of configure.ac files.
171 my $file = find_file ("autoscan/autoscan.list",
172 reverse (@prepend_include), @include);
173 my $table = new Autom4te::XFile "< " . open_quote ($file);
174 my $tables_are_consistent = 1;
176 while ($_ = $table->getline)
178 # Ignore blank lines and comments.
180 if /^\s*$/ || /^\s*\#/;
182 # '<kind>: <word> <macro invocation>' or...
183 # '<kind>: <word> warn: <message>'.
184 if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
186 my ($kind, $word, $macro) = ($1, $2, $3);
187 error "$file:$.: invalid kind: $_"
188 unless grep { $_ eq $kind } @kinds;
189 push @{$macro{$kind}{$word}}, $macro;
193 error "$file:$.: invalid definition: $_";
199 foreach my $kind (@kinds)
201 foreach my $word (sort keys %{$macro{$kind}})
203 print "$kind: $word: @{$macro{$kind}{$word}}\n";
211 # used ($KIND, $WORD, [$WHERE])
212 # -----------------------------
213 # $WORD is used as a $KIND.
216 my ($kind, $word, $where) = @_;
217 $where ||= "$File::Find::name:$.";
219 # Check for all the libraries. But `-links' is certainly a
220 # `find' argument, and `-le', a `test' argument.
221 ($kind eq 'library' && $word !~ /^(e|inks)$/)
222 # Other than libraries are to be checked only if listed in
223 # the Autoscan library files.
224 || defined $macro{$kind}{$word}
227 push (@{$used{$kind}{$word}}, $where);
233 ## ----------------------- ##
234 ## Scanning source files. ##
235 ## ----------------------- ##
238 # scan_c_file ($FILE-NAME)
239 # ------------------------
242 my ($file_name) = @_;
243 push @cfiles, $File::Find::name;
245 # Nonzero if in a multiline comment.
248 my $file = new Autom4te::XFile "< " . open_quote ($file_name);
250 while ($_ = $file->getline)
252 # Strip out comments.
253 if ($in_comment && s,^.*?\*/,,)
257 # The whole line is inside a commment.
262 # Starting on this line.
268 # Preprocessor directives.
271 if (/^include\s*<([^>]*)>/)
275 if (s/^(if|ifdef|ifndef|elif)\s+//)
277 foreach my $word (split (/\W+/))
279 used ('identifier', $word)
280 unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
283 # Ignore other preprocessor directives.
287 # Remove string and character constants.
291 # Tokens in the code.
292 # Maybe we should ignore function definitions (in column 0)?
293 while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
295 used ('function', $1);
297 while (s/\b([a-zA-Z_]\w*)\b/ /)
299 used ('identifier', $1);
307 # scan_makefile($MAKEFILE-NAME)
308 # -----------------------------
309 sub scan_makefile ($)
311 my ($file_name) = @_;
312 push @makefiles, $File::Find::name;
314 my $file = new Autom4te::XFile "< " . open_quote ($file_name);
316 while ($_ = $file->getline)
318 # Strip out comments.
321 # Variable assignments.
322 while (s/\b([a-zA-Z_]\w*)\s*=/ /)
324 used ('makevar', $1);
326 # Be sure to catch a whole word. For instance `lex$U.$(OBJEXT)'
327 # is a single token. Otherwise we might believe `lex' is needed.
328 foreach my $word (split (/\s+/))
331 if ($word =~ /^-l([a-zA-Z_]\w*)$/)
333 used ('library', $1);
335 # Tokens in the code.
336 # We allow some additional characters, e.g., `+', since
337 # autoscan/programs includes `c++'.
338 if ($word =~ /^[a-zA-Z_][\w+]*$/)
340 used ('program', $word);
349 # scan_sh_file($SHELL-SCRIPT-NAME)
350 # --------------------------------
353 my ($file_name) = @_;
354 push @shfiles, $File::Find::name;
356 my $file = new Autom4te::XFile "< " . open_quote ($file_name);
358 while ($_ = $file->getline)
360 # Strip out comments and variable references.
365 # Tokens in the code.
366 while (s/\b([a-zA-Z_]\w*)\b/ /)
368 used ('program', $1);
378 # Called by &find on each file. $_ contains the current file name with
379 # the current directory of the walk through.
382 # Wanted only if there is no corresponding FILE.in.
386 # Save $_ as Find::File requires it to be preserved.
389 # Strip a useless leading `./'.
390 $File::Find::name =~ s,^\./,,;
392 if ($_ ne '.' and -d $_ and
393 -f "$_/configure.in" ||
394 -f "$_/configure.ac" ||
395 -f "$_/configure.gnu" ||
398 $File::Find::prune = 1;
399 push @subdirs, $File::Find::name;
401 if (/\.[chlym](\.in)?$/)
403 used 'program', 'cc', $File::Find::name;
406 elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
408 used 'program', 'c++', $File::Find::name;
411 elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
412 || /^(?:GNUm|M|m)akefile(\.am)?$/)
416 elsif (/\.sh(\.in)?$/)
425 # Read through the files and collect lists of tokens in them
426 # that might create nonportabilities.
429 find (\&scan_file, '.');
433 print "cfiles: @cfiles\n";
434 print "makefiles: @makefiles\n";
435 print "shfiles: @shfiles\n";
437 foreach my $kind (@kinds)
440 foreach my $word (sort keys %{$used{$kind}})
442 print "$word: @{$used{$kind}{$word}}\n";
449 ## ----------------------- ##
450 ## Output configure.scan. ##
451 ## ----------------------- ##
454 # output_kind ($FILE, $KIND)
455 # --------------------------
458 my ($file, $kind) = @_;
459 # Lists of words to be checked with the generic macro.
462 print $file "\n# $kind_comment{$kind}\n"
463 if exists $kind_comment{$kind};
464 foreach my $word (sort keys %{$used{$kind}})
466 # Output the needed macro invocations in $configure_scan if not
467 # already printed, and remember these macros are needed.
468 foreach my $macro (@{$macro{$kind}{$word}})
470 if ($macro =~ /^warn:\s+(.*)/)
473 foreach my $location (@{$used{$kind}{$word}})
475 warn "$location: warning: $message\n";
478 elsif (exists $generic_macro{$kind}
479 && $macro eq $generic_macro{$kind})
482 push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
483 @{$used{$kind}{$word}});
487 if (! $printed{$macro})
489 print $file "$macro\n";
490 $printed{$macro} = 1;
492 push (@{$needed_macros{$macro}},
493 @{$used{$kind}{$word}});
497 print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
502 # output_libraries ($FILE)
503 # ------------------------
504 sub output_libraries ($)
508 print $file "\n# Checks for libraries.\n";
509 foreach my $word (sort keys %{$used{'library'}})
511 print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
512 print $file "AC_CHECK_LIB([$word], [main])\n";
517 # output ($CONFIGURE_SCAN)
518 # ------------------------
519 # Print a proto configure.ac.
522 my $configure_scan = shift;
523 my %unique_makefiles;
525 my $file = new Autom4te::XFile "> " . open_quote ($configure_scan);
528 ("# -*- Autoconf -*-\n" .
529 "# Process this file with autoconf to produce a configure script.\n" .
531 "AC_PREREQ([@VERSION@])\n" .
532 "AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])\n");
533 if (defined $cfiles[0])
535 print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
536 print $file "AC_CONFIG_HEADERS([config.h])\n";
539 output_kind ($file, 'program');
540 output_kind ($file, 'makevar');
541 output_libraries ($file);
542 output_kind ($file, 'header');
543 output_kind ($file, 'identifier');
544 output_kind ($file, 'function');
549 # Change DIR/Makefile.in to DIR/Makefile.
550 foreach my $m (@makefiles)
552 $m =~ s/\.(?:in|am)$//;
553 $unique_makefiles{$m}++;
555 print $file ("AC_CONFIG_FILES([",
557 sort keys %unique_makefiles), "])\n");
561 print $file ("AC_CONFIG_SUBDIRS([",
563 sort @subdirs), "])\n");
565 print $file "AC_OUTPUT\n";
572 ## --------------------------------------- ##
573 ## Checking the accuracy of configure.ac. ##
574 ## --------------------------------------- ##
577 # &check_configure_ac ($CONFIGURE_AC)
578 # -----------------------------------
579 # Use autoconf to check if all the suggested macros are included
581 sub check_configure_ac ($)
583 my ($configure_ac) = @_;
585 # Find what needed macros are invoked in CONFIGURE_AC.
586 # I'd be very happy if someone could explain to me why sort (uniq ...)
587 # doesn't work properly: I need `uniq (sort ...)'. --akim
589 join (' --trace=', '',
590 uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
592 verb "running: $autoconf $trace_option $configure_ac";
594 new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
596 while ($_ = $traces->getline)
599 my ($file, $line, $macro, @args) = split (/:/, $_);
600 if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
602 # To be rigorous, we should distinguish between space and comma
603 # separated macros. But there is no point.
604 foreach my $word (split (/\s|,/, $args[0]))
606 # AC_CHECK_MEMBERS wants `struct' or `union'.
607 if ($macro eq "AC_CHECK_MEMBERS"
608 && $word =~ /^stat.st_/)
610 $word = "struct " . $word;
612 delete $needed_macros{"$macro([$word])"};
617 delete $needed_macros{$macro};
623 # Report the missing macros.
624 foreach my $macro (sort keys %needed_macros)
626 warn ("$configure_ac: warning: missing $macro wanted by: "
627 . (${$needed_macros{$macro}}[0])
629 print $log "$me: warning: missing $macro wanted by: \n";
630 foreach my $need (@{$needed_macros{$macro}})
632 print $log "\t$need\n";
643 $log = new Autom4te::XFile "> " . open_quote ("$me.log");
645 $autoconf .= " --debug" if $debug;
646 $autoconf .= " --verbose" if $verbose;
647 $autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
648 $autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
650 my $configure_ac = find_configure_ac;
653 output ('configure.scan');
654 if (-f $configure_ac)
656 check_configure_ac ($configure_ac);
658 # This close is really needed. For some reason, probably best named
659 # a bug, it seems that the dtor of $LOG is not called automatically
660 # at END. It results in a truncated file.
664 ### Setup "GNU" style for perl-mode and cperl-mode.
666 ## perl-indent-level: 2
667 ## perl-continued-statement-offset: 2
668 ## perl-continued-brace-offset: 0
669 ## perl-brace-offset: 0
670 ## perl-brace-imaginary-offset: 0
671 ## perl-label-offset: -2
672 ## cperl-indent-level: 2
673 ## cperl-brace-offset: 0
674 ## cperl-continued-brace-offset: 0
675 ## cperl-label-offset: -2
676 ## cperl-extra-newline-before-brace: t
677 ## cperl-merge-trailing-else: nil
678 ## cperl-continued-statement-offset: 2