5 # autoscan - Create configure.scan (a preliminary configure.ac) for a package.
6 # Copyright (C) 1994, 1999-2017, 2020-2024 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>.
124 The full documentation for Autoconf can be read via 'info autoconf',
125 or on the Web at <https://www.gnu.org/software/autoconf/manual/>.
130 $version = "autoscan (@PACKAGE_NAME@) @VERSION@
131 Copyright (C) @RELEASE_YEAR@ Free Software Foundation, Inc.
132 License GPLv3+/Autoconf: GNU GPL version 3 or later
133 <https://gnu.org/licenses/gpl.html>, <https://gnu.org/licenses/exceptions.html>
134 This is free software: you are free to change and redistribute it.
135 There is NO WARRANTY, to the extent permitted by law.
137 Written by David J. MacKenzie and Akim Demaille.
143 ## ------------------------ ##
144 ## Command line interface. ##
145 ## ------------------------ ##
149 # Process any command line arguments.
152 getopt ('I|include=s' => \@include,
153 'B|prepend-include=s' => \@prepend_include);
155 die "$me: too many arguments
156 Try '$me --help' for more information.\n"
159 my $srcdir = $ARGV[0] || ".";
161 verb "srcdir = $srcdir";
162 chdir $srcdir || error "cannot cd to $srcdir: $!";
168 # Put values in the tables of what to do with each token.
171 # The data file format supports only one line of macros per function.
172 # If more than that is required for a common portability problem,
173 # a new Autoconf macro should probably be written for that case,
174 # instead of duplicating the code in lots of configure.ac files.
175 my $file = find_file ("autoscan/autoscan.list",
176 reverse (@prepend_include), @include);
177 my $table = new Autom4te::XFile ($file, "<");
178 my $tables_are_consistent = 1;
180 while ($_ = $table->getline)
182 # Ignore blank lines and comments.
184 if /^\s*$/ || /^\s*\#/;
186 # '<kind>: <word> <macro invocation>' or...
187 # '<kind>: <word> warn: <message>'.
188 if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
190 my ($kind, $word, $macro) = ($1, $2, $3);
191 error "$file:$.: invalid kind: $_"
192 unless grep { $_ eq $kind } @kinds;
193 push @{$macro{$kind}{$word}}, $macro;
197 error "$file:$.: invalid definition: $_";
203 foreach my $kind (@kinds)
205 foreach my $word (sort keys %{$macro{$kind}})
207 print "$kind: $word: @{$macro{$kind}{$word}}\n";
215 # used ($KIND, $WORD, [$WHERE])
216 # -----------------------------
217 # $WORD is used as a $KIND.
220 my ($kind, $word, $where) = @_;
221 $where ||= "$File::Find::name:$.";
223 # Check for all the libraries. But '-links' is certainly a
224 # 'find' argument, and '-le', a 'test' argument.
225 ($kind eq 'library' && $word !~ /^(e|inks)$/)
226 # Other than libraries are to be checked only if listed in
227 # the Autoscan library files.
228 || defined $macro{$kind}{$word}
231 push (@{$used{$kind}{$word}}, $where);
237 ## ----------------------- ##
238 ## Scanning source files. ##
239 ## ----------------------- ##
242 # scan_c_file ($FILE-NAME)
243 # ------------------------
246 my ($file_name) = @_;
247 push @cfiles, $File::Find::name;
249 # Nonzero if in a multiline comment.
252 my $file = new Autom4te::XFile ($file_name, "<");
254 while ($_ = $file->getline)
256 # Strip out comments.
257 if ($in_comment && s,^.*?\*/,,)
261 # The whole line is inside a comment.
266 # Starting on this line.
272 # Preprocessor directives.
275 if (/^include\s*<([^>]*)>/)
279 if (s/^(el)?if(n?def)?\s+//)
281 foreach my $word (split (/\W+/))
283 used ('identifier', $word)
284 unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
287 # Ignore other preprocessor directives.
291 # Remove string and character constants.
295 # Tokens in the code.
296 # Maybe we should ignore function definitions (in column 0)?
297 while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
299 used ('function', $1);
301 while (s/\b([a-zA-Z_]\w*)\b/ /)
303 used ('identifier', $1);
311 # scan_makefile($MAKEFILE-NAME)
312 # -----------------------------
313 sub scan_makefile ($)
315 my ($file_name) = @_;
316 push @makefiles, $File::Find::name;
318 my $file = new Autom4te::XFile ($file_name, "<");
320 while ($_ = $file->getline)
322 # Strip out comments.
325 # Variable assignments.
326 while (s/\b([a-zA-Z_]\w*)\s*=/ /)
328 used ('makevar', $1);
330 # Be sure to catch a whole word. For instance 'lex$U.$(OBJEXT)'
331 # is a single token. Otherwise we might believe 'lex' is needed.
332 foreach my $word (split (/\s+/))
335 if ($word =~ /^-l([a-zA-Z_]\w*)$/)
337 used ('library', $1);
339 # Tokens in the code.
340 # We allow some additional characters, e.g., '+', since
341 # autoscan/programs includes 'c++'.
342 if ($word =~ /^[a-zA-Z_][\w+]*$/)
344 used ('program', $word);
353 # scan_sh_file($SHELL-SCRIPT-NAME)
354 # --------------------------------
357 my ($file_name) = @_;
358 push @shfiles, $File::Find::name;
360 my $file = new Autom4te::XFile ($file_name, "<");
362 while ($_ = $file->getline)
364 # Strip out comments and variable references.
369 # Tokens in the code.
370 while (s/\b([a-zA-Z_]\w*)\b/ /)
372 used ('program', $1);
382 # Called by &find on each file. $_ contains the current file name with
383 # the current directory of the walk through.
386 # Wanted only if there is no corresponding FILE.in.
390 # Save $_ as Find::File requires it to be preserved.
393 # Strip a useless leading './'.
394 $File::Find::name =~ s,^\./,,;
396 if ($_ ne '.' and -d $_ and
397 -f "$_/configure.in" ||
398 -f "$_/configure.ac" ||
399 -f "$_/configure.gnu" ||
402 $File::Find::prune = 1;
403 push @subdirs, $File::Find::name;
405 if (/\.[chlym](\.in)?$/)
407 used 'program', 'cc', $File::Find::name;
410 elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
412 used 'program', 'c++', $File::Find::name;
415 elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
416 || /^(?:GNUm|M|m)akefile(\.am)?$/)
420 elsif (/\.sh(\.in)?$/)
429 # Read through the files and collect lists of tokens in them
430 # that might create nonportabilities.
433 find (\&scan_file, '.');
437 print "cfiles: @cfiles\n";
438 print "makefiles: @makefiles\n";
439 print "shfiles: @shfiles\n";
441 foreach my $kind (@kinds)
444 foreach my $word (sort keys %{$used{$kind}})
446 print "$word: @{$used{$kind}{$word}}\n";
453 ## ----------------------- ##
454 ## Output configure.scan. ##
455 ## ----------------------- ##
458 # output_kind ($FILE, $KIND)
459 # --------------------------
462 my ($file, $kind) = @_;
463 # Lists of words to be checked with the generic macro.
466 print $file "\n# $kind_comment{$kind}\n"
467 if exists $kind_comment{$kind};
468 foreach my $word (sort keys %{$used{$kind}})
470 # Output the needed macro invocations in configure.scan if not
471 # already printed, and remember these macros are needed.
472 foreach my $macro (@{$macro{$kind}{$word}})
474 if ($macro =~ /^warn:\s+(.*)/)
477 foreach my $location (@{$used{$kind}{$word}})
479 warn "$location: warning: $message\n";
482 elsif (exists $generic_macro{$kind}
483 && $macro eq $generic_macro{$kind})
486 push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
487 @{$used{$kind}{$word}});
491 if (! $printed{$macro})
493 print $file "$macro\n";
494 $printed{$macro} = 1;
496 push (@{$needed_macros{$macro}},
497 @{$used{$kind}{$word}});
501 print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
506 # output_libraries ($FILE)
507 # ------------------------
508 sub output_libraries ($)
512 print $file "\n# Checks for libraries.\n";
513 foreach my $word (sort keys %{$used{'library'}})
515 print $file "# FIXME: Replace 'main' with a function in '-l$word':\n";
516 print $file "AC_CHECK_LIB([$word], [main])\n";
521 # output ($CONFIGURE_SCAN)
522 # ------------------------
523 # Print a proto configure.ac.
526 my $configure_scan = shift;
527 my %unique_makefiles;
529 my $file = new Autom4te::XFile ($configure_scan, ">");
532 ("# -*- Autoconf -*-\n" .
533 "# Process this file with autoconf to produce a configure script.\n" .
535 "AC_PREREQ([@VERSION@])\n" .
536 "AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])\n");
537 if (defined $cfiles[0])
539 print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
540 print $file "AC_CONFIG_HEADERS([config.h])\n";
543 output_kind ($file, 'program');
544 output_kind ($file, 'makevar');
545 output_libraries ($file);
546 output_kind ($file, 'header');
547 output_kind ($file, 'identifier');
548 output_kind ($file, 'function');
553 # Change DIR/Makefile.in to DIR/Makefile.
554 foreach my $m (@makefiles)
556 $m =~ s/\.(?:in|am)$//;
557 $unique_makefiles{$m}++;
559 print $file ("AC_CONFIG_FILES([",
561 sort keys %unique_makefiles), "])\n");
565 print $file ("AC_CONFIG_SUBDIRS([",
567 sort @subdirs), "])\n");
569 print $file "AC_OUTPUT\n";
576 ## --------------------------------------- ##
577 ## Checking the accuracy of configure.ac. ##
578 ## --------------------------------------- ##
581 # &check_configure_ac ($CONFIGURE_AC)
582 # -----------------------------------
583 # Use autoconf to check if all the suggested macros are included
585 sub check_configure_ac ($)
587 my ($configure_ac) = @_;
589 # Find what needed macros are invoked in CONFIGURE_AC.
590 # I'd be very happy if someone could explain to me why sort (uniq ...)
591 # doesn't work properly: I need 'uniq (sort ...)'. --akim
593 join (' --trace=', '',
594 uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
596 # Suppress all warnings from the subsidiary autoconf invocation.
597 local $ENV{WARNINGS} = 'none';
599 verb "running: WARNINGS=none $autoconf $trace_option $configure_ac";
601 new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
603 while ($_ = $traces->getline)
606 my ($file, $line, $macro, @args) = split (/:/, $_);
607 if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
609 # To be rigorous, we should distinguish between space and comma
610 # separated macros. But there is no point.
611 foreach my $word (split (/\s|,/, $args[0]))
613 # AC_CHECK_MEMBERS wants 'struct' or 'union'.
614 if ($macro eq "AC_CHECK_MEMBERS"
615 && $word =~ /^stat.st_/)
617 $word = "struct " . $word;
619 delete $needed_macros{"$macro([$word])"};
624 delete $needed_macros{$macro};
630 # Report the missing macros.
631 foreach my $macro (sort keys %needed_macros)
633 warn ("$configure_ac: warning: missing $macro wanted by: "
634 . (${$needed_macros{$macro}}[0])
636 print $log "$me: warning: missing $macro wanted by: \n";
637 foreach my $need (@{$needed_macros{$macro}})
639 print $log "\t$need\n";
650 $log = new Autom4te::XFile ("$me.log", ">");
652 $autoconf .= " --debug" if $debug;
653 $autoconf .= " --verbose" if $verbose;
654 $autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
655 $autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
657 my $configure_ac = find_configure_ac;
660 output ('configure.scan');
661 if (-f $configure_ac)
663 check_configure_ac ($configure_ac);
665 # This close is really needed. For some reason, probably best named
666 # a bug, it seems that the dtor of $LOG is not called automatically
667 # at END. It results in a truncated file.
671 ### Setup "GNU" style for perl-mode and cperl-mode.
673 ## perl-indent-level: 2
674 ## perl-continued-statement-offset: 2
675 ## perl-continued-brace-offset: 0
676 ## perl-brace-offset: 0
677 ## perl-brace-imaginary-offset: 0
678 ## perl-label-offset: -2
679 ## cperl-indent-level: 2
680 ## cperl-brace-offset: 0
681 ## cperl-continued-brace-offset: 0
682 ## cperl-label-offset: -2
683 ## cperl-extra-newline-before-brace: t
684 ## cperl-merge-trailing-else: nil
685 ## cperl-continued-statement-offset: 2