* doc/autoconf.texi (Limitations of Usual Tools): Document sed
[autoconf.git] / bin / autoscan.in
blob6195af29a3fed4b95e0d7e3610f37fa0e8e6c701
1 #! @PERL@ -w
2 # -*- perl -*-
3 # @configure_input@
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)
12 # 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, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 # 02110-1301, USA.
24 # Written by David MacKenzie <djm@gnu.ai.mit.edu>.
26 eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
27     if 0;
29 BEGIN
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
37   # has detected.
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;
45 use Autom4te::XFile;
46 use File::Basename;
47 use File::Find;
48 use strict;
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
54                 makevar librarie);
56 # For each kind, the default macro.
57 my %generic_macro =
58   (
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'
64   );
66 my %kind_comment =
67   (
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.',
72   );
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.
78 my %used = ();
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.
83 my %macro = ();
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
87 # `alloca (...)'.
88 my %needed_macros =
89   (
90    'AC_PREREQ' => [$me],
91   );
93 my $configure_scan = 'configure.scan';
94 my $log;
96 # Autoconf and lib files.
97 my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
98 my $autoconf = "$autom4te --language=autoconf";
99 my @prepend_include;
100 my @include = ('@datadir@');
102 # $help
103 # -----
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
117 Library directories:
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";
123 # $version
124 # --------
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 ## ------------------------ ##
139 # parse_args ()
140 # -------------
141 # Process any command line arguments.
142 sub parse_args ()
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"
149     if @ARGV > 1;
151   my $srcdir = $ARGV[0] || ".";
153   verb "srcdir = $srcdir";
154   chdir $srcdir || error "cannot cd to $srcdir: $!";
158 # init_tables ()
159 # --------------
160 # Put values in the tables of what to do with each token.
161 sub init_tables ()
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)
173     {
174       # Ignore blank lines and comments.
175       next
176         if /^\s*$/ || /^\s*\#/;
178       # '<kind>: <word> <macro invocation>' or...
179       # '<kind>: <word> warn: <message>'.
180       if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
181         {
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;
186         }
187       else
188         {
189           error "$file:$.: invalid definition: $_";
190         }
191     }
193   if ($debug)
194     {
195       foreach my $kind (@kinds)
196         {
197           foreach my $word (sort keys %{$macro{$kind}})
198             {
199               print "$kind: $word: @{$macro{$kind}{$word}}\n";
200             }
201         }
203     }
207 # used ($KIND, $WORD, [$WHERE])
208 # -----------------------------
209 # $WORD is used as a $KIND.
210 sub used ($$;$)
212   my ($kind, $word, $where) = @_;
213   $where ||= "$File::Find::name:$.";
214   if (
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}
221      )
222     {
223       push (@{$used{$kind}{$word}}, $where);
224     }
229 ## ----------------------- ##
230 ## Scanning source files.  ##
231 ## ----------------------- ##
234 # scan_c_file ($FILE-NAME)
235 # ------------------------
236 sub scan_c_file ($)
238   my ($file_name) = @_;
239   push @cfiles, $File::Find::name;
241   # Nonzero if in a multiline comment.
242   my $in_comment = 0;
244   my $file = new Autom4te::XFile "<$file_name";
246   while ($_ = $file->getline)
247     {
248       # Strip out comments.
249       if ($in_comment && s,^.*?\*/,,)
250         {
251           $in_comment = 0;
252         }
253       # The whole line is inside a commment.
254       next if $in_comment;
255       # All on one line.
256       s,/\*.*?\*/,,g;
258       # Starting on this line.
259       if (s,/\*.*$,,)
260         {
261           $in_comment = 1;
262         }
264       # Preprocessor directives.
265       if (s/^\s*\#\s*//)
266         {
267           if (/^include\s*<([^>]*)>/)
268             {
269               used ('header', $1);
270             }
271           if (s/^(if|ifdef|ifndef|elif)\s+//)
272             {
273               foreach my $word (split (/\W+/))
274                 {
275                   used ('identifier', $word)
276                     unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
277                 }
278             }
279           # Ignore other preprocessor directives.
280           next;
281         }
283       # Remove string and character constants.
284       s,\"[^\"]*\",,g;
285       s,\'[^\']*\',,g;
287       # Tokens in the code.
288       # Maybe we should ignore function definitions (in column 0)?
289       while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
290         {
291           used ('function', $1);
292         }
293       while (s/\b([a-zA-Z_]\w*)\b/ /)
294         {
295           used ('identifier', $1);
296         }
297     }
299   $file->close;
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)
313     {
314       # Strip out comments.
315       s/#.*//;
317       # Variable assignments.
318       while (s/\b([a-zA-Z_]\w*)\s*=/ /)
319         {
320           used ('makevar', $1);
321         }
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+/))
325         {
326           # Libraries.
327           if ($word =~ /^-l([a-zA-Z_]\w*)$/)
328             {
329               used ('library', $1);
330             }
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+]*$/)
335             {
336               used ('program', $word);
337             }
338         }
339     }
341   $file->close;
345 # scan_sh_file($SHELL-SCRIPT-NAME)
346 # --------------------------------
347 sub scan_sh_file ($)
349   my ($file_name) = @_;
350   push @shfiles, $File::Find::name;
352   my $file = new Autom4te::XFile "<$file_name";
354   while ($_ = $file->getline)
355     {
356       # Strip out comments and variable references.
357       s/#.*//;
358       s/\${[^\}]*}//g;
359       s/@[^@]*@//g;
361       # Tokens in the code.
362       while (s/\b([a-zA-Z_]\w*)\b/ /)
363         {
364           used ('program', $1);
365         }
366     }
368   $file->close;
372 # scan_file ()
373 # ------------
374 # Called by &find on each file.  $_ contains the current file name with
375 # the current directory of the walk through.
376 sub scan_file ()
378   # Wanted only if there is no corresponding FILE.in.
379   return
380     if -f "$_.in";
382   # Save $_ as Find::File requires it to be preserved.
383   local $_ = $_;
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" ||
392       -f "$_/configure")
393     {
394       $File::Find::prune = 1;
395       push @subdirs, $File::Find::name;
396     }
397   if (/\.[chlym](\.in)?$/)
398     {
399       used 'program', 'cc', $File::Find::name;
400       scan_c_file ($_);
401     }
402   elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
403     {
404       used 'program', 'c++', $File::Find::name;
405       scan_c_file ($_);
406     }
407   elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
408          || /^(?:GNUm|M|m)akefile(\.am)?$/)
409     {
410       scan_makefile ($_);
411     }
412   elsif (/\.sh(\.in)?$/)
413     {
414       scan_sh_file ($_);
415     }
419 # scan_files ()
420 # -------------
421 # Read through the files and collect lists of tokens in them
422 # that might create nonportabilities.
423 sub scan_files ()
425   find (\&scan_file, '.');
427   if ($verbose)
428     {
429       print "cfiles: @cfiles\n";
430       print "makefiles: @makefiles\n";
431       print "shfiles: @shfiles\n";
433       foreach my $kind (@kinds)
434         {
435           print "\n$kind:\n";
436           foreach my $word (sort keys %{$used{$kind}})
437             {
438               print "$word: @{$used{$kind}{$word}}\n";
439             }
440         }
441     }
445 ## ----------------------- ##
446 ## Output configure.scan.  ##
447 ## ----------------------- ##
450 # output_kind ($FILE, $KIND)
451 # --------------------------
452 sub output_kind ($$)
454   my ($file, $kind) = @_;
455   # Lists of words to be checked with the generic macro.
456   my @have;
458   print $file "\n# $kind_comment{$kind}\n"
459     if exists $kind_comment{$kind};
460   foreach my $word (sort keys %{$used{$kind}})
461     {
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}})
465         {
466           if ($macro =~ /^warn:\s+(.*)/)
467             {
468               my $message = $1;
469               foreach my $location (@{$used{$kind}{$word}})
470                 {
471                   warn "$location: warning: $message\n";
472                 }
473             }
474           elsif (exists $generic_macro{$kind}
475               && $macro eq $generic_macro{$kind})
476             {
477               push (@have, $word);
478               push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
479                     @{$used{$kind}{$word}});
480             }
481           else
482             {
483               if (! $printed{$macro})
484                 {
485                   print $file "$macro\n";
486                   $printed{$macro} = 1;
487                 }
488               push (@{$needed_macros{$macro}},
489                     @{$used{$kind}{$word}});
490             }
491         }
492     }
493   print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
494     if @have;
498 # output_libraries ($FILE)
499 # ------------------------
500 sub output_libraries ($)
502   my ($file) = @_;
504   print $file "\n# Checks for libraries.\n";
505   foreach my $word (sort keys %{$used{'library'}})
506     {
507       print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
508       print $file "AC_CHECK_LIB([$word], [main])\n";
509     }
513 # output ($CONFIGURE_SCAN)
514 # ------------------------
515 # Print a proto configure.ac.
516 sub output ($)
518   my $configure_scan = shift;
519   my %unique_makefiles;
521   my $file = new Autom4te::XFile ">$configure_scan";
523   print $file
524     ("#                                               -*- Autoconf -*-\n" .
525      "# Process this file with autoconf to produce a configure script.\n" .
526      "\n" .
527      "AC_PREREQ(@VERSION@)\n" .
528      "AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)\n");
529   if (defined $cfiles[0])
530     {
531       print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
532       print $file "AC_CONFIG_HEADER([config.h])\n";
533     }
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');
542   print $file "\n";
543   if (@makefiles)
544     {
545       # Change DIR/Makefile.in to DIR/Makefile.
546       foreach my $m (@makefiles)
547         {
548           $m =~ s/\.(?:in|am)$//;
549           $unique_makefiles{$m}++;
550         }
551       print $file ("AC_CONFIG_FILES([",
552                    join ("\n                 ",
553                          sort keys %unique_makefiles), "])\n");
554     }
555   if (@subdirs)
556     {
557       print $file ("AC_CONFIG_SUBDIRS([",
558                    join ("\n                   ",
559                          sort @subdirs), "])\n");
560     }
561   print $file "AC_OUTPUT\n";
563   $file->close;
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
576 # in CONFIGURE_AC.
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
584   my $trace_option =
585     join (' --trace=', '',
586           uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
588   verb "running: $autoconf $trace_option $configure_ac";
589   my $traces =
590     new Autom4te::XFile "$autoconf $trace_option $configure_ac|";
592   while ($_ = $traces->getline)
593     {
594       chomp;
595       my ($file, $line, $macro, @args) = split (/:/, $_);
596       if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
597         {
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]))
601             {
602               # AC_CHECK_MEMBERS wants `struct' or `union'.
603               if ($macro eq "AC_CHECK_MEMBERS"
604                   && $word =~ /^stat.st_/)
605                 {
606                   $word = "struct " . $word;
607                 }
608               delete $needed_macros{"$macro([$word])"};
609             }
610         }
611       else
612         {
613           delete $needed_macros{$macro};
614         }
615     }
617   $traces->close;
619   # Report the missing macros.
620   foreach my $macro (sort keys %needed_macros)
621     {
622       warn ("$configure_ac: warning: missing $macro wanted by: "
623             . (${$needed_macros{$macro}}[0])
624             . "\n");
625       print $log "$me: warning: missing $macro wanted by: \n";
626       foreach my $need (@{$needed_macros{$macro}})
627         {
628           print $log "\t$need\n";
629         }
630     }
634 ## -------------- ##
635 ## Main program.  ##
636 ## -------------- ##
638 parse_args;
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;
647 init_tables;
648 scan_files;
649 output ('configure.scan');
650 if (-f $configure_ac)
651   {
652     check_configure_ac ($configure_ac);
653   }
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.
657 $log->close;
658 exit 0;
660 ### Setup "GNU" style for perl-mode and cperl-mode.
661 ## Local Variables:
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
675 ## End: