5 # autoscan - Create configure.scan (a preliminary configure.ac) for a package.
6 # Copyright (C) 1994, 1999-2017, 2020-2022 Free Software Foundation,
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 <https://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 use warnings FATAL => 'all';
33 my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
34 unshift @INC, $pkgdatadir;
36 # Override SHELL. On DJGPP SHELL may not be set to a shell
37 # that can handle redirection and quote arguments correctly,
38 # e.g.: COMMAND.COM. For DJGPP always use the shell that configure
40 $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');
46 use Autom4te::ChannelDefs;
47 use Autom4te::Configure_ac;
48 use Autom4te::FileUtils;
49 use Autom4te::General;
52 my (@cfiles, @makefiles, @shfiles, @subdirs, %printed);
54 # The kind of the words we are looking for.
55 my @kinds = qw (function header identifier program
58 # For each kind, the default macro.
61 'function' => 'AC_CHECK_FUNCS',
62 'header' => 'AC_CHECK_HEADERS',
63 'identifier' => 'AC_CHECK_TYPES',
64 'program' => 'AC_CHECK_PROGS',
65 'library' => 'AC_CHECK_LIB'
70 'function' => 'Checks for library functions.',
71 'header' => 'Checks for header files.',
72 'identifier' => 'Checks for typedefs, structures, and compiler characteristics.',
73 'program' => 'Checks for programs.',
76 # $USED{KIND}{ITEM} is the list of locations where the ITEM (of KIND) was
77 # used in the user package.
78 # For instance $USED{function}{alloca} is the list of 'file:line' where
79 # 'alloca (...)' appears.
82 # $MACRO{KIND}{ITEM} is the list of macros to use to test ITEM.
83 # Initialized from lib/autoscan/*. E.g., $MACRO{function}{alloca} contains
84 # the singleton AC_FUNC_ALLOCA. Some require several checks.
87 # $NEEDED_MACROS{MACRO} is an array of locations requiring MACRO.
88 # E.g., $NEEDED_MACROS{AC_FUNC_ALLOC} the list of 'file:line' containing
97 # Autoconf and lib files.
98 my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
99 my $autoconf = "$autom4te --language=autoconf";
101 my @include = ('@pkgdatadir@');
105 $help = "Usage: $0 [OPTION]... [SRCDIR]
107 Examine source files in the directory tree rooted at SRCDIR, or the
108 current directory if none is given. Search the source files for
109 common portability problems, check for incompleteness of
110 'configure.ac', and create a file 'configure.scan' which is a
111 preliminary 'configure.ac' for that package.
113 -h, --help print this help, then exit
114 -V, --version print version number, then exit
115 -v, --verbose verbosely report processing
116 -d, --debug don't remove temporary files
119 -B, --prepend-include=DIR prepend directory DIR to search path
120 -I, --include=DIR append directory DIR to search path
122 Report bugs to <bug-autoconf\@gnu.org>.
123 GNU Autoconf home page: <https://www.gnu.org/software/autoconf/>.
124 General help using GNU software: <https://www.gnu.org/gethelp/>.
129 $version = "autoscan (@PACKAGE_NAME@) @VERSION@
130 Copyright (C) @RELEASE_YEAR@ Free Software Foundation, Inc.
131 License GPLv3+/Autoconf: GNU GPL version 3 or later
132 <https://gnu.org/licenses/gpl.html>, <https://gnu.org/licenses/exceptions.html>
133 This is free software: you are free to change and redistribute it.
134 There is NO WARRANTY, to the extent permitted by law.
136 Written by David J. MacKenzie and Akim Demaille.
142 ## ------------------------ ##
143 ## Command line interface. ##
144 ## ------------------------ ##
148 # Process any command line arguments.
151 getopt ('I|include=s' => \@include,
152 'B|prepend-include=s' => \@prepend_include);
154 die "$me: too many arguments
155 Try '$me --help' for more information.\n"
158 my $srcdir = $ARGV[0] || ".";
160 verb "srcdir = $srcdir";
161 chdir $srcdir || error "cannot cd to $srcdir: $!";
167 # Put values in the tables of what to do with each token.
170 # The data file format supports only one line of macros per function.
171 # If more than that is required for a common portability problem,
172 # a new Autoconf macro should probably be written for that case,
173 # instead of duplicating the code in lots of configure.ac files.
174 my $file = find_file ("autoscan/autoscan.list",
175 reverse (@prepend_include), @include);
176 my $table = new Autom4te::XFile ($file, "<");
177 my $tables_are_consistent = 1;
179 while ($_ = $table->getline)
181 # Ignore blank lines and comments.
183 if /^\s*$/ || /^\s*\#/;
185 # '<kind>: <word> <macro invocation>' or...
186 # '<kind>: <word> warn: <message>'.
187 if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
189 my ($kind, $word, $macro) = ($1, $2, $3);
190 error "$file:$.: invalid kind: $_"
191 unless grep { $_ eq $kind } @kinds;
192 push @{$macro{$kind}{$word}}, $macro;
196 error "$file:$.: invalid definition: $_";
202 foreach my $kind (@kinds)
204 foreach my $word (sort keys %{$macro{$kind}})
206 print "$kind: $word: @{$macro{$kind}{$word}}\n";
214 # used ($KIND, $WORD, [$WHERE])
215 # -----------------------------
216 # $WORD is used as a $KIND.
219 my ($kind, $word, $where) = @_;
220 $where ||= "$File::Find::name:$.";
222 # Check for all the libraries. But '-links' is certainly a
223 # 'find' argument, and '-le', a 'test' argument.
224 ($kind eq 'library' && $word !~ /^(e|inks)$/)
225 # Other than libraries are to be checked only if listed in
226 # the Autoscan library files.
227 || defined $macro{$kind}{$word}
230 push (@{$used{$kind}{$word}}, $where);
236 ## ----------------------- ##
237 ## Scanning source files. ##
238 ## ----------------------- ##
241 # scan_c_file ($FILE-NAME)
242 # ------------------------
245 my ($file_name) = @_;
246 push @cfiles, $File::Find::name;
248 # Nonzero if in a multiline comment.
251 my $file = new Autom4te::XFile ($file_name, "<");
253 while ($_ = $file->getline)
255 # Strip out comments.
256 if ($in_comment && s,^.*?\*/,,)
260 # The whole line is inside a comment.
265 # Starting on this line.
271 # Preprocessor directives.
274 if (/^include\s*<([^>]*)>/)
278 if (s/^(if|ifdef|ifndef|elif)\s+//)
280 foreach my $word (split (/\W+/))
282 used ('identifier', $word)
283 unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
286 # Ignore other preprocessor directives.
290 # Remove string and character constants.
294 # Tokens in the code.
295 # Maybe we should ignore function definitions (in column 0)?
296 while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
298 used ('function', $1);
300 while (s/\b([a-zA-Z_]\w*)\b/ /)
302 used ('identifier', $1);
310 # scan_makefile($MAKEFILE-NAME)
311 # -----------------------------
312 sub scan_makefile ($)
314 my ($file_name) = @_;
315 push @makefiles, $File::Find::name;
317 my $file = new Autom4te::XFile ($file_name, "<");
319 while ($_ = $file->getline)
321 # Strip out comments.
324 # Variable assignments.
325 while (s/\b([a-zA-Z_]\w*)\s*=/ /)
327 used ('makevar', $1);
329 # Be sure to catch a whole word. For instance 'lex$U.$(OBJEXT)'
330 # is a single token. Otherwise we might believe 'lex' is needed.
331 foreach my $word (split (/\s+/))
334 if ($word =~ /^-l([a-zA-Z_]\w*)$/)
336 used ('library', $1);
338 # Tokens in the code.
339 # We allow some additional characters, e.g., '+', since
340 # autoscan/programs includes 'c++'.
341 if ($word =~ /^[a-zA-Z_][\w+]*$/)
343 used ('program', $word);
352 # scan_sh_file($SHELL-SCRIPT-NAME)
353 # --------------------------------
356 my ($file_name) = @_;
357 push @shfiles, $File::Find::name;
359 my $file = new Autom4te::XFile ($file_name, "<");
361 while ($_ = $file->getline)
363 # Strip out comments and variable references.
368 # Tokens in the code.
369 while (s/\b([a-zA-Z_]\w*)\b/ /)
371 used ('program', $1);
381 # Called by &find on each file. $_ contains the current file name with
382 # the current directory of the walk through.
385 # Wanted only if there is no corresponding FILE.in.
389 # Save $_ as Find::File requires it to be preserved.
392 # Strip a useless leading './'.
393 $File::Find::name =~ s,^\./,,;
395 if ($_ ne '.' and -d $_ and
396 -f "$_/configure.in" ||
397 -f "$_/configure.ac" ||
398 -f "$_/configure.gnu" ||
401 $File::Find::prune = 1;
402 push @subdirs, $File::Find::name;
404 if (/\.[chlym](\.in)?$/)
406 used 'program', 'cc', $File::Find::name;
409 elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
411 used 'program', 'c++', $File::Find::name;
414 elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
415 || /^(?:GNUm|M|m)akefile(\.am)?$/)
419 elsif (/\.sh(\.in)?$/)
428 # Read through the files and collect lists of tokens in them
429 # that might create nonportabilities.
432 find (\&scan_file, '.');
436 print "cfiles: @cfiles\n";
437 print "makefiles: @makefiles\n";
438 print "shfiles: @shfiles\n";
440 foreach my $kind (@kinds)
443 foreach my $word (sort keys %{$used{$kind}})
445 print "$word: @{$used{$kind}{$word}}\n";
452 ## ----------------------- ##
453 ## Output configure.scan. ##
454 ## ----------------------- ##
457 # output_kind ($FILE, $KIND)
458 # --------------------------
461 my ($file, $kind) = @_;
462 # Lists of words to be checked with the generic macro.
465 print $file "\n# $kind_comment{$kind}\n"
466 if exists $kind_comment{$kind};
467 foreach my $word (sort keys %{$used{$kind}})
469 # Output the needed macro invocations in configure.scan if not
470 # already printed, and remember these macros are needed.
471 foreach my $macro (@{$macro{$kind}{$word}})
473 if ($macro =~ /^warn:\s+(.*)/)
476 foreach my $location (@{$used{$kind}{$word}})
478 warn "$location: warning: $message\n";
481 elsif (exists $generic_macro{$kind}
482 && $macro eq $generic_macro{$kind})
485 push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
486 @{$used{$kind}{$word}});
490 if (! $printed{$macro})
492 print $file "$macro\n";
493 $printed{$macro} = 1;
495 push (@{$needed_macros{$macro}},
496 @{$used{$kind}{$word}});
500 print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
505 # output_libraries ($FILE)
506 # ------------------------
507 sub output_libraries ($)
511 print $file "\n# Checks for libraries.\n";
512 foreach my $word (sort keys %{$used{'library'}})
514 print $file "# FIXME: Replace 'main' with a function in '-l$word':\n";
515 print $file "AC_CHECK_LIB([$word], [main])\n";
520 # output ($CONFIGURE_SCAN)
521 # ------------------------
522 # Print a proto configure.ac.
525 my $configure_scan = shift;
526 my %unique_makefiles;
528 my $file = new Autom4te::XFile ($configure_scan, ">");
531 ("# -*- Autoconf -*-\n" .
532 "# Process this file with autoconf to produce a configure script.\n" .
534 "AC_PREREQ([@VERSION@])\n" .
535 "AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])\n");
536 if (defined $cfiles[0])
538 print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
539 print $file "AC_CONFIG_HEADERS([config.h])\n";
542 output_kind ($file, 'program');
543 output_kind ($file, 'makevar');
544 output_libraries ($file);
545 output_kind ($file, 'header');
546 output_kind ($file, 'identifier');
547 output_kind ($file, 'function');
552 # Change DIR/Makefile.in to DIR/Makefile.
553 foreach my $m (@makefiles)
555 $m =~ s/\.(?:in|am)$//;
556 $unique_makefiles{$m}++;
558 print $file ("AC_CONFIG_FILES([",
560 sort keys %unique_makefiles), "])\n");
564 print $file ("AC_CONFIG_SUBDIRS([",
566 sort @subdirs), "])\n");
568 print $file "AC_OUTPUT\n";
575 ## --------------------------------------- ##
576 ## Checking the accuracy of configure.ac. ##
577 ## --------------------------------------- ##
580 # &check_configure_ac ($CONFIGURE_AC)
581 # -----------------------------------
582 # Use autoconf to check if all the suggested macros are included
584 sub check_configure_ac ($)
586 my ($configure_ac) = @_;
588 # Find what needed macros are invoked in CONFIGURE_AC.
589 # I'd be very happy if someone could explain to me why sort (uniq ...)
590 # doesn't work properly: I need 'uniq (sort ...)'. --akim
592 join (' --trace=', '',
593 uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
595 # Suppress all warnings from the subsidiary autoconf invocation.
596 local $ENV{WARNINGS} = 'none';
598 verb "running: WARNINGS=none $autoconf $trace_option $configure_ac";
600 new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
602 while ($_ = $traces->getline)
605 my ($file, $line, $macro, @args) = split (/:/, $_);
606 if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
608 # To be rigorous, we should distinguish between space and comma
609 # separated macros. But there is no point.
610 foreach my $word (split (/\s|,/, $args[0]))
612 # AC_CHECK_MEMBERS wants 'struct' or 'union'.
613 if ($macro eq "AC_CHECK_MEMBERS"
614 && $word =~ /^stat.st_/)
616 $word = "struct " . $word;
618 delete $needed_macros{"$macro([$word])"};
623 delete $needed_macros{$macro};
629 # Report the missing macros.
630 foreach my $macro (sort keys %needed_macros)
632 warn ("$configure_ac: warning: missing $macro wanted by: "
633 . (${$needed_macros{$macro}}[0])
635 print $log "$me: warning: missing $macro wanted by: \n";
636 foreach my $need (@{$needed_macros{$macro}})
638 print $log "\t$need\n";
649 $log = new Autom4te::XFile ("$me.log", ">");
651 $autoconf .= " --debug" if $debug;
652 $autoconf .= " --verbose" if $verbose;
653 $autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
654 $autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
656 my $configure_ac = find_configure_ac;
659 output ('configure.scan');
660 if (-f $configure_ac)
662 check_configure_ac ($configure_ac);
664 # This close is really needed. For some reason, probably best named
665 # a bug, it seems that the dtor of $LOG is not called automatically
666 # at END. It results in a truncated file.
670 ### Setup "GNU" style for perl-mode and cperl-mode.
672 ## perl-indent-level: 2
673 ## perl-continued-statement-offset: 2
674 ## perl-continued-brace-offset: 0
675 ## perl-brace-offset: 0
676 ## perl-brace-imaginary-offset: 0
677 ## perl-label-offset: -2
678 ## cperl-indent-level: 2
679 ## cperl-brace-offset: 0
680 ## cperl-continued-brace-offset: 0
681 ## cperl-label-offset: -2
682 ## cperl-extra-newline-before-brace: t
683 ## cperl-merge-trailing-else: nil
684 ## cperl-continued-statement-offset: 2