use Getopt::Std;
use strict;
getopts('VvO:');
use vars qw($atend
$stuff
$opt_v
$opt_V
$opt_O
$curpos
$esc
$page_mgmt_unit
$horizontal_position
$horizontal_unit
$vertical_unit
$vertical_position
$raster_x
$raster_y
$print_offsets
%seqtable
@offsets);
$atend = 0;
%seqtable = ( "@", 0,
"(R", "REMOTE",
"(", "VARIABLE",
"U", 1,
"\\", 2,
"\$", 2,
"r", 1,
"\031", 1,
".", "SPECIAL",
"i", "SPECIAL1",
"\000", 2,
"\001", 22
);
$esc = "\033";
$curpos = 0;
$page_mgmt_unit = 360;
$horizontal_unit = 180;
$vertical_unit = 360;
$vertical_position = 0;
$horizontal_position = 0;
$print_offsets = 0;
sub get_stuff($) {
my ($where) = @_;
my ($end) = length $stuff;
if ($curpos == 0 && $end == 0) {
$stuff = <>; $end = length $stuff;
}
my ($old_end) = length $stuff;
my ($tmp);
my ($bytes_to_read) = 4096;
if ($where - $end > $bytes_to_read) {
$bytes_to_read = $where - $end;
}
while ($end < $where) {
my $foo = read ARGV, $tmp, $bytes_to_read;
$stuff .= $tmp;
$end = length $stuff;
if ($old_end == $end) {
$atend = 1;
return 0;
} else {
$bytes_to_read -= $end - $old_end;
$old_end = $end;
}
}
return 1;
}
sub increment_curpos($) {
my ($curpos_increment) = @_;
substr($stuff, 0, $curpos_increment) = "";
$curpos += $curpos_increment;
}
sub do_remote_command() {
print "\n";
printf "%08x ", $curpos;
print "1b ( R ";
increment_curpos(3);
get_stuff(2);
my $lchar = substr($stuff, 0, 1);
my $nlchar = unpack("C", $lchar);
my $hchar = substr($stuff, 1, 1);
my $nhchar = unpack("C", $hchar);
printf "%02x %02x ", $nlchar, $nhchar;
my $skipchars = ($nhchar * 256) + $nlchar;
increment_curpos(2);
my $i;
my $char;
my $nchar;
get_stuff($skipchars);
for ($i = 0; $i < $skipchars; $i++) {
$char = substr($stuff, $i, 1);
$nchar = unpack("C", $char);
if ($nchar >= 32 && $nchar < 127) {
print $char;
} else {
printf "%02x ", $nchar;
}
}
increment_curpos($skipchars);
while (get_stuff(2) &&
substr($stuff, 0, 2) =~ /[A-Z0-9][A-Z0-9]/) {
print "\n";
printf "%08x ", $curpos;
my ($cmd) = substr($stuff, 0, 2);
print $cmd;
increment_curpos(2);
get_stuff(2);
$lchar = substr($stuff, 0, 1);
$nlchar = unpack("C", $lchar);
$hchar = substr($stuff, 1, 1);
$nhchar = unpack("C", $hchar);
if ($cmd eq "DF") {
$skipchars = 0;
} else {
$skipchars = ($nhchar * 256) + $nlchar;
}
printf "%02x %02x ", $nlchar, $nhchar;
increment_curpos(2);
get_stuff($skipchars);
for ($i = 0; $i < $skipchars; $i++) {
printf "%02x ", unpack("C", substr($stuff, $i, 1));
}
increment_curpos($skipchars);
}
}
sub print_prefix_bytes($) {
my ($bytes_to_print) = @_;
print "\n";
printf "%08x ", $curpos;
print "1b ";
my $i;
my $char;
my $nchar;
get_stuff($bytes_to_print);
for ($i = 1; $i < $bytes_to_print; $i++) {
$char = substr($stuff, $i, 1);
$nchar = unpack("C", $char);
if ($i < 2 && $nchar >= 32 && $nchar < 127) {
print " $char ";
} else {
printf "%02x ", unpack("C", $char);
}
}
}
sub print_output_data($$$$$$) {
my ($comptype, $bitsperpixel, $dots, $rows, $dot_scale, $color) = @_;
my $counter;
my $fchar;
my $last_row = 0;
my $first_row = -1;
my $i;
my $vstuff;
$dots *= 8;
$dots /= $dot_scale;
my $real_dots = $dots / $bitsperpixel;
if ($opt_v) {
print " ($real_dots dots, $rows rows, $bitsperpixel bits";
}
my $savedots = $dots;
if ($comptype == 0) {
if ($opt_V) {
get_stuff($dots);
printf "%*v02x ", " ", substr($stuff, 0, $dots);
}
increment_curpos($dots);
} elsif ($comptype == 1) {
foreach $i (0..$rows-1) {
my ($found_something) = 0;
$dots = $savedots;
my ($tstuff) = "\n $i ";;
while ($dots > 0) {
get_stuff(1);
$counter = ord(substr($stuff, 0, 1));
increment_curpos(1);
if ($counter <= 127) {
$counter++;
get_stuff($counter);
if ($opt_v || $opt_V) {
my $tmp = sprintf "%*v02x ", " ", substr($stuff, 0, $counter);
if (!($tmp =~ /^[0 ]+$/)) {
$found_something = 1;
$last_row = $i;
if ($first_row == -1) {
$first_row = $i;
}
}
if ($opt_V) {
$tstuff .= $tmp;
}
}
increment_curpos($counter);
} else {
$counter = 257 - $counter;
get_stuff(1);
if ($opt_v || $opt_V) {
$fchar = sprintf "%v02x ", substr($stuff, 0, 1);
if ($fchar ne "00 ") {
$found_something = 1;
$last_row = $i;
if ($first_row == -1) {
$first_row = $i;
}
}
}
if ($opt_V) {
map { $tstuff .= $fchar } (0..$counter - 1);
}
increment_curpos(1);
}
$dots -= $counter * 8;
}
if ($opt_V && $found_something) {
$vstuff .= $tstuff;
}
}
if ($opt_v) {
my ($offset) = $offsets[$color];
my ($first_position) = ($vertical_position / $vertical_unit)
+ ($first_row + $offset) * $raster_y;
my ($last_position) = ($vertical_position / $vertical_unit)
+ ($last_row + $offset) * $raster_y;
my ($final_position) = ($vertical_position / $vertical_unit)
+ ($rows + $offset) * $raster_y;
my ($final_horizontal) = $horizontal_position +
($real_dots * $page_mgmt_unit * $raster_x);
if ($print_offsets) {
printf (" %d,%d+%d %.4f %d,%d+%d %.4f %.4f) ",
$horizontal_position, $first_row, $offset, $first_position,
$final_horizontal, $last_row, $offset, $last_position,
$final_position);
} else {
printf (" %d,%d %.4f %d,%d %.4f %.4f) ",
$horizontal_position, $first_row, $first_position,
$final_horizontal, $last_row, $last_position,
$final_position);
}
}
if ($opt_V) {
print " $vstuff";
}
} else {
print "\nUnknown compression type $comptype!\n";
}
}
sub do_special_command() {
get_stuff(8);
my $comptype = unpack("C", substr($stuff, 2, 1));
my $color = 0;
my $dots = unpack("v", substr($stuff, 6, 2));
my $rows = unpack("C", substr($stuff, 5, 1));
print_prefix_bytes(8);
increment_curpos(8);
print_output_data($comptype, 1, $dots, $rows, 8, $color);
get_stuff(1);
while (substr($stuff, 0, 1) eq "\r") {
increment_curpos(1);
}
}
sub do_special1_command() {
get_stuff(9);
my $color = unpack("C", substr($stuff, 2, 1));
my $comptype = unpack("C", substr($stuff, 3, 1));
my $bitsperpixel = unpack("C", substr($stuff, 4, 1));
my $dots = unpack("v", substr($stuff, 5, 2));
my $rows = unpack("v", substr($stuff, 7, 2));
print_prefix_bytes(9);
increment_curpos(9);
print_output_data($comptype, $bitsperpixel, $dots, $rows, 1, $color);
get_stuff(1);
while (substr($stuff, 0, 1) eq "\r") {
increment_curpos(1);
}
}
sub get_long($) {
my ($string) = @_;
my ($tmp) = unpack("V", $string);
if ($tmp >= (1 << 31)) {
return -(0xffffffff ^ $tmp) - 1;
} else {
return $tmp;
}
}
sub get_short($) {
my ($string) = @_;
my ($tmp) = unpack("v", $string);
if ($tmp >= (1 << 15)) {
return -(0xffff ^ $tmp) - 1;
} else {
return $tmp;
}
}
sub get_byte($) {
my ($string) = @_;
return unpack("C", $string);
}
if ($opt_O) {
my (@stuff) = split /,/, $opt_O;
map {
my ($key, $val) = split /=/;
if ($val) {
$print_offsets = 1;
}
@offsets[$key] = $val;
} @stuff;
}
while (! $atend) {
my $found;
my $key;
my $skipchars;
my $startoff;
my $kchar;
my $nkchar;
my $lchar;
my $nlchar;
my $hchar;
my $nhchar;
my $i;
my $char;
my $nchar;
my $bytes;
get_stuff(2);
if (substr($stuff, 0, 1) eq "$esc") {
$found = 0;
foreach $key (sort { length $b <=> length $a } keys %seqtable) {
get_stuff(1 + length $key);
if (substr($stuff, 1, length $key) eq $key) {
$skipchars = $seqtable{$key};
if ($skipchars eq "SPECIAL") {
do_special_command();
$found = 2;
} elsif ($skipchars eq "SPECIAL1") {
do_special1_command();
$found = 2;
} elsif ($skipchars eq "REMOTE") {
do_remote_command();
$found = 2;
} else {
print "\n";
printf "%08x ", $curpos;
print "1b ";
$startoff = 0;
my $print_stuff = 0;
if ($skipchars eq "VARIABLE") {
get_stuff((length $key) + 3);
$kchar = substr($stuff, (length $key) + 1, 1);
$nkchar = unpack("C", $kchar);
$lchar = substr($stuff, (length $key) + 2, 1);
$nlchar = unpack("C", $lchar);
$hchar = substr($stuff, (length $key) + 3, 1);
$nhchar = unpack("C", $hchar);
$skipchars = ($nhchar * 256) + $nlchar;
$startoff = 3;
$print_stuff = 1;
}
get_stuff($skipchars + (length $key) + $startoff + 1);
for ($i = 0;
$i < $skipchars + (length $key) + $startoff;
$i++) {
$char = substr($stuff, $i + 1, 1);
$nchar = unpack("C", $char);
if ($i < 3 && $nchar >= 32 && $nchar < 127) {
print " $char ";
} else {
printf "%02x ", unpack("C", $char);
}
}
if ($print_stuff) {
my $xchar = substr($stuff, 2, 1);
if ($xchar eq "c") {
my ($top, $bottom);
if ($skipchars == 8) {
$top = get_long(substr($stuff, 5, 4));
$bottom = get_long(substr($stuff, 9, 4));
} else {
$top = get_short(substr($stuff, 5, 2));
$bottom = get_short(substr($stuff, 7, 2));
}
if ($opt_v) {
printf (" (page format %d %d %.2f %.2f)",
$top, $bottom, $top / $page_mgmt_unit,
$bottom / $page_mgmt_unit);
}
$vertical_position =
$top * $vertical_unit / $page_mgmt_unit;
} elsif ($xchar eq "S") {
my ($width, $height);
if ($skipchars == 8) {
$width = get_long(substr($stuff, 5, 4));
$height = get_long(substr($stuff, 9, 4));
} else {
$width = get_short(substr($stuff, 5, 2));
$height = get_short(substr($stuff, 7, 2));
}
if ($opt_v) {
printf (" (paper size %d %d %.2f %.2f)",
$width, $height, $width / $page_mgmt_unit,
$height / $page_mgmt_unit);
}
} elsif ($xchar eq "C") {
my ($length);
if ($skipchars == 4) {
$length = get_long(substr($stuff, 5, 4));
} else {
$length = get_short(substr($stuff, 5, 2));
}
if ($opt_v) {
printf (" (page length %d %.2f)",
$length, $length / $page_mgmt_unit);
}
} elsif ($xchar eq "D") {
my $base = get_short(substr($stuff, 5, 2));
my $y = get_byte(substr($stuff, 7, 1));
my $x = get_byte(substr($stuff, 8, 1));
$raster_x = $x / $base;
$raster_y = $y / $base;
if ($opt_v) {
printf (" (raster base %d, %d x %d)",
$base, $base / $x, $base / $y);
}
} elsif ($xchar eq "U") {
if ($skipchars == 5) {
my $page_mgmt = get_byte(substr($stuff, 5, 1));
my $vertical = get_byte(substr($stuff, 6, 1));
my $horiz = get_byte(substr($stuff, 7, 1));
my $scale = get_short(substr($stuff, 8, 2));
$page_mgmt_unit = $scale / $page_mgmt;
$horizontal_unit = $scale / $horiz;
$vertical_unit = $scale / $vertical;
if ($opt_v) {
printf (" (units base %d mgmt %d vert %d horiz %d)",
$scale, $page_mgmt_unit,
$vertical_unit, $horizontal_unit);
}
} else {
my $page_mgmt = get_byte(substr($stuff, 5, 1));
if ($opt_v) {
printf " (units base = %d/720)", $page_mgmt;
}
$page_mgmt_unit = $page_mgmt;
$horizontal_unit = $page_mgmt;
$vertical_unit = $page_mgmt;
}
} elsif ($xchar eq "v") {
my ($length);
if ($skipchars == 4) {
$length = get_long(substr($stuff, 5, 4));
} else {
$length = get_short(substr($stuff, 5, 2));
}
$vertical_position += $length;
if ($opt_v) {
printf (" (skip vertical %d at %d %.4f)",
$length, $vertical_position,
$vertical_position / $vertical_unit);
}
} elsif ($xchar eq "\$") {
my ($length);
if ($skipchars == 4) {
$horizontal_position =
get_long(substr($stuff, 5, 4));
} else {
$horizontal_position =
get_short(substr($stuff, 5, 2));
}
if ($opt_v) {
printf (" (horizontal position %d %.4f)",
$horizontal_position,
$horizontal_position / $horizontal_unit);
}
}
}
$found = 1;
}
$bytes = length($key) + 1 + $skipchars + $startoff;
last;
}
}
if (! $found) {
print "\n";
printf "%08x ", $curpos;
print "1b ";
increment_curpos(1);
} elsif ($found == 1) {
increment_curpos($bytes);
}
} elsif (substr($stuff, 0, 1) eq "\0" ||
substr($stuff, 0, 1) eq "\f") {
get_stuff(1);
$char = substr($stuff, 0, 1);
$nchar = unpack("C", $char);
if ($nchar >= 32 && $nchar < 127) {
print " $char ";
} else {
printf "%02x ", unpack("C", $char);
}
increment_curpos(1);
} else {
get_stuff(1);
$char = substr($stuff, 0, 1);
$nchar = unpack("C", $char);
if ($nchar >= 32 && $nchar < 127) {
print " *$char ";
} else {
printf "*%02x ", unpack("C", $char);
}
increment_curpos(1);
}
}
print "\n";