Start overhauling compiler. It was working at least minimally
Malcolm Beattie [Wed, 10 Dec 1997 18:33:53 +0000 (18:33 +0000)]
right up until the final tweak of B.xs to add threadsv_names
at which point building it provokes a seg fault in perl while
doing the xsubpp :-(.

p4raw-id: //depot/perlext/Compiler@357

16 files changed:
B.pm
B.xs
B/Asmdata.pm
B/C.pm
B/CC.pm
Makefile.PL
bytecode.pl
byteperl.c
byterun.c
byterun.h
cc_harness
cc_runtime.h
ccop.c
ccop.h
test_harness
test_harness_cc

diff --git a/B.pm b/B.pm
index e304062..3878712 100644 (file)
--- a/B.pm
+++ b/B.pm
@@ -10,7 +10,7 @@ require DynaLoader;
 require Exporter;
 @ISA = qw(Exporter DynaLoader);
 @EXPORT_OK = qw(byteload_fh byteload_string minus_c ppname
-               class peekop cast_I32 cstring cchar hash
+               class peekop cast_I32 cstring cchar hash threadsv_names
                main_root main_start main_cv svref_2object
                walkoptree walkoptree_slow walkoptree_exec walksymtable
                parents comppadlist sv_undef compile_stats timing_info);
diff --git a/B.xs b/B.xs
index 7d20097..b73464a 100644 (file)
--- a/B.xs
+++ b/B.xs
@@ -13,7 +13,6 @@
 #include "INTERN.h"
 #include "bytecode.h"
 #include "byterun.h"
-#include "ccop.h"
 
 static char *svclassnames[] = {
     "B::NULL",
@@ -34,6 +33,142 @@ static char *svclassnames[] = {
     "B::IO",
 };
 
+typedef enum {
+    OPc_NULL,  /* 0 */
+    OPc_BASEOP,        /* 1 */
+    OPc_UNOP,  /* 2 */
+    OPc_BINOP, /* 3 */
+    OPc_LOGOP, /* 4 */
+    OPc_CONDOP,        /* 5 */
+    OPc_LISTOP,        /* 6 */
+    OPc_PMOP,  /* 7 */
+    OPc_SVOP,  /* 8 */
+    OPc_GVOP,  /* 9 */
+    OPc_PVOP,  /* 10 */
+    OPc_CVOP,  /* 11 */
+    OPc_LOOP,  /* 12 */
+    OPc_COP    /* 13 */
+} opclass;
+
+static char *opclassnames[] = {
+    "B::NULL",
+    "B::OP",
+    "B::UNOP",
+    "B::BINOP",
+    "B::LOGOP",
+    "B::CONDOP",
+    "B::LISTOP",
+    "B::PMOP",
+    "B::SVOP",
+    "B::GVOP",
+    "B::PVOP",
+    "B::CVOP",
+    "B::LOOP",
+    "B::COP"   
+};
+
+static opclass
+cc_opclass(o)
+OP *   o;
+{
+    if (!o)
+       return OPc_NULL;
+
+    if (o->op_type == 0)
+       return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
+
+    if (o->op_type == OP_SASSIGN)
+       return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
+
+    switch (opargs[o->op_type] & OA_CLASS_MASK) {
+    case OA_BASEOP:
+       return OPc_BASEOP;
+
+    case OA_UNOP:
+       return OPc_UNOP;
+
+    case OA_BINOP:
+       return OPc_BINOP;
+
+    case OA_LOGOP:
+       return OPc_LOGOP;
+
+    case OA_CONDOP:
+       return OPc_CONDOP;
+
+    case OA_LISTOP:
+       return OPc_LISTOP;
+
+    case OA_PMOP:
+       return OPc_PMOP;
+
+    case OA_SVOP:
+       return OPc_SVOP;
+
+    case OA_GVOP:
+       return OPc_GVOP;
+
+    case OA_PVOP:
+       return OPc_PVOP;
+
+    case OA_LOOP:
+       return OPc_LOOP;
+
+    case OA_COP:
+       return OPc_COP;
+
+    case OA_BASEOP_OR_UNOP:
+       /*
+        * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
+        * whether bare parens were seen. perly.y uses OPf_SPECIAL to
+        * signal whether an OP or an UNOP was chosen.
+        * Frederic.Chauveau@pasteur.fr says we need to check for OPf_KIDS too.
+        */
+       return ((o->op_flags & OPf_SPECIAL) ? OPc_BASEOP :
+               (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP);
+
+    case OA_FILESTATOP:
+       /*
+        * The file stat OPs are created via UNI(OP_foo) in toke.c but use
+        * the OPf_REF flag to distinguish between OP types instead of the
+        * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
+        * return OPc_UNOP so that walkoptree can find our children. If
+        * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
+        * (no argument to the operator) it's an OP; with OPf_REF set it's
+        * a GVOP (and op_gv is the GV for the filehandle argument).
+        */
+       return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
+               (o->op_flags & OPf_REF) ? OPc_GVOP : OPc_BASEOP);
+
+    case OA_LOOPEXOP:
+       /*
+        * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
+        * label was omitted (in which case it's a BASEOP) or else a term was
+        * seen. In this last case, all except goto are definitely PVOP but
+        * goto is either a PVOP (with an ordinary constant label), an UNOP
+        * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
+        * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
+        * get set.
+        */
+       if (o->op_flags & OPf_STACKED)
+           return OPc_UNOP;
+       else if (o->op_flags & OPf_SPECIAL)
+           return OPc_BASEOP;
+       else
+           return OPc_PVOP;
+    }
+    warn("can't determine class of operator %s, assuming BASEOP\n",
+        op_name[o->op_type]);
+    return OPc_BASEOP;
+}
+
+static char *
+cc_opclassname(o)
+OP *   o;
+{
+    return opclassnames[cc_opclass(o)];
+}
+
 static SV *
 make_sv_object(arg, sv)
 SV *arg;
@@ -260,7 +395,6 @@ walkoptree(opsv, method)
 SV *opsv;
 char *method;
 {
-    dTHR;
     dSP;
     OP *o;
     
@@ -386,8 +520,10 @@ ppname(opnum)
        int     opnum
     CODE:
        ST(0) = sv_newmortal();
-       if (opnum >= 0 && opnum < sizeof(ppnames)/sizeof(char*))
-           sv_setpv(ST(0), ppnames[opnum]);
+       if (opnum >= 0 && opnum < maxo) {
+           sv_setpvn(ST(0), "pp_", 3);
+           sv_catpv(ST(0), op_name[opnum]);
+       }
 
 void
 hash(sv)
@@ -421,9 +557,19 @@ SV *
 cchar(sv)
        SV *    sv
 
+void
+threadsv_names()
+    PPCODE:
+       int i;
+       STRLEN len = strlen(threadsv_names);
+
+       EXTEND(sp, len);
+       for (i = 0; i < len; i++)
+           PUSHs(sv_2mortal(newSVpv(&threadsv_names[i], 1)));
+
+
 #define OP_next(o)     o->op_next
 #define OP_sibling(o)  o->op_sibling
-#define OP_ppaddr(o)   ppnames[o->op_type]
 #define OP_desc(o)     op_desc[o->op_type]
 #define OP_targ(o)     o->op_targ
 #define OP_type(o)     o->op_type
@@ -444,6 +590,10 @@ OP_sibling(o)
 char *
 OP_ppaddr(o)
        B::OP           o
+    CODE:
+       ST(0) = sv_newmortal();
+       sv_setpvn(ST(0), "pp_", 3);
+       sv_catpv(ST(0), op_name[o->op_type]);
 
 char *
 OP_desc(o)
@@ -518,10 +668,8 @@ LISTOP_children(o)
 #define PMOP_pmreplstart(o)    o->op_pmreplstart
 #define PMOP_pmnext(o)         o->op_pmnext
 #define PMOP_pmregexp(o)       o->op_pmregexp
-#define PMOP_pmshort(o)                o->op_pmshort
 #define PMOP_pmflags(o)                o->op_pmflags
 #define PMOP_pmpermflags(o)    o->op_pmpermflags
-#define PMOP_pmslen(o)         o->op_pmslen
 
 MODULE = B     PACKAGE = B::PMOP               PREFIX = PMOP_
 
@@ -550,10 +698,6 @@ B::PMOP
 PMOP_pmnext(o)
        B::PMOP         o
 
-B::SV
-PMOP_pmshort(o)
-       B::PMOP         o
-
 U16
 PMOP_pmflags(o)
        B::PMOP         o
@@ -562,10 +706,6 @@ U16
 PMOP_pmpermflags(o)
        B::PMOP         o
 
-U8
-PMOP_pmslen(o)
-       B::PMOP         o
-
 void
 PMOP_precomp(o)
        B::PMOP         o
index 68e1a07..3a3cf6d 100644 (file)
@@ -121,26 +121,24 @@ $insn_data{op_pmreplrootgv} = [97, \&PUT_objindex, "GET_objindex"];
 $insn_data{op_pmreplstart} = [98, \&PUT_objindex, "GET_objindex"];
 $insn_data{op_pmnext} = [99, \&PUT_objindex, "GET_objindex"];
 $insn_data{pregcomp} = [100, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{op_pmshort} = [101, \&PUT_objindex, "GET_objindex"];
-$insn_data{op_pmflags} = [102, \&PUT_U16, "GET_U16"];
-$insn_data{op_pmpermflags} = [103, \&PUT_U16, "GET_U16"];
-$insn_data{op_pmslen} = [104, \&PUT_U8, "GET_U8"];
-$insn_data{op_sv} = [105, \&PUT_objindex, "GET_objindex"];
-$insn_data{op_gv} = [106, \&PUT_objindex, "GET_objindex"];
-$insn_data{op_pv} = [107, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{op_pv_tr} = [108, \&PUT_op_tr_array, "GET_op_tr_array"];
-$insn_data{op_redoop} = [109, \&PUT_objindex, "GET_objindex"];
-$insn_data{op_nextop} = [110, \&PUT_objindex, "GET_objindex"];
-$insn_data{op_lastop} = [111, \&PUT_objindex, "GET_objindex"];
-$insn_data{cop_label} = [112, \&PUT_pvcontents, "GET_pvcontents"];
-$insn_data{cop_stash} = [113, \&PUT_objindex, "GET_objindex"];
-$insn_data{cop_filegv} = [114, \&PUT_objindex, "GET_objindex"];
-$insn_data{cop_seq} = [115, \&PUT_U32, "GET_U32"];
-$insn_data{cop_arybase} = [116, \&PUT_I32, "GET_I32"];
-$insn_data{cop_line} = [117, \&PUT_U16, "GET_U16"];
-$insn_data{main_start} = [118, \&PUT_objindex, "GET_objindex"];
-$insn_data{main_root} = [119, \&PUT_objindex, "GET_objindex"];
-$insn_data{curpad} = [120, \&PUT_objindex, "GET_objindex"];
+$insn_data{op_pmflags} = [101, \&PUT_U16, "GET_U16"];
+$insn_data{op_pmpermflags} = [102, \&PUT_U16, "GET_U16"];
+$insn_data{op_sv} = [103, \&PUT_objindex, "GET_objindex"];
+$insn_data{op_gv} = [104, \&PUT_objindex, "GET_objindex"];
+$insn_data{op_pv} = [105, \&PUT_pvcontents, "GET_pvcontents"];
+$insn_data{op_pv_tr} = [106, \&PUT_op_tr_array, "GET_op_tr_array"];
+$insn_data{op_redoop} = [107, \&PUT_objindex, "GET_objindex"];
+$insn_data{op_nextop} = [108, \&PUT_objindex, "GET_objindex"];
+$insn_data{op_lastop} = [109, \&PUT_objindex, "GET_objindex"];
+$insn_data{cop_label} = [110, \&PUT_pvcontents, "GET_pvcontents"];
+$insn_data{cop_stash} = [111, \&PUT_objindex, "GET_objindex"];
+$insn_data{cop_filegv} = [112, \&PUT_objindex, "GET_objindex"];
+$insn_data{cop_seq} = [113, \&PUT_U32, "GET_U32"];
+$insn_data{cop_arybase} = [114, \&PUT_I32, "GET_I32"];
+$insn_data{cop_line} = [115, \&PUT_U16, "GET_U16"];
+$insn_data{main_start} = [116, \&PUT_objindex, "GET_objindex"];
+$insn_data{main_root} = [117, \&PUT_objindex, "GET_objindex"];
+$insn_data{curpad} = [118, \&PUT_objindex, "GET_objindex"];
 
 my ($insn_name, $insn_data);
 while (($insn_name, $insn_data) = each %insn_data) {
diff --git a/B/C.pm b/B/C.pm
index 4ca8219..5d903c0 100644 (file)
--- a/B/C.pm
+++ b/B/C.pm
@@ -12,7 +12,8 @@ use Exporter ();
                init_sections set_callback save_unused_subs objsym);
 
 use B qw(minus_c sv_undef walkoptree walksymtable main_root main_start peekop
-        class cstring cchar svref_2object compile_stats comppadlist hash);
+        class cstring cchar svref_2object compile_stats comppadlist hashi
+        threadsv_names);
 use B::Asmdata qw(@specialsv_name);
 
 use FileHandle;
@@ -33,6 +34,11 @@ my $nullop_count;
 my $pv_copy_on_grow;
 my ($debug_cops, $debug_av, $debug_cv, $debug_mg);
 
+my @threadsv_names;
+BEGIN {
+    @threadsv_names = threadsv_names();
+}
+
 # Code sections
 my ($init, $decl, $symsect, $binopsect, $condopsect, $copsect, $cvopsect,
     $gvopsect, $listopsect, $logopsect, $loopsect, $opsect, $pmopsect,
@@ -62,6 +68,10 @@ my $op_seq = 65535;
 
 sub AVf_REAL () { 1 }
 
+# XXX This shouldn't really be hardcoded here but it saves
+# looking up the name of every BASEOP in B::OP
+sub OP_THREADSV () { 345 }
+
 sub savesym {
     my ($obj, $value) = @_;
     my $sym = sprintf("s\\_%x", $$obj);
@@ -107,6 +117,11 @@ sub B::OP::save {
     my ($op, $level) = @_;
     my $type = $op->type;
     $nullop_count++ unless $type;
+    if ($type == OP_THREADSV) {
+       # saves looking up ppaddr but it's a bit naughty to hard code this
+       $init->add(sprintf("(void)find_threadsv(%s);",
+                          cstring($threadsv_names[$op->targ]));
+    }
     $opsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x",
                         ${$op->next}, ${$op->sibling}, $op->ppaddr, $op->targ,
                         $type, $op_seq, $op->flags, $op->private));
@@ -244,7 +259,6 @@ sub B::COP::save {
 
 sub B::PMOP::save {
     my ($op, $level) = @_;
-    my $shortsym = $op->pmshort->save;
     my $replroot = $op->pmreplroot;
     my $replstart = $op->pmreplstart;
     my $replrootfield = sprintf("s\\_%x", $$replroot);
@@ -266,12 +280,12 @@ sub B::PMOP::save {
     # pmnext handling is broken in perl itself, I think. Bad op_pmnext
     # fields aren't noticed in perl's runtime (unless you try reset) but we
     # segfault when trying to dereference it to find op->op_pmnext->op_type
-    $pmopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u, %s, %s, 0, 0, %s, 0x%x, 0x%x, %u",
+    $pmopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u, %s, %s, 0, 0, 0x%x, 0x%x",
                           ${$op->next}, ${$op->sibling}, $ppaddr, $op->targ,
                           $op->type, $op_seq, $op->flags, $op->private,
                           ${$op->first}, ${$op->last}, $op->children,
-                          $replrootfield, $replstartfield, $shortsym,
-                          $op->pmflags, $op->pmpermflags, $op->pmslen));
+                          $replrootfield, $replstartfield,
+                          $op->pmflags, $op->pmpermflags,));
     my $pm = sprintf("pmop_list[%d]", $pmopsect->index);
     my $re = $op->precomp;
     if (defined($re)) {
@@ -857,7 +871,11 @@ sub output_all {
        }
     }
 
-    print "static int $init_name()\n{\n";
+    print <<"EOT";
+static int $init_name()
+{
+       dTHR;
+EOT
     $init->output(\*STDOUT, "\t%s\n");
     print "\treturn 0;\n}\n";
     if ($verbose) {
@@ -898,6 +916,10 @@ typedef struct {
     long       xcv_depth;              /* >= 2 indicates recursive call */
     AV *       xcv_padlist;
     CV *       xcv_outside;
+#ifdef USE_THREADS
+    perl_mutex *xcv_mutexp;
+    struct perl_thread *xcv_owner;     /* current owner thread */
+#endif /* USE_THREADS */
     U8         xcv_flags;
 } XPVCV_or_similar;
 #define ANYINIT(i) i
@@ -918,31 +940,16 @@ EOT
 
 sub output_boilerplate {
     print <<'EOT';
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "EXTERN.h"
 #include "perl.h"
 #ifndef PATCHLEVEL
 #include "patchlevel.h"
 #endif
 
-#ifdef __cplusplus
-}
-#  define EXTERN_C extern "C"
-#else
-#  define EXTERN_C extern
-#endif
-
 /* Workaround for mapstart: the only op which needs a different ppaddr */
 #undef pp_mapstart
 #define pp_mapstart pp_grepstart
 
-#if PATCHLEVEL < 4
-#define vivify_ref(sv, to_what) provide_ref(op, sv)
-#endif
-
 static void xs_init _((void));
 static PerlInterpreter *my_perl;
 EOT
@@ -966,11 +973,7 @@ main(int argc, char **argv, char **env)
 
     PERL_SYS_INIT(&argc,&argv);
  
-#if PATCHLEVEL > 3 || (PATCHLEVEL == 3 && SUBVERSION >= 1)
     perl_init_i18nl10n(1);
-#else
-    perl_init_i18nl14n(1);
-#endif
 
     if (!do_undump) {
        my_perl = perl_alloc();
diff --git a/B/CC.pm b/B/CC.pm
index 25956dd..fc7cf6d 100644 (file)
--- a/B/CC.pm
+++ b/B/CC.pm
@@ -162,7 +162,7 @@ sub init_pp {
     $ppname = shift;
     $runtime_list_ref = [];
     $declare_ref = {};
-    runtime("dSP;");
+    runtime("djSP;");
     declare("I32", "oldsave");
     declare("SV", "**svp");
     map { declare("SV", "*$_") } qw(sv src dst left right);
@@ -544,7 +544,6 @@ sub pp_padsv {
        if ($private & OPpLVAL_INTRO) {
            runtime("SAVECLEARSV(curpad[$ix]);");
        } elsif ($private & OPpDEREF) {
-           loadop($op) if $patchlevel < 4;
            runtime(sprintf("vivify_ref(curpad[%d], %d);",
                            $ix, $private & OPpDEREF));
            $pad[$ix]->invalidate;
@@ -947,7 +946,7 @@ sub pp_entersub {
     write_back_lexicals(REGISTER|TEMPORARY);
     write_back_stack();
     my $sym = doop($op);
-    runtime("if (op != ($sym)->op_next) op = (*op->op_ppaddr)();");
+    runtime("if (op != ($sym)->op_next) op = (*op->op_ppaddr)(ARGS);");
     runtime("SPAGAIN;");
     $know_op = 0;
     invalidate_lexicals(REGISTER|TEMPORARY);
@@ -966,7 +965,7 @@ sub pp_leavewrite {
     my $sym = doop($op);
     # XXX Is this the right way to distinguish between it returning
     # CvSTART(cv) (via doform) and pop_return()?
-    runtime("if (op) op = (*op->op_ppaddr)();");
+    runtime("if (op) op = (*op->op_ppaddr)(ARGS);");
     runtime("SPAGAIN;");
     $know_op = 0;
     invalidate_lexicals(REGISTER|TEMPORARY);
index 7331bfd..b3b9bd0 100644 (file)
@@ -3,11 +3,10 @@ use Config;
 
 WriteMakefile(
     NAME       => "B",
-    VERSION    => "a4",
-    OBJECT     => "B.o ccop.o byterun.o",
+    VERSION    => "a5",
+    OBJECT     => "B.o byterun.o",
     depend     => {
-       "B.o"           => "B.c ccop.h bytecode.h byterun.h",
-       "ccop.o"        => "ccop.c ccop.h"
+       "B.o"           => "B.c bytecode.h byterun.h",
     },
     clean      => {
        FILES           => "perl byteperl btest btest.c *.o B.c *~"
@@ -37,7 +36,7 @@ regen_headers:
 # at the moment because a standlone Perl program needs to set up curpad
 # which is overwritten on exit from an XSUB.
 #
-byteperl: byteperl.o B.o ccop.o byterun.o
-       $(CC) -o byteperl byteperl.o B.o ccop.o byterun.o $(LDFLAGS) -L$(PERL_ARCHLIB)/CORE -lperl $(LIBS)
+byteperl: byteperl.o B.o byterun.o
+       $(CC) -o byteperl byteperl.o B.o byterun.o $(LDFLAGS) -L$(PERL_ARCHLIB)/CORE -lperl $(LIBS)
 EOT
 }
index f24f379..0dd7c1e 100644 (file)
@@ -40,14 +40,14 @@ if (-f "byterun.c") {
 if (-f "byterun.h") {
     rename("byterun.h", "byterun.h.old");
 }
-if (-f "Asmdata.pm") {
-    rename("Asmdata.pm", "Asmdata.pm.old");
+if (-f "B/Asmdata.pm") {
+    rename("B/Asmdata.pm", "B/Asmdata.pm.old");
 }
 
 #
 # Start with boilerplate for Asmdata.pm
 #
-open(ASMDATA_PM, ">Asmdata.pm") or die "Asmdata.pm: $!";
+open(ASMDATA_PM, ">B/Asmdata.pm") or die "Asmdata.pm: $!";
 print ASMDATA_PM $perl_header, <<'EOT';
 package B::Asmdata;
 use Exporter;
@@ -356,10 +356,8 @@ op_pmreplrootgv    *(SV**)&cPMOP->op_pmreplroot    svindex
 op_pmreplstart cPMOP->op_pmreplstart   opindex
 op_pmnext      *(OP**)&cPMOP->op_pmnext        opindex
 pregcomp       op                      pvcontents      x
-op_pmshort     cPMOP->op_pmshort       svindex
 op_pmflags     cPMOP->op_pmflags       U16
 op_pmpermflags cPMOP->op_pmpermflags   U16
-op_pmslen      cPMOP->op_pmslen        char
 op_sv          cSVOP->op_sv            svindex
 op_gv          *(SV**)&cGVOP->op_gv    svindex
 op_pv          cPVOP->op_pv            pvcontents
index c40e0d3..b86615a 100644 (file)
@@ -1,7 +1,3 @@
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include "EXTERN.h"
 #include "perl.h"
 #ifndef PATCHLEVEL
@@ -9,13 +5,6 @@ extern "C" {
 #endif
 #include "byterun.h"
 
-#ifdef __cplusplus
-}
-#  define EXTERN_C extern "C"
-#else
-#  define EXTERN_C extern
-#endif
-
 static void xs_init _((void));
 static PerlInterpreter *my_perl;
 
index d478a90..6b242e5 100644 (file)
--- a/byterun.c
+++ b/byterun.c
@@ -723,140 +723,126 @@ FILE *fp;
                BSET_pregcomp(op, arg);
                break;
            }
-         case INSN_OP_PMSHORT:         /* 101 */
-           {
-               svindex arg;
-               BGET_objindex(arg);
-               cPMOP->op_pmshort = arg;
-               break;
-           }
-         case INSN_OP_PMFLAGS:         /* 102 */
+         case INSN_OP_PMFLAGS:         /* 101 */
            {
                U16 arg;
                BGET_U16(arg);
                cPMOP->op_pmflags = arg;
                break;
            }
-         case INSN_OP_PMPERMFLAGS:             /* 103 */
+         case INSN_OP_PMPERMFLAGS:             /* 102 */
            {
                U16 arg;
                BGET_U16(arg);
                cPMOP->op_pmpermflags = arg;
                break;
            }
-         case INSN_OP_PMSLEN:          /* 104 */
-           {
-               char arg;
-               BGET_U8(arg);
-               cPMOP->op_pmslen = arg;
-               break;
-           }
-         case INSN_OP_SV:              /* 105 */
+         case INSN_OP_SV:              /* 103 */
            {
                svindex arg;
                BGET_objindex(arg);
                cSVOP->op_sv = arg;
                break;
            }
-         case INSN_OP_GV:              /* 106 */
+         case INSN_OP_GV:              /* 104 */
            {
                svindex arg;
                BGET_objindex(arg);
                *(SV**)&cGVOP->op_gv = arg;
                break;
            }
-         case INSN_OP_PV:              /* 107 */
+         case INSN_OP_PV:              /* 105 */
            {
                pvcontents arg;
                BGET_pvcontents(arg);
                cPVOP->op_pv = arg;
                break;
            }
-         case INSN_OP_PV_TR:           /* 108 */
+         case INSN_OP_PV_TR:           /* 106 */
            {
                op_tr_array arg;
                BGET_op_tr_array(arg);
                cPVOP->op_pv = arg;
                break;
            }
-         case INSN_OP_REDOOP:          /* 109 */
+         case INSN_OP_REDOOP:          /* 107 */
            {
                opindex arg;
                BGET_objindex(arg);
                cLOOP->op_redoop = arg;
                break;
            }
-         case INSN_OP_NEXTOP:          /* 110 */
+         case INSN_OP_NEXTOP:          /* 108 */
            {
                opindex arg;
                BGET_objindex(arg);
                cLOOP->op_nextop = arg;
                break;
            }
-         case INSN_OP_LASTOP:          /* 111 */
+         case INSN_OP_LASTOP:          /* 109 */
            {
                opindex arg;
                BGET_objindex(arg);
                cLOOP->op_lastop = arg;
                break;
            }
-         case INSN_COP_LABEL:          /* 112 */
+         case INSN_COP_LABEL:          /* 110 */
            {
                pvcontents arg;
                BGET_pvcontents(arg);
                cCOP->cop_label = arg;
                break;
            }
-         case INSN_COP_STASH:          /* 113 */
+         case INSN_COP_STASH:          /* 111 */
            {
                svindex arg;
                BGET_objindex(arg);
                *(SV**)&cCOP->cop_stash = arg;
                break;
            }
-         case INSN_COP_FILEGV:         /* 114 */
+         case INSN_COP_FILEGV:         /* 112 */
            {
                svindex arg;
                BGET_objindex(arg);
                *(SV**)&cCOP->cop_filegv = arg;
                break;
            }
-         case INSN_COP_SEQ:            /* 115 */
+         case INSN_COP_SEQ:            /* 113 */
            {
                U32 arg;
                BGET_U32(arg);
                cCOP->cop_seq = arg;
                break;
            }
-         case INSN_COP_ARYBASE:                /* 116 */
+         case INSN_COP_ARYBASE:                /* 114 */
            {
                I32 arg;
                BGET_I32(arg);
                cCOP->cop_arybase = arg;
                break;
            }
-         case INSN_COP_LINE:           /* 117 */
+         case INSN_COP_LINE:           /* 115 */
            {
                line_t arg;
                BGET_U16(arg);
                cCOP->cop_line = arg;
                break;
            }
-         case INSN_MAIN_START:         /* 118 */
+         case INSN_MAIN_START:         /* 116 */
            {
                opindex arg;
                BGET_objindex(arg);
                main_start = arg;
                break;
            }
-         case INSN_MAIN_ROOT:          /* 119 */
+         case INSN_MAIN_ROOT:          /* 117 */
            {
                opindex arg;
                BGET_objindex(arg);
                main_root = arg;
                break;
            }
-         case INSN_CURPAD:             /* 120 */
+         case INSN_CURPAD:             /* 118 */
            {
                svindex arg;
                BGET_objindex(arg);
index b8c557c..0e10b63 100644 (file)
--- a/byterun.h
+++ b/byterun.h
@@ -130,27 +130,25 @@ enum {
     INSN_OP_PMREPLSTART,                       /* 98 */
     INSN_OP_PMNEXT,                    /* 99 */
     INSN_PREGCOMP,                     /* 100 */
-    INSN_OP_PMSHORT,                   /* 101 */
-    INSN_OP_PMFLAGS,                   /* 102 */
-    INSN_OP_PMPERMFLAGS,                       /* 103 */
-    INSN_OP_PMSLEN,                    /* 104 */
-    INSN_OP_SV,                        /* 105 */
-    INSN_OP_GV,                        /* 106 */
-    INSN_OP_PV,                        /* 107 */
-    INSN_OP_PV_TR,                     /* 108 */
-    INSN_OP_REDOOP,                    /* 109 */
-    INSN_OP_NEXTOP,                    /* 110 */
-    INSN_OP_LASTOP,                    /* 111 */
-    INSN_COP_LABEL,                    /* 112 */
-    INSN_COP_STASH,                    /* 113 */
-    INSN_COP_FILEGV,                   /* 114 */
-    INSN_COP_SEQ,                      /* 115 */
-    INSN_COP_ARYBASE,                  /* 116 */
-    INSN_COP_LINE,                     /* 117 */
-    INSN_MAIN_START,                   /* 118 */
-    INSN_MAIN_ROOT,                    /* 119 */
-    INSN_CURPAD,                       /* 120 */
-    MAX_INSN = 120
+    INSN_OP_PMFLAGS,                   /* 101 */
+    INSN_OP_PMPERMFLAGS,                       /* 102 */
+    INSN_OP_SV,                        /* 103 */
+    INSN_OP_GV,                        /* 104 */
+    INSN_OP_PV,                        /* 105 */
+    INSN_OP_PV_TR,                     /* 106 */
+    INSN_OP_REDOOP,                    /* 107 */
+    INSN_OP_NEXTOP,                    /* 108 */
+    INSN_OP_LASTOP,                    /* 109 */
+    INSN_COP_LABEL,                    /* 110 */
+    INSN_COP_STASH,                    /* 111 */
+    INSN_COP_FILEGV,                   /* 112 */
+    INSN_COP_SEQ,                      /* 113 */
+    INSN_COP_ARYBASE,                  /* 114 */
+    INSN_COP_LINE,                     /* 115 */
+    INSN_MAIN_START,                   /* 116 */
+    INSN_MAIN_ROOT,                    /* 117 */
+    INSN_CURPAD,                       /* 118 */
+    MAX_INSN = 118
 };
 
 enum {
index 6db623a..b00b65d 100644 (file)
@@ -1,6 +1,6 @@
 use Config;
 
-$libdir = "$Config{installarchlib}/CORE";
+$libdir = $ENV{PERL_SRC} || "$Config{installarchlib}/CORE";
 
 if (!grep(/^-[cS]$/, @ARGV)) {
     $linkargs = sprintf("%s -L$libdir -lperl %s", @Config{qw(ldflags libs)});
index 5d2e640..fe830c0 100644 (file)
@@ -1,4 +1,4 @@
-#define DOOP(ppname) PUTBACK; op = ppname(); SPAGAIN
+#define DOOP(ppname) PUTBACK; op = ppname(ARGS); SPAGAIN
 
 #define PP_LIST(g) do {                        \
        dMARK;                          \
        SPAGAIN;                \
     } while(0)
 
-#if PATCHLEVEL < 3
-#define RUN() run()
-#else
-#define RUN() runops()
-#endif
-
-#if PATCHLEVEL > 3
 /* Anyone using eval "" deserves this mess */
 #define PP_EVAL(ppaddr, nxt) do {              \
        dJMPENV;                                \
@@ -50,9 +43,9 @@
        JMPENV_PUSH(ret);                       \
        switch (ret) {                          \
        case 0:                                 \
-           op = ppaddr();                      \
+           op = ppaddr(ARGS);                  \
            retstack[retstack_ix - 1] = Nullop; \
-           if (op != nxt) RUN();               \
+           if (op != nxt) runops();            \
            JMPENV_POP;                         \
            break;                              \
        case 1: JMPENV_POP; JMPENV_JUMP(1);     \
        case 3: JMPENV_POP; SPAGAIN; goto label;\
        }                                       \
     } while (0)
-#else
-/* Anyone using eval "" deserves this mess */
-#define PP_EVAL(ppaddr, nxt) do {              \
-       Sigjmp_buf oldtop;                      \
-       Copy(top_env,oldtop,1,Sigjmp_buf);      \
-       PUTBACK;                                \
-       switch (Sigsetjmp(top_env,1)) {         \
-       case 0:                                 \
-           op = ppaddr();                      \
-           retstack[retstack_ix - 1] = Nullop; \
-           Copy(oldtop,top_env,1,Sigjmp_buf);  \
-           if (op != nxt) RUN();               \
-           break;                              \
-       case 1: Copy(oldtop,top_env,1,Sigjmp_buf); Siglongjmp(top_env,1); \
-       case 2: Copy(oldtop,top_env,1,Sigjmp_buf); Siglongjmp(top_env,2); \
-       case 3:                                 \
-           Copy(oldtop,top_env,1,Sigjmp_buf);  \
-           if (restartop != nxt)               \
-               Siglongjmp(top_env, 3);         \
-       }                                       \
-       op = nxt;                               \
-       SPAGAIN;                                \
-    } while (0)
-
-#define PP_ENTERTRY(jmpbuf,label) do {         \
-       Copy(top_env,jmpbuf,1,Sigjmp_buf);      \
-       switch (Sigsetjmp(top_env,1)) {         \
-       case 1: Copy(jmpbuf,top_env,1,Sigjmp_buf); Siglongjmp(top_env,1); \
-       case 2: Copy(jmpbuf,top_env,1,Sigjmp_buf); Siglongjmp(top_env,2); \
-       case 3: Copy(jmpbuf,top_env,1,Sigjmp_buf); SPAGAIN; goto label; \
-       }                                       \
-    } while (0)
-#endif
diff --git a/ccop.c b/ccop.c
index 4d4ed85..20902c7 100644 (file)
--- a/ccop.c
+++ b/ccop.c
@@ -29,535 +29,105 @@ static char *opclassnames[] = {
     "B::COP"   
 };
 
-static opclass
-cc_baseop(o)
-OP *o;
-{
-    return OPc_BASEOP;
-}
-
-static opclass
-cc_unop(o)
-OP *o;
-{
-    return OPc_UNOP;
-}
-
-static opclass
-cc_binop(o)
-OP *o;
-{
-    return OPc_BINOP;
-}
-
-static opclass
-cc_logop(o)
-OP *o;
-{
-    return OPc_LOGOP;
-}
-
-static opclass
-cc_condop(o)
-OP *o;
-{
-    return OPc_CONDOP;
-}
-
-static opclass
-cc_listop(o)
-OP *o;
+opclass
+cc_opclass(o)
+OP *   o;
 {
-    return OPc_LISTOP;
-}
+    if (!o)
+       return OPc_NULL;
 
-static opclass
-cc_pmop(o)
-OP *o;
-{
-    return OPc_PMOP;
-}
+    if (o->op_type == 0)
+       return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
 
-static opclass
-cc_svop(o)
-OP *o;
-{
-    return OPc_SVOP;
-}
+    if (o->op_type == OP_SASSIGN)
+       return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
 
-static opclass
-cc_gvop(o)
-OP *o;
-{
-    return OPc_GVOP;
-}
-
-static opclass
-cc_pvop(o)
-OP *o;
-{
-    return OPc_PVOP;
-}
+    switch (opargs[o->op_type] & OA_CLASS_MASK) {
+    case OA_BASEOP:
+       return OPc_BASEOP;
 
-static opclass
-cc_cvop(o)
-OP *o;
-{
-    return OPc_CVOP;
-}
+    case OA_UNOP:
+       return OPc_UNOP;
 
-static opclass
-cc_loop(o)
-OP *o;
-{
-    return OPc_LOOP;
-}
+    case OA_BINOP:
+       return OPc_BINOP;
 
-static opclass
-cc_cop(o)
-OP *o;
-{
-    return OPc_COP;
-}
+    case OA_LOGOP:
+       return OPc_LOGOP;
 
-/* Nullified ops with children still need to be able to find o->op_first */
-static opclass
-cc_nullop(o)
-OP *o;
-{
-    return ((o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP);
-}
+    case OA_CONDOP:
+       return OPc_CONDOP;
 
-static opclass
-cc_stub(o)
-OP *o;
-{
-    warn("compiler stub for %s, assuming BASEOP\n", ppnames[o->op_type]);
-    return OPc_BASEOP;         /* XXX lie */
-}
+    case OA_LISTOP:
+       return OPc_LISTOP;
 
-/*
- * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on whether
- * bare parens were seen. perly.y uses OPf_SPECIAL to signal whether an
- * OP or an UNOP was chosen.
- * Frederic.Chauveau@pasteur.fr says we need to check for OPf_KIDS too.
- */
-static opclass
-cc_baseop_or_unop(o)
-OP *o;
-{
-    return ((o->op_flags & OPf_SPECIAL) ? OPc_BASEOP :
-           (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP);
-}
+    case OA_PMOP:
+       return OPc_PMOP;
 
-/*
- * The file stat OPs are created via UNI(OP_foo) in toke.c but use
- * the OPf_REF flag to distinguish between OP types instead of the
- * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
- * return OPc_UNOP so that walkoptree can find our children. If
- * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
- * (no argument to the operator) it's an OP; with OPf_REF set it's
- * a GVOP (and op_gv is the GV for the filehandle argument).
- */
-static opclass
-cc_filestatop(o)
-OP *o;
-{
-    return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
-           (o->op_flags & OPf_REF) ? OPc_GVOP : OPc_BASEOP);
-}
+    case OA_SVOP:
+       return OPc_SVOP;
 
-/*
- * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
- * label was omitted (in which case it's a BASEOP) or else a term was
- * seen. In this last case, all except goto are definitely PVOP but goto
- * is either a PVOP (with an ordinary constant label), an UNOP with
- * OPf_STACKED (with a non-constant non-sub) or an UNOP for OP_REFGEN
- * (with goto &sub) in which case OPf_STACKED also seems to get set.
- */
+    case OA_GVOP:
+       return OPc_GVOP;
 
-static opclass
-cc_loopexop(o)
-OP *o;
-{
-    if (o->op_flags & OPf_STACKED)
-       return OPc_UNOP;
-    else if (o->op_flags & OPf_SPECIAL)
-       return OPc_BASEOP;
-    else
+    case OA_PVOP:
        return OPc_PVOP;
-}
-
-static opclass
-cc_sassign(o)
-OP *o;
-{
-    return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
-}
 
-static opclass (*ccopaddr[])_((OP *o)) = {
-       cc_nullop,              /* null */
-       cc_baseop,              /* stub */
-       cc_baseop_or_unop,      /* scalar */
-       cc_baseop,              /* pushmark */
-       cc_baseop,              /* wantarray */
-       cc_svop,                /* const */
-       cc_gvop,                /* gvsv */
-       cc_gvop,                /* gv */
-       cc_binop,               /* gelem */
-       cc_baseop,              /* padsv */
-       cc_baseop,              /* padav */
-       cc_baseop,              /* padhv */
-       cc_baseop,              /* padany */
-       cc_pmop,                /* pushre */
-       cc_unop,                /* rv2gv */
-       cc_unop,                /* rv2sv */
-       cc_unop,                /* av2arylen */
-       cc_unop,                /* rv2cv */
-       cc_svop,                /* anoncode */
-       cc_baseop_or_unop,      /* prototype */
-       cc_unop,                /* refgen */
-       cc_unop,                /* srefgen */
-       cc_baseop_or_unop,      /* ref */
-       cc_listop,              /* bless */
-       cc_baseop_or_unop,      /* backtick */
-       cc_listop,              /* glob */
-       cc_baseop_or_unop,      /* readline */
-       cc_stub,                /* rcatline */
-       cc_unop,                /* regcmaybe */
-       cc_logop,               /* regcomp */
-       cc_pmop,                /* match */
-       cc_pmop,                /* subst */
-       cc_logop,               /* substcont */
-       cc_pvop,                /* trans */
-       cc_sassign,             /* sassign */
-       cc_binop,               /* aassign */
-       cc_baseop_or_unop,      /* chop */
-       cc_baseop_or_unop,      /* schop */
-       cc_baseop_or_unop,      /* chomp */
-       cc_baseop_or_unop,      /* schomp */
-       cc_baseop_or_unop,      /* defined */
-       cc_baseop_or_unop,      /* undef */
-       cc_baseop_or_unop,      /* study */
-       cc_baseop_or_unop,      /* pos */
-       cc_unop,                /* preinc */
-       cc_unop,                /* i_preinc */
-       cc_unop,                /* predec */
-       cc_unop,                /* i_predec */
-       cc_unop,                /* postinc */
-       cc_unop,                /* i_postinc */
-       cc_unop,                /* postdec */
-       cc_unop,                /* i_postdec */
-       cc_binop,               /* pow */
-       cc_binop,               /* multiply */
-       cc_binop,               /* i_multiply */
-       cc_binop,               /* divide */
-       cc_binop,               /* i_divide */
-       cc_binop,               /* modulo */
-       cc_binop,               /* i_modulo */
-       cc_binop,               /* repeat */
-       cc_binop,               /* add */
-       cc_binop,               /* i_add */
-       cc_binop,               /* subtract */
-       cc_binop,               /* i_subtract */
-       cc_binop,               /* concat */
-       cc_listop,              /* stringify */
-       cc_binop,               /* left_shift */
-       cc_binop,               /* right_shift */
-       cc_binop,               /* lt */
-       cc_binop,               /* i_lt */
-       cc_binop,               /* gt */
-       cc_binop,               /* i_gt */
-       cc_binop,               /* le */
-       cc_binop,               /* i_le */
-       cc_binop,               /* ge */
-       cc_binop,               /* i_ge */
-       cc_binop,               /* eq */
-       cc_binop,               /* i_eq */
-       cc_binop,               /* ne */
-       cc_binop,               /* i_ne */
-       cc_binop,               /* ncmp */
-       cc_binop,               /* i_ncmp */
-       cc_binop,               /* slt */
-       cc_binop,               /* sgt */
-       cc_binop,               /* sle */
-       cc_binop,               /* sge */
-       cc_binop,               /* seq */
-       cc_binop,               /* sne */
-       cc_binop,               /* scmp */
-       cc_binop,               /* bit_and */
-       cc_binop,               /* bit_xor */
-       cc_binop,               /* bit_or */
-       cc_unop,                /* negate */
-       cc_unop,                /* i_negate */
-       cc_unop,                /* not */
-       cc_unop,                /* complement */
-       cc_listop,              /* atan2 */
-       cc_baseop_or_unop,      /* sin */
-       cc_baseop_or_unop,      /* cos */
-       cc_baseop_or_unop,      /* rand */
-       cc_baseop_or_unop,      /* srand */
-       cc_baseop_or_unop,      /* exp */
-       cc_baseop_or_unop,      /* log */
-       cc_baseop_or_unop,      /* sqrt */
-       cc_baseop_or_unop,      /* int */
-       cc_baseop_or_unop,      /* hex */
-       cc_baseop_or_unop,      /* oct */
-       cc_baseop_or_unop,      /* abs */
-       cc_baseop_or_unop,      /* length */
-       cc_listop,              /* substr */
-       cc_listop,              /* vec */
-       cc_listop,              /* index */
-       cc_listop,              /* rindex */
-       cc_listop,              /* sprintf */
-       cc_listop,              /* formline */
-       cc_baseop_or_unop,      /* ord */
-       cc_baseop_or_unop,      /* chr */
-       cc_listop,              /* crypt */
-       cc_baseop_or_unop,      /* ucfirst */
-       cc_baseop_or_unop,      /* lcfirst */
-       cc_baseop_or_unop,      /* uc */
-       cc_baseop_or_unop,      /* lc */
-       cc_baseop_or_unop,      /* quotemeta */
-       cc_unop,                /* rv2av */
-       cc_gvop,                /* aelemfast */
-       cc_binop,               /* aelem */
-       cc_listop,              /* aslice */
-       cc_baseop_or_unop,      /* each */
-       cc_baseop_or_unop,      /* values */
-       cc_baseop_or_unop,      /* keys */
-       cc_baseop_or_unop,      /* delete */
-       cc_baseop_or_unop,      /* exists */
-       cc_unop,                /* rv2hv */
-       cc_binop,               /* helem */
-       cc_listop,              /* hslice */
-       cc_listop,              /* unpack */
-       cc_listop,              /* pack */
-       cc_listop,              /* split */
-       cc_listop,              /* join */
-       cc_listop,              /* list */
-       cc_binop,               /* lslice */
-       cc_listop,              /* anonlist */
-       cc_listop,              /* anonhash */
-       cc_listop,              /* splice */
-       cc_listop,              /* push */
-       cc_baseop_or_unop,      /* pop */
-       cc_baseop_or_unop,      /* shift */
-       cc_listop,              /* unshift */
-       cc_listop,              /* sort */
-       cc_listop,              /* reverse */
-       cc_listop,              /* grepstart */
-       cc_logop,               /* grepwhile */
-       cc_listop,              /* mapstart */
-       cc_logop,               /* mapwhile */
-       cc_condop,              /* range */
-       cc_unop,                /* flip */
-       cc_unop,                /* flop */
-       cc_logop,               /* and */
-       cc_logop,               /* or */
-       cc_logop,               /* xor */
-       cc_condop,              /* cond_expr */
-       cc_logop,               /* andassign */
-       cc_logop,               /* orassign */
-       cc_unop,                /* method */
-       cc_unop,                /* entersub */
-       cc_unop,                /* leavesub */
-       cc_baseop_or_unop,      /* caller */
-       cc_listop,              /* warn */
-       cc_listop,              /* die */
-       cc_baseop_or_unop,      /* reset */
-       cc_listop,              /* lineseq */
-       cc_cop,                 /* nextstate */
-       cc_cop,                 /* dbstate */
-       cc_baseop,              /* unstack */
-       cc_baseop,              /* enter */
-       cc_listop,              /* leave */
-       cc_listop,              /* scope */
-       cc_loop,                /* enteriter */
-       cc_baseop,              /* iter */
-       cc_loop,                /* enterloop */
-       cc_binop,               /* leaveloop */
-       cc_listop,              /* return */
-       cc_loopexop,            /* last */
-       cc_loopexop,            /* next */
-       cc_loopexop,            /* redo */
-       cc_loopexop,            /* dump */
-       cc_loopexop,            /* goto */
-       cc_baseop_or_unop,      /* exit */
-       cc_listop,              /* open */
-       cc_baseop_or_unop,      /* close */
-       cc_listop,              /* pipe_op */
-       cc_baseop_or_unop,      /* fileno */
-       cc_baseop_or_unop,      /* umask */
-       cc_baseop_or_unop,      /* binmode */
-       cc_listop,              /* tie */
-       cc_baseop_or_unop,      /* untie */
-       cc_baseop_or_unop,      /* tied */
-       cc_listop,              /* dbmopen */
-       cc_baseop_or_unop,      /* dbmclose */
-       cc_listop,              /* sselect */
-       cc_listop,              /* select */
-       cc_baseop_or_unop,      /* getc */
-       cc_listop,              /* read */
-       cc_baseop_or_unop,      /* enterwrite */
-       cc_unop,                /* leavewrite */
-       cc_listop,              /* prtf */
-       cc_listop,              /* print */
-       cc_listop,              /* sysopen */
-#if PATCHLEVEL > 3
-       cc_listop,              /* sysseek */
-#endif
-       cc_listop,              /* sysread */
-       cc_listop,              /* syswrite */
-       cc_listop,              /* send */
-       cc_listop,              /* recv */
-       cc_baseop_or_unop,      /* eof */
-       cc_baseop_or_unop,      /* tell */
-       cc_listop,              /* seek */
-       cc_listop,              /* truncate */
-       cc_listop,              /* fcntl */
-       cc_listop,              /* ioctl */
-       cc_listop,              /* flock */
-       cc_listop,              /* socket */
-       cc_listop,              /* sockpair */
-       cc_listop,              /* bind */
-       cc_listop,              /* connect */
-       cc_listop,              /* listen */
-       cc_listop,              /* accept */
-       cc_listop,              /* shutdown */
-       cc_listop,              /* gsockopt */
-       cc_listop,              /* ssockopt */
-       cc_baseop_or_unop,      /* getsockname */
-       cc_baseop_or_unop,      /* getpeername */
-       cc_filestatop,          /* lstat */
-       cc_filestatop,          /* stat */
-       cc_filestatop,          /* ftrread */
-       cc_filestatop,          /* ftrwrite */
-       cc_filestatop,          /* ftrexec */
-       cc_filestatop,          /* fteread */
-       cc_filestatop,          /* ftewrite */
-       cc_filestatop,          /* fteexec */
-       cc_filestatop,          /* ftis */
-       cc_filestatop,          /* fteowned */
-       cc_filestatop,          /* ftrowned */
-       cc_filestatop,          /* ftzero */
-       cc_filestatop,          /* ftsize */
-       cc_filestatop,          /* ftmtime */
-       cc_filestatop,          /* ftatime */
-       cc_filestatop,          /* ftctime */
-       cc_filestatop,          /* ftsock */
-       cc_filestatop,          /* ftchr */
-       cc_filestatop,          /* ftblk */
-       cc_filestatop,          /* ftfile */
-       cc_filestatop,          /* ftdir */
-       cc_filestatop,          /* ftpipe */
-       cc_filestatop,          /* ftlink */
-       cc_filestatop,          /* ftsuid */
-       cc_filestatop,          /* ftsgid */
-       cc_filestatop,          /* ftsvtx */
-       cc_filestatop,          /* fttty */
-       cc_filestatop,          /* fttext */
-       cc_filestatop,          /* ftbinary */
-       cc_baseop_or_unop,      /* chdir */
-       cc_listop,              /* chown */
-       cc_baseop_or_unop,      /* chroot */
-       cc_listop,              /* unlink */
-       cc_listop,              /* chmod */
-       cc_listop,              /* utime */
-       cc_listop,              /* rename */
-       cc_listop,              /* link */
-       cc_listop,              /* symlink */
-       cc_baseop_or_unop,      /* readlink */
-       cc_listop,              /* mkdir */
-       cc_baseop_or_unop,      /* rmdir */
-       cc_listop,              /* open_dir */
-       cc_baseop_or_unop,      /* readdir */
-       cc_baseop_or_unop,      /* telldir */
-       cc_listop,              /* seekdir */
-       cc_baseop_or_unop,      /* rewinddir */
-       cc_baseop_or_unop,      /* closedir */
-       cc_baseop,              /* fork */
-       cc_baseop,              /* wait */
-       cc_listop,              /* waitpid */
-       cc_listop,              /* system */
-       cc_listop,              /* exec */
-       cc_listop,              /* kill */
-       cc_baseop,              /* getppid */
-       cc_baseop_or_unop,      /* getpgrp */
-       cc_listop,              /* setpgrp */
-       cc_listop,              /* getpriority */
-       cc_listop,              /* setpriority */
-       cc_baseop,              /* time */
-       cc_baseop,              /* tms */
-       cc_baseop_or_unop,      /* localtime */
-       cc_baseop_or_unop,      /* gmtime */
-       cc_baseop_or_unop,      /* alarm */
-       cc_baseop_or_unop,      /* sleep */
-       cc_listop,              /* shmget */
-       cc_listop,              /* shmctl */
-       cc_listop,              /* shmread */
-       cc_listop,              /* shmwrite */
-       cc_listop,              /* msgget */
-       cc_listop,              /* msgctl */
-       cc_listop,              /* msgsnd */
-       cc_listop,              /* msgrcv */
-       cc_listop,              /* semget */
-       cc_listop,              /* semctl */
-       cc_listop,              /* semop */
-       cc_baseop_or_unop,      /* require */
-       cc_unop,                /* dofile */
-       cc_baseop_or_unop,      /* entereval */
-       cc_unop,                /* leaveeval */
-       cc_logop,               /* entertry */
-       cc_listop,              /* leavetry */
-       cc_baseop_or_unop,      /* ghbyname */
-       cc_listop,              /* ghbyaddr */
-       cc_baseop,              /* ghostent */
-       cc_baseop_or_unop,      /* gnbyname */
-       cc_listop,              /* gnbyaddr */
-       cc_baseop,              /* gnetent */
-       cc_baseop_or_unop,      /* gpbyname */
-       cc_listop,              /* gpbynumber */
-       cc_baseop,              /* gprotoent */
-       cc_listop,              /* gsbyname */
-       cc_listop,              /* gsbyport */
-       cc_baseop,              /* gservent */
-       cc_baseop_or_unop,      /* shostent */
-       cc_baseop_or_unop,      /* snetent */
-       cc_baseop_or_unop,      /* sprotoent */
-       cc_baseop_or_unop,      /* sservent */
-       cc_baseop,              /* ehostent */
-       cc_baseop,              /* enetent */
-       cc_baseop,              /* eprotoent */
-       cc_baseop,              /* eservent */
-       cc_baseop_or_unop,      /* gpwnam */
-       cc_baseop_or_unop,      /* gpwuid */
-       cc_baseop,              /* gpwent */
-       cc_baseop,              /* spwent */
-       cc_baseop,              /* epwent */
-       cc_baseop_or_unop,      /* ggrnam */
-       cc_baseop_or_unop,      /* ggrgid */
-       cc_baseop,              /* ggrent */
-       cc_baseop,              /* sgrent */
-       cc_baseop,              /* egrent */
-       cc_baseop,              /* getlogin */
-       cc_listop,              /* syscall */
-#if PATCHLEVEL > 4 || (PATCHLEVEL == 4 && SUBVERSION > 50)
-       cc_baseop_or_unop,      /* lock */
-#endif
-};
-
-opclass
-cc_opclass(o)
-OP *   o;
-{
-    return o ? (*ccopaddr[o->op_type])(o) : OPc_NULL;
+    case OA_LOOP:
+       return OPc_LOOP;
+
+    case OA_COP:
+       return OPc_COP;
+
+    case OA_BASEOP_OR_UNOP:
+       /*
+        * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on
+        * whether bare parens were seen. perly.y uses OPf_SPECIAL to
+        * signal whether an OP or an UNOP was chosen.
+        * Frederic.Chauveau@pasteur.fr says we need to check for OPf_KIDS too.
+        */
+       return ((o->op_flags & OPf_SPECIAL) ? OPc_BASEOP :
+               (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP);
+
+    case OA_FILESTATOP:
+       /*
+        * The file stat OPs are created via UNI(OP_foo) in toke.c but use
+        * the OPf_REF flag to distinguish between OP types instead of the
+        * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we
+        * return OPc_UNOP so that walkoptree can find our children. If
+        * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set
+        * (no argument to the operator) it's an OP; with OPf_REF set it's
+        * a GVOP (and op_gv is the GV for the filehandle argument).
+        */
+       return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :
+               (o->op_flags & OPf_REF) ? OPc_GVOP : OPc_BASEOP);
+
+    case OA_LOOPEXOP:
+       /*
+        * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a
+        * label was omitted (in which case it's a BASEOP) or else a term was
+        * seen. In this last case, all except goto are definitely PVOP but
+        * goto is either a PVOP (with an ordinary constant label), an UNOP
+        * with OPf_STACKED (with a non-constant non-sub) or an UNOP for
+        * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to
+        * get set.
+        */
+       if (o->op_flags & OPf_STACKED)
+           return OPc_UNOP;
+       else if (o->op_flags & OPf_SPECIAL)
+           return OPc_BASEOP;
+       else
+           return OPc_PVOP;
+    }
+    warn("can't determine class of operator %s, assuming BASEOP\n",
+        ppnames[o->op_type]);
+    return OPc_BASEOP;
 }
 
 char *
 cc_opclassname(o)
 OP *   o;
 {
-    return opclassnames[o ? (*ccopaddr[o->op_type])(o) : OPc_NULL];
+    return opclassnames[cc_opclass(o)];
 }
 
diff --git a/ccop.h b/ccop.h
index 4665a0e..03cfbe5 100644 (file)
--- a/ccop.h
+++ b/ccop.h
@@ -21,359 +21,3 @@ typedef enum {
 
 opclass        cc_opclass _((OP *o));
 char * cc_opclassname _((OP *o));              
-
-#ifndef DOINIT
-EXT char *ppnames[];
-#else
-EXT char *ppnames[] = {
-       "pp_null",
-       "pp_stub",
-       "pp_scalar",
-       "pp_pushmark",
-       "pp_wantarray",
-       "pp_const",
-       "pp_gvsv",
-       "pp_gv",
-       "pp_gelem",
-       "pp_padsv",
-       "pp_padav",
-       "pp_padhv",
-       "pp_padany",
-       "pp_pushre",
-       "pp_rv2gv",
-       "pp_rv2sv",
-       "pp_av2arylen",
-       "pp_rv2cv",
-       "pp_anoncode",
-       "pp_prototype",
-       "pp_refgen",
-       "pp_srefgen",
-       "pp_ref",
-       "pp_bless",
-       "pp_backtick",
-       "pp_glob",
-       "pp_readline",
-       "pp_rcatline",
-       "pp_regcmaybe",
-       "pp_regcomp",
-       "pp_match",
-       "pp_subst",
-       "pp_substcont",
-       "pp_trans",
-       "pp_sassign",
-       "pp_aassign",
-       "pp_chop",
-       "pp_schop",
-       "pp_chomp",
-       "pp_schomp",
-       "pp_defined",
-       "pp_undef",
-       "pp_study",
-       "pp_pos",
-       "pp_preinc",
-       "pp_i_preinc",
-       "pp_predec",
-       "pp_i_predec",
-       "pp_postinc",
-       "pp_i_postinc",
-       "pp_postdec",
-       "pp_i_postdec",
-       "pp_pow",
-       "pp_multiply",
-       "pp_i_multiply",
-       "pp_divide",
-       "pp_i_divide",
-       "pp_modulo",
-       "pp_i_modulo",
-       "pp_repeat",
-       "pp_add",
-       "pp_i_add",
-       "pp_subtract",
-       "pp_i_subtract",
-       "pp_concat",
-       "pp_stringify",
-       "pp_left_shift",
-       "pp_right_shift",
-       "pp_lt",
-       "pp_i_lt",
-       "pp_gt",
-       "pp_i_gt",
-       "pp_le",
-       "pp_i_le",
-       "pp_ge",
-       "pp_i_ge",
-       "pp_eq",
-       "pp_i_eq",
-       "pp_ne",
-       "pp_i_ne",
-       "pp_ncmp",
-       "pp_i_ncmp",
-       "pp_slt",
-       "pp_sgt",
-       "pp_sle",
-       "pp_sge",
-       "pp_seq",
-       "pp_sne",
-       "pp_scmp",
-       "pp_bit_and",
-       "pp_bit_xor",
-       "pp_bit_or",
-       "pp_negate",
-       "pp_i_negate",
-       "pp_not",
-       "pp_complement",
-       "pp_atan2",
-       "pp_sin",
-       "pp_cos",
-       "pp_rand",
-       "pp_srand",
-       "pp_exp",
-       "pp_log",
-       "pp_sqrt",
-       "pp_int",
-       "pp_hex",
-       "pp_oct",
-       "pp_abs",
-       "pp_length",
-       "pp_substr",
-       "pp_vec",
-       "pp_index",
-       "pp_rindex",
-       "pp_sprintf",
-       "pp_formline",
-       "pp_ord",
-       "pp_chr",
-       "pp_crypt",
-       "pp_ucfirst",
-       "pp_lcfirst",
-       "pp_uc",
-       "pp_lc",
-       "pp_quotemeta",
-       "pp_rv2av",
-       "pp_aelemfast",
-       "pp_aelem",
-       "pp_aslice",
-       "pp_each",
-       "pp_values",
-       "pp_keys",
-       "pp_delete",
-       "pp_exists",
-       "pp_rv2hv",
-       "pp_helem",
-       "pp_hslice",
-       "pp_unpack",
-       "pp_pack",
-       "pp_split",
-       "pp_join",
-       "pp_list",
-       "pp_lslice",
-       "pp_anonlist",
-       "pp_anonhash",
-       "pp_splice",
-       "pp_push",
-       "pp_pop",
-       "pp_shift",
-       "pp_unshift",
-       "pp_sort",
-       "pp_reverse",
-       "pp_grepstart",
-       "pp_grepwhile",
-       "pp_mapstart",
-       "pp_mapwhile",
-       "pp_range",
-       "pp_flip",
-       "pp_flop",
-       "pp_and",
-       "pp_or",
-       "pp_xor",
-       "pp_cond_expr",
-       "pp_andassign",
-       "pp_orassign",
-       "pp_method",
-       "pp_entersub",
-       "pp_leavesub",
-       "pp_caller",
-       "pp_warn",
-       "pp_die",
-       "pp_reset",
-       "pp_lineseq",
-       "pp_nextstate",
-       "pp_dbstate",
-       "pp_unstack",
-       "pp_enter",
-       "pp_leave",
-       "pp_scope",
-       "pp_enteriter",
-       "pp_iter",
-       "pp_enterloop",
-       "pp_leaveloop",
-       "pp_return",
-       "pp_last",
-       "pp_next",
-       "pp_redo",
-       "pp_dump",
-       "pp_goto",
-       "pp_exit",
-       "pp_open",
-       "pp_close",
-       "pp_pipe_op",
-       "pp_fileno",
-       "pp_umask",
-       "pp_binmode",
-       "pp_tie",
-       "pp_untie",
-       "pp_tied",
-       "pp_dbmopen",
-       "pp_dbmclose",
-       "pp_sselect",
-       "pp_select",
-       "pp_getc",
-       "pp_read",
-       "pp_enterwrite",
-       "pp_leavewrite",
-       "pp_prtf",
-       "pp_print",
-       "pp_sysopen",
-#if PATCHLEVEL > 3
-       "pp_sysseek",
-#endif
-       "pp_sysread",
-       "pp_syswrite",
-       "pp_send",
-       "pp_recv",
-       "pp_eof",
-       "pp_tell",
-       "pp_seek",
-       "pp_truncate",
-       "pp_fcntl",
-       "pp_ioctl",
-       "pp_flock",
-       "pp_socket",
-       "pp_sockpair",
-       "pp_bind",
-       "pp_connect",
-       "pp_listen",
-       "pp_accept",
-       "pp_shutdown",
-       "pp_gsockopt",
-       "pp_ssockopt",
-       "pp_getsockname",
-       "pp_getpeername",
-       "pp_lstat",
-       "pp_stat",
-       "pp_ftrread",
-       "pp_ftrwrite",
-       "pp_ftrexec",
-       "pp_fteread",
-       "pp_ftewrite",
-       "pp_fteexec",
-       "pp_ftis",
-       "pp_fteowned",
-       "pp_ftrowned",
-       "pp_ftzero",
-       "pp_ftsize",
-       "pp_ftmtime",
-       "pp_ftatime",
-       "pp_ftctime",
-       "pp_ftsock",
-       "pp_ftchr",
-       "pp_ftblk",
-       "pp_ftfile",
-       "pp_ftdir",
-       "pp_ftpipe",
-       "pp_ftlink",
-       "pp_ftsuid",
-       "pp_ftsgid",
-       "pp_ftsvtx",
-       "pp_fttty",
-       "pp_fttext",
-       "pp_ftbinary",
-       "pp_chdir",
-       "pp_chown",
-       "pp_chroot",
-       "pp_unlink",
-       "pp_chmod",
-       "pp_utime",
-       "pp_rename",
-       "pp_link",
-       "pp_symlink",
-       "pp_readlink",
-       "pp_mkdir",
-       "pp_rmdir",
-       "pp_open_dir",
-       "pp_readdir",
-       "pp_telldir",
-       "pp_seekdir",
-       "pp_rewinddir",
-       "pp_closedir",
-       "pp_fork",
-       "pp_wait",
-       "pp_waitpid",
-       "pp_system",
-       "pp_exec",
-       "pp_kill",
-       "pp_getppid",
-       "pp_getpgrp",
-       "pp_setpgrp",
-       "pp_getpriority",
-       "pp_setpriority",
-       "pp_time",
-       "pp_tms",
-       "pp_localtime",
-       "pp_gmtime",
-       "pp_alarm",
-       "pp_sleep",
-       "pp_shmget",
-       "pp_shmctl",
-       "pp_shmread",
-       "pp_shmwrite",
-       "pp_msgget",
-       "pp_msgctl",
-       "pp_msgsnd",
-       "pp_msgrcv",
-       "pp_semget",
-       "pp_semctl",
-       "pp_semop",
-       "pp_require",
-       "pp_dofile",
-       "pp_entereval",
-       "pp_leaveeval",
-       "pp_entertry",
-       "pp_leavetry",
-       "pp_ghbyname",
-       "pp_ghbyaddr",
-       "pp_ghostent",
-       "pp_gnbyname",
-       "pp_gnbyaddr",
-       "pp_gnetent",
-       "pp_gpbyname",
-       "pp_gpbynumber",
-       "pp_gprotoent",
-       "pp_gsbyname",
-       "pp_gsbyport",
-       "pp_gservent",
-       "pp_shostent",
-       "pp_snetent",
-       "pp_sprotoent",
-       "pp_sservent",
-       "pp_ehostent",
-       "pp_enetent",
-       "pp_eprotoent",
-       "pp_eservent",
-       "pp_gpwnam",
-       "pp_gpwuid",
-       "pp_gpwent",
-       "pp_spwent",
-       "pp_epwent",
-       "pp_ggrnam",
-       "pp_ggrgid",
-       "pp_ggrent",
-       "pp_sgrent",
-       "pp_egrent",
-       "pp_getlogin",
-       "pp_syscall",
-#if PATCHLEVEL > 4 || (PATCHLEVEL == 4 && SUBVERSION > 50)
-       "pp_lock",
-#endif
-};
-#endif
index 048fdc9..1a294ce 100755 (executable)
@@ -3,7 +3,12 @@ cwd=`pwd`
 if [ -f bperl ]; then
     perl=./bperl
 else
-    perl="perl -Iblib/arch"
+    perl="perl -Mblib"
+fi
+if [ "X$PERL_SRC" != "X" ]; then
+    testdir=$PERL_SRC/t
+else
+    testdir=t
 fi
 for pl in ${1+"$@"}
 do
@@ -11,5 +16,5 @@ do
     $perl -MO=C,-obtest.tc $pl                 \
        && mv btest.tc btest.c                  \
        && $perl cc_harness -o btest btest.c    \
-       && (cd t; $cwd/btest)
+       && (cd $testdir; $cwd/btest)
 done
index 01157a5..b0ff87e 100755 (executable)
@@ -3,7 +3,12 @@ cwd=`pwd`
 if [ -f bperl ]; then
     perl=./bperl
 else
-    perl="perl -Iblib/arch"
+    perl="perl -Mblib"
+fi
+if [ "X$PERL_SRC" != "X" ]; then
+    testdir=$PERL_SRC/t
+else
+    testdir=t
 fi
 for pl in ${1+"$@"}
 do
@@ -11,5 +16,5 @@ do
     $perl -MO=CC,-obtest.tc $pl                        \
        && mv btest.tc btest.c                  \
        && $perl cc_harness -O2 -o btest btest.c\
-       && (cd t; $cwd/btest)
+       && (cd $testdir; $cwd/btest)
 done