summaryrefslogtreecommitdiffstats
path: root/source4/script/configure_check_unused.pl
blob: 52d8deeb27f9e48bff254984397b6d0e083e51f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/perl
# Script that finds macros in a configure script that are not 
# used in a set of C files.
# Copyright Jelmer Vernooij <jelmer@samba.org>, GPL
#
# Usage: ./$ARGV[0] configure.in [c-files...]

use strict;

sub autoconf_parse($$$$)
{
	my $in = shift;
	my $defines = shift;
	my $functions = shift;
	my $headers = shift;

	open(IN, $in) or die("Can't open $in");

	my $ln = 0;

	foreach(<IN>) {
		$ln++;

		if(/AC_DEFINE\(([^,]+),/) { 
			$defines->{$1} = "$in:$ln";
		} 
	
		if(/AC_CHECK_FUNCS\(\[*(.[^],)]+)/) {
			foreach(split / /, $1) { 
				$functions->{$_} = "$in:$ln";
			}
		}

		if(/AC_CHECK_FUNC\(([^,)]+)/) {
			$functions->{$1} = "$in:$ln";
		}

		if(/AC_CHECK_HEADERS\(\[*([^],)]+)/) {
			foreach(split / /, $1) { 
				$headers->{$_} = "$in:$ln";
			}
		}

		if(/AC_CHECK_HEADER\(([^,)]+)/) {
			$headers->{$1} = "$in:$ln";
		}

		if(/sinclude\(([^,]+)\)/) {
			autoconf_parse($1, $defines, $functions, $headers);
		}
	}

	close IN;
}

# Return the symbols and headers used by a C file
sub cfile_parse($$$)
{
	my $in = shift;
	my $symbols = shift;
	my $headers = shift;

	open(FI, $in) or die("Can't open $in");
	my $ln = 0;	
	my $line;
	while($line = <FI>) { 
		$ln++;
		$_ = $line;
		if (/\#([ \t]*)include ["<]([^">]+)/) { 
			$headers->{$2} = "$in:$ln";
		}

		$_ = $line;
		while(/([A-Za-z0-9_]+)/g) { 
			$symbols->{$1} = "$in:$ln";
		}
	}
	close FI;
}

my %ac_defines = ();
my %ac_func_checks = ();
my %ac_headers = ();
my %symbols = ();
my %headers = ();

if (scalar(@ARGV) <= 1) {
	print("Usage: configure_find_unused.pl configure.in [CFILE...]\n");
	exit 0;
}

autoconf_parse(shift(@ARGV), \%ac_defines, \%ac_func_checks, \%ac_headers);
cfile_parse($_, \%symbols, \%headers) foreach(@ARGV);

(keys %ac_defines) or warn("No defines found in configure.in file, parse error?");

foreach (keys %ac_defines) {
	if (not defined($symbols{$_})) {
		print "$ac_defines{$_}: Autoconf-defined $_ is unused\n";
	}
}

(keys %ac_func_checks) or warn("No function checks found in configure.in file, parse error?");

foreach (keys %ac_func_checks) {
	my $def = "HAVE_".uc($_);
	if (not defined($symbols{$_})) {
		print "$ac_func_checks{$_}: Autoconf-checked function `$_' is unused\n";
	} elsif (not defined($symbols{$def})) {
		print "$ac_func_checks{$_}: Autoconf-define `$def' for function `$_' is unused\n";
	}
}

(keys %ac_headers) or warn("No headers found in configure.in file, parse error?");

foreach (keys %ac_headers) {
	my $def = "HAVE_".uc($_);
	$def =~ s/[\/\.]/_/g;
	if (not defined($headers{$_})) {
		print "$ac_headers{$_}: Autoconf-checked header `$_' is unused\n";
	} elsif (not defined($symbols{$def})) {
		print "$ac_headers{$_}: Autoconf-define `$def' for header `$_' is unused\n"; 
	}
}