#!/usr/bin/perl

# this script is written by Stephan Kulow <coolo@kde.org> with
# much help from Sirtaj Singh Kang <ssk@physics.unimelb.edu.au>

%files = ();

if ($ARGV[0]) {
  $topdir = $ARGV[0];
} else {
  $topdir=`pwd`;
}
chomp $topdir;

$lastdir = '.';


# this is the important part. Left from the '=>' you find the regular
# expression for the g++ output and right from '=>' the header file to
# include
%messages = 
(
 'warning: implicit declaration of function `int i18n\(\.\.\.\)\'' => "klocale",
 '`i18n\' undeclared \(first use this function\)' => "klocale",
 'variable `class QPixmap \S*\' has initializer but incomplete type' => "qpixmap",
 '`kapp\' undeclared \(first use this function\)' => "kapp",
 'no matching function for call to `KLocale::' => "klocale",
 '`klocale\' undeclared \(first use this function\)' => "klocale",
 'no matching function for call to `QPopupMenu::' => "qpopupmenu",
 '`QTextStream\' undeclared \(first use this function\)' => "qtextstream",
 '`QTextStream\' was not declared in this scope' => "qtextstream",
 'incomplete type `QSocketNotifier\'' => "qsocketnotifier",
 'no matching function for call to `KConfig' => "kconfig",
 'variable `class KConfig \S*\' has initializer but incomplete type' => "kconfig",
 'warning: implicit declaration of function `int kdDebug' => "kdebug",
 'warning: implicit declaration of function `int kdWarning' => "kdebug",
 '`QFile\' undeclared \(first use this function' => "qfile",
 'type `KConfigBase\' is not a base type for type `KConfig' => "kconfig",
 'invalid use of undefined type `class QAccel' => "qaccel",
 'aggregate `class KConfig \S*\' has incomplete type' => "kconfig",
 '`stderr\' undeclared \(first use this function' => "stdio",
 'invalid use of undefined type `class KConfig' => "kconfig",
 'warning: implicit declaration of function `int f?printf' => "stdio",
 'no method `KGlobal::' => "kglobal",
 '`KGlobal\' undeclared \(first use this function\)' => "kglobal",
 'warning: implicit declaration of function `int locate\(\.\.\.\)' => "kstddirs",
 '`locate\' undeclared \(first use this function\)' => "kstddirs",
 'no matching function for call to `KStandardDirs' => "kstddirs",
 'no method `KStandardDirs::' => "kstddirs",
 'variable `class QFile \S*\' has initializer but incomplete type' => "qfile",
 'warning: implicit declaration of function `int ICON\(\.\.\.\)' => "kiconloader",
 '`QMessageBox\' undeclared \(first use this function\)' => "qmessagebox",
 'no matching function for call to `QBoxLayout::QBoxLayout' => "qlayout",
 '`QUriDrag\' undeclared \(first use this function\)' => "qdragobject",
 'no matching function for call to `KMenuBar::' => "kmenubar",
);

%changes = ();

while(<>)
{
  if (/make.*Entering directory \`(.+)\'/) {
    $lastdir = $1;
    $lastdir =~ s/^$topdir\///;
    print STDERR "entering $lastdir\n";
    next;
  }
  if (/^([^:]*):\d*: (.*)$/) {
    $file = $1;
    $line = $2;
    if ($file !~ m,^\/,) {
      $file = "$lastdir/$file";
    }
    
  } else {
    print STDERR $_;
    next;
  }
  
  next if defined($changes{$file});

  print STDERR $_;

  foreach $message (keys %messages) {
    if ($line =~ /$message/) {
      $changes{$file} = $messages{$message};
      fixFile($file, $messages{$message});
    }
  }
  
}

sub fixFile
{
  my( $file, $adding ) = @_;
  
  my $lastinclude = "";

  # read file
  open ( FILE, "$file" ) || die "Can't read $file";
  
  my $flines;
  my $cpplevel = 0;

  while (<FILE>) {
    $flines .= $_;
    if ($_ =~ m/^#if/) {
       $cpplevel = $cpplevel + 1;
    }
    if ($_ =~ m/^#endif/) {
       $cpplevel = $cpplevel - 1;
    }
    if ($cpplevel == 0 && $_ =~ m/^(#include\s*[\"<]\S*\.h[\">]\S*)/) {
       $lastinclude = $1;
    }
  }
  
  close FILE;
  
  my $success;

  if (!$lastinclude) {
    print STDERR "ERROR: no include found!\n";
    return;
  }

  if ($flines =~ m/#include\s*[\"<]$adding\.h[\">]\s*\n/) {
    print STDERR "ERROR: $adding.h already included!\n";
    $success = 0;
    return;
  }
  if ($flines =~ /(\n$lastinclude)/) {
    $flines =~ s/$lastinclude/$lastinclude\n#include <$adding.h>/;
      print STDERR "ADDED after \"$lastinclude\" $adding.h\n";
    $success = 1;
  } else {
    print STDERR "ERROR: can't find $lastinclude in $file\n";
    $success = 0;
  }
	    
  return if (!$success);
      
  # write file
      
  rename($file, "$file.old");
  open( FILE, ">$file" ) || die "Can't write to $file";
  print FILE $flines;    
  close FILE;
}
