summaryrefslogtreecommitdiff
path: root/scripts
Side-by-side diff
Diffstat (limited to 'scripts') (more/less context) (ignore whitespace changes)
-rwxr-xr-xscripts/cvscheck344
-rwxr-xr-xscripts/fixincludes61
2 files changed, 347 insertions, 58 deletions
diff --git a/scripts/cvscheck b/scripts/cvscheck
new file mode 100755
index 0000000..1b7ba0b
--- a/dev/null
+++ b/scripts/cvscheck
@@ -0,0 +1,344 @@
+#!/usr/bin/perl
+
+use POSIX qw(mktime ctime);
+use Time::Local qw( timegm );
+
+# Offline check for status of files in a checked-out
+# CVS module.
+# Dirk Mueller <mueller@kde.org> Oct 2001
+
+# based on cvschanged by
+# Sirtaj Singh Kang <taj@kde.org> Nov 1998.
+
+if ( defined $ARGV[0] && $ARGV[0] eq "--help") {
+ print "cvscheck (c) 2001 Dirk Mueller <mueller\@kde.org>\n\nUsage:\n";
+ print " cvscheck <dir>\n\n";
+ print "Prints information about the status of your local CVS checkout without\n";
+ print "communicating with the server (therefore in speed only limited by your\n";
+ print "hard-disk throughput, much unlike cvs -n up).\n\n";
+ print "Every file is printed with a status character in front of its name:\n";
+ print "? foobar.c file is not known to CVS - maybe you should add it?\n";
+ print "M foobar.c file is for sure locally modified.\n";
+ print "m foobar.c file *might* have local changes (needs a diff with the server).\n";
+ print "C foobar.c file has a CVS conflict and therefore cannot be committed.\n";
+ print "U foobar.c file is in CVS but its somehow missing in your local checkout.\n";
+ print "T foobar.c file has an unusual sticky CVS tag.\n";
+ print "A foobar.c you cvs add'ed this file but did not yet commit.\n";
+ print "R foobar.c you cvs rm'ed this file but did not yet commit.\n";
+
+ exit;
+}
+
+# default is HEAD
+$standardtag = "";
+@dirqueue = @ARGV;
+@merged = ();
+@uncommitted = ();
+@missing = ();
+@tagged = ();
+@removed = ();
+@unknown = ();
+@modified = ();
+@conflicts = ();
+
+@monthlist = ( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec" );
+%months = ();
+
+# convert text stamp to GMT
+sub strToTime
+{
+ my( $timestr ) = @_;
+
+ if( ! ($timestr =~
+ /^(\w+)\s*(\w+)\s*(\d+)\s*(\d+):(\d+):(\d+)\s*(\d+)/) ) {
+
+ return -1;
+ }
+
+ # CVS timestamps are in GMT.
+
+ my( $tm ) = timegm( $6, $5, $4, $3, $months{ $2 }, $7 - 1900);
+
+ return $tm;
+}
+
+sub processEntries
+{
+ my ( $dir ) = @_;
+ my %dirunknown = ();
+
+ opendir (DIR, "$dir") || warn "Couldn't read '$dir'";
+ # first assume all are unknown
+ while ( $e = readdir(DIR) ) {
+ next if ($e eq ".");
+ next if ($e eq "..");
+ next if ($e eq "RCS");
+ next if ($e eq "SCCS");
+ next if ($e eq "CVS");
+ next if ($e eq "CVS.adm");
+ next if ($e eq "RCSLOG");
+ next if ($e eq "tags");
+ next if ($e eq "TAGS");
+ next if ($e eq ".make.state");
+ next if ($e eq ".nse_depinfo");
+ next if ($e eq "core");
+ next if ($e eq ".libs");
+ next if ($e eq ".deps");
+ next if ($e =~ /^.+~$/);
+ next if ($e =~ /^\#.+$/);
+ next if ($e =~ /^\.\#.+$/);
+ next if ($e =~ /^,.+$/);
+ next if ($e =~ /^_\$.+$/);
+ next if ($e =~ /^.+\$$/);
+ next if ($e =~ /^.+\.old$/);
+ next if ($e =~ /^.+\.bak$/);
+ next if ($e =~ /^.+\.BAK$/);
+ next if ($e =~ /^.+\.orig$/);
+ next if ($e =~ /^.+\.rej$/);
+ next if ($e =~ /^\.del-.+$/);
+ next if ($e =~ /^.+\.a$/);
+ next if ($e =~ /^.+\.olb$/);
+ next if ($e =~ /^.+\.o$/);
+ next if ($e =~ /^.*\.obj$/);
+ next if ($e =~ /^.+\.so$/);
+ next if ($e =~ /^.+\.Z$/);
+ next if ($e =~ /^.+\.elc$/);
+ next if ($e =~ /^.+\.ln$/);
+ next if ($e =~ /^cvslog\..*$/);
+
+ # kde specific entries
+ # TODO read from CVSROOT/cvsignore !
+ next if ($e eq "config.cache");
+ next if ($e eq "config.log");
+ next if ($e eq "config.status");
+ next if ($e eq "index.cache.bz2");
+ next if ($e eq ".memdump");
+ next if ($e eq "autom4te.cache");
+ next if ($e eq "autom4te.cache");
+ next if ($e eq "Makefile.rules.in");
+ next if ($e =~ /^.*\.moc$/);
+ next if ($e =~ /^.+\.gmo$/);
+ next if ($e =~ /^.+\.moc\.[^\.]+$/);
+ next if ($e =~ /^.+\.lo$/);
+ next if ($e =~ /^.+\.la$/);
+ next if ($e =~ /^.+\.rpo$/);
+ next if ($e =~ /^.+\.closure$/);
+ next if ($e =~ /^.+\.all_cpp\.cpp$/);
+ next if ($e =~ /^.+\.all_C\.C$/);
+ next if ($e =~ /^.+\.all_cc\.cc$/);
+ next if ($e =~ /^.+_meta_unload\.[^\.]+$/);
+ next if ($e =~ /^.+\.kidl$/);
+ next if ($e =~ /^.+_skel\.[^\.]+$/);
+ next if ($e eq "Makefile.rules.in");
+
+ $dirunknown{$e} = 1;
+ }
+ closedir(DIR);
+ if( open(CVSIGNORE, $dir."/.cvsignore") ) {
+ while(<CVSIGNORE>) {
+ next if (! /^(\S+)\s*$/ );
+ my $entry = $1;
+ if ($entry =~ /[\*\?]/) {
+ my $pattern = quotemeta $entry;
+ $pattern =~ s/\\\*/.*/g;
+ $pattern =~ s/\\\?/./g;
+ foreach $m (keys (%dirunknown)) {
+ $dirunknown{$m} = 0 if ($m =~ /^$pattern$/);
+ }
+ next;
+ }
+ $dirunknown{$entry} = 0;
+ }
+ close(CVSIGNORE);
+ }
+
+ if ( !open( ENTRIES, $dir."/CVS/Entries" ) ) {
+ print "I CVS/Entries missing in $dir\n";
+ return;
+ }
+ my $oldstandardtag = $standardtag;
+ my $staginfo = "";
+ if( open(CVSTAG, $dir."/CVS/Tag" ) ) {
+ my $line = <CVSTAG>;
+ if($line =~ /^[TN](.+)$/) {
+ $standardtag = $1;
+ $staginfo = $1;
+ }
+ else {
+ # something with D - assume HEAD
+ $oldstandardtag = $standardtag = ""; # its HEAD
+ print "I $dir has sticky date: $line\n";
+ }
+ close(CVSTAG);
+ }
+ else {
+ $standardtag = ""; # its HEAD
+ $staginfo = "(HEAD)";
+ }
+ print "I $dir has sticky tag $staginfo\n" if($standardtag ne $oldstandardtag);
+ while( <ENTRIES> ) {
+ if ( m#^\s*D/([^/]+)/# ) {
+ push ( @dirqueue, "$dir/$1" ) if (-d "$dir/$1");
+ $dirunknown{$1} = 0;
+ next;
+ }
+
+ next if !m#^\s*/([^/]+)/([-]*[\d\.]*)/([^/]+)/([^/]*)/(\S*)$#;
+ $fname = $1;
+ $ver = $2;
+ $stamp = $3;
+ $options = $4;
+ $tag = $5;
+ $tag = $1 if ($tag =~ /^T(.+)$/);
+
+ $dirunknown{$fname} = 0;
+
+ my $taginfo="";
+ if ( $tag ne $standardtag ) {
+ if ($tag eq "") {
+ $taginfo = " (HEAD)";
+ }
+ else {
+ $taginfo = " ($tag)";
+ }
+ }
+ if ($options =~ /^\-k(.)$/) {
+ $taginfo .= " (no RCS-tags)" if($1 eq "o" or $1 eq "b");
+ $taginfo .= " (RCS values only)" if($1 eq "v");
+ $taginfo .= " (RCS keywords only)" if($1 eq "k");
+ }
+ my $state = $stamp;
+ if( $stamp =~ m(^(.+)\+(.+)$) ) {
+ $state = $1;
+ $stamp = $2;
+ }
+ if ( $state =~ /merge/ ) {
+ # modified version merged with update from server
+ # check for a conflict
+ if ( open (F, "$dir/$fname") ) {
+ my @conflict = grep /^<<<<<<</, <F>;
+ close (F);
+ if( @conflict ) {
+ push @conflicts, "$dir/$fname$taginfo";
+ next;
+ }
+ }
+ else {
+ push @missing, "$dir/$fname$taginfo";
+ next;
+ }
+ }
+ if ( $ver =~ /^\-.*/ ) {
+ push @removed, "$dir/$fname$taginfo";
+ next;
+ }
+ $mtm = strToTime( $stamp );
+ if( $mtm < 0 ) {
+ if ( $ver eq "0" ) {
+ push @uncommitted, "$dir/$fname$taginfo";
+ }
+ else {
+ push @merged, "$dir/$fname$taginfo";
+ }
+ next;
+ }
+ @sparams = lstat( "$dir/$fname" );
+
+ if ( $#sparams < 0 ) {
+ push @missing, "$dir/$fname$taginfo";
+ next;
+ }
+ if( $mtm < $sparams[ 9 ] ) {
+ push @modified, "$dir/$fname$taginfo";
+ next;
+ }
+ if ( $tag ne $standardtag ) {
+ push @tagged, "$dir/$fname$taginfo";
+ }
+ }
+ close( ENTRIES );
+
+ my @unknownlist = sort keys (%dirunknown);
+ foreach $entry (@unknownlist) {
+ next if ($dirunknown{$entry} == 0);
+ # ignore unusual files
+ next if (-l "$dir/$entry" );
+ # ifnore if its a directory in CVS
+ next if (-d "$dir/$entry" and -d "$dir/$entry/CVS");
+ push @unknown, "$dir/$entry";
+ }
+}
+
+# month assoc array for name -> index lookups
+$mctr = 0;
+
+foreach $month ( @monthlist ) {
+ $months{ $month } = $mctr;
+ $mctr++;
+}
+
+# Try current directory if none specified
+
+if( $#dirqueue < 0 ) {
+ push( @dirqueue, "." );
+}
+
+# process directory queue
+foreach $dir ( @dirqueue ) {
+ processEntries( $dir );
+}
+
+foreach $f ( @unknown ) {
+ $f =~ s/^\.\///;
+ print "? $f\n";
+}
+
+foreach $f( @modified ) {
+ $f =~ s/^\.\///;
+ print "M $f\n";
+}
+
+foreach $f ( @missing ) {
+ $f =~ s/^\.\///;
+ print "U $f\n";
+}
+
+foreach $f ( @merged ) {
+ $f =~ s/^\.\///;
+ print "m $f\n";
+}
+
+foreach $f ( @tagged ) {
+ $f =~ s/^\.\///;
+ print "T $f\n";
+}
+
+foreach $f ( @uncommitted ) {
+ $f =~ s/^\.\///;
+ print "A $f\n";
+}
+
+foreach $f ( @removed ) {
+ $f =~ s/^\.\///;
+ print "R $f\n";
+}
+
+foreach $f ( @conflicts ) {
+ $f =~ s/^\.\///;
+ print "C $f\n";
+}
+
+
+=head1 NAME
+
+cvscheck -- Lists all files in checked out CVS modules that have been
+edited or changed locally. No connection is required to the CVS server,
+therefore being extremely fast.
+
+=head1 AUTHOR
+
+Dirk Mueller <mueller@kde.org>
+based on cvschanged by Sirtaj Singh Kang <taj@kde.org>
+
+=cut
diff --git a/scripts/fixincludes b/scripts/fixincludes
index da8613c..f07965e 100755
--- a/scripts/fixincludes
+++ b/scripts/fixincludes
@@ -1,587 +1,532 @@
#!/usr/bin/perl -w
# tries to reduce the number of includes in KDE source files
# (c) 2001 Dirk Mueller <mueller@kde.org>
use File::Basename;
use Cwd;
# declaration of useful subroutines
sub find_fixable_sources ($);
sub find_fixable_headers($);
sub find_removable_includes ($);
sub warn_before_modifying ($);
sub remove_include ($$$);
sub replace_include ($$$);
sub fix_duplicates($);
sub fix_compat_includes($);
sub fix_unnecessary($);
sub copy_file($$);
sub process_source_file($);
# 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!!)
+$verbose = 1; # turns on debugging
+$modify = 1; # if 1 it should try to fix the files as well
+$experimental = 1; # 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: fixincludes [--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",
);
# 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;
}
# 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 ($cpplevel == 0 && $level > 0 && $line =~ m/^\#include\s*[\"<]$include[\">]\S*$/) {
if ($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*/) {
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);
}
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 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);
}
}
}
# 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";
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($objextension eq "BUG") {
warn "can't figure out right compile command for $srcfile :-(\n??? unused, or didn't compile in the first place?\n";
warn "$output";
chdir($origdir);
return;
}
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");
# check if it is its own header file
my $blankhdr = $include;
$blankhdr =~ s/(.*)\.[^\.]+/$1/;
next if ($blankhdr eq $blanksrc);
chdir($srcdir);
local $localbackup = $srcfile . "#fixincludes";
# 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);
unlink "$builddir/$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
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 {
# better luck next time
print "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 @_;
print "Checking: $file\n" if($verbose);
&fix_compat_includes($file);
&fix_duplicates($file);
if ($experimental) {
&fix_unnecessary($file);
}
print "\n" if ($verbose);
}
# 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" if($? >> 8 == 0);
}
# 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 = (".");
foreach $dir ( @dirlist ) {
opendir (DIR, "$dir") || warn "Couldn't read '$dir'";
my $subdir = "";
while( $subdir = readdir(DIR)) {
next if ($subdir =~ /^\..*/);
push @dirlist, "$dir/$subdir" if ( -d "$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);
foreach $file(@headers) {
print "Checking: $file\n" if($verbose);
&fix_compat_includes($file);
&fix_duplicates($file);
}
@sources = &find_fixable_sources($dir);
foreach $file(@sources) {
&process_source_file($file);
}
}