-rwxr-xr-x | scripts/cvscheck | 344 | ||||
-rwxr-xr-x | scripts/fixincludes | 61 |
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); } } |