source: trunk/third/autoconf/autoscan.pl @ 13391

Revision 13391, 9.3 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r13390, which included commits to RCS files with non-trunk default branches.
Line 
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}
Note: See TracBrowser for help on using the repository browser.