#!/usr/bin/perl use Digest;@d=qw{black white red cyan green purple blue yellow transparent gold silver bronze platinum diamond glass stone apples bananas cherries grapes lemons mangoes melons oranges papayas peaches pears persimmons pineapples raspberries strawberries watermelons sweet fresh tasty large small heavy light soft hard solid precious rare vintage expensive spicy bitter};sub E{print STDERR $_[0];exit 1}sub D{$x=undef;if(open($h,"<$_[0]")){binmode$h;eval{$a=Digest->new("MD5");$x=$a->addfile($h)->digest};}$x="ERROR: $!"unless defined$x;}sub P{@l=();map{$x=$y=$z=undef;map{$w=lc$_;for($i=0;$i<=$#d&&$d[$i]ne$w;$i++){}if($i<16){$x=$i;}elsif($i<32){$y=$i-16;}elsif($i<=$#d){$z=$i-32;}}split/\s+/,$_;if(defined($x)&&defined($y)&&defined($z)){push@l,[$z,($x<<4)|$y];}}split/\+/,$a;}sub Q{D($z=$_[0]);if($x=~/^ERROR: /){print"$z: $x\n";return 1;}foreach(@l){if(ord(substr($x,$$_[0],1))!=$$_[1]){print"$z: FAILED\n";return 1;}}print"$z: OK\n";return 0;}@n=@ARGV;$e=0;if($#n<0&&-t STDIN){E"To compute digest:\n\n\t$0 files... > digest.txt\n\nTo check digest:\n\n\t$0 -c digest.txt\n\t$0 -c 'digest_string' file\n\n";}if(@n&&$n[0]eq"-c"){shift@n;$a=$#n<0?"-":shift@n;P();if(@l){push@n,"-"if$#n<0;map{$e+=Q($_)}@n;}else{open$c,"<$a"or E"Can not open $a: $!\n";map{chomp$_;$s=index($_,"*");if($s>0){$a=substr($_,0,$s);P();$e+=Q(substr($_,$s+1))if@l;}}<$c>;}}else{@g=();push@n,"-"if$#n<0;foreach(@n){D($_);if($x=~/^ERROR: (.*)/){print STDERR"Error reading $_: $1\n";$e++;next;}push@g,[$x,$_];}if(@g){%u=map{$$_[0]=>""}@g;$y=scalar keys%u;for($a=1;$y>0&&$a<=16;$a++){for($z=0;$z<16-$a;$z++){%U=();map{if(exists$U{$w=substr($_,$z,$a)}){$U{$w}=undef;}else{$U{$w}=$_;}}keys%u;map{$x=$U{$_};if(defined$x&&$u{$x}eq""){@l=();for($i=$z;$i<$z+$a;$i++){$w=ord(substr($x,$i,1));push@l,$d[$i+32]." ".$d[$w>>4]." ".$d[($w&15)+16];}$u{$x}=join" + ",@l;$y--;}}keys%U;}}$y=0;map{$y=$_ if$y<$_}map{length$u{$_}}keys%u;map{$x=$u{$$_[0]};print$x," "x($y+1-length($x)),"*$$_[1]\n";}@g;}}E"$e errors\n"if$e;