lyx_mirror/development/autotests/searchPatterns.pl

326 lines
6.9 KiB
Perl
Executable File

#! /usr/bin/env perl
# -*- mode: perl; -*-
#
# file searchPatterns.pl
# Uses patterns-file to consecutively process given tex-file
# Command succedes if each pattern matches the file content in given order
#
# How to use:
#
# searchPatterns.pl patterns=<name of file with patterns> log=<name of file to check against>
use strict;
use warnings;
sub sexit($); # Print synax and exit
sub readPatterns($); # Process patterns file
sub processLogFile($); #
sub convertPattern($); # check for regex, comment
sub convertSimplePattern($); # escape some chars, (e.g. ']' ==> '\]')
sub printInvalid($$); # display lines which should not match
my ($logfile, $patternsfile, $basename, $newbase) = (undef, undef, undef);
my %options = (
"log" => \$logfile,
"patterns" => \$patternsfile,
"base" => \$basename,
);
my @patterns = ();
for my $arg (@ARGV) {
if ($arg eq "-help") {
&sexit(0);
}
if ($arg =~ /^([^=]+)=(.+)$/) {
my ($what, $val) = ($1, $2);
if (exists($options{$what})) {
if (defined(${$options{$what}})) {
print "Param \"$what\" already handled\n";
sexit(1);
}
${$options{$what}} = $val;
if ($what ne "base") {
if ($what eq "log") {
if ($logfile =~ /^(.+)\.log[a-z]?\.txt$/) {
$newbase = $1;
}
}
elsif ($what eq "patterns") {
if ($patternsfile =~ /^(.+)\.ctrl$/) {
$newbase = $1;
}
}
else {
print "Software error, unhandled param \"$what\"\n";
&sexit(1);
}
}
}
else {
print "Unknown param \"$what\"\n";
&sexit(1);
}
}
else {
print "Wrong param syntax for \"$arg\"\n";
&sexit(1);
}
}
$basename = $newbase if (! defined($basename));
if (defined($basename)) {
for my $k (keys %options) {
next if ($k eq "base");
if (! defined(${$options{$k}})) {
if ($k eq "log") {
$logfile = $basename . ".loga.txt";
}
elsif ($k eq "patterns") {
$patternsfile = $basename . ".ctrl";
}
}
}
}
for my $k (keys %options) {
next if ($k eq "base");
if (! defined(${$options{$k}})) {
print "Param \"$k\" not defined\n";
&sexit(1);
}
if (! -r ${$options{$k}}) {
print "File \"${$options{$k}}\" is not readable\n";
&sexit(1);
}
}
# Read patterns
print "\nControlfile\t= $patternsfile\n";
print "Log-file\t= $logfile\n\n";
&readPatterns($patternsfile);
if (&processLogFile($logfile) > 0) {
print "Errors occured, exiting\n";
exit(1);
}
exit(0);
sub syntax()
{
print "Syntax:\n";
print " $0";
for my $k (keys %options) {
my $type = "filename";
$type = "basename" if ($k eq "base");
print " \[$k=<$type>\]";
}
print "\n";
}
sub sexit($)
{
my ($exval) = @_;
&syntax();
exit($exval);
}
sub convertPattern($)
{
my ($pat) = @_;
if ($pat eq "") {
return("");
}
return $pat if ($pat =~ /^Comment:/);
if ($pat =~ s/^((Err)?Regex):\s+//) {
# PassThrough variant
return($1 . ":" . $pat);
}
elsif ($pat =~ s/^((Err)?Simple):\s+//) {
my $ermark = $2;
$ermark = "" if (!defined($ermark));
return $ermark . "Regex:" . &convertSimplePattern($pat);
}
else {
# This should not happen.
return undef;
}
}
sub convertSimplePattern($)
{
# Convert all chars '[]()+'
my ($pat) = @_;
if ($pat eq "") {
return("");
}
if ($pat =~ /^(.*)(\\n)(.*)$/) {
# do not convert '\n'
my ($first, $found, $third) = ($1, $2, $3);
$first = &convertSimplePattern($first);
$third = &convertSimplePattern($third);
return("$first$found$third");
}
if ($pat =~ /^(.*)([\[\]\(\)\+\^\{\}\\])(.*)$/) {
my ($first, $found, $third) = ($1, $2, $3);
$first = &convertSimplePattern($first);
$third = &convertSimplePattern($third);
return($first . "\\$found" . $third);
}
# Substitue white spaces
while ($pat =~ s/[\s]+/\\s\+/) {};
return($pat);
}
sub readPatterns($)
{
my ($patfile) = @_;
my $errors = 0;
if (open(FP, $patfile)) {
my $line = 0;
while (my $p = <FP>) {
$line++;
chomp($p);
$p = &convertPattern($p);
if (defined($p)) {
push(@patterns, $p) if ($p ne "");
}
else {
print "Wrong entry in patterns-file at line $line\n";
$errors++;
}
}
close(FP);
}
if ($errors > 0) {
exit(1);
}
}
sub processLogFile($)
{
my ($log) = @_;
my $found;
my $errors = 1;
my @savedlines = ();
my $readsavedlines = 0;
my $savedline;
my $comment = "";
if (open(FL, $log)) {
$errors = 0;
my $line = 0;
my @ErrPatterns = ();
my $minprevlines = 0;
for my $pat (@patterns) {
if ($pat =~ /^Comment:\s*(.*)$/) {
$comment = $1;
$comment =~ s/\s+$//;
if ($comment ne "") {
print "............ $comment ..........\n";
}
next;
}
if ($pat =~ /^(Err)?Regex:(.*)$/) {
my ($type, $regex) = ($1, $2);
next if ($regex eq "");
if (defined($type)) {
# This regex should not apply until next 'found line'
my $erlines = () = $regex =~ /\\n/g;
$minprevlines = $erlines if ($erlines > $minprevlines);
push(@ErrPatterns, $regex);
next;
}
else {
# This is the pattern which we are looking for
$pat = $regex;
}
}
#print "Searching for \"$pat\"\n";
$found = 0;
my $invalidmessages = 0;
my $prevlines = () = $pat =~ /\\n/g; # Number of lines in pattern
$prevlines = $minprevlines if ($prevlines < $minprevlines);
my @prevl = ();
for (my $i = 0; $i <= $prevlines; $i++) {
push(@prevl, "\n");
}
my @lines = ();
if ($readsavedlines) {
# Last regex not found
@lines = @savedlines;
@savedlines = ();
$line = $savedline;
}
else {
$savedline = $line;
}
while (1) {
my $l;
if ($readsavedlines) {
$l = shift(@lines);
}
else {
$l = <FL>;
}
last if (! $l);
for (my $i = 0; $i < $prevlines; $i++) {
$prevl[$i] = $prevl[$i+1];
}
$prevl[$prevlines] = $l;
my $check = join("", @prevl);
$line++;
if ($check =~ /$pat/) {
my $fline = $line - $prevlines;
print "$fline:\tfound \"$pat\"\n";
$found = 1;
# Do not search in already found area
for (my $i = 0; $i <= $prevlines; $i++) {
$prevl[$i] = "\n";
}
if ($readsavedlines) {
@savedlines = @lines;
}
else {
@savedlines = ();
}
$savedline = $line;
last;
}
else {
push(@savedlines, $l);
# Check for not wanted patterns
for my $ep (@ErrPatterns) {
if ($check =~ /$ep/) {
$errors++;
if ($invalidmessages++ < 10) {
my $fline = $line - $prevlines;
&printInvalid($fline, $check);
}
last;
}
}
}
}
if (! $found) {
$errors++;
print "\tNOT found \"$pat\" in remainder of file\n";
$readsavedlines = 1;
}
@ErrPatterns = (); # clean search for not wanted patterns
$minprevlines = 0;
}
close(FL);
}
return($errors);
}
sub printInvalid($$)
{
my ($line, $check) = @_;
my @chk = split(/\n/, $check);
print("$line:\tInvalid match: " . shift(@chk) . "\n");
for my $l (@chk) {
print("\t\t\t$l\n");
}
}