"B::COP"
};
+static int walkoptree_debug = 0; /* Flag for walkoptree debug hook */
+
static opclass
-cc_opclass(o)
-OP * o;
+cc_opclass(OP *o)
{
if (!o)
return OPc_NULL;
}
static char *
-cc_opclassname(o)
-OP * o;
+cc_opclassname(OP *o)
{
return opclassnames[cc_opclass(o)];
}
static SV *
-make_sv_object(arg, sv)
-SV *arg;
-SV *sv;
+make_sv_object(SV *arg, SV *sv)
{
char *type = 0;
IV iv;
}
static SV *
-make_mg_object(arg, mg)
-SV *arg;
-MAGIC *mg;
+make_mg_object(SV *arg, MAGIC *mg)
{
sv_setiv(newSVrv(arg, "B::MAGIC"), (IV)mg);
return arg;
}
static SV *
-cstring(sv)
-SV *sv;
+cstring(SV *sv)
{
SV *sstr = newSVpv("", 0);
STRLEN len;
}
static SV *
-cchar(sv)
-SV *sv;
+cchar(SV *sv)
{
SV *sstr = newSVpv("'", 0);
char *s = SvPV(sv, na);
}
void *
-bset_obj_store(obj, ix)
-void *obj;
-I32 ix;
+bset_obj_store(void *obj, I32 ix)
{
if (ix > obj_list_fill) {
if (obj_list_fill == -1)
}
#ifdef INDIRECT_BGET_MACROS
-void freadpv(len, data)
-U32 len;
-void *data;
+void freadpv(U32 len, void *data)
{
New(666, pv.xpv_pv, len, char);
fread(pv.xpv_pv, 1, len, (FILE*)data);
pv.xpv_cur = len - 1;
}
-void byteload_fh(fp)
-FILE *fp;
+void byteload_fh(FILE *fp)
{
struct bytestream bs;
bs.data = fp;
byterun(bs);
}
-static int fgetc_fromstring(data)
-void *data;
+static int fgetc_fromstring(void *data)
{
char **strp = (char **)data;
return *(*strp)++;
}
-static int fread_fromstring(argp, elemsize, nelem, data)
-char *argp;
-size_t elemsize;
-size_t nelem;
-void *data;
+static int fread_fromstring(char *argp, size_t elemsize, size_t nelem,
+ void *data)
{
char **strp = (char **)data;
size_t len = elemsize * nelem;
return (int)len;
}
-static void freadpv_fromstring(len, data)
-U32 len;
-void *data;
+static void freadpv_fromstring(U32 len, void *data)
{
char **strp = (char **)data;
*strp += len;
}
-void byteload_string(str)
-char *str;
+void byteload_string(char *str)
{
struct bytestream bs;
bs.data = &str;
byterun(bs);
}
#else
-void byteload_fh(fp)
-FILE *fp;
+void byteload_fh(FILE *fp)
{
byterun(fp);
}
-void byteload_string(str)
-char *str;
+void byteload_string(char *str)
{
croak("Must compile with -DINDIRECT_BGET_MACROS for byteload_string");
}
#endif /* INDIRECT_BGET_MACROS */
void
-walkoptree(opsv, method)
-SV *opsv;
-char *method;
+walkoptree(SV *opsv, char *method)
{
dSP;
OP *o;
croak("opsv is not a reference");
opsv = sv_mortalcopy(opsv);
o = (OP*)SvIV((SV*)SvRV(opsv));
+ if (walkoptree_debug) {
+ PUSHMARK(sp);
+ XPUSHs(opsv);
+ PUTBACK;
+ perl_call_method("walkoptree_debug", G_DISCARD);
+ }
PUSHMARK(sp);
XPUSHs(opsv);
PUTBACK;
char * method
int
+walkoptree_debug(...)
+ CODE:
+ RETVAL = walkoptree_debug;
+ if (items > 0 && SvTRUE(ST(1)))
+ walkoptree_debug = 1;
+ OUTPUT:
+ RETVAL
+
+int
byteload_fh(fp)
FILE * fp
CODE:
# Bytecode.pm
#
-# Copyright (c) 1996 Malcolm Beattie
+# Copyright (c) 1996-1998 Malcolm Beattie
#
# You may distribute under the terms of either the GNU General Public
# License or the Artistic License, as specified in the README file.
package B::Bytecode;
use strict;
use Carp;
+use IO::File;
use B qw(minus_c main_cv main_root main_start comppadlist
class peekop walkoptree svref_2object cstring walksymtable);
# XXX Shouldn't be hardwired
sub IOK () { 0x01010000 }
-my ($verbose, $module_only, $no_assemble, $debug_cv);
+my ($verbose, $module_only, $no_assemble, $debug_bc, $debug_cv);
my $assembler_pid;
# Optimisation options. On the command line, use hyphens instead of
sub mark_saved { $saved{${$_[0]}} = 1 }
sub unmark_saved { $saved{${$_[0]}} = 0 }
-my $debug = 0;
-sub debug { $debug = shift }
+sub debug { $debug_bc = shift }
sub B::OBJECT::nyi {
my $obj = shift;
stop($ix);
}
+sub B::OP::walkoptree_debug {
+ my $op = shift;
+ warn(sprintf("walkoptree: %s\n", peekop($op)));
+}
+
sub B::OP::bytecode {
my $op = shift;
my $next = $op->next;
}
$nextix = $next->objix;
- printf "# %s\n", peekop($op) if $debug;
+ printf "# %s\n", peekop($op) if $debug_bc;
ldop($ix);
print "op_next $nextix\n";
print "op_sibling $sibix\n" unless $strip_syntree;
my $filegv = $op->filegv;
my $filegvix = $filegv->objix;
my $line = $op->line;
- if ($debug) {
+ if ($debug_bc) {
printf "# line %s:%d\n", $filegv->SV->PV, $line;
}
$op->B::OP::bytecode;
sub B::PMOP::bytecode {
my $op = shift;
- my $short = $op->pmshort;
- my $shortix = $short->objix;
my $replroot = $op->pmreplroot;
my $replrootix = $replroot->objix;
my $replstartix = $op->pmreplstart->objix;
# pmnext is corrupt in some PMOPs (see misc.t for example)
#my $pmnextix = $op->pmnext->objix;
- $short->bytecode;
if ($$replroot) {
# OP_PUSHRE (a mutated version of OP_MATCH for the regexp
# argument to a split) stores a GV in op_pmreplroot instead
}
my $re = pvstring($op->precomp);
# op_pmnext omitted since a perl bug means it's sometime corrupt
- printf <<"EOT", $op->pmflags, $op->pmpermflags, $op->pmslen;
-op_pmshort $shortix
+ printf <<"EOT", $op->pmflags, $op->pmpermflags;
op_pmflags 0x%x
op_pmpermflags 0x%x
-op_pmslen %d
newpv $re
pregcomp
EOT
my $curpadix = $curpad->objix;
$curpad->bytecode;
walkoptree(main_root, "bytecode");
+ warn "done main program, now walking symbol table\n" if $debug_bc;
my ($pack, %exclude);
- foreach $pack (qw(B O AutoLoader DynaLoader Config DB VMS
- strict vars FileHandle Exporter Carp)) {
+ foreach $pack (qw(B O AutoLoader DynaLoader Config DB VMS strict vars
+ FileHandle Exporter Carp UNIVERSAL IO Fcntl Symbol
+ SelectSaver blib Cwd))
+ {
$exclude{$pack."::"} = 1;
}
no strict qw(vars refs);
- walksymtable(\%{"main::"}, "bytecodecv",sub { !defined($exclude{$_[0]}) });
+ walksymtable(\%{"main::"}, "bytecodecv", sub {
+ warn "considering $_[0]\n" if $debug_bc;
+ return !defined($exclude{$_[0]});
+ });
if (!$module_only) {
printf "main_root %d\n", main_root->objix;
printf "main_start %d\n", main_start->objix;
}
}
-sub prepare_output {
- # Plumbing for output
- if (!$no_assemble) {
- pipe(READER, WRITER) or die "pipe: $!\n";
- $assembler_pid = fork();
- die "fork: $!\n" unless defined($assembler_pid);
- if ($assembler_pid) {
- # parent
- close WRITER;
- assemble_fh(\*READER, sub { print @_ });
- exit(0);
- } else {
- # child
- close READER;
- open(STDOUT, ">&WRITER") or die "dup: $!\n";
- }
- }
+sub prepare_assemble {
+ my $newfh = IO::File->new_tmpfile;
+ select($newfh);
+ return $newfh;
+}
+
+sub do_assemble {
+ my $fh = shift;
+ seek($fh, 0, 0); # rewind the temporary file
+ assemble_fh($fh, sub { print OUT @_ });
}
sub compile {
my @options = @_;
my ($option, $opt, $arg);
+ open(OUT, ">&STDOUT");
+ select(OUT);
OPTION:
while ($option = shift @options) {
if ($option =~ /^-(.)(.*)/) {
last OPTION;
} elsif ($opt eq "o") {
$arg ||= shift @options;
- open(STDOUT, ">$arg") or return "$arg: $!\n";
+ open(OUT, ">$arg") or return "$arg: $!\n";
} elsif ($opt eq "D") {
$arg ||= shift @options;
foreach $arg (split(//, $arg)) {
- if ($arg eq "o") {
+ if ($arg eq "b") {
+ $| = 1;
+ debug(1);
+ } elsif ($arg eq "o") {
B->debug(1);
} elsif ($arg eq "a") {
B::Assembler::debug(1);
if (@options) {
return sub {
my $objname;
- prepare_output();
+ my $newfh;
+ $newfh = prepare_assemble() unless $no_assemble;
foreach $objname (@options) {
eval "bytecompile_object(\\$objname)";
}
- waitpid($assembler_pid, 0) if defined($assembler_pid);
+ do_assemble($newfh) unless $no_assemble;
}
} else {
return sub {
- prepare_output();
+ my $newfh;
+ $newfh = prepare_assemble() unless $no_assemble;
bytecompile_main();
- waitpid($assembler_pid, 0) if defined($assembler_pid);
+ do_assemble($newfh) unless $no_assemble;
}
}
}