2000/08/31 (木) 21:50:42      [mirai]
#! /usr/local/bin/perl


# 簡易ダンパー
# perl perldump.pl infile.dat // infile.datの中身を先頭から256バイト分表示
# perl perldump.pl infile.dat 1024 5000 // infile.datの中身を5000バイト目から1024バイト分表示

# 対象ファイル(引数1)
$openfile = $ARGV[0];
# ダンプする範囲(引数2・バイト)
$dump_width = $ARGV[1] || 256;
# ダンプをはじめる位置(引数3・先頭からのバイト)
$dump_offset = $ARGV[2] || 0;

# main
OpenFile();
DumpData();
close(IN);
exit(0);

sub OpenFile {
	open(IN,"$openfile") || die "Can't Open infile!\n -> $!\n";
	flock(IN,2);
	binmode(IN);
	seek(IN,$dump_offset,0);
}

sub DumpData {
	my(@dumper,$buffer,@linebuf,$col_count,$row_count,$octet_count);
	my $buf_width = 1024;
	
	# プリヘダ
	print STDERR '-' x 30,' dumped data ','-' x 30,"\n";
	print STDERR ' ' x 8;
	foreach (0 .. 15) {
		printf STDERR ("+%X ",$_);
	}
	print STDERR ' ' x 17,"\n";
	
	# 最初の行(パディング)
	$row_count = int($dump_offset / 16);
	printf STDERR ("%05X0  ",$row_count);
	$col_count = int($dump_offset % 16);
	print STDERR '   ' x $col_count;
	for ($i = 0;$i < $col_count;$i++) {
		push(@linebuf,'');
	}
	
	# 出力
	OUTPUT_LOOP: {
		$octet_count = 0;
		for (;;) {
			read(IN,$buffer,$buf_width) || last;
			foreach $byte (unpack('C*',$buffer)) {
				# メイン出力
				printf("%02X ",$byte);
				push(@linebuf,$byte);
				if (! (++$col_count % 16)) {
					OptionalOut(\@linebuf);
					undef(@linebuf);
					$col_count = 0;
					$row_count++;
					print STDERR "\n";
					# ここから次の行
					printf STDERR ("%05X0  ",$row_count);
				}
				if (++$octet_count >= $dump_width) {
					last OUTPUT_LOOP;
				}
			}
		}
	}
	
	# 最後の行(パディング)
	if ($col_count) {
		while ($col_count++ % 16) {
			print STDERR '   ';
			push(@linebuf,'');
		}
		OptionalOut(\@linebuf);
	}
}

sub OptionalOut {
	my $buf = shift;
	
	print STDERR ' ';
	foreach (@$buf) {
		if ($_ > 30) {
			printf STDERR ("%c",$_);
		} elsif ($_ eq '') {
			print STDERR ' ';
		} else {
			print STDERR '.';
		}
	}
}