| 1 | #!/usr/bin/perl -w
|
|---|
| 2 | # find a list of #include lines in C code that might not be needed
|
|---|
| 3 | # usually called with something like this:
|
|---|
| 4 | # minimal_includes.pl `find . -name "*.c"`
|
|---|
| 5 | # Andrew Tridgell <tridge@samba.org>
|
|---|
| 6 |
|
|---|
| 7 | use strict;
|
|---|
| 8 | use Data::Dumper;
|
|---|
| 9 | use Getopt::Long;
|
|---|
| 10 |
|
|---|
| 11 | my $opt_help = 0;
|
|---|
| 12 | my $opt_remove = 0;
|
|---|
| 13 | my $opt_skip_system = 0;
|
|---|
| 14 |
|
|---|
| 15 | #####################################################################
|
|---|
| 16 | # write a string into a file
|
|---|
| 17 | sub FileSave($$)
|
|---|
| 18 | {
|
|---|
| 19 | my($filename) = shift;
|
|---|
| 20 | my($v) = shift;
|
|---|
| 21 | local(*FILE);
|
|---|
| 22 | open(FILE, ">$filename") || die "can't open $filename";
|
|---|
| 23 | print FILE $v;
|
|---|
| 24 | close(FILE);
|
|---|
| 25 | }
|
|---|
| 26 |
|
|---|
| 27 | sub load_lines($)
|
|---|
| 28 | {
|
|---|
| 29 | my $fname = shift;
|
|---|
| 30 | my @lines = split(/^/m, `cat $fname`);
|
|---|
| 31 | return @lines;
|
|---|
| 32 | }
|
|---|
| 33 |
|
|---|
| 34 | sub save_lines($$)
|
|---|
| 35 | {
|
|---|
| 36 | my $fname = shift;
|
|---|
| 37 | my $lines = shift;
|
|---|
| 38 | my $data = join('', @{$lines});
|
|---|
| 39 | FileSave($fname, $data);
|
|---|
| 40 | }
|
|---|
| 41 |
|
|---|
| 42 | sub test_compile($)
|
|---|
| 43 | {
|
|---|
| 44 | my $fname = shift;
|
|---|
| 45 | my $obj;
|
|---|
| 46 | if ($fname =~ s/(.*)\.c$/$1.o/) {
|
|---|
| 47 | $obj = "$1.o";
|
|---|
| 48 | } else {
|
|---|
| 49 | return "NOT A C FILE";
|
|---|
| 50 | }
|
|---|
| 51 | unlink($obj);
|
|---|
| 52 | my $ret = `make $obj 2>&1`;
|
|---|
| 53 | if (!unlink("$obj")) {
|
|---|
| 54 | return "COMPILE FAILED";
|
|---|
| 55 | }
|
|---|
| 56 | return $ret;
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | sub test_include($$$$)
|
|---|
| 60 | {
|
|---|
| 61 | my $fname = shift;
|
|---|
| 62 | my $lines = shift;
|
|---|
| 63 | my $i = shift;
|
|---|
| 64 | my $original = shift;
|
|---|
| 65 | my $line = $lines->[$i];
|
|---|
| 66 | my $testfname;
|
|---|
| 67 |
|
|---|
| 68 | $lines->[$i] = "";
|
|---|
| 69 |
|
|---|
| 70 | `/bin/mv -f $fname $fname.misaved` && die "failed to rename $fname";
|
|---|
| 71 | save_lines($fname, $lines);
|
|---|
| 72 |
|
|---|
| 73 | my $out = test_compile($fname);
|
|---|
| 74 |
|
|---|
| 75 | if ($out eq $original) {
|
|---|
| 76 | if ($opt_remove) {
|
|---|
| 77 | if ($opt_skip_system &&
|
|---|
| 78 | $line =~ /system\//) {
|
|---|
| 79 | print "$fname: not removing system include $line\n";
|
|---|
| 80 | } else {
|
|---|
| 81 | print "$fname: removing $line\n";
|
|---|
| 82 | return;
|
|---|
| 83 | }
|
|---|
| 84 | } else {
|
|---|
| 85 | print "$fname: might be able to remove $line\n";
|
|---|
| 86 | }
|
|---|
| 87 | }
|
|---|
| 88 |
|
|---|
| 89 | $lines->[$i] = $line;
|
|---|
| 90 | `/bin/mv -f $fname.misaved $fname` && die "failed to restore $fname";
|
|---|
| 91 | }
|
|---|
| 92 |
|
|---|
| 93 | sub process_file($)
|
|---|
| 94 | {
|
|---|
| 95 | my $fname = shift;
|
|---|
| 96 | my @lines = load_lines($fname);
|
|---|
| 97 | my $num_lines = $#lines;
|
|---|
| 98 |
|
|---|
| 99 | my $original = test_compile($fname);
|
|---|
| 100 |
|
|---|
| 101 | if ($original eq "COMPILE FAILED") {
|
|---|
| 102 | print "Failed to compile $fname\n";
|
|---|
| 103 | return;
|
|---|
| 104 | }
|
|---|
| 105 |
|
|---|
| 106 | print "Processing $fname (with $num_lines lines)\n";
|
|---|
| 107 |
|
|---|
| 108 | my $if_level = 0;
|
|---|
| 109 |
|
|---|
| 110 | for (my $i=0;$i<=$num_lines;$i++) {
|
|---|
| 111 | my $line = $lines[$i];
|
|---|
| 112 | if ($line =~ /^\#\s*if/) {
|
|---|
| 113 | $if_level++;
|
|---|
| 114 | }
|
|---|
| 115 | if ($line =~ /^\#\s*endif/) {
|
|---|
| 116 | $if_level--;
|
|---|
| 117 | }
|
|---|
| 118 | if ($if_level == 0 &&
|
|---|
| 119 | $line =~ /^\#\s*include/ &&
|
|---|
| 120 | !($line =~ /needed/)) {
|
|---|
| 121 | test_include($fname, \@lines, $i, $original);
|
|---|
| 122 | }
|
|---|
| 123 | }
|
|---|
| 124 | }
|
|---|
| 125 |
|
|---|
| 126 |
|
|---|
| 127 | #########################################
|
|---|
| 128 | # display help text
|
|---|
| 129 | sub ShowHelp()
|
|---|
| 130 | {
|
|---|
| 131 | print "
|
|---|
| 132 | minimise includes
|
|---|
| 133 | Copyright (C) tridge\@samba.org
|
|---|
| 134 |
|
|---|
| 135 | Usage: minimal_includes.pl [options] <C files....>
|
|---|
| 136 |
|
|---|
| 137 | Options:
|
|---|
| 138 | --help show help
|
|---|
| 139 | --remove remove includes, don't just list them
|
|---|
| 140 | --skip-system don't remove system/ includes
|
|---|
| 141 | ";
|
|---|
| 142 | }
|
|---|
| 143 |
|
|---|
| 144 |
|
|---|
| 145 | # main program
|
|---|
| 146 | GetOptions (
|
|---|
| 147 | 'h|help|?' => \$opt_help,
|
|---|
| 148 | 'remove' => \$opt_remove,
|
|---|
| 149 | 'skip-system' => \$opt_skip_system,
|
|---|
| 150 | );
|
|---|
| 151 |
|
|---|
| 152 | if ($opt_help) {
|
|---|
| 153 | ShowHelp();
|
|---|
| 154 | exit(0);
|
|---|
| 155 | }
|
|---|
| 156 |
|
|---|
| 157 | for (my $i=0;$i<=$#ARGV;$i++) {
|
|---|
| 158 | my $fname = $ARGV[$i];
|
|---|
| 159 | process_file($fname);
|
|---|
| 160 | }
|
|---|