autoscan.in 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. #! @PERL@ -w
  2. # -*- perl -*-
  3. # @configure_input@
  4. # autoscan - Create configure.scan (a preliminary configure.ac) for a package.
  5. # Copyright (C) 1994, 1999-2012 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 3 of the License, or
  9. # (at your option) 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.
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. # Written by David MacKenzie <djm@gnu.ai.mit.edu>.
  17. eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
  18. if 0;
  19. BEGIN
  20. {
  21. my $pkgdatadir = $ENV{'autom4te_perllibdir'} || '@pkgdatadir@';
  22. unshift @INC, $pkgdatadir;
  23. # Override SHELL. On DJGPP SHELL may not be set to a shell
  24. # that can handle redirection and quote arguments correctly,
  25. # e.g.: COMMAND.COM. For DJGPP always use the shell that configure
  26. # has detected.
  27. $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');
  28. }
  29. use Autom4te::ChannelDefs;
  30. use Autom4te::Configure_ac;
  31. use Autom4te::General;
  32. use Autom4te::FileUtils;
  33. use Autom4te::XFile;
  34. use File::Basename;
  35. use File::Find;
  36. use strict;
  37. use vars qw(@cfiles @makefiles @shfiles @subdirs %printed);
  38. # The kind of the words we are looking for.
  39. my @kinds = qw (function header identifier program
  40. makevar librarie);
  41. # For each kind, the default macro.
  42. my %generic_macro =
  43. (
  44. 'function' => 'AC_CHECK_FUNCS',
  45. 'header' => 'AC_CHECK_HEADERS',
  46. 'identifier' => 'AC_CHECK_TYPES',
  47. 'program' => 'AC_CHECK_PROGS',
  48. 'library' => 'AC_CHECK_LIB'
  49. );
  50. my %kind_comment =
  51. (
  52. 'function' => 'Checks for library functions.',
  53. 'header' => 'Checks for header files.',
  54. 'identifier' => 'Checks for typedefs, structures, and compiler characteristics.',
  55. 'program' => 'Checks for programs.',
  56. );
  57. # $USED{KIND}{ITEM} is the list of locations where the ITEM (of KIND) was used
  58. # in the user package.
  59. # For instance $USED{function}{alloca} is the list of `file:line' where
  60. # `alloca (...)' appears.
  61. my %used = ();
  62. # $MACRO{KIND}{ITEM} is the list of macros to use to test ITEM.
  63. # Initialized from lib/autoscan/*. E.g., $MACRO{function}{alloca} contains
  64. # the singleton AC_FUNC_ALLOCA. Some require several checks.
  65. my %macro = ();
  66. # $NEEDED_MACROS{MACRO} is an array of locations requiring MACRO.
  67. # E.g., $NEEDED_MACROS{AC_FUNC_ALLOC} the list of `file:line' containing
  68. # `alloca (...)'.
  69. my %needed_macros =
  70. (
  71. 'AC_PREREQ' => [$me],
  72. );
  73. my $configure_scan = 'configure.scan';
  74. my $log;
  75. # Autoconf and lib files.
  76. my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
  77. my $autoconf = "$autom4te --language=autoconf";
  78. my @prepend_include;
  79. my @include = ('@pkgdatadir@');
  80. # $help
  81. # -----
  82. $help = "Usage: $0 [OPTION]... [SRCDIR]
  83. Examine source files in the directory tree rooted at SRCDIR, or the
  84. current directory if none is given. Search the source files for
  85. common portability problems, check for incompleteness of
  86. `configure.ac', and create a file `$configure_scan' which is a
  87. preliminary `configure.ac' for that package.
  88. -h, --help print this help, then exit
  89. -V, --version print version number, then exit
  90. -v, --verbose verbosely report processing
  91. -d, --debug don't remove temporary files
  92. Library directories:
  93. -B, --prepend-include=DIR prepend directory DIR to search path
  94. -I, --include=DIR append directory DIR to search path
  95. Report bugs to <bug-autoconf\@gnu.org>.
  96. GNU Autoconf home page: <http://www.gnu.org/software/autoconf/>.
  97. General help using GNU software: <http://www.gnu.org/gethelp/>.
  98. ";
  99. # $version
  100. # --------
  101. $version = "autoscan (@PACKAGE_NAME@) @VERSION@
  102. Copyright (C) @RELEASE_YEAR@ Free Software Foundation, Inc.
  103. License GPLv3+/Autoconf: GNU GPL version 3 or later
  104. <http://gnu.org/licenses/gpl.html>, <http://gnu.org/licenses/exceptions.html>
  105. This is free software: you are free to change and redistribute it.
  106. There is NO WARRANTY, to the extent permitted by law.
  107. Written by David J. MacKenzie and Akim Demaille.
  108. ";
  109. ## ------------------------ ##
  110. ## Command line interface. ##
  111. ## ------------------------ ##
  112. # parse_args ()
  113. # -------------
  114. # Process any command line arguments.
  115. sub parse_args ()
  116. {
  117. getopt ('I|include=s' => \@include,
  118. 'B|prepend-include=s' => \@prepend_include);
  119. die "$me: too many arguments
  120. Try `$me --help' for more information.\n"
  121. if @ARGV > 1;
  122. my $srcdir = $ARGV[0] || ".";
  123. verb "srcdir = $srcdir";
  124. chdir $srcdir || error "cannot cd to $srcdir: $!";
  125. }
  126. # init_tables ()
  127. # --------------
  128. # Put values in the tables of what to do with each token.
  129. sub init_tables ()
  130. {
  131. # The data file format supports only one line of macros per function.
  132. # If more than that is required for a common portability problem,
  133. # a new Autoconf macro should probably be written for that case,
  134. # instead of duplicating the code in lots of configure.ac files.
  135. my $file = find_file ("autoscan/autoscan.list",
  136. reverse (@prepend_include), @include);
  137. my $table = new Autom4te::XFile "< " . open_quote ($file);
  138. my $tables_are_consistent = 1;
  139. while ($_ = $table->getline)
  140. {
  141. # Ignore blank lines and comments.
  142. next
  143. if /^\s*$/ || /^\s*\#/;
  144. # '<kind>: <word> <macro invocation>' or...
  145. # '<kind>: <word> warn: <message>'.
  146. if (/^(\S+):\s+(\S+)\s+(\S.*)$/)
  147. {
  148. my ($kind, $word, $macro) = ($1, $2, $3);
  149. error "$file:$.: invalid kind: $_"
  150. unless grep { $_ eq $kind } @kinds;
  151. push @{$macro{$kind}{$word}}, $macro;
  152. }
  153. else
  154. {
  155. error "$file:$.: invalid definition: $_";
  156. }
  157. }
  158. if ($debug)
  159. {
  160. foreach my $kind (@kinds)
  161. {
  162. foreach my $word (sort keys %{$macro{$kind}})
  163. {
  164. print "$kind: $word: @{$macro{$kind}{$word}}\n";
  165. }
  166. }
  167. }
  168. }
  169. # used ($KIND, $WORD, [$WHERE])
  170. # -----------------------------
  171. # $WORD is used as a $KIND.
  172. sub used ($$;$)
  173. {
  174. my ($kind, $word, $where) = @_;
  175. $where ||= "$File::Find::name:$.";
  176. if (
  177. # Check for all the libraries. But `-links' is certainly a
  178. # `find' argument, and `-le', a `test' argument.
  179. ($kind eq 'library' && $word !~ /^(e|inks)$/)
  180. # Other than libraries are to be checked only if listed in
  181. # the Autoscan library files.
  182. || defined $macro{$kind}{$word}
  183. )
  184. {
  185. push (@{$used{$kind}{$word}}, $where);
  186. }
  187. }
  188. ## ----------------------- ##
  189. ## Scanning source files. ##
  190. ## ----------------------- ##
  191. # scan_c_file ($FILE-NAME)
  192. # ------------------------
  193. sub scan_c_file ($)
  194. {
  195. my ($file_name) = @_;
  196. push @cfiles, $File::Find::name;
  197. # Nonzero if in a multiline comment.
  198. my $in_comment = 0;
  199. my $file = new Autom4te::XFile "< " . open_quote ($file_name);
  200. while ($_ = $file->getline)
  201. {
  202. # Strip out comments.
  203. if ($in_comment && s,^.*?\*/,,)
  204. {
  205. $in_comment = 0;
  206. }
  207. # The whole line is inside a comment.
  208. next if $in_comment;
  209. # All on one line.
  210. s,/\*.*?\*/,,g;
  211. # Starting on this line.
  212. if (s,/\*.*$,,)
  213. {
  214. $in_comment = 1;
  215. }
  216. # Preprocessor directives.
  217. if (s/^\s*\#\s*//)
  218. {
  219. if (/^include\s*<([^>]*)>/)
  220. {
  221. used ('header', $1);
  222. }
  223. if (s/^(if|ifdef|ifndef|elif)\s+//)
  224. {
  225. foreach my $word (split (/\W+/))
  226. {
  227. used ('identifier', $word)
  228. unless $word eq 'defined' || $word !~ /^[a-zA-Z_]/;
  229. }
  230. }
  231. # Ignore other preprocessor directives.
  232. next;
  233. }
  234. # Remove string and character constants.
  235. s,\"[^\"]*\",,g;
  236. s,\'[^\']*\',,g;
  237. # Tokens in the code.
  238. # Maybe we should ignore function definitions (in column 0)?
  239. while (s/\b([a-zA-Z_]\w*)\s*\(/ /)
  240. {
  241. used ('function', $1);
  242. }
  243. while (s/\b([a-zA-Z_]\w*)\b/ /)
  244. {
  245. used ('identifier', $1);
  246. }
  247. }
  248. $file->close;
  249. }
  250. # scan_makefile($MAKEFILE-NAME)
  251. # -----------------------------
  252. sub scan_makefile ($)
  253. {
  254. my ($file_name) = @_;
  255. push @makefiles, $File::Find::name;
  256. my $file = new Autom4te::XFile "< " . open_quote ($file_name);
  257. while ($_ = $file->getline)
  258. {
  259. # Strip out comments.
  260. s/#.*//;
  261. # Variable assignments.
  262. while (s/\b([a-zA-Z_]\w*)\s*=/ /)
  263. {
  264. used ('makevar', $1);
  265. }
  266. # Be sure to catch a whole word. For instance `lex$U.$(OBJEXT)'
  267. # is a single token. Otherwise we might believe `lex' is needed.
  268. foreach my $word (split (/\s+/))
  269. {
  270. # Libraries.
  271. if ($word =~ /^-l([a-zA-Z_]\w*)$/)
  272. {
  273. used ('library', $1);
  274. }
  275. # Tokens in the code.
  276. # We allow some additional characters, e.g., `+', since
  277. # autoscan/programs includes `c++'.
  278. if ($word =~ /^[a-zA-Z_][\w+]*$/)
  279. {
  280. used ('program', $word);
  281. }
  282. }
  283. }
  284. $file->close;
  285. }
  286. # scan_sh_file($SHELL-SCRIPT-NAME)
  287. # --------------------------------
  288. sub scan_sh_file ($)
  289. {
  290. my ($file_name) = @_;
  291. push @shfiles, $File::Find::name;
  292. my $file = new Autom4te::XFile "< " . open_quote ($file_name);
  293. while ($_ = $file->getline)
  294. {
  295. # Strip out comments and variable references.
  296. s/#.*//;
  297. s/\${[^\}]*}//g;
  298. s/@[^@]*@//g;
  299. # Tokens in the code.
  300. while (s/\b([a-zA-Z_]\w*)\b/ /)
  301. {
  302. used ('program', $1);
  303. }
  304. }
  305. $file->close;
  306. }
  307. # scan_file ()
  308. # ------------
  309. # Called by &find on each file. $_ contains the current file name with
  310. # the current directory of the walk through.
  311. sub scan_file ()
  312. {
  313. # Wanted only if there is no corresponding FILE.in.
  314. return
  315. if -f "$_.in";
  316. # Save $_ as Find::File requires it to be preserved.
  317. local $_ = $_;
  318. # Strip a useless leading `./'.
  319. $File::Find::name =~ s,^\./,,;
  320. if ($_ ne '.' and -d $_ and
  321. -f "$_/configure.in" ||
  322. -f "$_/configure.ac" ||
  323. -f "$_/configure.gnu" ||
  324. -f "$_/configure")
  325. {
  326. $File::Find::prune = 1;
  327. push @subdirs, $File::Find::name;
  328. }
  329. if (/\.[chlym](\.in)?$/)
  330. {
  331. used 'program', 'cc', $File::Find::name;
  332. scan_c_file ($_);
  333. }
  334. elsif (/\.(cc|cpp|cxx|CC|C|hh|hpp|hxx|HH|H|yy|ypp|ll|lpp)(\.in)?$/)
  335. {
  336. used 'program', 'c++', $File::Find::name;
  337. scan_c_file ($_);
  338. }
  339. elsif ((/^((?:GNUm|M|m)akefile)(\.in)?$/ && ! -f "$1.am")
  340. || /^(?:GNUm|M|m)akefile(\.am)?$/)
  341. {
  342. scan_makefile ($_);
  343. }
  344. elsif (/\.sh(\.in)?$/)
  345. {
  346. scan_sh_file ($_);
  347. }
  348. }
  349. # scan_files ()
  350. # -------------
  351. # Read through the files and collect lists of tokens in them
  352. # that might create nonportabilities.
  353. sub scan_files ()
  354. {
  355. find (\&scan_file, '.');
  356. if ($verbose)
  357. {
  358. print "cfiles: @cfiles\n";
  359. print "makefiles: @makefiles\n";
  360. print "shfiles: @shfiles\n";
  361. foreach my $kind (@kinds)
  362. {
  363. print "\n$kind:\n";
  364. foreach my $word (sort keys %{$used{$kind}})
  365. {
  366. print "$word: @{$used{$kind}{$word}}\n";
  367. }
  368. }
  369. }
  370. }
  371. ## ----------------------- ##
  372. ## Output configure.scan. ##
  373. ## ----------------------- ##
  374. # output_kind ($FILE, $KIND)
  375. # --------------------------
  376. sub output_kind ($$)
  377. {
  378. my ($file, $kind) = @_;
  379. # Lists of words to be checked with the generic macro.
  380. my @have;
  381. print $file "\n# $kind_comment{$kind}\n"
  382. if exists $kind_comment{$kind};
  383. foreach my $word (sort keys %{$used{$kind}})
  384. {
  385. # Output the needed macro invocations in $configure_scan if not
  386. # already printed, and remember these macros are needed.
  387. foreach my $macro (@{$macro{$kind}{$word}})
  388. {
  389. if ($macro =~ /^warn:\s+(.*)/)
  390. {
  391. my $message = $1;
  392. foreach my $location (@{$used{$kind}{$word}})
  393. {
  394. warn "$location: warning: $message\n";
  395. }
  396. }
  397. elsif (exists $generic_macro{$kind}
  398. && $macro eq $generic_macro{$kind})
  399. {
  400. push (@have, $word);
  401. push (@{$needed_macros{"$generic_macro{$kind}([$word])"}},
  402. @{$used{$kind}{$word}});
  403. }
  404. else
  405. {
  406. if (! $printed{$macro})
  407. {
  408. print $file "$macro\n";
  409. $printed{$macro} = 1;
  410. }
  411. push (@{$needed_macros{$macro}},
  412. @{$used{$kind}{$word}});
  413. }
  414. }
  415. }
  416. print $file "$generic_macro{$kind}([" . join(' ', sort(@have)) . "])\n"
  417. if @have;
  418. }
  419. # output_libraries ($FILE)
  420. # ------------------------
  421. sub output_libraries ($)
  422. {
  423. my ($file) = @_;
  424. print $file "\n# Checks for libraries.\n";
  425. foreach my $word (sort keys %{$used{'library'}})
  426. {
  427. print $file "# FIXME: Replace `main' with a function in `-l$word':\n";
  428. print $file "AC_CHECK_LIB([$word], [main])\n";
  429. }
  430. }
  431. # output ($CONFIGURE_SCAN)
  432. # ------------------------
  433. # Print a proto configure.ac.
  434. sub output ($)
  435. {
  436. my $configure_scan = shift;
  437. my %unique_makefiles;
  438. my $file = new Autom4te::XFile "> " . open_quote ($configure_scan);
  439. print $file
  440. ("# -*- Autoconf -*-\n" .
  441. "# Process this file with autoconf to produce a configure script.\n" .
  442. "\n" .
  443. "AC_PREREQ([@VERSION@])\n" .
  444. "AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])\n");
  445. if (defined $cfiles[0])
  446. {
  447. print $file "AC_CONFIG_SRCDIR([$cfiles[0]])\n";
  448. print $file "AC_CONFIG_HEADERS([config.h])\n";
  449. }
  450. output_kind ($file, 'program');
  451. output_kind ($file, 'makevar');
  452. output_libraries ($file);
  453. output_kind ($file, 'header');
  454. output_kind ($file, 'identifier');
  455. output_kind ($file, 'function');
  456. print $file "\n";
  457. if (@makefiles)
  458. {
  459. # Change DIR/Makefile.in to DIR/Makefile.
  460. foreach my $m (@makefiles)
  461. {
  462. $m =~ s/\.(?:in|am)$//;
  463. $unique_makefiles{$m}++;
  464. }
  465. print $file ("AC_CONFIG_FILES([",
  466. join ("\n ",
  467. sort keys %unique_makefiles), "])\n");
  468. }
  469. if (@subdirs)
  470. {
  471. print $file ("AC_CONFIG_SUBDIRS([",
  472. join ("\n ",
  473. sort @subdirs), "])\n");
  474. }
  475. print $file "AC_OUTPUT\n";
  476. $file->close;
  477. }
  478. ## --------------------------------------- ##
  479. ## Checking the accuracy of configure.ac. ##
  480. ## --------------------------------------- ##
  481. # &check_configure_ac ($CONFIGURE_AC)
  482. # -----------------------------------
  483. # Use autoconf to check if all the suggested macros are included
  484. # in CONFIGURE_AC.
  485. sub check_configure_ac ($)
  486. {
  487. my ($configure_ac) = @_;
  488. # Find what needed macros are invoked in CONFIGURE_AC.
  489. # I'd be very happy if someone could explain to me why sort (uniq ...)
  490. # doesn't work properly: I need `uniq (sort ...)'. --akim
  491. my $trace_option =
  492. join (' --trace=', '',
  493. uniq (sort (map { s/\(.*//; $_ } keys %needed_macros)));
  494. verb "running: $autoconf $trace_option $configure_ac";
  495. my $traces =
  496. new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
  497. while ($_ = $traces->getline)
  498. {
  499. chomp;
  500. my ($file, $line, $macro, @args) = split (/:/, $_);
  501. if ($macro =~ /^AC_CHECK_(HEADER|FUNC|TYPE|MEMBER)S$/)
  502. {
  503. # To be rigorous, we should distinguish between space and comma
  504. # separated macros. But there is no point.
  505. foreach my $word (split (/\s|,/, $args[0]))
  506. {
  507. # AC_CHECK_MEMBERS wants `struct' or `union'.
  508. if ($macro eq "AC_CHECK_MEMBERS"
  509. && $word =~ /^stat.st_/)
  510. {
  511. $word = "struct " . $word;
  512. }
  513. delete $needed_macros{"$macro([$word])"};
  514. }
  515. }
  516. else
  517. {
  518. delete $needed_macros{$macro};
  519. }
  520. }
  521. $traces->close;
  522. # Report the missing macros.
  523. foreach my $macro (sort keys %needed_macros)
  524. {
  525. warn ("$configure_ac: warning: missing $macro wanted by: "
  526. . (${$needed_macros{$macro}}[0])
  527. . "\n");
  528. print $log "$me: warning: missing $macro wanted by: \n";
  529. foreach my $need (@{$needed_macros{$macro}})
  530. {
  531. print $log "\t$need\n";
  532. }
  533. }
  534. }
  535. ## -------------- ##
  536. ## Main program. ##
  537. ## -------------- ##
  538. parse_args;
  539. $log = new Autom4te::XFile "> " . open_quote ("$me.log");
  540. $autoconf .= " --debug" if $debug;
  541. $autoconf .= " --verbose" if $verbose;
  542. $autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
  543. $autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
  544. my $configure_ac = find_configure_ac;
  545. init_tables;
  546. scan_files;
  547. output ('configure.scan');
  548. if (-f $configure_ac)
  549. {
  550. check_configure_ac ($configure_ac);
  551. }
  552. # This close is really needed. For some reason, probably best named
  553. # a bug, it seems that the dtor of $LOG is not called automatically
  554. # at END. It results in a truncated file.
  555. $log->close;
  556. exit 0;
  557. ### Setup "GNU" style for perl-mode and cperl-mode.
  558. ## Local Variables:
  559. ## perl-indent-level: 2
  560. ## perl-continued-statement-offset: 2
  561. ## perl-continued-brace-offset: 0
  562. ## perl-brace-offset: 0
  563. ## perl-brace-imaginary-offset: 0
  564. ## perl-label-offset: -2
  565. ## cperl-indent-level: 2
  566. ## cperl-brace-offset: 0
  567. ## cperl-continued-brace-offset: 0
  568. ## cperl-label-offset: -2
  569. ## cperl-extra-newline-before-brace: t
  570. ## cperl-merge-trailing-else: nil
  571. ## cperl-continued-statement-offset: 2
  572. ## End: