#!/afs/athena/contrib/perl/p

#
# Requires
#
unshift(@INC, '/afs/sipb/user/mkgray/bin');
require 'getopts.pl';
require 'report-types.pl';
require 'presentation-types.pl';

#
# Main
#
$ConfigFile = 'wr.conf';
&Getopts('c:');
$ConfigFile = $opt_c if $opt_c;

$RawConfig = &RawReadConfig;
&ParseConfig($RawConfig);
$parser = &ConstructParser($splitline);
eval($parser);
print $@;

#
# Subroutines
#
sub RawReadConfig {
    local($rawfile);

    open(CF, $ConfigFile)||die("Can't find config file $ConfigFile\n");
    while(<CF>){
	next if /^#/;

	$rawfile.= $_;
    }
    $rawfile;
}

sub ParseConfig {
    local($config) = @_;

    ($header, @reports) = split(/\n\n/, $config);
    $header =~ /LogFileFormat (.+)/;
    $fmtstring = $1;

    $_excludes = '0 ';

    while($header =~ /Exclude (\w+) (.+)/g){
	$var = $1; $pat = $2;
	$c = ($pat=~/^!/) ? "!":"=";
	$pat = substr($pat, 1) if $pat=~/^!/;
	$_excludes .= "|| (\$$var $c"."~ $pat) ";
    }

    if($fmtstring eq "Common"){
	$splitline = 
	    '($host, $crap, $from, $time, $zone, $method, $path, $version, $code, $size) = ($_=~/([^ ]+) ([^ ]+) ([^\[])+\[([^ ]+) ([^\]]+)\] \"([^ ]+) ([^ ]+) ([^\"]+)\" (\d+) (\d+)/);';
#	$splitline .= "print \"\$host got \$path\\n\";";
    }
    else{
	$splitline = "($fmtstring) = split;";
    }

    for $report (@reports){
	$excludes = "0 ";
	$report=~/Report (\w+) (\w+) ?(.*)/ || 
	    die "No Report in record in $ConfigFile";
	$name = $1;
	$type = $2;
	$opts = $3; @opts=split(' ', $opts);

	while($report=~/Exclude (\w+) (.+)/g){
	    $var = $1; $pat = $2;
	    $c = ($pat=~/^!/) ? "!":"=";
	    $pat = substr($pat, 1) if $pat=~/^!/;
	    $excludes .= "|| (\\\$$var $c"."~ $pat) ";
	}
	eval("\$$name"."_excludes = \"$excludes\"");

	while($report =~ /Present (\w+) (.+)/g){
	    $presentmethod = $1; $opts = $2;
	    $presentations{$name} .= "$presentmethod:$opts\n";
	}


	$1='';
	if($report=~/Title (.+)/){
	    $Title{$name} = $1;
	}
	else{
	    $Title{$name} = "Report (No Title)";
	}

	&AddReporter($name, $type, @opts);
    }

}

sub ConstructParser {
    local($splitline) = @_;
    local($code)='';

    $code .= "##### Initial Block\n";
    $code .= join("\n", @initialblock)."\n";
    $code .= "##### End Initial Block\n\n";

    $code .= "##### Main loop\n";
    $code .= "while(<>){"."\n";
    $code .= "$splitline"."\n";
    $code .= "if(!\$last_time){ \$first_time = \"\$month \$day \$time\"; }",
    "\n";
    $code .= "\$last_time = \"\$month \$day \$time\";", "\n";
    $code .= "next if ($_excludes);"."\n";
    $code .= join("\n", @preprocblock)."\n";
    $code .= join("\n", @countblock)."\n";
    $code .= "}"."\n";
    $code .= "##### End main loop\n\n\n";


    $code .= join("\n", @reportblock);

    $code =~ s/\n\n\n/\n\n/g;
    print("Parser--------------------\n$code\n--------------------------\n");
    $code;
}

sub AddReporter {
    local($name, $type, @repspecs) = @_;

    push(@initialblock,
	 &InitialCode($name, $type, @repspecs));

    push(@preprocblock,
	 &PreProcCode($name, $type, @repspecs));

    push(@countblock, 
	 &CountCode($name, $type, @repspecs));

    push(@reportblock,
	 &ReportCode($name, $type, @repspecs));
}

sub InitialCode {
    local($name, $type, @repspecs) = @_;
    local($code);

    $code = "%$name = ();"."\n";
    $code .= "\$total_$name = 0;"."\n";

    $code;
}

sub PreProcCode {
    local($name, $type, @repspecs) = @_;

    if($DidPreProc{$type}){
	'';
    }
    else{
	$DidPreProc{$type}=1;
	$PPCode{$type};
    }
}

sub CountCode {
    local($name, $type, @repspecs) = @_;
    local($countwhat);

    $countwhat = $TypeToCountVariableMap{$type};

    eval("\$localexcludes = \$$name"."_excludes");
    if($localexcludes){
	$countstring = 
	    "(++\$$name{\$$countwhat} && ++\$total_$name".") unless ($localexcludes);";
    }
    else{
	$countstring = "\$$name{\$$countwhat}++;";
    }
    $countstring;
}

sub ReportCode {
    local($name, $type, @specs) = @_;
    local(@mypresentations) = ();
    local($code) = '';
    
    $code .= &$type($name, @specs);
    $code .= "\$report[1] = \$Title{\$report[1]};"."\n";
    
    @mypresentations = split(/\n/, $presentations{$name});
    for (@mypresentations){
	($howpresent, $opts) = split(/:/, $_);
	$opstring = join("\", \"", split(' ', $opts));
	$opstring = "\"".$opstring."\"";
	$code .= "\&$howpresent($opstring);","\n";
    }
    $code;
}


#
# Utility routines
#
sub pad {
    local($string, $len) = @_;
    local($padding);
 
    $padding = " " x ($len-length($string));
    $string.$padding;
}
