Fix up mix of man(7)/mdoc(7).
[netbsd-mini2440.git] / gnu / dist / autoconf / autoscan.in
blob3cbd47bb07f1ed694e58a7dc4d4fcae0ee1d1e11
1 #! @PERL@ -w
2 # -*- perl -*-
3 # autoscan - Create configure.scan (a preliminary configure.ac) for a package.
4 # Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2, or (at your option)
9 # any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 # 02111-1307, USA.
21 # Written by David MacKenzie <djm@gnu.ai.mit.edu>.
23 use 5.005;
24 use File::Basename;
25 use File::Find;
26 use Getopt::Long;
27 use IO::File;
28 use strict;
30 use vars qw(@cfiles @makefiles @shfiles %c_keywords %printed);
32 my $me = basename ($0);
33 my $verbose = 0;
35 # $USED{KIND}{ITEM} is set if ITEM is used in the program.
36 # It is set to its list of locations.
37 my %used = ();
39 # $MACRO{KIND}{ITEM} is the list of macros to use to test ITEM.
40 my %macro = ();
42 # $NEEDED_MACROS{MACRO} is an array of locations requiring MACRO.
43 my %needed_macros = ();
45 my @kinds = qw (functions headers identifiers programs makevars libraries);
47 # For each kind, the default macro.
48 my %generic_macro =
49   (
50    'functions'   => 'AC_CHECK_FUNCS',
51    'headers'     => 'AC_CHECK_HEADERS',
52    'identifiers' => 'AC_CHECK_TYPES',
53    'programs'    => 'AC_CHECK_PROGS',
54    'libraries'   => 'AC_CHECK_LIB'
55   );
57 my %kind_comment =
58   (
59    'functions' => 'Checks for library functions.',
60    'headers' => 'Checks for header files.',
61    'identifiers' => 'Checks for typedefs, structures, and compiler characteristics.',
62    'programs' => 'Checks for programs.',
63   );
65 my $configure_scan = 'configure.scan';
66 my $log = new IO::File ">$me.log"
67   or die "$me: cannot open $me.log: $!\n";
69 # Autoconf and lib files.
70 my $autoconf;
71 my $datadir = $ENV{"AC_MACRODIR"} || "@datadir@";
73 # Exit nonzero whenever closing STDOUT fails.
74 sub END
76   use POSIX qw (_exit);
77   # This is required if the code might send any output to stdout
78   # E.g., even --version or --help.  So it's best to do it unconditionally.
79   close STDOUT
80     or (warn "$me: closing standard output: $!\n"), _exit (1);
84 ## ------------------------ ##
85 ## Command line interface.  ##
86 ## ------------------------ ##
89 # print_usage ()
90 # --------------
91 # Display usage (--help).
92 sub print_usage ()
94   print "Usage: $0 [OPTION] ... [SRCDIR]
96 Examine source files in the directory tree rooted at SRCDIR, or the
97 current directory if none is given.  Search the source files for
98 common portability problems, check for incompleteness of
99 `configure.ac', and create a file `$configure_scan' which is a
100 preliminary `configure.ac' for that package.
102   -h, --help            print this help, then exit
103   -V, --version         print version number, then exit
104   -v, --verbose         verbosely report processing
106 Library directories:
107   -A, --autoconf-dir=ACDIR  Autoconf's files location (rarely needed)
108   -l, --localdir=DIR        location of `aclocal.m4' and `acconfig.h'
110 Report bugs to <bug-autoconf\@gnu.org>.\n";
111   exit 0;
115 # print_version ()
116 # ----------------
117 # Display version (--version).
118 sub print_version
120   print "autoscan (@PACKAGE_NAME@) @VERSION@
121 Written by David J. MacKenzie.
123 Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
124 This is free software; see the source for copying conditions.  There is NO
125 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
126   exit 0;
130 # parse_args ()
131 # -------------
132 # Process any command line arguments.
133 sub parse_args ()
135   my $srcdir;
136   Getopt::Long::config ("bundling");
137   Getopt::Long::GetOptions ("A|autoconf-dir|m|macrodir=s" => \$datadir,
138                             "h|help" => \&print_usage,
139                             "V|version" => \&print_version,
140                             "v|verbose" => \$verbose)
141     or exit 1;
143   die "$me: too many arguments
144 Try `$me --help' for more information.\n"
145     if (@ARGV > 1);
146   ($srcdir) = @ARGV;
147   $srcdir = "."
148     if !defined $srcdir;
150   print "srcdir=$srcdir\n" if $verbose;
151   chdir $srcdir || die "$me: cannot cd to $srcdir: $!\n";
155 # find_autoconf
156 # -------------
157 # Find the lib files and autoconf.
158 sub find_autoconf
160   my $dir = dirname ($0);
161   # We test "$dir/autoconf" in case we are in the build tree, in which case
162   # the names are not transformed yet.
163   foreach my $file ($ENV{"AUTOCONF"} || '',
164                     "$dir/@autoconf-name@",
165                     "$dir/autoconf",
166                     "@bindir@/@autoconf-name@")
167     {
168       if (-x $file)
169         {
170           $autoconf = $file;
171           last;
172         }
173     }
177 # $CONFIGURE_AC
178 # &find_configure_ac ()
179 # ---------------------
180 sub find_configure_ac ()
182   if (-f 'configure.ac')
183     {
184       if (-f 'configure.in')
185         {
186           warn "warning: `configure.ac' and `configure.in' both present.\n";
187           warn "warning: proceeding with `configure.ac'.\n";
188         }
189       return 'configure.ac';
190     }
191   elsif (-f 'configure.in')
192     {
193       return 'configure.in';
194     }
195   return;
199 # init_tables ()
200 # --------------
201 # Put values in the tables of what to do with each token.
202 sub init_tables ()
204   # Initialize a table of C keywords (to ignore).
205   # Taken from K&R 1st edition p. 180.
206   # ANSI C, GNU C, and C++ keywords can introduce portability problems,
207   # so don't ignore them.
209   foreach (qw (int char float double struct union long short unsigned
210                auto extern register typedef static goto return sizeof break
211                continue if else for do while switch case default))
212     {
213       $c_keywords{$_} = 0;
214     }
216   # The data file format supports only one line of macros per function.
217   # If more than that is required for a common portability problem,
218   # a new Autoconf macro should probably be written for that case,
219   # instead of duplicating the code in lots of configure.ac files.
220   my $tables_are_consistent = 1;
221   foreach my $kind (@kinds)
222     {
223       my $file = "$datadir/ac$kind";
224       my $table = new IO::File $file
225         or die "$me: cannot open $file: $!\n";
226       while ($_ = $table->getline)
227         {
228           # Ignore blank lines and comments.
229           next
230             if /^\s*$/ || /^\s*\#/;
231           unless (/^(\S+)\s+(\S.*)$/ || /^(\S+)\s*$/)
232             {
233               die "$me: cannot parse definition in $file:\n$_\n";
234             }
235           my $word = $1;
236           my $macro = $2 || $generic_macro{$kind};
237           # The default macro must be explicitly listed for words
238           # which have a specific macros.  This allows to enforce
239           # consistency checks.
240           if (!defined $2 && exists $macro{$kind}{$word})
241             {
242               warn ("$datadir/ac$kind:$.: "
243                     . "ignoring implicit call to the generic macro for $word\n");
244               $tables_are_consistent = 0;
245             }
246           else
247             {
248               push @{$macro{$kind}{$word}}, $macro;
249             }
250         }
251       $table->close
252         or die "$me: cannot close $file: $!\n";
253     }
255   die "$me: some tables are inconsistent\n"
256     if !$tables_are_consistent;
261 ## ----------------------- ##
262 ## Scanning source files.  ##
263 ## ----------------------- ##
266 # scan_c_file(FILENAME)
267 # ---------------------
268 sub scan_c_file ($)
270   my ($filename) = @_;
272   push (@cfiles, $File::Find::name);
274   # Nonzero if in a multiline comment.
275   my $in_comment = 0;
277   my $file = new IO::File "<$filename"
278     or die "$me: cannot open $filename: $!\n";
280   while ($_ = $file->getline)
281     {
282       # Strip out comments, approximately.
283       # Ending on this line.
284       if ($in_comment && m,\*/,)
285         {
286           s,.*\*/,,;
287           $in_comment = 0;
288         }
289       # All on one line.
290       s,/\*.*\*/,,g;
291       # Starting on this line.
292       if (m,/\*,)
293         {
294           $in_comment = 1;
295         }
296       # Continuing on this line.
297       next if $in_comment;
299       # Preprocessor directives.
300       if (/^\s*\#\s*include\s*<([^>]*)>/)
301         {
302           push (@{$used{'headers'}{$1}}, "$File::Find::name:$.");
303         }
304       # Ignore other preprocessor directives.
305       next if /^\s*\#/;
307       # Remove string and character constants.
308       s,\"[^\"]*\",,g;
309       s,\'[^\']*\',,g;
311       # Tokens in the code.
312       # Maybe we should ignore function definitions (in column 0)?
313       while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
314         {
315           push (@{$used{'functions'}{$1}}, "$File::Find::name:$.")
316             if !defined $c_keywords{$1};
317         }
318       while (s/\b([a-zA-Z_]\w*)\b/ /)
319         {
320           push (@{$used{'identifiers'}{$1}}, "$File::Find::name:$.")
321             if !defined $c_keywords{$1};
322         }
323     }
325   $file->close
326     or die "$me: cannot close $filename: $!\n";
330 # scan_makefile(MAKEFILE-NAME)
331 # ----------------------------
332 sub scan_makefile ($)
334   my ($filename) = @_;
335   push (@makefiles, $File::Find::name);
337   my $file = new IO::File "<$filename"
338     or die "$me: cannot open $filename: $!\n";
340   while ($_ = $file->getline)
341     {
342       # Strip out comments and variable references.
343       s/#.*//;
344       s/\$\([^\)]*\)//g;
345       s/\${[^\}]*}//g;
346       s/@[^@]*@//g;
348       # Variable assignments.
349       while (s/\b([a-zA-Z_]\w*)\s*=/ /)
350         {
351           push (@{$used{'makevars'}{$1}}, "$File::Find::name:$.");
352         }
353       # Libraries.
354       while (s/\B-l([a-zA-Z_]\w*)\b/ /)
355         {
356           push (@{$used{'libraries'}{$1}}, "$File::Find::name:$.");
357         }
358       # Tokens in the code.
359       while (s/(?<![-\w.])([a-zA-Z_][\w+.-]+)/ /)
360         {
361           push (@{$used{'programs'}{$1}}, "$File::Find::name:$.");
362         }
363     }
365   $file->close
366     or die "$me: cannot close $filename: $!\n";
370 # scan_sh_file(SHELL-SCRIPT-NAME)
371 # -------------------------------
372 sub scan_sh_file ($)
374   my ($filename) = @_;
375   push (@shfiles, $File::Find::name);
377   my $file = new IO::File "<$filename"
378     or die "$me: cannot open $filename: $!\n";
380   while ($_ = $file->getline)
381     {
382       # Strip out comments and variable references.
383       s/#.*//;
384       s/#.*//;
385       s/\${[^\}]*}//g;
386       s/@[^@]*@//g;
388       # Tokens in the code.
389       while (s/\b([a-zA-Z_]\w*)\b/ /)
390         {
391           push (@{$used{'programs'}{$1}}, "$File::Find::name:$.");
392         }
393     }
395   $file->close
396     or die "$me: cannot close $filename: $!\n";
400 # scan_file ()
401 # ------------
402 # Called by &find on each file.  $_ contains the current filename with
403 # the current directory of the walk through.
404 sub scan_file ()
406   # Wanted only if there is no corresponding FILE.in.
407   return
408     if -f "$_.in";
410   # Save $_ as Find::File requires it to be preserved.
411   my $underscore = $_;
413   # Strip a useless leading `./'.
414   $File::Find::name =~ s,^\./,,;
416   if (/\.[chlym](\.in)?$/)
417     {
418       push (@{$used{'programs'}{"cc"}}, $File::Find::name);
419       scan_c_file ($_);
420     }
421   elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
422     {
423       push (@{$used{'programs'}{"c++"}}, $File::Find::name);
424       scan_c_file ($_);
425     }
426   elsif (/^[Mm]akefile(\.in)?$/ || /^GNUmakefile(\.in)?$/)
427     {
428       scan_makefile ($_);
429     }
430   elsif (/\.sh(\.in)?$/)
431     {
432       scan_sh_file ($_);
433     }
435   $_ = $underscore;
439 # scan_files ()
440 # -------------
441 # Read through the files and collect lists of tokens in them
442 # that might create nonportabilities.
443 sub scan_files ()
445   find (\&scan_file, '.');
447   if ($verbose)
448     {
449       print "cfiles:", join(" ", @cfiles), "\n";
450       print "makefiles:", join(" ", @makefiles), "\n";
451       print "shfiles:", join(" ", @shfiles), "\n";
453       foreach my $kind (@kinds)
454         {
455           print "\n$kind:\n";
456           foreach my $word (sort keys %{$used{$kind}})
457             {
458               print "$word: @{$used{$kind}{$word}}\n";
459             }
460         }
461     }
465 ## ----------------------- ##
466 ## Output configure.scan.  ##
467 ## ----------------------- ##
470 # output_kind ($FILE, $KIND)
471 # --------------------------
472 sub output_kind ($$)
474   my ($file, $kind) = @_;
475   # Lists of words to be checked with the generic macro.
476   my @have;
478   print $file "\n# $kind_comment{$kind}\n"
479     if exists $kind_comment{$kind};
480   foreach my $word (sort keys %{$used{$kind}})
481     {
482       # Words that were caught, but not to be checked according to
483       # the autoscan library files.
484       next
485         if ! exists $macro{$kind}{$word};
487       # Output the needed macro invocations in $configure_scan if not
488       # already printed, and remember these macros are needed.
489       foreach my $macro (@{$macro{$kind}{$word}})
490         {
491           if (exists $generic_macro{$kind}
492               && $macro eq $generic_macro{$kind})
493             {
494               push (@have, $word);
495               push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
496                     @{$used{$kind}{$word}});
497             }
498           else
499             {
500               if (! $printed{$macro})
501                 {
502                   print $file "$macro\n";
503                   $printed{$macro} = 1;
504                 }
505               push (@{$needed_macros{$macro}},
506                     @{$used{$kind}{$word}});
507             }
508         }
509     }
510   print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
511     if @have;
515 # output_libraries ($FILE)
516 # ------------------------
517 sub output_libraries ($)
519   my ($file) = @_;
521   print $file "\n# Checks for libraries.\n";
522   foreach my $word (sort keys %{$used{'libraries'}})
523     {
524       print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
525       print $file "AC_CHECK_LIB([$word], [main])\n";
526     }
530 # output (CONFIGURE_SCAN)
531 # -----------------------
532 # Print a proto configure.ac.
533 sub output ($)
535   my $configure_scan = shift;
536   my %unique_makefiles;
538   my $file = new IO::File ">$configure_scan"
539     or die "$me: cannot create $configure_scan: $!\n";
541   print $file "# Process this file with autoconf to produce a configure script.\n";
542   print $file "AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)\n";
543   if (defined $cfiles[0])
544     {
545       print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
546       print $file "AC_CONFIG_HEADER([config.h])\n";
547     }
549   output_kind ($file, 'programs');
550   output_kind ($file, 'makevars');
551   output_libraries ($file);
552   output_kind ($file, 'headers');
553   output_kind ($file, 'identifiers');
554   output_kind ($file, 'functions');
556   # Change DIR/Makefile.in to DIR/Makefile.
557   foreach my $m (@makefiles)
558     {
559       $m =~ s/\.in$//;
560       $unique_makefiles{$m}++;
561     }
562   print $file "\nAC_CONFIG_FILES([",
563        join ("\n                 ", sort keys %unique_makefiles), "])\n";
564   print $file "AC_OUTPUT\n";
566   $file->close
567     or die "$me: cannot close $configure_scan: $!\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
580 # in CONFIGURE_AC.
581 sub check_configure_ac ($)
583   my ($configure_ac) = @_;
584   my ($trace_option) = '';
586   # Find what needed macros are invoked in CONFIGURE_AC.
587   foreach my $macro (sort keys %needed_macros)
588     {
589       $macro =~ s/\(.*//;
590       $trace_option .= " -t $macro";
591     }
593   my $traces =
594     new IO::File "$autoconf -A $datadir $trace_option $configure_ac|"
595       or die "$me: cannot create read traces: $!\n";
597   while ($_ = $traces->getline)
598     {
599       chomp;
600       my ($file, $line, $macro, @args) = split (/:/, $_);
601       if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
602         {
603           # To be rigorous, we should distinguish between space and comma
604           # separated macros.  But there is no point.
605           foreach my $word (split (/\s|,/, $args[0]))
606             {
607               # AC_CHECK_MEMBERS wants `struct' or `union'.
608               if ($macro eq "AC_CHECK_MEMBERS"
609                   && $word =~ /^stat.st_/)
610                 {
611                   $word = "struct " . $word;
612                 }
613               delete ($needed_macros{"$macro([$word])"});
614             }
615         }
616       else
617         {
618           delete ($needed_macros{$macro});
619         }
620     }
622   $traces->close
623     or die "$me: cannot close: $!\n";
625   # Report the missing macros.
626   foreach my $macro (sort keys %needed_macros)
627     {
628       warn ("$configure_ac: warning: missing $macro wanted by: "
629             . (${$needed_macros{$macro}}[0])
630             . "\n");
631       print $log "$me: warning: missing $macro wanted by: \n";
632       foreach my $need (@{$needed_macros{$macro}})
633         {
634           print $log "\t$need\n";
635         }
636     }
640 ## -------------- ##
641 ## Main program.  ##
642 ## -------------- ##
644 parse_args;
645 # Find the lib files and autoconf.
646 find_autoconf;
647 my $configure_ac = find_configure_ac;
648 init_tables;
649 scan_files;
650 output ('configure.scan');
651 if ($configure_ac)
652   {
653     check_configure_ac ($configure_ac);
654   }
656 $log->close
657   or die "$me: cannot close $me.log: $!\n";
659 exit 0;