#!/usr/bin/perl -w # compresses messages for taipan.c. # Reads lines from stdin of the form: # label "message text" # writes C code to stdout. # by default, an asm include file "asm.inc" is created, containing # definitions of messages which exactly match a dictionary entry. # with -n, "asm.inc" is not created. # with -d, dumps messages to be encoded, after dictionary replacement. if(@ARGV) { if($ARGV[0] eq '-n') { $skip_msg_inc++; } elsif($ARGV[0] eq '-d') { $dump++; $skip_msg_inc++; } } # make dictionary from textdecomp.s comments open my $t, ") { next unless /^dict(\d\d):.*;\s*"([^"]*)"/; my $id = $1; my $dictlabel = "dict$1"; if($id < 27) { $id = chr($id + 96); } else { $id = chr($id - 27 + 65); } my $value = 'Z' . $id; my $key = quotemeta $2; $dictionary{$key} = $value; $dictlabels{$value} = $dictlabel; } close $t; #for(sort keys %dictionary) { # warn "'$_' => $dictionary{$_}\n"; #} #exit 0; if(!$skip_msg_inc) { open ASMINC, ">msg.inc" or die $!; print ASMINC "; do not edit, contents are generated by messages.pl\n\n"; } print "// do not edit, contents are generated by messages.pl\n\n"; while() { chomp; $msgcount++; /^(\w+)\s/; my $label = $1; s/^\w+\s+//; my $orig = $_; print " input: $_\n" if $dump; s/"//g; s/\\r//g; s/\\n/\n/g; $total_in += (1 + length); my $dict_used = 0; for my $dk (sort { length $b <=> length $a || $a cmp $b } keys %dictionary) { if(s/$dk/$dictionary{$dk}/g) { $dict_used = 1; } } # if a string turns out to be exactly a dict entry, no need to include # the compressed version in messages.c. if(!$skip_msg_inc && /^Z.$/) { print "\nextern const char M_$label\[\]; // dictionary used, $dictlabels{$_}\n\n"; print ASMINC " _M_$label = $dictlabels{$_}\n .export _M_$label\n\n"; next; } if($dump) { my $w = $_; $w =~ s/\n/\\n/g; print "output: \"$w\"\n\n"; next; } open my $out, ">msg.out" or die $!; print $out $_; close $out; system("./textcomp < msg.out > msg.tmp 2>/dev/null"); open my $result, ") { my @got = split " ", $_; $readbytes = @got; print join(", ", @got); $total_out += @got; } close $result; die "failed to compress $orig\n" unless $readbytes; print "\n};" . ($dict_used ? " // dictionary used" : "") . "\n\n"; } close ASMINC unless $skip_msg_inc; exit 0 if $dump; print "// messages: $msgcount\n"; print "// total input size: $total_in\n"; print "// total output size: $total_out\n"; print "// compression: " . ($total_in - $total_out) . "\n"; print "// ratio: " . sprintf("%.1f", $total_out * 100 / $total_in) . "%\n"; # commented-out messages can go in the pod section below: =pod illion "illion" # somehow this wastes 2 bytes fine "fine" run "Run" # too short to be worth compression how_much_spc "How much " =cut