1#! @PERL@ 2# autoscan - Create configure.scan (a preliminary configure.in) for a package. 3# Copyright (C) 1994 Free Software Foundation, Inc. 4 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. 9 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. 14 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. 19 20# Written by David MacKenzie <djm@gnu.ai.mit.edu>. 21 22require "find.pl"; 23 24$datadir = $ENV{"AC_MACRODIR"} || "@datadir@"; 25$verbose = 0; 26# Reference these variables to pacify perl -w. 27undef %identifiers_macros; 28undef %makevars_macros; 29undef %programs_macros; 30 31&parse_args; 32&init_tables; 33&find('.'); 34&scan_files; 35&output; 36 37exit 0; 38 39# Process any command line arguments. 40sub parse_args 41{ 42 local ($usage) = 43 "Usage: autoscan [--macrodir=dir] [--help] [--verbose] [--version] [srcdir]\n"; 44 45 foreach $_ (@ARGV) { 46 if (/^--m[a-z]*=(.*)/) { 47 $datadir = $1; 48 } elsif (/^--h/) { 49 print "$usage"; 50 exit 0; 51 } elsif (/^--verb/) { 52 $verbose = 1; 53 } elsif (/^--vers/) { 54 &version; 55 } elsif (/^[^-]/) { 56 die "$usage" if defined($srcdir); 57 # Top level directory of the package being autoscanned. 58 $srcdir = $_; 59 } else { 60 die "$usage"; 61 } 62 } 63 64 $srcdir="." if !defined($srcdir); 65 66 print "srcdir=$srcdir\n" if $verbose; 67 chdir $srcdir || die "$0: cannot cd to $srcdir: $!\n"; 68 69 open(CONF, ">configure.scan") || 70 die "$0: cannot create configure.scan: $!\n"; 71} 72 73# Print the version number and exit. 74sub version 75{ 76 open(ACG, "<$datadir/acgeneral.m4") || 77 die "$0: cannot open $datadir/acgeneral.m4: $!\n"; 78 while (<ACG>) { 79 if (/define.AC_ACVERSION.\s*([0-9.]+)/) { 80 print "Autoconf version $1\n"; 81 exit 0; 82 } 83 } 84 die "Autoconf version unknown\n"; 85} 86 87# Put values in the tables of what to do with each token. 88sub init_tables 89{ 90 local($kind, $word, $macro); 91 92 # Initialize a table of C keywords (to ignore). 93 # Taken from K&R 1st edition p. 180. 94 # ANSI C, GNU C, and C++ keywords can introduce portability problems, 95 # so don't ignore them. 96 foreach $word ('int', 'char', 'float', 'double', 'struct', 'union', 97 'long', 'short', 'unsigned', 'auto', 'extern', 'register', 98 'typedef', 'static', 'goto', 'return', 'sizeof', 'break', 99 'continue', 'if', 'else', 'for', 'do', 'while', 'switch', 100 'case', 'default') { 101 $c_keywords{$word} = 0; 102 } 103 104 # The data file format supports only one line of macros per function. 105 # If more than that is required for a common portability problem, 106 # a new Autoconf macro should probably be written for that case, 107 # instead of duplicating the code in lots of configure.in files. 108 109 foreach $kind ('functions', 'headers', 'identifiers', 'programs', 110 'makevars') { 111 open(TABLE, "<$datadir/ac$kind") || 112 die "$0: cannot open $datadir/ac$kind: $!\n"; 113 while (<TABLE>) { 114 next if /^\s*$/ || /^\s*#/; # Ignore blank lines and comments. 115 ($word, $macro) = split; 116 eval "\$$kind" . "_macros{\$word} = \$macro"; 117 } 118 close(TABLE); 119 } 120} 121 122# Collect names of various kinds of files in the package. 123# Called by &find on each file. 124sub wanted 125{ 126 if (/^.*\.[chlymC]$/ || /^.*\.cc$/) { 127 $name =~ s?^\./??; push(@cfiles, $name); 128 } 129 elsif (/^[Mm]akefile$/ || /^[Mm]akefile\.in$/ || /^GNUmakefile$/) { 130 $name =~ s?^\./??; push(@makefiles, $name); 131 } 132 elsif (/^.*\.sh$/) { 133 $name =~ s?^\./??; push(@shfiles, $name); 134 } 135} 136 137# Read through the files and collect lists of tokens in them 138# that might create nonportabilities. 139sub scan_files 140{ 141 $initfile = $cfiles[0]; # Pick one at random. 142 143 if ($verbose) { 144 print "cfiles:", join(" ", @cfiles), "\n"; 145 print "makefiles:", join(" ", @makefiles), "\n"; 146 print "shfiles:", join(" ", @shfiles), "\n"; 147 } 148 149 foreach $file (@cfiles) { 150 &scan_c_file($file); 151 } 152 153 foreach $file (@makefiles) { 154 &scan_makefile($file); 155 } 156 157 foreach $file (@shfiles) { 158 &scan_sh_file($file); 159 } 160} 161 162sub scan_c_file 163{ 164 local($file) = @_; 165 local($in_comment) = 0; # Nonzero if in a multiline comment. 166 167 open(CFILE, "<$file") || die "$0: cannot open $file: $!\n"; 168 while (<CFILE>) { 169 # Strip out comments, approximately. 170 # Ending on this line. 171 if ($in_comment && m,\*/,) { 172 s,.*\*/,,; 173 $in_comment = 0; 174 } 175 # All on one line. 176 s,/\*.*\*/,,g; 177 # Starting on this line. 178 if (m,/\*,) { 179 $in_comment = 1; 180 } 181 # Continuing on this line. 182 next if $in_comment; 183 184 # Preprocessor directives. 185 if (/^\s*#\s*include\s*<([^>]*)>/) { 186 $headers{$1}++; 187 } 188 # Ignore other preprocessor directives. 189 next if /^\s*#/; 190 191 # Remove string and character constants. 192 s,\"[^\"]*\",,g; 193 s,\'[^\']*\',,g; 194 195 # Tokens in the code. 196 # Maybe we should ignore function definitions (in column 0)? 197 while (s/\W([a-zA-Z_]\w*)\s*\(/ /) { 198 $functions{$1}++ if !defined($c_keywords{$1}); 199 } 200 while (s/\W([a-zA-Z_]\w*)\W/ /) { 201 $identifiers{$1}++ if !defined($c_keywords{$1}); 202 } 203 } 204 close(CFILE); 205 206 if ($verbose) { 207 local($word); 208 209 print "\n$file functions:\n"; 210 foreach $word (sort keys %functions) { 211 print "$word $functions{$word}\n"; 212 } 213 214 print "\n$file identifiers:\n"; 215 foreach $word (sort keys %identifiers) { 216 print "$word $identifiers{$word}\n"; 217 } 218 219 print "\n$file headers:\n"; 220 foreach $word (sort keys %headers) { 221 print "$word $headers{$word}\n"; 222 } 223 } 224} 225 226sub scan_makefile 227{ 228 local($file) = @_; 229 230 open(MFILE, "<$file") || die "$0: cannot open $file: $!\n"; 231 while (<MFILE>) { 232 # Strip out comments and variable references. 233 s/#.*//; 234 s/\$\([^\)]*\)//g; 235 s/\${[^\}]*}//g; 236 s/@[^@]*@//g; 237 238 # Variable assignments. 239 while (s/\W([a-zA-Z_]\w*)\s*=/ /) { 240 $makevars{$1}++; 241 } 242 # Libraries. 243 while (s/\W-l([a-zA-Z_]\w*)\W/ /) { 244 $libraries{$1}++; 245 } 246 # Tokens in the code. 247 while (s/\W([a-zA-Z_]\w*)\W/ /) { 248 $programs{$1}++; 249 } 250 } 251 close(MFILE); 252 253 if ($verbose) { 254 local($word); 255 256 print "\n$file makevars:\n"; 257 foreach $word (sort keys %makevars) { 258 print "$word $makevars{$word}\n"; 259 } 260 261 print "\n$file libraries:\n"; 262 foreach $word (sort keys %libraries) { 263 print "$word $libraries{$word}\n"; 264 } 265 266 print "\n$file programs:\n"; 267 foreach $word (sort keys %programs) { 268 print "$word $programs{$word}\n"; 269 } 270 } 271} 272 273sub scan_sh_file 274{ 275 local($file) = @_; 276 277 open(MFILE, "<$file") || die "$0: cannot open $file: $!\n"; 278 while (<MFILE>) { 279 # Strip out comments and variable references. 280 s/#.*//; 281 s/\${[^\}]*}//g; 282 s/@[^@]*@//g; 283 284 # Tokens in the code. 285 while (s/\W([a-zA-Z_]\w*)\W/ /) { 286 $programs{$1}++; 287 } 288 } 289 close(MFILE); 290 291 if ($verbose) { 292 local($word); 293 294 print "\n$file programs:\n"; 295 foreach $word (sort keys %programs) { 296 print "$word $programs{$word}\n"; 297 } 298 } 299} 300 301# Print a configure.in. 302sub output 303{ 304 local (%unique_makefiles); 305 306 print CONF "dnl Process this file with autoconf to produce a configure script.\n"; 307 print CONF "AC_INIT($initfile)\n"; 308 309 &output_programs; 310 &output_headers; 311 &output_identifiers; 312 &output_functions; 313 314 # Change DIR/Makefile.in to DIR/Makefile. 315 foreach $_ (@makefiles) { 316 s/\.in$//; 317 $unique_makefiles{$_}++; 318 } 319 print CONF "\nAC_OUTPUT(", join(" ", keys(%unique_makefiles)), ")\n"; 320 321 close CONF; 322} 323 324# Print Autoconf macro $1 if it's not undef and hasn't been printed already. 325sub print_unique 326{ 327 local($macro) = @_; 328 329 if (defined($macro) && !defined($printed{$macro})) { 330 print CONF "$macro\n"; 331 $printed{$macro} = 1; 332 } 333} 334 335sub output_programs 336{ 337 local ($word); 338 339 print CONF "\ndnl Checks for programs.\n"; 340 foreach $word (sort keys %programs) { 341 &print_unique($programs_macros{$word}); 342 } 343 foreach $word (sort keys %makevars) { 344 &print_unique($makevars_macros{$word}); 345 } 346 print CONF "\ndnl Checks for libraries.\n"; 347 foreach $word (sort keys %libraries) { 348 print CONF "dnl Replace `\main\' with a function in -l$word:\n"; 349 print CONF "AC_CHECK_LIB($word, main)\n"; 350 } 351} 352 353sub output_headers 354{ 355 local ($word); 356 357 print CONF "\ndnl Checks for header files.\n"; 358 foreach $word (sort keys %headers) { 359 if (defined($headers_macros{$word}) && 360 $headers_macros{$word} eq 'AC_CHECK_HEADERS') { 361 push(@have_headers, $word); 362 } else { 363 &print_unique($headers_macros{$word}); 364 } 365 } 366 print CONF "AC_CHECK_HEADERS(" . join(' ', sort(@have_headers)) . ")\n" 367 if defined(@have_headers); 368} 369 370sub output_identifiers 371{ 372 local ($word); 373 374 print CONF "\ndnl Checks for typedefs, structures, and compiler characteristics.\n"; 375 foreach $word (sort keys %identifiers) { 376 &print_unique($identifiers_macros{$word}); 377 } 378} 379 380sub output_functions 381{ 382 local ($word); 383 384 print CONF "\ndnl Checks for library functions.\n"; 385 foreach $word (sort keys %functions) { 386 if (defined($functions_macros{$word}) && 387 $functions_macros{$word} eq 'AC_CHECK_FUNCS') { 388 push(@have_funcs, $word); 389 } else { 390 &print_unique($functions_macros{$word}); 391 } 392 } 393 print CONF "AC_CHECK_FUNCS(" . join(' ', sort(@have_funcs)) . ")\n" 394 if defined(@have_funcs); 395} 396