#!/usr/bin/perl # $Id: squish-flu,v 1.6 2003/12/04 07:40:05 tomj Exp $ # 3 Dec 2003 NOTE: # # bigrep seems to really screw up. # BUG: Plotter output can't rely on end-of-line-wrap # when using squish-flu; it invokes wraparound. # Needs looking at. # This post-processes a "Flutterwumper" file output by Don Lancaster's # flutools PostScript; it strips extraneous whitespace, and compresses # runsof identical commands (NNNNNNNNNNNNNNNNNNEEEEEEEEEEEEEEE...) # with the 'repeat' command supported by the Model 423. # # This is meant as a filter for t2a. # The repeat command is simply the < character followed # by a repeat count with ASCII offset " ": # # <9 # means repeat the most-recent command 9 times. The maximum # repeat count is $MAXRUN, character ~. # Set true if Model 423 supports the big repeat command. my $bigrep= 0; $MAXRUN= 94; # max. size encodable in ASCII my $c= undef; # most recent command character, my $lastc= undef; # for detecting runs my $count= 0; # length of run, my $linelen= 0; # output a newline every so often my ($charsin, $charsout); # in and out counts my ($longest_run, $run_total, $run_count, $run_maxed)= (0, 0, 0, 0); # Turn on autoflush (which see), else printing isn't flushed # to the pipe until the program terminates. use Getopt::Std; use vars qw/$opt_h $opt_q/; getopts ('qh'); print STDERR "squish-flu -h for usage\n" if not $opt_q; &usage() if $opt_h; $|= 1; foreach (<>) { # from stdin, next if /^\%/; # ignore comments, foreach (split (//, $_)) { # decompose into characters, next if /\n/; # ignore all this stuff, next if /\r/; next if /\s/; ++$charsin; if ($_ eq $lastc) { # if a repeat, ++$count; # count another, } else { # different command, &outrun(); # flush command, $lastc= $_; # new command, } } } &outrun(); # flush last command. if (not $opt_q) { print STDERR "squish-flu: $charsin in, $charsout out.\n"; if ($charsin and $charsout) { my $avg= int ($run_total / $run_count * 10) / 10; print STDERR "squish-flu: $run_count runs, $avg avg; "; print STDERR "$run_maxed runs > $MAXRUN, longest $longest_run.\n"; my $foo= int ($charsin / $charsout * 10) / 10; print STDERR "Compressed $foo:1\n"; } } # Output a run of characters. If the count < 4 just output sans # repeat. sub outrun { return if not defined $lastc; if ($count > 4) { ++$run_count; # another run, $run_total += $count; # to calc avg, $longest_run= $count if $count > $longest_run; ++$run_maxed if $count > $MAXRUN; } print $lastc; # output the command, ++$linelen; while ($bigrep && $count >= 100) { # long run command, print "?"; my $n= int ($count / 100); print chr ($n + 32); $count -= $n * 100; ++$charsout; $linelen += 3; # watch this, } while ($count > 2) { # output up to $MAXRUN print "<"; # at a time, my $n= $count; $n= $MAXRUN if $n > $MAXRUN; print chr ($n + 32); # repeat count, ++$charsout; $count -= $n; $linelen += 3; # watch this, } for (; $count; --$count) { print $lastc; # output simple. ++$charsout; ++$linelen; } if ($linelen > 40) { # keeps paper tape print "\n"; # records short, ++$charsout; $linelen= 0; } } sub usage { print << "USAGE"; Run-length-encode a Flutterwumper command stream. -q Quiet, no chatter. USAGE exit; }