#!/bin/perl

sub Usage {
    print "usage: check-output [-Dlevel] number wanted-size [been-thru]\n";
    exit 1;
}

&Usage if ($ARGV[0] eq '');

if ($ARGV[0] =~ /^-D/) { $DEBUG = $'+0; shift; }

$want_size = $ARGV[0]+0; shift;
$want_number = $ARGV[0]+0; shift;
$want_filters = ($#ARGV != -1) ? $ARGV[0] : ''; shift;

&Usage if ($want_size == 0 || $want_number == 0);

$exitstatus = 0;
$size = 0;
$lines_per_page = 66;
@found_filters = ();
while (<>) { push (@FILE, $_); }

###########################################################################

sub strip_filters {
    local ($FILTER) = $_[0];
    local ($strip_str);

    while ($FILE[0] =~ s/^${FILTER}: //) {
	push(@found_filters, $FILTER);
	$strip_str .= "$FILTER: ";
    }

    # now strip the prefix off all the lines
    eval 'for $_ (0 .. ' . $#FILE . ') { $FILE[$_] =~ s/^' . $strip_str . '//g; }';
}

sub found_something {
    local ($_) = $_[0];
    ($ALREADY_GOT{$_}) || push (@found_filters, $_);
    $ALREADY_GOT{$_}++;
}

sub check_banner_lines {
    local ($start_of_banner) = $_[0];
    local ($linecount, $banner_pagenum, $i, $len, $long_banner);

    $long_banner = 1;
    for    ($i = $start_of_banner, $linecount = 1, $len = $#FILE,
		$banner_pagenum = $PAGE[$i];
	    ($i <= $len) && ($linecount <= $lines_per_page) &&
	   	($PAGE[$i] == $banner_pagenum);
	    $i++, $linecount++)
    {
	$_ = $FILE[$i];
	next if (/^[ Xo#*]*$/);		# skip big banner lines
	next if (/^\*+ SEQ .*$/);	# skip w_stef's banner

	if (/^\*\*\* ([be]p): /) {	# "bp" program output
	    &found_something ($1);
	    $long_banner = 0;
	    next;
	}

	&found_something ("banner");
	/^User: / && next;
	/^Date: / && next;
	/^Job: / && next;
	/^Class: / && next;
	chop; printf "[banner: %s] ", $_;
	$exitstatus = 5;
    }
    $linecount--;			# the last one doesn't count
    if ($long_banner && ($linecount != $lines_per_page - 1)) {
	printf "[banner length: %d != wanted %d] ", $linecount, $lines_per_page - 1;
	$exitstatus = 6;
    }
    $i - 1;
}

sub strip_banner {
    local ($i, $len);

    @NEWFILE = ();
    for ($i = 0, $len = $#FILE; $i <= $len; $i++) {
	$_ = $FILE[$i];

	if (/^\*+/) {
	    if ($PAGE_ROW[$i] != 0) {
		printf "[banner not at start-of-page] ";
		$exitstatus = 7;
	    }
	    # stars = start of big banner; invoke check_banner_lines
	    # and skip past the banner page completely.
	    $i = &check_banner_lines ($i);

	} elsif (/^\S+:\S+\s+Job: /) {	# "sb" short banner
	    &found_something ("sb");
	    next;

	} else {
	    push (@NEWFILE, $_);
	}
    }
    @FILE = @NEWFILE;		# replace with new version (no banners)
}

sub dbg_print {
    local ($label, $linecount, $pagecount, $_) = @_;

    return unless ($DEBUG);
    chop; s/^(.{30}).*$/\1/ && ($_ .= " (etc.)");
    printf "$label:%s>%2d,%2d>%s\n",
	($linecount % $lines_per_page == 0) ? '%' : ' ',
	$linecount, $pagecount, $_;
}

sub strip_formfeeds {
    local ($linecount);
    local ($i, $len);
    local (@NEWFILE) = ();

    for    ($i = 0, $linecount = 0, $len = $#FILE, $non_empty = 0, $pagecount = 1;
	    $i <= $len; $i++)
    {
	$_ = $FILE[$i];

	if ($linecount % $lines_per_page == 0) {
	    $linecount = 0;
	}

	if ($_ =~ /^__MULTI_SEPERATOR__$/) {
	    $linecount = 0; next;
	}

	while (s/^//g) {
	    $preff = $`;
	    $pagecount++;

	    if ($preff eq '') {
		if (!$non_empty) {
		    printf "[empty page %d]\n", $pagecount - 1;
		    $exitstatus = 9;
		}
	    } else {
		&dbg_print ("strip-ff", $linecount, $pagecount, $preff);
		push (@NEWFILE, $preff);
		$PAGE_ROW[$i] = $linecount++;
		$PAGE[$i] = $pagecount;
	    }
	    $linecount = 0;
	    $non_empty = 0;
	}

	if ($_ !~ /^$/) {
	    $non_empty++;
	}
	&dbg_print ("strip-ff", $linecount, $pagecount, $_);
	push (@NEWFILE, $_); $PAGE_ROW[$i] = $linecount++;
	$PAGE[$i] = $pagecount;
    }

    if (!$non_empty && ($pagecount != 1) && ($linecount != 0)) {
	print "[blank page $pagecount] ";
	$exitstatus = 10;
    }
    @FILE = @NEWFILE;
}

sub strip_bin_pr {
    # pretty crude pr fixer -- deletes blank lines completely.
    local ($found_pr_header) = 0;
    local (@NEWFILE) = ();

    for ($i = 0, $len = $#FILE; $i <= $len; $i++) {
	$_ = $FILE[$i];

	/^$/ && next;
	if (/^... .. ..:.. ....\s+\S+ Page \d+\s*$/) {
	    # this is a pr header -- note that we found it.
	    $found_pr_header = 1;
	    next;
	}
	push (@NEWFILE, $_);
    }

    if ($found_pr_header) {
	push(@found_filters, "pr");
	@FILE = @NEWFILE;
    }
}

###########################################################################
# strip the filters and check the banners

&strip_filters ("lp");
&strip_filters ("of");
&strip_formfeeds;
if ($DEBUG > 1) {
    for ($i = 0, $len = $#FILE; $i <= $len; $i++) {
	&dbg_print ("prestrip", $PAGE_ROW[$i], $PAGE[$i], $FILE[$i]);
    }
}
&strip_banner;
&strip_filters ("if");
&strip_filters ("fe");
&strip_filters ("pr");
&strip_bin_pr;

###########################################################################
if ($DEBUG) {
    for ($i = 0, $len = $#FILE; $i <= $len; $i++) {
	&dbg_print ("final", $PAGE_ROW[$i], $PAGE[$i], $FILE[$i]);
    }
}

###########################################################################
# check to see if any filters were not used

if ($#found_filters >= 0) {
    $filters = join (',', @found_filters);
    if ($filters ne $want_filters) {
	printf "[mismatch: \"%s\" != wanted \"%s\"] ", $filters, $want_filters;
	$exitstatus = 4;
    }
}

###########################################################################
# check to see that its size matches (after we've stripped off the
# banners, filters, formfeeds etc.)

for $_ (@FILE) { $size += length ($_); }
$wanted = $want_size * $want_number;
if ($size < $wanted) { print "[too small: $size < $wanted] "; $exitstatus = 2; }
if ($size > $wanted) { print "[too big: $size > $wanted] "; $exitstatus = 3; }

###########################################################################
# check for coredumps in the spool directory

$coreloc = "spool/".$ENV{'PRINTER'}."/core";
if (-f $coreloc) {
    $newcore = "core.".$ENV{'PRINTER'};
    rename ($coreloc, $newcore);
    print "[dumped core ($newcore)] "; $exitstatus = 5;
}

###########################################################################
# check to see if any log messages were produced

$logmsgs = "";
open (LOG, "< spool/LOG");
while (<LOG>) {
    / \([A-Z]+\) / || next;	# needs to be a non-debug message
    s/^/  /g; $logmsgs .= $_;
}
close LOG;

if ($logmsgs ne "") {
  print "[errors:]\n", $logmsgs, "  ... ";
  $exitstatus = 1;
}

exit $exitstatus;
