#!/usr/bin/perl -wi

# add bar numbers to lilypond files
# only works for some files see code below

use strict;

my %len = (
    '\breve'  => 2,
    '\longa'  => 4,
    '\maxima' => 8,
);

my $ln = 0; # next bar number
my $lvl = 0; # 0 is outside music
my $timet = 4;
my $timeb = 4;
while (<>) {
    chomp;
    my $line = $_;
    my $lnum = "";

    tr/ \t/ /s;
    s/ $//;
    s/%.*//;

    if ($lvl < 1) { # outside
	$ln = 1;
	if (m/^[a-zA-Z]+ =.* (\\relative [a-h](e?s|is)?[,']*|\\figuremode|\\chordmode) \{/) {
	    if (m/\}$/) {
		# ignore oneliners
	    } else {
		$lvl = 1;
		#print STDERR "$lvl $ln: $line\n";
	    }
	} elsif (m/\\new Dynamics \{/) {
	    $lvl = 1;
	}
    } else { # inside
	if (m/^ ?}.*{$/) {
	    #
	} elsif (m/{$/) {
	    $lvl++;
	    #print STDERR "$lvl $ln: $line\n";
	} elsif (m/^ ?}/) {
	    $lvl--;
	    #print STDERR "$lvl $ln: $line\n";
	} elsif (m/^$/) {
	    # don't add bar numbers to empty lines
	} elsif (m/^ ?\\set Score.currentBarNumber = #(\d+)$/) {
	    my $num = $1;
	    $ln = $num;
	} elsif (m/^ ?\\partial \d+/) {
	    $ln--;
	} elsif (m/^ ?\\time (\d+)\/(\d+)$/) {
	    $timet = $1;
	    $timeb = $2;
	} elsif (m/^ ?\\[a-z_]+( [a-z0-9\/]+)?$/) {
	    # I'm assuming that \commands stands on a line by itself
	} elsif (m/^ [sR](\d+|\\breve|\\longa|\\maxima)\.? ?(\* ?(\d+))? (\\bar \".*\"|\\break)? ?\|/) {
	    my $num = $3;
	    if (!defined($num)) { $num = 1; }
	    if ($line =~ m/% ?\d+(\.\.\d+)?/) {
		$line =~ s/[ \t]*% ?\d+(\.\.\d+)?//;
	    }
	    if ($num == 1) {
		$lnum = " % $ln";
		$ln++;
	    } else {
		my $end = $ln + $num - 1;
		$lnum = " % $ln..$end";
		$ln += $num;
	    }
	} elsif (m/\\repeat unfold (\d+) \{[^|]*\| ?\}/) {
	    my $num = $1;
	    if ($line =~ m/% ?\d+(\.\.\d+)?/) {
		$line =~ s/[ \t]*% ?\d+(\.\.\d+)?//;
	    }
	    if ($num == 1) {
		$lnum = " % $ln";
		$ln++;
	    } else {
		my $end = $ln + $num - 1;
		$lnum = " % $ln..$end";
		$ln += $num;
	    }
	} elsif (m/\|/) {
	    if ($line =~ m/% ?\d+(\.\.\d+)?/) {
		$line =~ s/[ \t]*% ?\d+(\.\.\d+)?//;
	    }
	    $lnum = " % $ln";
	    $ln++;
	} elsif (m/[a-hr]([,']*)(\d+|\\breve|\\longa|\\maxima)\.?(\*(\d+)(\/(\d+))?(\*(\d+))?)?/) {
	    # TODO: allow this if a cmd line opt.is set
	    my $num = 1;
	    my $len = $2;
	    my $m1 = $4;
	    my $m2 = $6;
	    my $m3 = $8;
	    if (!defined($m3)) { $m3 = 1; }
	    if (!defined($m2)) { $m2 = 1; }
	    if (!defined($m1)) { $m1 = 1; }
	    if ($line =~ m/% ?\d+(\.\.\d+)?/) {
		$line =~ s/[ \t]*% ?\d+(\.\.\d+)?//;
	    }
	    if (defined($len{$len})) {
		$num = int($len{$len} * $m1 / $m2 * $m3 * $timeb / $timet + 0.3);
	    }
	    if ($num <= 1) {
		$lnum = " % $ln";
		$ln++;
	    } else {
		my $end = $ln + $num - 1;
		$lnum = " % $ln..$end";
		$ln += $num;
	    }
	} else {
	    #print STDERR "<$_>\n";
	    #print STDERR "<$line>\n";
	}
    }

    print $line . $lnum . "\n";
}
