#!/usr/bin/perl -w

my $batchmode = 0;
my $debug = 0;
if ($ARGV[0] eq "--batchmode") {
   $batchmode = 1;
   shift;
}
if ($ARGV[0] eq "--debug") {
   $debug = 1;
   shift;
}

my $filename = $ARGV[0];
$filename =~ s/^.*\///g;
my @PATCHES;
my @PATCHES_COMMENTED;
my @APPLIED;
my $errors = 0;

my $col_red = "";
my $col_yel = "";
my $col_norm = "";

unless ($batchmode) {
    $col_red = "[1;31m";
    $col_yel = "[0;33m";
    $col_norm = "[m";
}

while (<>) {
   if (/^(#\s*)?[Pp]atch[0-9\s]*:/) {
	my ($front,$back) = split(":",$_,2);
	my $commented = ($front =~ /^#/) ? 1 : 0;
	$front =~ s/^(#\s*)?[Pp]atch//;
	$front =~ s/\s*$//;
	$front = 0 unless $front;
	$back =~ s/\s*$//;
	$back =~ s/^\s*//;
	$back =~ s/^.*\///g;
	$PATCHES[$front] = $back;
	$PATCHES_COMMENTED[$front] = 1 if $commented;
	next;
    }
   if (/^%auto(?:setup|patch)\b/) { # automatically applies all patches
	exit(0);
   }
   if (/^([#\s]*)?%[Pp]atch/ || /^#[Pp]atch/) {
	my $applied = (/^#/) ? 2 :1;
	my @line = split (/\s+/,$_);
	my $had_P = grep {/^-P/} @line;
	while (@line) {
		my $arg = shift (@line);
		if ($arg eq "-P") {
			$arg = shift (@line);
			if ($arg =~ /^[0-9]/) {
				$APPLIED[$arg] = $applied;
			} else {
				print STDERR "$col_red(E) %patch -P without following numeric argument$col_norm\n";
				print STDERR "line was $_\n" if $debug;
				$errors++;
			}
		} elsif ($arg =~ /^-P/) {
			$arg =~ s/^-P//;
			if ($arg =~ /^[0-9]/) {
				$APPLIED[$arg] = $applied unless $APPLIED[$arg];
			} else {
				print STDERR "$col_red(E) %patch -P without following numeric argument$col_norm\n";
				print STDERR "line was $_\n" if $debug;
				$errors++;
			}
		} elsif ($arg =~ /^([#\s]*)?%[Pp]atch$/) {
			unless ($had_P) {
				$arg = 0;
				$APPLIED[$arg] = $applied unless $APPLIED[$arg];
			}
		} elsif ($arg =~ /^([#\s]*)?%?patch[^-]/ || $arg =~ /^([#\s]*)?%?Patch[^-].*:.*/) {
			unless ( /^\s*#patches/ ) {
			$arg =~ s/^([#\s]*)?%?[Pp]atch//;
			if ($arg =~ /^[0-9]/) {
				$APPLIED[$arg] = $applied unless $APPLIED[$arg];
			} else {
				print STDERR "$col_red(E) %patchZZZ without following numeric argument$col_norm\n";
				print STDERR "line was $_\n" if $debug;
				$errors++;
			}
			}
		}
	}
	next;
   }
   if (/%\{?(PATCH|Patch|patch|P:)[0-9]+\}?/) {
	$_ =~ s/^.*%\{?(PATCH|Patch|patch|P:)//;
	$_ =~ s/^([0-9]*).*$/$1/;
	$APPLIED[$_] = 3 if (/[0-9]+/ && !$APPLIED[$_]);
   }
}

for my $i (1...$#PATCHES) {
	next unless $PATCHES[$i];
	next if $APPLIED[$i] && $APPLIED[$i] == 1;
        if ($APPLIED[$i] && $APPLIED[$i] == 2) {
		print STDERR "$col_yel(W) $filename: patch $i $PATCHES[$i] is commented out$col_norm\n";
		next;
	}
        if ($APPLIED[$i] && $APPLIED[$i] == 3) {
		print STDERR "$col_yel(W) $filename: patch $i $PATCHES[$i]: mentioned in specfile but not applied via %patch$col_norm\n";
		next;
	}
        if ($PATCHES_COMMENTED[$i]) {
		print STDERR "$col_yel(W) $filename: patch $i $PATCHES[$i]: is commented out$col_norm\n";
                next;
	}
	print STDERR "$col_red(E) $filename: patch $i $PATCHES[$i] apparently not applied (or not applied via %patch)$col_norm\n";
	$errors++;
}
for my $j (1...$#APPLIED) {
	next unless $APPLIED[$j];
	next if $APPLIED[$j];
	next if $PATCHES[$j] == 2;
	print STDERR "$col_red(E) $filename: patch number $j referenced but not defined$col_norm\n";
	$errors++;
}

exit ($errors > 0);

