#!/usr/bin/env perl
# Parameter sweep tool.
# Rok Zitko, zitko@theorie.physik.uni-goettingen.de, Oct 2008
# $Id: looper,v 1.4 2008/10/07 11:28:25 zitko Exp zitko $

use strict;
use warnings;

my $verbose = 1; # verbose diagnostics

my ($before, $prelude, $loop, $after); # loop control

$before = ""; # system command before the loop
$prelude = ""; # perl code before the loop
$loop = ""; # system command for each new iteration
$after = ""; # system command after the loop

my @code; # generated perl code for looping
my @forloopcode; # generated for loop lines
my $looplevel; # for loop nesting level

# Output line before the loop
sub preline {
    my $line = shift;
    unshift (@code, $line);
}

# Output for loop line
sub forline {
    my $line = shift;
    push (@forloopcode, $line);
}

# Output line inside the loop
sub loopline {
    my $line = shift;
    push (@code, $line);
}

# Output line after the loop
sub postline {
    my $line = shift;
    push (@code, $line);
}

# Read the input from STDIN.
while (<>) {
    if (/^#/) { # Either comment or macro line
	if (/^#BEFORE:\s*(.*)/) {
	    $before = $1;
	} elsif (/^#PRELUDE:\s*(.*)/) {
	    $prelude = $1;
	} elsif (/^#LOOP:\s*(.*)/) {
	    $loop = $1;
	} elsif (/^#AFTER:\s*(.*)/) {
	    $after = $1;
	}
    } else {
	if (/^@(.*)/) { # Loop statement
	    forline "for($1) { \n";
	    $looplevel++;
	} elsif (/^!(.*)/) { # Verbatim Perl expression
	    chomp;
	    loopline "$_;\n";
	} else {
	    chomp;
	    loopline "print F \"$_\\n\"; \n";
	}
    }
}

my $closebrackets = "";
for (my $cnt = 1; $cnt <= $looplevel; $cnt++) {
    $closebrackets = "$closebrackets } ";
}

if ($verbose) {
    print "BEFORE: $before\n";
    print "PRELUDE: $prelude\n";
    print "LOOP: $loop\n";
    print "AFTER: $after\n";
}

# The actual work is done here:

system $before;

open (SCRIPT, "|perl -") or die "Can't write to perl.";
print SCRIPT <<ENDSCRIPT;
$prelude;
\$cnt = 0;
@forloopcode
\$cnt++;
open(F, "|$loop");
@code;
close(F);
$closebrackets
ENDSCRIPT
close (SCRIPT);

system $after;
