#!/usr/bin/perl -w use strict; use Carp; # This little program generates GDIFF files from textual version of the # format. It's only intended purpose is for generating test files for # this module. See t/data/*.gdiff.txt for example input files. my %DATA_OPCODE = ( ushort => "\xF7", int => "\xF8", ); my %COPY_OPCODE = ( ushort_ubyte => "\xF9", ushort_ushort => "\xFA", ushort_int => "\xFB", int_ubyte => "\xFC", int_ushort => "\xFD", int_int => "\xFE", long_int => "\xFF", ); binmode STDOUT or die "error setting stdout to binmode: $!"; # The header is always the same. print "\xD1\xFF\xD1\xFF\x04"; while (<>) { chomp; next unless /\S/; next if /^\s*#/; my ($opcode, @arg) = split ' '; @arg = map { parse_arg($_) } @arg; if ($opcode =~ /^data_(\d+)$/i) { my $n = $1; die "line $.: bad 'data_N' command\n" unless $n >= 1 && $n <= 246 && @arg == 1; die "line $.: wrong amount of data in 'data_N' command\n" unless length $arg[0] == $n; print chr($n), $arg[0]; } elsif ($opcode =~ /^data_(ushort|int)$/i) { my $len_type = lc $1; die "line $.: wrong number of args\n" unless @arg == 2; die "line $.: wrong amount of data in second arg\n" unless $arg[0] == length $arg[1]; print $DATA_OPCODE{$len_type}; write_num($len_type, $arg[0]); print $arg[1]; } elsif ($opcode =~ /^copy_(ushort|int|long)_(ubyte|ushort|int)$/i) { my $offset_type = lc $1; my $len_type = lc $2; die "line $.: wrong number of args\n" unless @arg == 2; print $COPY_OPCODE{"${offset_type}_$len_type"}; write_num($offset_type, $arg[0]); write_num($len_type, $arg[1]); } else { die "line $.: unrecognized command '$opcode'\n"; } } # EOF opcode. print "\x00"; sub parse_arg { local $_ = shift; if (/^"(.*)"\z/) { $_ = $1; s/\\n/\n/g; return $_; } elsif (/^0x[\dA-F]+\z/i || /^0\d+\z/) { return oct; } elsif (/^(\d+)\z/) { return $1; } else { die "line $.: bad arg '$_'\n"; } } sub write_num { my ($type, $num) = @_; if ($type eq 'ubyte') { die "line $.: ubyte value out of range\n" if $num > 0xFF; print chr($num); } elsif ($type eq 'ushort') { die "line $.: ushort value out of range\n" if $num > 0xFFFF; print pack('n', $num); } elsif ($type eq 'int') { print pack('N', $num); } elsif ($type eq 'long') { # TODO die "support for 'long' type not implemented yet"; } else { croak "bad number type '$type'"; } } # vi:ts=4 sw=4 expandtab: