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 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 $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
32 unshift @INC, $pkgdatadir;
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 = ('@pkgdatadir@');
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>.
122 GNU Autoconf home page: <http://www.gnu.org/software/autoconf/>.
123 General help using GNU software: <http://www.gnu.org/gethelp/>.
128 $version = "autoscan (@PACKAGE_NAME@) @VERSION@
129 Copyright (C) @RELEASE_YEAR@ Free Software Foundation, Inc.
130 License GPLv2+: GNU GPL version 2 or later
131 <http://gnu.org/licenses/old-licenses/gpl-2.0.html>
132 This is free software: you are free to change and redistribute it.
133 There is NO WARRANTY, to the extent permitted by law.
135 Written by David J. MacKenzie and Akim Demaille.
141 ## ------------------------ ##
142 ## Command line interface. ##
143 ## ------------------------ ##
147 # Process any command line arguments.
150 getopt ('I|include=s' => \@include,
151 'B|prepend-include=s' => \@prepend_include);
153 die "$me: too many arguments
154 Try `$me --help' for more information.\n"
157 my $srcdir = $ARGV[0] || ".";
159 verb "srcdir = $srcdir";
160 chdir $srcdir || error "cannot cd to $srcdir: $!";
166 # Put values in the tables of what to do with each token.
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 "< " . open_quote ($file);
176 my $tables_are_consistent = 1;
178 while ($_ = $table->getline)
180 # Ignore blank lines and comments.
182 if /^\s*$/ || /^\s*\#/;
184 # '<kind>: <word> <macro invocation>' or...
185 # '<kind>: <word> warn: <message>'.
186 if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
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;
195 error "$file:$.: invalid definition: $_";
201 foreach my $kind (@kinds)
203 foreach my $word (sort keys %{$macro{$kind}})
205 print "$kind: $word: @{$macro{$kind}{$word}}\n";
213 # used ($KIND, $WORD, [$WHERE])
214 # -----------------------------
215 # $WORD is used as a $KIND.
218 my ($kind, $word, $where) = @_;
219 $where ||= "$File::Find::name:$.";
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}
229 push (@{$used{$kind}{$word}}, $where);
235 ## ----------------------- ##
236 ## Scanning source files. ##
237 ## ----------------------- ##
240 # scan_c_file ($FILE-NAME)
241 # ------------------------
244 my ($file_name) = @_;
245 push @cfiles, $File::Find::name;
247 # Nonzero if in a multiline comment.
250 my $file = new Autom4te::XFile "< " . open_quote ($file_name);
252 while ($_ = $file->getline)
254 # Strip out comments.
255 if ($in_comment && s,^.*?\*/,,)
259 # The whole line is inside a commment.
264 # Starting on this line.
270 # Preprocessor directives.
273 if (/^include\s*<([^>]*)>/)
277 if (s/^(if|ifdef|ifndef|elif)\s+//)
279 foreach my $word (split (/\W+/))
281 used ('identifier', $word)
282 unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
285 # Ignore other preprocessor directives.
289 # Remove string and character constants.
293 # Tokens in the code.
294 # Maybe we should ignore function definitions (in column 0)?
295 while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
297 used ('function', $1);
299 while (s/\b([a-zA-Z_]\w*)\b/ /)
301 used ('identifier', $1);
309 # scan_makefile($MAKEFILE-NAME)
310 # -----------------------------
311 sub scan_makefile ($)
313 my ($file_name) = @_;
314 push @makefiles, $File::Find::name;
316 my $file = new Autom4te::XFile "< " . open_quote ($file_name);
318 while ($_ = $file->getline)
320 # Strip out comments.
323 # Variable assignments.
324 while (s/\b([a-zA-Z_]\w*)\s*=/ /)
326 used ('makevar', $1);
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+/))
333 if ($word =~ /^-l([a-zA-Z_]\w*)$/)
335 used ('library', $1);
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+]*$/)
342 used ('program', $word);
351 # scan_sh_file($SHELL-SCRIPT-NAME)
352 # --------------------------------
355 my ($file_name) = @_;
356 push @shfiles, $File::Find::name;
358 my $file = new Autom4te::XFile "< " . open_quote ($file_name);
360 while ($_ = $file->getline)
362 # Strip out comments and variable references.
367 # Tokens in the code.
368 while (s/\b([a-zA-Z_]\w*)\b/ /)
370 used ('program', $1);
380 # Called by &find on each file. $_ contains the current file name with
381 # the current directory of the walk through.
384 # Wanted only if there is no corresponding FILE.in.
388 # Save $_ as Find::File requires it to be preserved.
391 # Strip a useless leading `./'.
392 $File::Find::name =~ s,^\./,,;
394 if ($_ ne '.' and -d $_ and
395 -f "$_/configure.in" ||
396 -f "$_/configure.ac" ||
397 -f "$_/configure.gnu" ||
400 $File::Find::prune = 1;
401 push @subdirs, $File::Find::name;
403 if (/\.[chlym](\.in)?$/)
405 used 'program', 'cc', $File::Find::name;
408 elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
410 used 'program', 'c++', $File::Find::name;
413 elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
414 || /^(?:GNUm|M|m)akefile(\.am)?$/)
418 elsif (/\.sh(\.in)?$/)
427 # Read through the files and collect lists of tokens in them
428 # that might create nonportabilities.
431 find (\&scan_file, '.');
435 print "cfiles: @cfiles\n";
436 print "makefiles: @makefiles\n";
437 print "shfiles: @shfiles\n";
439 foreach my $kind (@kinds)
442 foreach my $word (sort keys %{$used{$kind}})
444 print "$word: @{$used{$kind}{$word}}\n";
451 ## ----------------------- ##
452 ## Output configure.scan. ##
453 ## ----------------------- ##
456 # output_kind ($FILE, $KIND)
457 # --------------------------
460 my ($file, $kind) = @_;
461 # Lists of words to be checked with the generic macro.
464 print $file "\n# $kind_comment{$kind}\n"
465 if exists $kind_comment{$kind};
466 foreach my $word (sort keys %{$used{$kind}})
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}})
472 if ($macro =~ /^warn:\s+(.*)/)
475 foreach my $location (@{$used{$kind}{$word}})
477 warn "$location: warning: $message\n";
480 elsif (exists $generic_macro{$kind}
481 && $macro eq $generic_macro{$kind})
484 push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
485 @{$used{$kind}{$word}});
489 if (! $printed{$macro})
491 print $file "$macro\n";
492 $printed{$macro} = 1;
494 push (@{$needed_macros{$macro}},
495 @{$used{$kind}{$word}});
499 print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
504 # output_libraries ($FILE)
505 # ------------------------
506 sub output_libraries ($)
510 print $file "\n# Checks for libraries.\n";
511 foreach my $word (sort keys %{$used{'library'}})
513 print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
514 print $file "AC_CHECK_LIB([$word], [main])\n";
519 # output ($CONFIGURE_SCAN)
520 # ------------------------
521 # Print a proto configure.ac.
524 my $configure_scan = shift;
525 my %unique_makefiles;
527 my $file = new Autom4te::XFile "> " . open_quote ($configure_scan);
530 ("# -*- Autoconf -*-\n" .
531 "# Process this file with autoconf to produce a configure script.\n" .
533 "AC_PREREQ([@VERSION@])\n" .
534 "AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])\n");
535 if (defined $cfiles[0])
537 print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
538 print $file "AC_CONFIG_HEADERS([config.h])\n";
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');
551 # Change DIR/Makefile.in to DIR/Makefile.
552 foreach my $m (@makefiles)
554 $m =~ s/\.(?:in|am)$//;
555 $unique_makefiles{$m}++;
557 print $file ("AC_CONFIG_FILES([",
559 sort keys %unique_makefiles), "])\n");
563 print $file ("AC_CONFIG_SUBDIRS([",
565 sort @subdirs), "])\n");
567 print $file "AC_OUTPUT\n";
574 ## --------------------------------------- ##
575 ## Checking the accuracy of configure.ac. ##
576 ## --------------------------------------- ##
579 # &check_configure_ac ($CONFIGURE_AC)
580 # -----------------------------------
581 # Use autoconf to check if all the suggested macros are included
583 sub check_configure_ac ($)
585 my ($configure_ac) = @_;
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
591 join (' --trace=', '',
592 uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
594 verb "running: $autoconf $trace_option $configure_ac";
596 new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
598 while ($_ = $traces->getline)
601 my ($file, $line, $macro, @args) = split (/:/, $_);
602 if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
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]))
608 # AC_CHECK_MEMBERS wants `struct' or `union'.
609 if ($macro eq "AC_CHECK_MEMBERS"
610 && $word =~ /^stat.st_/)
612 $word = "struct " . $word;
614 delete $needed_macros{"$macro([$word])"};
619 delete $needed_macros{$macro};
625 # Report the missing macros.
626 foreach my $macro (sort keys %needed_macros)
628 warn ("$configure_ac: warning: missing $macro wanted by: "
629 . (${$needed_macros{$macro}}[0])
631 print $log "$me: warning: missing $macro wanted by: \n";
632 foreach my $need (@{$needed_macros{$macro}})
634 print $log "\t$need\n";
645 $log = new Autom4te::XFile "> " . open_quote ("$me.log");
647 $autoconf .= " --debug" if $debug;
648 $autoconf .= " --verbose" if $verbose;
649 $autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
650 $autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
652 my $configure_ac = find_configure_ac;
655 output ('configure.scan');
656 if (-f $configure_ac)
658 check_configure_ac ($configure_ac);
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.
666 ### Setup "GNU" style for perl-mode and cperl-mode.
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