#!/usr/bin/perl -w # $Id: asm-11_expect 1065 2018-11-04 11:32:06Z mueller $ # # Copyright 2013-2018 by Walter F.J. Mueller # # This program is free software; you may redistribute and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for complete details. # # Revision History: # Date Rev Version Comment # 2018-11-03 1065 1.1 add and use bailout; update exit code usage # 2013-03-29 500 1.0 Initial version # 2013-03-24 499 0.1 First draft # use 5.14.0; # require Perl 5.14 or higher use strict; # require strict checking use FileHandle; use Getopt::Long; my %opts = (); GetOptions(\%opts, "help", "tline", "tcheck" ) or bailout("bad command options"); my $errcnt; # total error count autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe if (exists $opts{help}) { print_help(); exit 0; } bailout("no input files specified") if scalar(@ARGV) == 0; foreach my $fname (@ARGV) { do_file($fname); } exit 2 if $errcnt > 0; exit 0; #------------------------------------------------------------------------------- # #; Input file list: # 1 6 ; comment # 1 17 000000 zero: # 1 23 002000 000101 w0: .word 101 # 1 17 001011 377 .byte ^c0 # 1 70 001206 046374 001234 001234 bic 1234(r3),@1234(r4) # 1 24 001036 067527 066162 020544 .word "Wo,"rl,"d!,0 # 000000 #EEfnolinno dot... word1. word2. word2. # # 1 2 3 #0123456789012345678901234567890123456789 # sub do_file { my ($fname) = @_; my $fh; if ($fname eq "-") { $fh = *STDIN; } else { bailout("'$fname' not found or readable") if (not -r $fname); $fh = new FileHandle; $fh->open($fname) or bailout("failed to open '$fname': $!"); } my @errmsg; # error message list my $echeck = 0; my $c_string; my $c_pend; while (<$fh>) { chomp; next if m/^;/; print "$_\n" if $opts{tline}; my $line = $_; my $rest = $_; my $err; if (substr($rest,2,1) =~ m/^[A-Z]$/) { $rest =~ m/^([A-Z]+)$/; $err = $1; $rest = $'; } else { $err = substr($rest,0,2); $err =~ s/\s//g; $rest = substr($rest,2); } my $fileno; my $lineno; if (substr($rest,0,8) =~ m/^\s+(\d+)\s+(\d+)$/) { $fileno = int($1); $lineno = int($2); $rest = substr($rest,8); } else { next; } my $dot; if (substr($rest,0,7) eq ' ') { $rest = substr($rest,7); } elsif (substr($rest,0,7) =~ m/^\s([0-7]{6})/) { $dot = oct($1); $rest = substr($rest,7); } else { next; } my @dat; my $isbyte; # words ? if ($rest =~ m/^(\s([0-7]{6})){1,3}/) { for (my $i=0; $i<3; $i++) { last unless substr($rest,1,6) =~ m/[0-7]{6}/; push @dat, oct(substr($rest,1,6)); $rest = substr($rest,7); } # bytes ? } elsif ($rest =~ m/^(\s([0-7]{3})){1,5}/) { for (my $i=0; $i<5; $i++) { last unless substr($rest,1,3) =~ m/[0-7]{3}/; $isbyte = 1; push @dat, oct(substr($rest,1,3)); $rest = substr($rest,4); } $rest = substr($rest,1); } # look for expect condition (unless one is pending) if ($c_pend) { $c_pend = undef; } else { if ($rest =~ m/;;!!(.*)$/) { $c_string = $1; if ($rest =~ m/^\s*;;!!/) { $c_pend = 1; next; } } } # no expect condition defined: look for unexpected etags unless (defined $c_string) { if ($err ne '') { push @errmsg, {msg => sprintf("unexpected error '%s'", $err), line => $line}; } next; } # expect condition defined: parse it my $c_err; my $c_dot; my @c_dat; my $c_rest = $c_string; if ($c_rest =~ m/^\s*([A-Z]+)/) { $c_err = $1; $c_rest = $'; } if ($c_rest =~ m/^\s*([0-7]{6}:)/) { $c_dot = oct($1); $c_rest = $'; } while (length($c_rest)) { last unless $c_rest =~ m/^\s*([0-7]+)/; push @c_dat, oct($1); $c_rest = $'; } unless ($c_rest =~ m/^\s*$/) { push @errmsg, {msg => sprintf("can't parse expect, rest='%s'", $c_rest), line => ';;!! ' . $c_string}; $c_string = undef; next; } if ($opts{tcheck}) { print "exp: "; printf " err=%s", $c_err if defined $c_err; printf " dot=%6.6o", $c_dot if defined $c_dot; if (scalar(@c_dat)) { print " dat="; foreach (@c_dat) { printf "%6.6o ", $_; } } print "\n"; } if (defined $c_err) { if ($c_err ne $err) { push @errmsg, {msg => sprintf("error mismatch: found='%s', expect='%s'", $err, $c_err), line => $line}; } } if (defined $c_dot) { if (defined $dot) { if ($c_dot != $dot) { push @errmsg, {msg => sprintf(". mismatch: found=%6.6o, expect=%6.6o", $dot, $c_dot), line => $line}; } } else { push @errmsg, {msg => sprintf(". check miss: nothing found, expect=%6.6o", $c_dot), line => $line}; } } if (scalar(@c_dat)) { my $nc = scalar(@c_dat); $nc = scalar(@dat) if $nc < scalar(@dat); for (my $i=0; $i<$nc; $i++) { if (defined $c_dat[$i] && defined $dat[$i]) { if ($c_dat[$i] != $dat[$i]) { push @errmsg, {msg => sprintf("data %d mismatch: found=%6.6o, expect=%6.6o", $i, $dat[$i], $c_dat[$i]), line => $line}; } } elsif (defined $c_dat[$i] && ! defined $dat[$i]) { push @errmsg, {msg => sprintf("data %d mismatch: nothing found, expected=%6.6o", $i, $c_dat[$i]), line => $line}; } elsif (! defined $c_dat[$i] && defined $dat[$i]) { push @errmsg, {msg => sprintf("data %d mismatch: found=%6.6o, nothing expected", $i, $dat[$i]), line => $line}; } } } # trace expects if ($opts{tcheck} && $echeck != scalar(@errmsg)) { $echeck = scalar(@errmsg); printf "FAIL: %s\n", $errmsg[-1]{msg}; } # invalidate expect condition $c_string = undef; } # done with file my $verdict = scalar(@errmsg) ? 'FAILED' : 'OK'; printf "asm-11_expect: %s %s\n", $fname, $verdict; foreach (@errmsg) { printf " FAIL: %s\n in: %s\n", $$_{msg}, $$_{line}; } $errcnt += scalar(@errmsg); return; } #------------------------------------------------------------------------------- sub bailout { my ($msg) = @_; print STDERR "asm-11_expect-F: $msg\n"; exit 1; } #------------------------------------------------------------------------------- sub print_help { print "usage: asm-11_expect \n"; print " --tline trace input lines\n"; print " --tcheck trace expect checks\n"; return; }