.
[autoconf.git] / autoscan.in
blob38434287c1eb3f2e5a8381ab3fb9d4e14b397e81
1 #! @PERL@ -w
2 # autoscan - Create configure.scan (a preliminary configure.ac) for a package.
3 # Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2, or (at your option)
8 # any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 # 02111-1307, USA.
20 # Written by David MacKenzie <djm@gnu.ai.mit.edu>.
22 use 5.005;
23 require "find.pl";
24 use Getopt::Long;
25 use strict;
27 use vars qw($autoconf $datadir $initfile $me $name $verbose
28             @cfiles @makefiles @shfiles
29             %functions_macros %headers_macros %identifiers_macros
30             %programs_macros %makevars_macros %needed_macros
31             %c_keywords %programs %headers %identifiers %makevars
32             %libraries %functions %printed);
34 ($me = $0) =~ s,.*/,,;
35 $verbose = 0;
37 # Reference these variables to pacify perl -w.
38 %identifiers_macros = ();
39 %makevars_macros = ();
40 %programs_macros = ();
41 %needed_macros = ();
43 my @kinds = qw (functions headers identifiers programs makevars);
45 # For each kind, the default macro.
46 my %generic_macro =
47   (
48    'functions'   => 'AC_CHECK_FUNCS',
49    'headers'     => 'AC_CHECK_HEADERS',
50    'identifiers' => 'AC_CHECK_TYPES',
51    'programs'    => 'AC_CHECK_PROGS'
52   );
55 my $configure_scan = 'configure.scan';
58 # Exit nonzero whenever closing STDOUT fails.
59 sub END
61   use POSIX qw (_exit);
62   # This is required if the code might send any output to stdout
63   # E.g., even --version or --help.  So it's best to do it unconditionally.
64   close STDOUT
65     or (warn "$me: closing standard output: $!\n"), _exit (1);
68 # find_autoconf
69 # -------------
70 # Find the lib files and autoconf.
71 sub find_autoconf
73   $datadir = $ENV{"AC_MACRODIR"} || "@datadir@";
74   (my $dir = $0) =~ s,[^/]*$,,;
75   $autoconf = '';
76   # We test "$dir/autoconf" in case we are in the build tree, in which case
77   # the names are not transformed yet.
78   foreach my $file ($ENV{"AUTOCONF"} || '',
79                     "$dir/@autoconf-name@",
80                     "$dir/autoconf",
81                     "@bindir@/@autoconf-name@")
82     {
83       if (-x $file)
84         {
85           $autoconf = $file;
86           last;
87         }
88     }
92 # $CONFIGURE_AC
93 # &find_configure_ac ()
94 # ---------------------
95 sub find_configure_ac ()
97   if (-f 'configure.ac')
98     {
99       if (-f 'configure.in')
100         {
101           warn "warning: `configure.ac' and `configure.in' both present.\n";
102           warn "warning: proceeding with `configure.ac'.\n";
103         }
104       return 'configure.ac';
105     }
106   elsif (-f 'configure.in')
107     {
108       return 'configure.in';
109     }
110   return;
114 # print_usage ()
115 # --------------
116 # Display usage (--help).
117 sub print_usage ()
119   print "Usage: $0 [OPTION] ... [SRCDIR]
121 Examine source files in the directory tree rooted at SRCDIR, or the
122 current directory if none is given.  Search the source files for
123 common portability problems and create a file `$configure_scan' which
124 is a preliminary `configure.ac' for that package.
126   -h, --help            print this help, then exit
127   -V, --version         print version number, then exit
128   -v, --verbose         verbosely report processing
130 Library directories:
131   -A, --autoconf-dir=ACDIR  Autoconf's files location (rarely needed)
132   -l, --localdir=DIR        location of `aclocal.m4' and `acconfig.h'
134 Report bugs to <bug-autoconf\@gnu.org>.\n";
135   exit 0;
139 # print_version ()
140 # ----------------
141 # Display version (--version).
142 sub print_version
144   print "autoscan (@PACKAGE_NAME@) @VERSION@
145 Written by David J. MacKenzie.
147 Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
148 This is free software; see the source for copying conditions.  There is NO
149 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
150   exit 0;
154 # parse_args ()
155 # -------------
156 # Process any command line arguments.
157 sub parse_args ()
159   my $srcdir;
160   Getopt::Long::config ("bundling");
161   Getopt::Long::GetOptions ("A|autoconf-dir|m|macrodir=s" => \$datadir,
162                             "h|help" => \&print_usage,
163                             "V|version" => \&print_version,
164                             "v|verbose" => \$verbose)
165     or exit 1;
167   die "$me: too many arguments
168 Try `$me --help' for more information.\n"
169     if (@ARGV > 1);
170   ($srcdir) = @ARGV;
171   $srcdir = "."
172     if !defined $srcdir;
174   print "srcdir=$srcdir\n" if $verbose;
175   chdir $srcdir || die "$me: cannot cd to $srcdir: $!\n";
179 # init_tables ()
180 # --------------
181 # Put values in the tables of what to do with each token.
182 sub init_tables ()
184   # Initialize a table of C keywords (to ignore).
185   # Taken from K&R 1st edition p. 180.
186   # ANSI C, GNU C, and C++ keywords can introduce portability problems,
187   # so don't ignore them.
188   foreach my $word (qw (int char float double struct union long short
189                         unsigned auto extern register typedef static
190                         goto return sizeof break continue if else for
191                         do while switch case default))
192     {
193       $c_keywords{$word} = 0;
194     }
196   # The data file format supports only one line of macros per function.
197   # If more than that is required for a common portability problem,
198   # a new Autoconf macro should probably be written for that case,
199   # instead of duplicating the code in lots of configure.ac files.
201   foreach my $kind (@kinds)
202     {
203       my $file = "$datadir/ac$kind";
204       open TABLE, $file or
205         die "$me: cannot open $file: $!\n";
206       while (<TABLE>)
207         {
208           # Ignore blank lines and comments.
209           next
210             if /^\s*$/ || /^\s*\#/;
211           unless (/^(\S+)\s+(\S.*)$/ || /^(\S+)\s*$/)
212             {
213               die "$me: cannot parse definition in $file:\n$_\n";
214             }
215           my $word = $1;
216           my $macro = $2 || $generic_macro{$kind};
217           eval "\$$kind" . "_macros{\$word} = \$macro";
218         }
219       close(TABLE);
220     }
224 # wanted ()
225 # ---------
226 # Collect names of various kinds of files in the package.
227 # Called by &find on each file.
228 sub wanted ()
230   # Strip a useless leading `./'.
231   $name =~ s,^\./,,;
233   if (/^.*\.[chlymC]$/ || /^.*\.cc$/)
234     {
235       push (@cfiles, $name);
236     }
237   elsif (/^[Mm]akefile$/ || /^GNUmakefile$/)
238     {
239       # Wanted only if there is no corresponding Makefile.in.
240       # Using Find, $_ contains the current filename with the current
241       # directory of the walk through.
242       push (@makefiles, $name)
243         if ! -f "$_.in";
244     }
245   elsif (/^[Mm]akefile\.in$/)
246     {
247       push (@makefiles, $name);
248     }
249   elsif (/^.*\.sh$/)
250     {
251       push (@shfiles, $name);
252     }
256 # scan_files ()
257 # -------------
258 # Read through the files and collect lists of tokens in them
259 # that might create nonportabilities.
260 sub scan_files ()
262   my $file;
263   if (defined $cfiles[0])
264     {
265       $initfile = $cfiles[0];           # Pick one at random.
266     }
268   foreach $file (@cfiles)
269     {
270       push (@{$programs{"cc"}}, $file);
271       scan_c_file ($file);
272     }
274   foreach $file (@makefiles)
275     {
276       scan_makefile ($file);
277     }
279   foreach $file (@shfiles)
280     {
281       scan_sh_file ($file);
282     }
284   if ($verbose)
285     {
286       print "cfiles:", join(" ", @cfiles), "\n";
287       print "makefiles:", join(" ", @makefiles), "\n";
288       print "shfiles:", join(" ", @shfiles), "\n";
290       foreach my $class (qw (functions identifiers headers
291                        makevars libraries programs))
292         {
293           print "\n$class:\n";
294           my $h = eval "\\\%$class";
295           foreach my $word (sort keys %$h)
296             {
297               print "$word: @{$h->{$word}}\n";
298             }
299         }
300     }
304 # scan_c_file(FILE)
305 # -----------------
306 sub scan_c_file ($)
308   my ($file) = @_;
309   my ($in_comment) = 0; # Nonzero if in a multiline comment.
311   open(CFILE, "<$file") || die "$me: cannot open $file: $!\n";
312   while (<CFILE>)
313     {
314       # Strip out comments, approximately.
315       # Ending on this line.
316       if ($in_comment && m,\*/,)
317         {
318           s,.*\*/,,;
319           $in_comment = 0;
320         }
321       # All on one line.
322       s,/\*.*\*/,,g;
323       # Starting on this line.
324       if (m,/\*,)
325         {
326           $in_comment = 1;
327         }
328       # Continuing on this line.
329       next if $in_comment;
331       # Preprocessor directives.
332       if (/^\s*\#\s*include\s*<([^>]*)>/)
333         {
334           push (@{$headers{$1}}, "$file:$.");
335         }
336       # Ignore other preprocessor directives.
337       next if /^\s*\#/;
339       # Remove string and character constants.
340       s,\"[^\"]*\",,g;
341       s,\'[^\']*\',,g;
343       # Tokens in the code.
344       # Maybe we should ignore function definitions (in column 0)?
345       while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
346         {
347           push (@{$functions{$1}}, "$file:$.")
348             if !defined $c_keywords{$1};
349         }
350       while (s/\b([a-zA-Z_]\w*)\b/ /)
351         {
352           push (@{$identifiers{$1}}, "$file:$.")
353             if !defined $c_keywords{$1};
354         }
355     }
356   close(CFILE);
360 # scan_makefile(MAKEFILE)
361 # -----------------------
362 sub scan_makefile ($)
364   my ($file) = @_;
366   open(MFILE, "<$file") || die "$me: cannot open $file: $!\n";
367   while (<MFILE>)
368     {
369       # Strip out comments and variable references.
370       s/#.*//;
371       s/\$\([^\)]*\)//g;
372       s/\${[^\}]*}//g;
373       s/@[^@]*@//g;
375       # Variable assignments.
376       while (s/\b([a-zA-Z_]\w*)\s*=/ /)
377         {
378           push (@{$makevars{$1}}, "$file:$.");
379         }
380       # Libraries.
381       while (s/\B-l([a-zA-Z_]\w*)\b/ /)
382         {
383           push (@{$libraries{$1}}, "$file:$.");
384         }
385       # Tokens in the code.
386       while (s/\b([a-zA-Z_]\w*)\b/ /)
387         {
388           push (@{$programs{$1}}, "$file:$.");
389         }
390     }
391   close(MFILE);
395 # scan_sh_file(SHELL-SCRIPT)
396 # --------------------------
397 sub scan_sh_file ($)
399   my ($file) = @_;
401   open(MFILE, "<$file") || die "$me: cannot open $file: $!\n";
402   while (<MFILE>)
403     {
404       # Strip out comments and variable references.
405       s/#.*//;
406       s/\${[^\}]*}//g;
407       s/@[^@]*@//g;
409       # Tokens in the code.
410       while (s/\b([a-zA-Z_]\w*)\b/ /)
411         {
412           push (@{$programs{$1}}, "$file:$.");
413         }
414     }
415   close(MFILE);
419 # print_unique ($MACRO, @WHERE)
420 # -----------------------------
421 # $MACRO is wanted from $WHERE, hence (i) print $MACRO in $configure_scan
422 # if it exists and hasn't been printed already, (ii), remember it's needed.
423 sub print_unique ($@)
425   my ($macro, @where) = @_;
427   if (defined $macro && !defined $printed{$macro})
428     {
429       print CONF "$macro\n";
430       $printed{$macro} = 1;
432       push (@{$needed_macros{$macro}}, @where);
433     }
437 # output_programs ()
438 # ------------------
439 sub output_programs ()
441   print CONF "\n# Checks for programs.\n";
442   foreach my $word (sort keys %programs)
443     {
444       print_unique ($programs_macros{$word}, @{$programs{$word}});
445     }
446   foreach my $word (sort keys %makevars)
447     {
448       print_unique ($makevars_macros{$word}, @{$makevars{$word}});
449     }
453 # output_libraries ()
454 # -------------------
455 sub output_libraries ()
457   print CONF "\n# Checks for libraries.\n";
458   foreach my $word (sort keys %libraries)
459     {
460       print CONF "# FIXME: Replace `main' with a function in `-l$word':\n";
461       print CONF "AC_CHECK_LIB([$word], [main])\n";
462     }
466 # output_headers ()
467 # -----------------
468 sub output_headers ()
470   my @have_headers;
472   print CONF "\n# Checks for header files.\n";
473   foreach my $word (sort keys %headers)
474     {
475       if (defined $headers_macros{$word})
476         {
477           if ($headers_macros{$word} eq 'AC_CHECK_HEADERS')
478             {
479               push (@have_headers, $word);
480               push (@{$needed_macros{"AC_CHECK_HEADERS([$word])"}},
481                     @{$headers{$word}});
482             }
483           else
484             {
485               print_unique ($headers_macros{$word}, @{$headers{$word}});
486             }
487         }
488     }
489   print CONF "AC_CHECK_HEADERS([" . join(' ', sort(@have_headers)) . "])\n"
490     if @have_headers;
494 # output_identifiers ()
495 # ---------------------
496 sub output_identifiers ()
498   my @have_types;
500   print CONF "\n# Checks for typedefs, structures, and compiler characteristics.\n";
501   foreach my $word (sort keys %identifiers)
502     {
503       if (defined $identifiers_macros{$word})
504         {
505           if ($identifiers_macros{$word} eq 'AC_CHECK_TYPES')
506             {
507               push (@have_types, $word);
508               push (@{$needed_macros{"AC_CHECK_TYPES([$word])"}},
509                     @{$identifiers{$word}});
510             }
511           else
512             {
513               print_unique ($identifiers_macros{$word},
514                             @{$identifiers{$word}});
515             }
516         }
517     }
518   print CONF "AC_CHECK_TYPES([" . join(', ', sort(@have_types)) . "])\n"
519     if @have_types;
523 # output_functions ()
524 # -------------------
525 sub output_functions ()
527   my @have_funcs;
529   print CONF "\n# Checks for library functions.\n";
530   foreach my $word (sort keys %functions)
531     {
532       if (defined $functions_macros{$word})
533         {
534           if ($functions_macros{$word} eq 'AC_CHECK_FUNCS')
535             {
536               push (@have_funcs, $word);
537               push (@{$needed_macros{"AC_CHECK_FUNCS([$word])"}},
538                     @{$functions{$word}});
539             }
540           else
541             {
542               print_unique ($functions_macros{$word},
543                             @{$functions{$word}});
544             }
545         }
546     }
547   print CONF "AC_CHECK_FUNCS([" . join(' ', sort(@have_funcs)) . "])\n"
548     if @have_funcs;
552 # output (CONFIGURE_SCAN)
553 # -----------------------
554 # Print a proto configure.ac.
555 sub output ($)
557   my $configure_scan = shift;
558   my %unique_makefiles;
560   open (CONF, ">$configure_scan") ||
561     die "$me: cannot create $configure_scan: $!\n";
563   print CONF "# Process this file with autoconf to produce a configure script.\n";
564   print CONF "AC_INIT\n";
565   if (defined $initfile)
566     {
567       print CONF "AC_CONFIG_SRCDIR([$initfile])\n";
568     }
569   if (defined $cfiles[0])
570     {
571       print CONF "AC_CONFIG_HEADER([config.h])\n";
572     }
574   output_programs;
575   output_libraries;
576   output_headers;
577   output_identifiers;
578   output_functions;
580   # Change DIR/Makefile.in to DIR/Makefile.
581   foreach my $m (@makefiles)
582     {
583       $m =~ s/\.in$//;
584       $unique_makefiles{$m}++;
585     }
586   print CONF "\nAC_CONFIG_FILES([",
587        join ("\n                 ", keys(%unique_makefiles)), "])\n";
588   print CONF "AC_OUTPUT\n";
590   close CONF ||
591     die "$me: closing $configure_scan: $!\n";
595 # check_configure_ac (CONFIGURE_AC)
596 # ---------------------------------
597 # Use autoconf to check if all the suggested macros are included
598 # in CONFIGURE_AC.
599 sub check_configure_ac ($)
601   my ($configure_ac) = $@;
602   my ($trace_option) = '';
604   foreach my $macro (sort keys %needed_macros)
605     {
606       $macro =~ s/\(.*//;
607       $trace_option .= " -t $macro";
608     }
610   open (TRACES, "$autoconf -A $datadir $trace_option $configure_ac|") ||
611     die "$me: cannot create read traces: $!\n";
613   while (<TRACES>)
614     {
615       chomp;
616       my ($file, $line, $macro, @args) = split (/:/, $_);
617       if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
618         {
619           # To be rigorous, we should distinguish between space and comma
620           # separated macros.  But there is no point.
621           foreach my $word (split (/\s|,/, $args[0]))
622             {
623               # AC_CHECK_MEMBERS wants `struct' or `union'.
624               if ($macro eq "AC_CHECK_MEMBERS"
625                   && $word =~ /^stat.st_/)
626                 {
627                   $word = "struct " . $word;
628                 }
629               delete ($needed_macros{"$macro([$word])"});
630             }
631         }
632       else
633         {
634           delete ($needed_macros{$macro});
635         }
636     }
638   close (TRACES) ||
639     die "$me: cannot close traces: $!\n";
641   foreach my $macro (sort keys %needed_macros)
642     {
643       warn "$me: warning: missing $macro wanted by: \n";
644       foreach my $need (@{$needed_macros{$macro}})
645         {
646           warn "\t$need\n";
647         }
648     }
652 ## -------------- ##
653 ## Main program.  ##
654 ## -------------- ##
656 # Find the lib files and autoconf.
657 find_autoconf;
658 my $configure_ac = find_configure_ac;
659 parse_args;
660 init_tables;
661 find ('.');
662 scan_files;
663 output ('configure.scan');
664 if ($configure_ac)
665   {
666     check_configure_ac ($configure_ac);
667   }
669 exit 0;