{ my %prev; sub c_out { my( $fh, $c )= @_; if( ! defined $c ) { print $fh pack "CC", $c & 0xff, $c >> 8 if exists $prev{$fh}; } elsif( exists $prev{$fh} ) { print $fh pack "CC", $prev{$fh} | (($c&0xf)<<4), $c>>4; } else { print $fh pack "C", $c & 0xff; $prev{$fh}= ( $c>>8 ) & 0xf; return; } delete $prev{$fh}; } } { my %prev; sub c_in { my( $fh )= @_; my $c; if( exists $prev{$fh} ) { if( ! read( $fh, $c, 1 ) ) { die "Invalid trailing nybble ($prev{$fh})" unless 0 == delete $prev{$fh}; return; } return delete($prev{$fh})<<8 | unpack("C",$c); } else { my $len= read( $fh, $c, 2 ); die "Extra trailing byte (",unpack("C",$c),")" if 1 == $len; return if 0 == $len; ( $c, $prev{$fh} )= unpack "CC", $c; $c |= ($prev{$fh}&0xf)<<8; $prev{$fh} >>= 4; return $c; } } }