summaryrefslogtreecommitdiffstats
path: root/scripts/fixkdeincludes
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitbd9e6617827818fd043452c08c606f07b78014a0 (patch)
tree425bb4c3168f9c02f10150f235d2cb998dcc6108 /scripts/fixkdeincludes
downloadtdesdk-bd9e6617827818fd043452c08c606f07b78014a0.tar.gz
tdesdk-bd9e6617827818fd043452c08c606f07b78014a0.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdesdk@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'scripts/fixkdeincludes')
-rw-r--r--scripts/fixkdeincludes756
1 files changed, 756 insertions, 0 deletions
diff --git a/scripts/fixkdeincludes b/scripts/fixkdeincludes
new file mode 100644
index 00000000..54e4e9f6
--- /dev/null
+++ b/scripts/fixkdeincludes
@@ -0,0 +1,756 @@
+#!/usr/bin/perl -w
+# tries to reduce the number of includes in KDE source files
+# (c) 2001-2003 Dirk Mueller <mueller@kde.org>
+
+use File::Basename;
+use Cwd;
+
+# declaration of useful subroutines
+sub find_src_includes($);
+sub find_fixable_sources ($);
+sub find_fixable_headers($);
+sub find_removable_includes ($);
+sub warn_before_modifying ($);
+sub remove_include ($$$);
+sub replace_include ($$$);
+sub replace_include_type ($$);
+sub fix_duplicates($);
+sub fix_compat_includes($);
+sub fix_unnecessary($);
+sub fix_include_type($);
+sub copy_file($$);
+sub process_source_file($);
+sub extract_gcc_error($);
+
+# some global variables
+$verbose = 0; # turns on debugging
+$modify = 0; # if 1 it should try to fix the files as well
+$experimental = 0; # try&error if an include is obsolete (slow!!)
+@explicitfiles = (); # filled in if passing files on the command line
+
+# statistic variables
+$exp_success = 0;
+$exp_failure = 0;
+
+while (defined ($ARGV[0]))
+{
+ $_ = shift;
+ if (/^--help$|^-h$/) {
+ print "Usage: fixkdeincludes [--verbose | -v] [--experimental | -e ] [--modify | -m ]\n";
+ exit 0;
+ }
+ elsif (/^--verbose$|^-v$/) {
+ $verbose = 1; # Oh is there a problem...?
+ }
+ elsif (/^--modify$|^-m$/) {
+ $modify = 1;
+ }
+ elsif (/^--experimental$|^-e$/) {
+ $modify = 1;
+ $experimental = 1;
+ }
+ elsif (!/^-/) {
+ push @explicitfiles, $_;
+ }
+}
+
+$cppExt = "(cpp|cc|cxx|C|c\\+\\+)";
+$hExt = "(h|H|hh|hxx|hpp|h\\+\\+)";
+
+# list of compat headers. scroll down ... much of boring stuff here..
+%compatmap = (
+ 'qapp.h' => "qapplication.h",
+ 'qarray.h' => "qmemarray.h",
+ 'qbitarry.h' => "qbitarray.h",
+ 'qbttngrp.h' => "qbuttongroup.h",
+ 'qchkbox.h' => "qcheckbox.h",
+ 'qclipbrd.h' => "qclipboard.h",
+ 'qcollect.h' => "qptrcollection.h",
+ 'qcollection.h' => "qptrcollection.h",
+ 'qcombo.h' => "qcombobox.h",
+ 'qconnect.h' => "qconnection.h",
+ 'qdatetm.h' => "qdatetime.h",
+ 'qdrawutl.h' => "qdrawutil.h",
+ 'qdstream.h' => "qdatastream.h",
+ 'qfiledef.h' => "private/qfiledefs_p.h",
+ 'qfiledlg.h' => "qfiledialog.h",
+ 'qfileinf.h' => "qfileinfo.h",
+ 'qfontdta.h' => "qfontdata.h",
+ 'qfontinf.h' => "qfontinfo.h",
+ 'qfontmet.h' => "qfontmetrics.h",
+ 'qgrpbox.h' => "qgroupbox.h",
+ 'qintcach.h' => "qintcache.h",
+ 'qiodev.h' => "qiodevice.h",
+ 'qlcdnum.h' => "qlcdnumber.h",
+ 'qlined.h' => "qlineedit.h",
+ 'qlist.h' => "qptrlist.h",
+ 'qmenudta.h' => "qmenudata.h",
+ 'qmetaobj.h' => "qmetaobject.h",
+ 'qmlined.h' => "qtmultilineedit.h",
+ 'qmsgbox.h' => "qmessagebox.h",
+ 'qmultilinedit.h' => "qmultilineedit.h",
+ 'qobjcoll.h' => "qobjectlist.h>\n\#include <qobjectdict.h",
+ 'qobjdefs.h' => "qobjectdefs.h",
+ 'qpaintd.h' => "qpaintdevice.h",
+ 'qpaintdc.h' => "qpaintdevicedefs.h",
+ 'qpdevmet.h' => "qpaintdevicemetrics.h",
+ 'qpmcache.h' => "qpixmapcache.h",
+ 'qpntarry.h' => "qpointarray.h",
+ 'qpopmenu.h' => "qpopupmenu.h",
+ 'qprndlg.h' => "qprintdialog.h",
+ 'qprogbar.h' => "qprogressbar.h",
+ 'qprogdlg.h' => "qprogressdialog.h",
+ 'qpsprn.h' => "private/qpsprinter_p.h",
+ 'qpushbt.h' => "qpushbutton.h",
+ 'qqueue.h' => "qptrqueue.h",
+ 'qradiobt.h' => "qradiobutton.h",
+ 'qrangect.h' => "qrangecontrol.h",
+ 'qscrbar.h' => "qscrollbar.h",
+ 'qsocknot.h' => "qsocketnotifier.h",
+ 'qstack.h' => "qptrstack.h",
+ 'qtabdlg.h' => "qtabdialog.h",
+ 'qtstream.h' => "qtextstream.h",
+ 'qvector.h' => "qptrvector.h",
+ 'qwidcoll.h' => "qwidgetlist.h>\n\#include <qwidgetintdict.h",
+ 'qwindefs.h' => "qwindowdefs.h",
+
+# and now the KDE specific compat includes
+ 'kapp.h' => "kapplication.h",
+ 'kstddirs.h' => "kstandarddirs.h",
+ 'kuniqueapp.h' => "kuniqueapplication.h",
+ 'ktmainwindow.h'=> "kmainwindow.h",
+ 'kcolorbtn.h' => "kcolorbutton.h",
+ 'kcolordlg.h' => "kcolordialog.h",
+ 'kxmlgui.h' => "kxmlguifactory.h",
+ 'kdebugclasses.h' => "kdebug.h",
+);
+
+
+# now it starts to get interesting again
+
+# Look for source files in the given directory ($dir, first parameter)
+sub find_fixable_sources ($)
+{
+ # for now I grep the directory (requires srcdir==builddir)
+ # actually it should read the Makefile and
+ # find the _SOURCES / _OBJECTS tags that are put there by
+ # automake and am_edit, but thats an excercise to the reader ;-)
+
+ my ( $dir ) = @_;
+
+ opendir (DIR, "$dir") || die "Couldn't read '$dir'\n";
+ my @sources = grep { /^.*\.$cppExt$/o } readdir(DIR);
+ closedir(DIR);
+
+ print "found sources: [ " . join(' ', @sources) . " ] in $dir\n" if ($verbose);
+
+ # prefix them with $dir
+ my @retsources = ();
+ foreach $source(@sources) {
+ push @retsources, "$dir/$source";
+ }
+
+ return @retsources;
+}
+
+# Look for header files in the given directory ($dir, first parameter)
+sub find_fixable_headers ($)
+{
+ # for now I grep the directory (requires srcdir==builddir)
+ # actually it should read the Makefile and
+ # find the _HEADERS tags that are put there by
+ # automake and am_edit, but thats an excercise to the reader ;-)
+
+ my ( $dir ) = @_;
+
+ opendir (DIR, "$dir") || die "Couldn't read '$dir'\n";
+ my @headers = grep { /^.*\.$hExt$/o } readdir(DIR);
+ closedir(DIR);
+
+ print "found headers: [ " . join(' ', @headers) . " ] in $dir\n" if ($verbose);
+
+ # prefix them with $dir
+ my @retheaders = ();
+ foreach $source(@headers) {
+ push @retheaders, "$dir/$source";
+ }
+
+ return @retheaders;
+}
+
+sub find_removable_includes ($)
+{
+ my $srcfile = shift @_;
+ open(SRC, "< $srcfile") || die "find_removable_includes: couldn't open '$srcfile'\n";
+
+ my @includes = ();
+
+ # we skip all includes that are somehow ifdefed
+
+ my $cpplevel = 0;
+ $cpplevel = -1 if ($srcfile=~m/^.*\.$hExt$/); # plan for header-protection #ifndef/#define/#endif
+ while (<SRC>) {
+ if ($_ =~ m/^\#if/) {
+ $cpplevel = $cpplevel + 1;
+ next;
+ }
+ if ($_ =~ m/^\#endif/) {
+ $cpplevel = $cpplevel - 1;
+ next;
+ }
+ #if ($cpplevel == 0 && $_ =~ m/^\#include\s*[\"<]([qk]\S*\.h)[\">]\S*/) {
+ if ($cpplevel == 0 && (($_ =~ m/^\#include\s*\"(\S+\.h)\"\S*/) || ($_ =~ m/^\#include\s*\<([qk]\S+.h)\>\S*/))) {
+ push @includes, $1;
+ next;
+ }
+ }
+ close SRC;
+
+ print "No fixable includes found in $srcfile\n" if ($verbose and not @includes);
+ print "found includes: [ " . join(' ', @includes) . " ]\n" if ($verbose and @includes);
+
+ return @includes;
+}
+
+sub find_installed_headers($)
+{
+ my $sdir = shift @_;
+ my @includes = ();
+
+ open(I, "<$sdir/Makefile.am") || die "couldn't open $sdir/Makefile.am $!";
+
+ my $data = join('', <I>);
+ $data =~ s/\\\s*\n/ /g;
+
+ # now search for not installed headers
+ foreach my $line (split /^/, $data) {
+ if($line =~ /^(\w+)_HEADERS\s*=(.*)$/) {
+ next if $1 eq "noinst";
+ push @includes, split (' ', $2);
+ }
+ }
+ close(I);
+ return @includes;
+}
+
+# first parameter: srcfile
+# second parameter: include to remove
+# third parameter is the duplicate level: this include is removed $level times
+sub remove_include ($$$)
+{
+ my $srcfile = shift @_;
+ my $include = quotemeta(shift @_);
+ my $level = shift @_;
+
+ die "$srcfile is not read/writeable!\n" if( ! -r $srcfile || ! -w $srcfile);
+ open(I, "< $srcfile") or die "remove_include: couldn't open '$srcfile'\n";
+ my @contents = <I>;
+ close(I);
+
+ # ok, CPU time doesn't count so we do it the lazy way
+ # we should remove the last occurence of the include in the
+ # file because in case its a duplicate removing the first
+ # one could make a difference.
+ my @revcontents = reverse @contents;
+ @contents = ();
+
+ # we skip all inludes that are somehow ifdefed
+ # note the logic is reversed because it operates
+ # on reversed lines :)
+ my $cpplevel = 0;
+ $cpplevel = -1 if ($srcfile=~m/^.*\.$hExt$/); # plan for header-protection #ifndef/#define/#endif
+ foreach $line (@revcontents) {
+ if ($line =~ m/^\#if/) {
+ $cpplevel = $cpplevel - 1;
+ push @contents, $line;
+ next;
+ }
+
+ if ($line =~ m/^\#endif/) {
+ $cpplevel = $cpplevel + 1;
+ push @contents, $line;
+ next;
+ }
+
+ if ($level && $cpplevel == 0 &&
+ (($line =~ m/^\#include\s*\"$include\"\S*/) || ($line =~ m/^\#include\s*\<$include\>\S*/))) {
+ $level = $level - 1;
+ # skipping the line..
+ next;
+ }
+
+ push @contents, $line;
+ }
+
+ # now we have the fixed contents in @contents, although in wrong order
+ open(O, "> $srcfile") || die "remove_include: couldn't open '$srcfile' for writing\n";
+ print O reverse @contents;
+ close (O);
+}
+
+# first parameter: srcfile
+# second parameter: include to replace
+# third parameter the include file to replace it with
+sub replace_include ($$$)
+{
+ my $srcfile = shift @_;
+ my $include = quotemeta(shift @_);
+ my $destinclude = shift @_;
+
+ die "$srcfile is not read/writeable!\n" if( ! -r $srcfile || ! -w $srcfile);
+ open(I, "< $srcfile") or die "replace_include: couldn't open '$srcfile'\n";
+ my @contents = <I>;
+ close(I);
+
+ # ok, CPU time doesn't count so we do it the lazy way
+ my @revcontents = reverse @contents;
+ @contents = ();
+
+ # we skip all inludes that are somehow ifdefed
+ # note the logic is reversed because it operates
+ # on reversed lines :)
+ my $cpplevel = 0;
+ $cpplevel = -1 if ($srcfile=~m/^.*\.$hExt$/); # plan for header-protection #ifndef/#define/#endif
+ foreach $line (@revcontents) {
+ if ($line =~ m/^\#if/) {
+ $cpplevel = $cpplevel - 1;
+ push @contents, $line;
+ next;
+ }
+
+ if ($line =~ m/^\#endif/) {
+ $cpplevel = $cpplevel + 1;
+ push @contents, $line;
+ next;
+ }
+
+ if ($cpplevel == 0 &&
+ (($line =~ m/^\#include\s*\"$include\"\S*/) || ($line =~ m/^\#include\s*\<$include\>\S*/)))
+ {
+ print "HAH! found $include to replace in $srcfile!\n" if($verbose);
+ $line =~ s/(\#include\s*[\"<])$include([\">]\S*)/$1$destinclude$2/;
+ }
+
+ push @contents, $line;
+ }
+
+ # now we have the fixed contents in @contents
+ open(O, "> $srcfile") || die "replace_include: couldn't open '$srcfile' for writing\n";
+ print O reverse @contents;
+ close (O);
+}
+
+# fixes #include <foo.h> -> #include "foo.h"
+sub replace_include_type ($$)
+{
+ my ($srcfile, $include) = @_;
+
+ die "$srcfile is not read/writeable!\n" if( ! -r $srcfile || ! -w $srcfile);
+ open(I, "< $srcfile") or die "replace_include: couldn't open '$srcfile'\n";
+ my @contents = <I>;
+ close(I);
+
+ grep(s/^(\#include)\s*<$include>(.*)$/$1 \"$include\"$2/, @contents);
+
+ # now we have the fixed contents in @contents
+ open(O, "> $srcfile") || die "replace_include: couldn't open '$srcfile' for writing\n";
+ print O @contents;
+ close (O);
+}
+
+sub fix_duplicates($)
+{
+ my $srcfile = shift @_;
+
+ my @includes = &find_removable_includes($srcfile);
+
+ my %inclMap = ();
+
+ # initialize
+ foreach $include (@includes) {
+ $inclMap{$include} = 0;
+ }
+
+ # count number of occurences
+ foreach $include (@includes) {
+ $inclMap{$include} = $inclMap{$include} + 1;
+ }
+
+ # check for duplicates
+ foreach $include (keys %inclMap) {
+ next if $inclMap{$include} <= 1;
+
+ print "$srcfile: duplicate level ". $inclMap{$include} .": ". $include ."\n";
+
+ &remove_include($srcfile, $include, $inclMap{$include} - 1) if($modify);
+ }
+}
+
+sub extract_gcc_error($)
+{
+ my $out = shift;
+
+ # print "out: $out\n";
+
+ while ($out =~ m/^(.*?):([0-9]+):(.*)$/mg) # filename:lineno:message
+ {
+ my $field1 = $1 || "";
+ my $field2 = $2 || "";
+ my $field3 = $3 || "";
+
+ # print "f1: $field1, f2: $field2, f3: $field3\n";
+
+ next if ($field3 =~ m/\s+warning:.*/);
+ next if ($field3 =~ m/^\s*$/);
+ return basename($field1);
+ }
+ return "BUG!";
+}
+
+sub fix_compat_includes($)
+{
+ my $srcfile = shift @_;
+
+ my @includes = &find_removable_includes($srcfile);
+
+ my %inclMap = ();
+
+ # initialize
+ foreach $include (@includes) {
+ $inclMap{$include} = 0;
+ }
+
+ # count number of occurences
+ foreach $include (@includes) {
+ $inclMap{$include} = $inclMap{$include} + 1;
+ }
+
+ # check for compat headers
+ foreach $include (keys %inclMap) {
+ if( defined $compatmap{$include}) {
+ print "$srcfile: compat header: $include, to be replaced by ". $compatmap{$include} ."\n";
+ &replace_include($srcfile, $include, $compatmap{$include}) if($modify);
+ }
+ }
+}
+
+sub fix_include_type($)
+{
+ my $srcfile = shift @_;
+ my $srcdir = dirname($srcfile);
+
+ open(I, "<$srcfile") || die "couldn't open $srcfile in _fix_include_type";
+ my @bracketincs = grep s/^\s*\#include\s*<([^>]+)>\s*$/$1/, <I>;
+ close(I);
+
+ foreach my $include (@bracketincs) {
+ next if (!(-r "$srcdir/$include"));
+ next if (grep (/^$include$/, @instheaders));
+ next if ($include eq "config.h"); # oh don't get me started on that
+
+ print "$srcfile: #include <$include> should use #include \"...\"\n";
+ &replace_include_type($srcfile, $include) if($modify);
+ }
+}
+
+# copies a file from src to dest, overwrites destination if exists
+sub copy_file($$)
+{
+ my $src = shift(@_);
+ my $dst = shift(@_);
+
+ open(I, "< $src") or die "copy_file: can't open $src for input\n";
+ my @fcontents = <I>;
+ close(I);
+ open(O, "> $dst") or die "copy_file: can't open $dst for output\n";
+ print O @fcontents;
+ close(O);
+}
+
+# interrupt handler for fix_unnecessary
+sub sighandler_fix_unnecessary()
+{
+ my($sig) = @_;
+ print "Caught a SIG$sig--shutting down after restoring $srcfile\n";
+ chdir($srcdir);
+ unlink $srcfile || warn "couldn't unlink $srcfile";
+ rename $localbackup, $srcfile || warn "couldn't rename $localbackup to $srcfile";
+ exit(1);
+}
+
+sub fix_unnecessary($)
+{
+ local $srcfile = shift @_;
+ local $srcdir = dirname($srcfile);
+
+ # find canonical path for srcdir
+ my $origdir = cwd;
+ chdir($srcdir);
+ $srcdir = cwd;
+ print "srcdir=$srcdir\n" if($verbose);
+
+ my $builddir = $srcdir;
+ my $makecmd = "make";
+ if (defined $ENV{"OBJ_REPLACEMENT"})
+ {
+ # we have to use sed here, because perl can't do s#a#b#
+ $builddir = `echo $srcdir | sed -e "\$OBJ_REPLACEMENT"`;
+ chomp $builddir;
+ $makecmd = "makeobj";
+ }
+ print "builddir=$builddir\n" if($verbose);
+
+ my $tot = $exp_success + $exp_failure;
+ print "=============== $srcfile (successes: $exp_success; total: $tot)\n";
+
+ $srcfile = basename($srcfile);
+
+ # first figure out some details
+ my @includes = &find_removable_includes($srcfile);
+
+ my $blanksrc = $srcfile;
+ $blanksrc =~ s/(.*)\.[^\.]+/$1/;
+
+ print "Checking for initial compilation: ";
+ chdir($builddir);
+ my $objextension = "BUG";
+ if($srcfile =~ /\.$hExt$/o) {
+ $output = `$makecmd all 2>&1`;
+ $objextension = "all" if ( 0 == ($? >> 8));
+ }
+ else {
+ unlink "$blanksrc.lo";
+ my $output = `$makecmd $blanksrc.lo 2>&1`;
+ $objextension = ".lo" if ( 0 == ($? >> 8));
+ if($objextension eq "BUG") {
+ print "failed with .lo... ";
+ unlink "$blanksrc.o";
+ $output = `$makecmd $blanksrc.o 2>&1`;
+ $objextension = ".o" if ( 0 == ($? >> 8));
+ }
+ if($srcfile =~ /$hExt/) {
+ $output = `$makecmd $blanksrc.o 2>&1`;
+ $objextension = ".o" if ( 0 == ($? >> 8));
+ }
+ }
+ if($objextension eq "BUG") {
+ warn "can't figure out right compile command for $srcfile :-(\n" .
+ "??? unused, or didn't compile in the first place?\n" .
+ "$output";
+ chdir($origdir);
+ exit 1;
+ }
+
+ print "worked with $objextension\n";
+
+ # now try to drop some includes
+ foreach $include (@includes) {
+ # kdatastream is special because
+ # it will break the application if removed even
+ # if it continues to compile
+ next if( $include eq "kdatastream.h");
+ # I also like to have kdebug.h still in
+ # so that it's easy to add kdDebug calls
+ next if( $include eq "kdebug.h");
+ # avoid this one as it might cause
+ # certain code parts to be disabled from compilation
+ next if( $include eq "qmodules.h");
+ # don't remove this one either. causes conditional
+ # code to be compiled incorrectly
+ next if( $include eq "kdeversion.h");
+ # don't remove the config.h include
+ # conditional code may depend on this file
+ next if( $include eq "config.h");
+ # check if it is its own header file
+ my $blankhdr = $include;
+ $blankhdr =~ s/(.*)\.[^\.]+/$1/;
+ next if ($blankhdr eq $blanksrc);
+
+ chdir($srcdir);
+
+ local $localbackup = $srcfile . "#fixkdeincludes";
+
+ # preserve timestamp if possible for CVS
+ unlink $localbackup;
+ rename $srcfile, $localbackup;
+ copy_file($localbackup, $srcfile);
+
+ # revert to backup in case of interrupt (Ctrl+C)
+ $SIG{'INT'} = \&sighandler_fix_unnecessary;
+
+ # check if it still compiles
+ if($verbose) {
+ chdir($builddir);
+ # testing headers? need to compile everything
+ if($objextension eq "all") {
+ # wait a second for makefile timestamp comparisons
+ sleep 1;
+ `$makecmd all 2>&1`;
+ }
+ else {
+ unlink "$blanksrc$objextension";
+ `$makecmd $blanksrc$objextension 2>&1`;
+ }
+ die "unexpected error $output\nexitcode=" . ($? >> 8) if($? >> 8);
+ chdir($srcdir);
+ }
+
+ # duplicates have to be nuked here , so it will be dropped maximum once
+ print "trying without $include: ";
+ &remove_include($srcfile, $include, 1);
+
+ chdir($builddir);
+
+ # try if it compiles
+ if($objextension eq "all") {
+ sleep 1;
+ $output=`$makecmd $objextension 2>&1`;
+ }
+ else {
+ unlink "$builddir/$blanksrc$objextension";
+ $output=`$makecmd $blanksrc$objextension 2>&1`;
+ }
+ my $retcode = ($? >> 8);
+ #print "retcode=$retcode\n$output" if ($verbose);
+
+ chdir($srcdir);
+ if($retcode == 0) {
+ # wow, it worked, lets continue!
+ print "SUCCESS!\n";
+ $SIG{'INT'} = 'DEFAULT';
+ unlink $localbackup;
+ $exp_success = $exp_success + 1;
+ }
+ else {
+ # is this a fixable error?
+ if($objextension eq "all" and
+ &extract_gcc_error($output) ne $srcfile) {
+ print "failed (error in " . &extract_gcc_error($output) . ")\n";
+ # FIXME: implement fixup of the compilation error
+ # so that we can be much more agressive in removing
+ # unneeded includes from headers
+ }
+ else
+ {
+ # better luck next time
+ print "FATALLY failed\n";
+ }
+ unlink $srcfile;
+ rename $localbackup, $srcfile;
+ $SIG{'INT'} = 'DEFAULT';
+
+ $exp_failure = $exp_failure + 1;
+ }
+ }
+
+ print "\n";
+
+ chdir($origdir);
+}
+
+sub process_source_file($)
+{
+ local $file = shift @_;
+ my $pure = basename($file);
+ print "Checking: $file\n" if($verbose);
+ &fix_include_type($file);
+ &fix_compat_includes($file);
+ &fix_duplicates($file);
+ &fix_unnecessary($file) if ($experimental && !grep (/^$pure$/, @instheaders));
+ print "\n" if ($verbose);
+}
+
+sub check_for_automake_srcdir($)
+{
+ my $dir = shift;
+
+ return 0 if !( -r "$dir/Makefile.am");
+ return 1 if !( -r "$dir/Makefile");
+
+ # ok, now its either srcdir with srcdir==builddir, or its builddir,
+ # which we don't want.
+
+ open(I, "<$dir/Makefile") || die "couldn't read $dir/Makefile";
+ while(<I>) {
+ if(/^srcdir\s*=\s*(\S+)/) {
+ close(I);
+
+ if($1 ne ".") {
+ print "Skipping build dir: $dir\n" if($verbose);
+ return 0;
+ }
+ return 1;
+ }
+ }
+
+ close(I);
+ # ok, this makefile isn't generated by automake, we don't want that
+ return 0;
+}
+
+#############################################################################
+# here is the main logic
+#
+
+# warn about modified files
+if($modify) {
+ `cvscheck | grep '^[MmC]'`;
+ print "WARNING: you have pending local changes. You might commit them by accident!\n\n" if($? >> 8 == 0);
+}
+
+if($experimental) {
+ print "WARNING: The experimental mode is indeed experimental.\n";
+ print "It tries to reduce includes by testing if it would compile\n";
+ print "without a particular include. It might introduce subtle bugs\n";
+ print "or break compilation for make check or make final.\n\n";
+ print "This operation mode is known to be unsafe. You've been warned.\n";
+}
+
+# process files from the command line, if any
+if ( $#explicitfiles >= 0 ) {
+ foreach $file( @explicitfiles ) {
+ &process_source_file( $file );
+ }
+ exit 0;
+}
+
+# first generate a list of subdirectories
+@dirlist = ();
+push @dirlist, "." if (&check_for_automake_srcdir("."));
+die "current directory isn't srcdir!" if (!scalar @dirlist);
+foreach $dir ( @dirlist ) {
+ opendir (DIR, "$dir") || warn "Couldn't read '$dir'";
+ my $subdir = "";
+ while( $subdir = readdir(DIR)) {
+ next if ($subdir =~ /^\./);
+ next if !( -d "$dir/$subdir");
+ next if (! &check_for_automake_srcdir("$dir/$subdir"));
+
+ push @dirlist, "$dir/$subdir";
+ }
+ closedir(DIR);
+}
+
+# now iterate over all subdirs
+foreach $dir(@dirlist) {
+
+ # check if this directory wants not to be fixed
+ if(open(M, "$dir/Makefile.am")) {
+ my @mcontents = grep /(\-UQT_NO_COMPAT|\-UKDE_NO_COMPAT)/, <M>;
+ close(M);
+ if ( @mcontents ) {
+ print "Skipping directory: $dir\n";
+ next;
+ }
+ }
+
+ @headers = &find_fixable_headers($dir);
+ @instheaders = &find_installed_headers($dir);
+ foreach $file(@headers) {
+ &process_source_file($file);
+ }
+ @sources = &find_fixable_sources($dir);
+ foreach $file(@sources) {
+ &process_source_file($file);
+ }
+}