Move lib/B/... and lib/[BO].pm over to where they should be,
[p5sagit/p5-mst-13.2.git] / ext / B / B / Disassembler.pm
CommitLineData
a798dbf2 1# Disassembler.pm
2#
3# Copyright (c) 1996 Malcolm Beattie
4#
5# You may distribute under the terms of either the GNU General Public
6# License or the Artistic License, as specified in the README file.
7package B::Disassembler::BytecodeStream;
8use FileHandle;
9use Carp;
10use B qw(cstring cast_I32);
11@ISA = qw(FileHandle);
12sub readn {
13 my ($fh, $len) = @_;
14 my $data;
15 read($fh, $data, $len);
16 croak "reached EOF while reading $len bytes" unless length($data) == $len;
17 return $data;
18}
19
20sub GET_U8 {
21 my $fh = shift;
22 my $c = $fh->getc;
23 croak "reached EOF while reading U8" unless defined($c);
24 return ord($c);
25}
26
27sub GET_U16 {
28 my $fh = shift;
29 my $str = $fh->readn(2);
30 croak "reached EOF while reading U16" unless length($str) == 2;
31 return unpack("n", $str);
32}
33
34sub GET_U32 {
35 my $fh = shift;
36 my $str = $fh->readn(4);
37 croak "reached EOF while reading U32" unless length($str) == 4;
38 return unpack("N", $str);
39}
40
41sub GET_I32 {
42 my $fh = shift;
43 my $str = $fh->readn(4);
44 croak "reached EOF while reading I32" unless length($str) == 4;
45 return cast_I32(unpack("N", $str));
46}
47
48sub GET_objindex {
49 my $fh = shift;
50 my $str = $fh->readn(4);
51 croak "reached EOF while reading objindex" unless length($str) == 4;
52 return unpack("N", $str);
53}
54
55sub GET_strconst {
56 my $fh = shift;
57 my ($str, $c);
58 while (defined($c = $fh->getc) && $c ne "\0") {
59 $str .= $c;
60 }
61 croak "reached EOF while reading strconst" unless defined($c);
62 return cstring($str);
63}
64
65sub GET_pvcontents {}
66
67sub GET_PV {
68 my $fh = shift;
69 my $str;
70 my $len = $fh->GET_U32;
71 if ($len) {
72 read($fh, $str, $len);
73 croak "reached EOF while reading PV" unless length($str) == $len;
74 return cstring($str);
75 } else {
76 return '""';
77 }
78}
79
80sub GET_comment {
81 my $fh = shift;
82 my ($str, $c);
83 while (defined($c = $fh->getc) && $c ne "\n") {
84 $str .= $c;
85 }
86 croak "reached EOF while reading comment" unless defined($c);
87 return cstring($str);
88}
89
90sub GET_double {
91 my $fh = shift;
92 my ($str, $c);
93 while (defined($c = $fh->getc) && $c ne "\0") {
94 $str .= $c;
95 }
96 croak "reached EOF while reading double" unless defined($c);
97 return $str;
98}
99
100sub GET_none {}
101
102sub GET_op_tr_array {
103 my $fh = shift;
104 my @ary = unpack("n256", $fh->readn(256 * 2));
105 return join(",", @ary);
106}
107
108sub GET_IV64 {
109 my $fh = shift;
110 my ($hi, $lo) = unpack("NN", $fh->readn(8));
111 return sprintf("0x%4x%04x", $hi, $lo); # cheat
112}
113
114package B::Disassembler;
115use Exporter;
116@ISA = qw(Exporter);
117@EXPORT_OK = qw(disassemble_fh);
118use Carp;
119use strict;
120
121use B::Asmdata qw(%insn_data @insn_name);
122
123sub disassemble_fh {
124 my ($fh, $out) = @_;
125 my ($c, $getmeth, $insn, $arg);
126 bless $fh, "B::Disassembler::BytecodeStream";
127 while (defined($c = $fh->getc)) {
128 $c = ord($c);
129 $insn = $insn_name[$c];
130 if (!defined($insn) || $insn eq "unused") {
131 my $pos = $fh->tell - 1;
132 die "Illegal instruction code $c at stream offset $pos\n";
133 }
134 $getmeth = $insn_data{$insn}->[2];
135 $arg = $fh->$getmeth();
136 if (defined($arg)) {
137 &$out($insn, $arg);
138 } else {
139 &$out($insn);
140 }
141 }
142}
143
1441;