# !/usr/local/perl
#
#  Check for illegal ATtiny15 instructions in .lst file
#

$oops = 0;
$data = 0;
$label = '';
$num = 0;
$file = '??';
$code = '';
$hint = '';
while (<>) {
    $line = $_;
    # 71:motor.c
    if ($line =~ /^\s*(\d+)[:]\s*(\S+)\s*$/) {
        $num = $1;
        $file = $2;
        $code = '';
        next;
    #  65:candle.c      ****     delay_ms(10);
    } elsif ($line =~ /^\s*(\d+)[:]\s*(\S+)\s+[*]+\s+(.*)$/) {
        $num = $1;
        $file = $2;
        $code = $3;
        next;
    #  281            show_adc:
    } elsif ($line =~ /^\s*\d+\s+([^:]+):\s*$/) {
        $s = $1;
        if (!($s =~ /\./) && !($s =~ /^L_/)) {
            $label = $s;
        }
        next;
    }
    if ($line =~ /\s+push\s+/i) {
        ++$oops;
        $hint = 'Reduce stack depth and/or number of local variables';
    } elsif ($line =~ /\s+pop\s+/i) {
        ++$oops;
        $hint = 'Reduce stack depth and/or number of local variables';
    } elsif ($line =~ /\s+sbiw\s+/i) {
        ++$oops;
        $hint = 'Try using BYTE() macro for constant';
    } elsif ($line =~ /\s+adiw\s+/i) {
        ++$oops;
        $hint = 'Try using BYTE() macro for constant';
    } elsif ($line =~ /\s+lds\s+/i) {
        ++$oops;
        $hint = 'Try using BYTE() macro for non-zero constant';
    } elsif ($line =~ /\s+sts\s+/i) {
        ++$oops;
        $hint = 'Try using BYTE() macro for non-zero constants';
    } elsif ($line =~ /\.section\s+\.data/i) {
        ++$data;
        $hint = 'Try using BYTE() macro for non-zero constants';
    }
    if ($oops) {
        &dashes;
        if ($code eq '') {
            print STDERR "Illegal ATtiny opcode!\n$file:$num\n$label:$line";
        } else {
            print STDERR "Illegal ATtiny opcode!\n$file:$num: $code\n$label:$line";
        }
        &hint;
        &dashes;
        exit(1);
    }
}
if ($data > 0) {
    &dashes;
    print STDERR "Illegal .data section found!\n";
    &hint;
    &dashes;
    exit(1);
}
exit(0);

sub hint {
    if ($hint ne '') {
        print STDERR "Hint: $hint\n";
    }
}

sub dashes
{
        print STDERR
"--------------------------------------------------------------------------\n";
}
